1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <vcl/event.hxx>
21 #include <vcl/window.hxx>
22 #include <vcl/dockwin.hxx>
23 #include <vcl/layout.hxx>
24 #include <sal/log.hxx>
25 
26 #include <window.h>
27 #include <svdata.hxx>
28 #include <salframe.hxx>
29 #include <config_features.h>
30 #include <comphelper/scopeguard.hxx>
31 
32 #include "impldockingwrapper.hxx"
33 
34 namespace vcl {
35 
DataChanged(const DataChangedEvent &)36 void Window::DataChanged( const DataChangedEvent& )
37 {
38 }
39 
NotifyAllChildren(DataChangedEvent & rDCEvt)40 void Window::NotifyAllChildren( DataChangedEvent& rDCEvt )
41 {
42     CompatDataChanged( rDCEvt );
43 
44     vcl::Window* pChild = mpWindowImpl->mpFirstChild;
45     while ( pChild )
46     {
47         pChild->NotifyAllChildren( rDCEvt );
48         pChild = pChild->mpWindowImpl->mpNext;
49     }
50 }
51 
PreNotify(NotifyEvent & rNEvt)52 bool Window::PreNotify( NotifyEvent& rNEvt )
53 {
54     bool bDone = false;
55     if ( mpWindowImpl->mpParent && !ImplIsOverlapWindow() )
56         bDone = mpWindowImpl->mpParent->CompatPreNotify( rNEvt );
57 
58     if ( !bDone )
59     {
60         if( rNEvt.GetType() == MouseNotifyEvent::GETFOCUS )
61         {
62             bool bCompoundFocusChanged = false;
63             if ( mpWindowImpl->mbCompoundControl && !mpWindowImpl->mbCompoundControlHasFocus && HasChildPathFocus() )
64             {
65                 mpWindowImpl->mbCompoundControlHasFocus = true;
66                 bCompoundFocusChanged = true;
67             }
68 
69             if ( bCompoundFocusChanged || ( rNEvt.GetWindow() == this ) )
70                 CallEventListeners( VclEventId::WindowGetFocus );
71         }
72         else if( rNEvt.GetType() == MouseNotifyEvent::LOSEFOCUS )
73         {
74             bool bCompoundFocusChanged = false;
75             if ( mpWindowImpl->mbCompoundControl && mpWindowImpl->mbCompoundControlHasFocus && !HasChildPathFocus() )
76             {
77                 mpWindowImpl->mbCompoundControlHasFocus = false ;
78                 bCompoundFocusChanged = true;
79             }
80 
81             if ( bCompoundFocusChanged || ( rNEvt.GetWindow() == this ) )
82                 CallEventListeners( VclEventId::WindowLoseFocus );
83         }
84 
85         // #82968# mouse and key events will be notified after processing ( in ImplNotifyKeyMouseCommandEventListeners() )!
86         //    see also ImplHandleMouseEvent(), ImplHandleKey()
87 
88     }
89 
90     return bDone;
91 }
92 
93 namespace
94 {
parentNotDialogControl(Window * pWindow)95     bool parentNotDialogControl(Window* pWindow)
96     {
97         vcl::Window* pParent = getNonLayoutParent(pWindow);
98         if (!pParent)
99             return true;
100         return ((pParent->GetStyle() & (WB_DIALOGCONTROL | WB_NODIALOGCONTROL)) != WB_DIALOGCONTROL);
101     }
102 }
103 
EventNotify(NotifyEvent & rNEvt)104 bool Window::EventNotify( NotifyEvent& rNEvt )
105 {
106     bool bRet = false;
107 
108     if (isDisposed())
109         return false;
110 
111     // check for docking window
112     // but do nothing if window is docked and locked
113     ImplDockingWindowWrapper *pWrapper = ImplGetDockingManager()->GetDockingWindowWrapper( this );
114     if (pWrapper && ( pWrapper->IsFloatingMode() || !pWrapper->IsLocked() ))
115     {
116         const bool bDockingSupportCrippled = !StyleSettings::GetDockingFloatsSupported();
117 
118         if ( rNEvt.GetType() == MouseNotifyEvent::MOUSEBUTTONDOWN )
119         {
120             const MouseEvent* pMEvt = rNEvt.GetMouseEvent();
121             bool bHit = pWrapper->GetDragArea().IsInside( pMEvt->GetPosPixel() );
122             if ( pMEvt->IsLeft() )
123             {
124                 if (!bDockingSupportCrippled && pMEvt->IsMod1() && (pMEvt->GetClicks() == 2))
125                 {
126                     // ctrl double click toggles floating mode
127                     pWrapper->SetFloatingMode( !pWrapper->IsFloatingMode() );
128                     return true;
129                 }
130                 else if ( pMEvt->GetClicks() == 1 && bHit)
131                 {
132                     // allow start docking during mouse move
133                     pWrapper->ImplEnableStartDocking();
134                     return true;
135                 }
136             }
137         }
138         else if ( rNEvt.GetType() == MouseNotifyEvent::MOUSEMOVE )
139         {
140             const MouseEvent* pMEvt = rNEvt.GetMouseEvent();
141             bool bHit = pWrapper->GetDragArea().IsInside( pMEvt->GetPosPixel() );
142             if ( pMEvt->IsLeft() )
143             {
144                 // check if a single click initiated this sequence ( ImplStartDockingEnabled() )
145                 // check if window is docked and
146                 if( pWrapper->ImplStartDockingEnabled() && !pWrapper->IsFloatingMode() &&
147                     !pWrapper->IsDocking() && bHit )
148                 {
149                     Point   aPos = pMEvt->GetPosPixel();
150                     vcl::Window* pWindow = rNEvt.GetWindow();
151                     if ( pWindow != this )
152                     {
153                         aPos = pWindow->OutputToScreenPixel( aPos );
154                         aPos = ScreenToOutputPixel( aPos );
155                     }
156                     pWrapper->ImplStartDocking( aPos );
157                 }
158                 return true;
159             }
160         }
161         else if( rNEvt.GetType() == MouseNotifyEvent::KEYINPUT )
162         {
163             const vcl::KeyCode& rKey = rNEvt.GetKeyEvent()->GetKeyCode();
164             if (rKey.GetCode() == KEY_F10 && rKey.GetModifier() &&
165                 rKey.IsShift() && rKey.IsMod1() && !bDockingSupportCrippled)
166             {
167                 pWrapper->SetFloatingMode( !pWrapper->IsFloatingMode() );
168                 /* At this point the floating toolbar frame does not have the
169                  * input focus since these frames don't get the focus per default
170                  * To enable keyboard handling of this toolbar set the input focus
171                  * to the frame. This needs to be done with ToTop since GrabFocus
172                  * would not notice any change since "this" already has the focus.
173                  */
174                 if( pWrapper->IsFloatingMode() )
175                     ToTop( ToTopFlags::GrabFocusOnly );
176                 return true;
177             }
178         }
179     }
180 
181     // manage the dialogs
182     if ( (GetStyle() & (WB_DIALOGCONTROL | WB_NODIALOGCONTROL)) == WB_DIALOGCONTROL )
183     {
184         // if the parent also has dialog control activated, the parent takes over control
185         if ( (rNEvt.GetType() == MouseNotifyEvent::KEYINPUT) || (rNEvt.GetType() == MouseNotifyEvent::KEYUP) )
186         {
187             // ScGridWindow has WB_DIALOGCONTROL set, so pressing tab in ScCheckListMenuControl won't
188             // get processed here by the toplevel DockingWindow of ScCheckListMenuControl by
189             // just checking if parentNotDialogControl is true
190             bool bTopLevelFloatingWindow = (pWrapper && pWrapper->IsFloatingMode());
191             if (ImplIsOverlapWindow() || parentNotDialogControl(this) || bTopLevelFloatingWindow)
192             {
193                 bRet = ImplDlgCtrl( *rNEvt.GetKeyEvent(), rNEvt.GetType() == MouseNotifyEvent::KEYINPUT );
194             }
195         }
196         else if ( (rNEvt.GetType() == MouseNotifyEvent::GETFOCUS) || (rNEvt.GetType() == MouseNotifyEvent::LOSEFOCUS) )
197         {
198             ImplDlgCtrlFocusChanged( rNEvt.GetWindow(), rNEvt.GetType() == MouseNotifyEvent::GETFOCUS );
199             if ( (rNEvt.GetWindow() == this) && (rNEvt.GetType() == MouseNotifyEvent::GETFOCUS) &&
200                  !(GetStyle() & WB_TABSTOP) && !(mpWindowImpl->mnDlgCtrlFlags & DialogControlFlags::WantFocus) )
201             {
202                 vcl::Window* pFirstChild = ImplGetDlgWindow( 0, GetDlgWindowType::First );
203                 if ( pFirstChild )
204                     pFirstChild->ImplControlFocus();
205             }
206         }
207     }
208 
209     if ( !bRet )
210     {
211         if ( mpWindowImpl->mpParent && !ImplIsOverlapWindow() )
212             bRet = mpWindowImpl->mpParent->CompatNotify( rNEvt );
213     }
214 
215     return bRet;
216 }
217 
CallEventListeners(VclEventId nEvent,void * pData)218 void Window::CallEventListeners( VclEventId nEvent, void* pData )
219 {
220     VclWindowEvent aEvent( this, nEvent, pData );
221 
222     VclPtr<vcl::Window> xWindow = this;
223 
224     Application::ImplCallEventListeners( aEvent );
225 
226     if ( xWindow->isDisposed() )
227         return;
228 
229     // If maEventListeners is empty, the XVCLWindow has not yet been initialized.
230     // Calling GetComponentInterface will do that.
231     if (mpWindowImpl->maEventListeners.empty() && pData)
232         xWindow->GetComponentInterface();
233 
234     if (!mpWindowImpl->maEventListeners.empty())
235     {
236         // Copy the list, because this can be destroyed when calling a Link...
237         std::vector<Link<VclWindowEvent&,void>> aCopy( mpWindowImpl->maEventListeners );
238         // we use an iterating counter/flag and a set of deleted Link's to avoid O(n^2) behaviour
239         mpWindowImpl->mnEventListenersIteratingCount++;
240         auto& rWindowImpl = *mpWindowImpl;
241         comphelper::ScopeGuard aGuard(
242             [&rWindowImpl, &xWindow]()
243             {
244                 if (!xWindow->isDisposed())
245                 {
246                     rWindowImpl.mnEventListenersIteratingCount--;
247                     if (rWindowImpl.mnEventListenersIteratingCount == 0)
248                         rWindowImpl.maEventListenersDeleted.clear();
249                 }
250             }
251         );
252         for ( const Link<VclWindowEvent&,void>& rLink : aCopy )
253         {
254             if (xWindow->isDisposed()) break;
255             // check this hasn't been removed in some re-enterancy scenario fdo#47368
256             if( rWindowImpl.maEventListenersDeleted.find(rLink) == rWindowImpl.maEventListenersDeleted.end() )
257                 rLink.Call( aEvent );
258         }
259     }
260 
261     while ( xWindow )
262     {
263 
264         if ( xWindow->isDisposed() )
265             return;
266 
267         auto& rWindowImpl = *xWindow->mpWindowImpl;
268         if (!rWindowImpl.maChildEventListeners.empty())
269         {
270             // Copy the list, because this can be destroyed when calling a Link...
271             std::vector<Link<VclWindowEvent&,void>> aCopy( rWindowImpl.maChildEventListeners );
272             // we use an iterating counter/flag and a set of deleted Link's to avoid O(n^2) behaviour
273             rWindowImpl.mnChildEventListenersIteratingCount++;
274             comphelper::ScopeGuard aGuard(
275                 [&rWindowImpl, &xWindow]()
276                 {
277                     if (!xWindow->isDisposed())
278                     {
279                         rWindowImpl.mnChildEventListenersIteratingCount--;
280                         if (rWindowImpl.mnChildEventListenersIteratingCount == 0)
281                             rWindowImpl.maChildEventListenersDeleted.clear();
282                     }
283                 }
284             );
285             for ( const Link<VclWindowEvent&,void>& rLink : aCopy )
286             {
287                 if (xWindow->isDisposed())
288                     return;
289                 // Check this hasn't been removed in some re-enterancy scenario fdo#47368.
290                 if( rWindowImpl.maChildEventListenersDeleted.find(rLink) == rWindowImpl.maChildEventListenersDeleted.end() )
291                     rLink.Call( aEvent );
292             }
293         }
294 
295         if ( xWindow->isDisposed() )
296             return;
297 
298         xWindow = xWindow->GetParent();
299     }
300 }
301 
AddEventListener(const Link<VclWindowEvent &,void> & rEventListener)302 void Window::AddEventListener( const Link<VclWindowEvent&,void>& rEventListener )
303 {
304     mpWindowImpl->maEventListeners.push_back( rEventListener );
305 }
306 
RemoveEventListener(const Link<VclWindowEvent &,void> & rEventListener)307 void Window::RemoveEventListener( const Link<VclWindowEvent&,void>& rEventListener )
308 {
309     if (mpWindowImpl)
310     {
311         auto& rListeners = mpWindowImpl->maEventListeners;
312         rListeners.erase( std::remove(rListeners.begin(), rListeners.end(), rEventListener ), rListeners.end() );
313         if (mpWindowImpl->mnEventListenersIteratingCount)
314             mpWindowImpl->maEventListenersDeleted.insert(rEventListener);
315     }
316 }
317 
AddChildEventListener(const Link<VclWindowEvent &,void> & rEventListener)318 void Window::AddChildEventListener( const Link<VclWindowEvent&,void>& rEventListener )
319 {
320     mpWindowImpl->maChildEventListeners.push_back( rEventListener );
321 }
322 
RemoveChildEventListener(const Link<VclWindowEvent &,void> & rEventListener)323 void Window::RemoveChildEventListener( const Link<VclWindowEvent&,void>& rEventListener )
324 {
325     if (mpWindowImpl)
326     {
327         auto& rListeners = mpWindowImpl->maChildEventListeners;
328         rListeners.erase( std::remove(rListeners.begin(), rListeners.end(), rEventListener ), rListeners.end() );
329         if (mpWindowImpl->mnChildEventListenersIteratingCount)
330             mpWindowImpl->maChildEventListenersDeleted.insert(rEventListener);
331     }
332 }
333 
PostUserEvent(const Link<void *,void> & rLink,void * pCaller,bool bReferenceLink)334 ImplSVEvent * Window::PostUserEvent( const Link<void*,void>& rLink, void* pCaller, bool bReferenceLink )
335 {
336     std::unique_ptr<ImplSVEvent> pSVEvent(new ImplSVEvent);
337     pSVEvent->mpData    = pCaller;
338     pSVEvent->maLink    = rLink;
339     pSVEvent->mpWindow  = this;
340     pSVEvent->mbCall    = true;
341     if (bReferenceLink)
342     {
343         pSVEvent->mpInstanceRef = static_cast<vcl::Window *>(rLink.GetInstance());
344     }
345 
346     auto pTmpEvent = pSVEvent.get();
347     if (!mpWindowImpl->mpFrame->PostEvent( std::move(pSVEvent) ))
348         return nullptr;
349     return pTmpEvent;
350 }
351 
RemoveUserEvent(ImplSVEvent * nUserEvent)352 void Window::RemoveUserEvent( ImplSVEvent * nUserEvent )
353 {
354     SAL_WARN_IF( nUserEvent->mpWindow.get() != this, "vcl",
355                 "Window::RemoveUserEvent(): Event doesn't send to this window or is already removed" );
356     SAL_WARN_IF( !nUserEvent->mbCall, "vcl",
357                 "Window::RemoveUserEvent(): Event is already removed" );
358 
359     if ( nUserEvent->mpWindow )
360     {
361         nUserEvent->mpWindow = nullptr;
362     }
363 
364     nUserEvent->mbCall = false;
365 }
366 
367 
ImplTranslateMouseEvent(const MouseEvent & rE,vcl::Window const * pSource,vcl::Window const * pDest)368 static MouseEvent ImplTranslateMouseEvent( const MouseEvent& rE, vcl::Window const * pSource, vcl::Window const * pDest )
369 {
370     // the mouse event occurred in a different window, we need to translate the coordinates of
371     // the mouse cursor within that (source) window to the coordinates the mouse cursor would
372     // be in the destination window
373     Point aPos = pSource->OutputToScreenPixel( rE.GetPosPixel() );
374     return MouseEvent( pDest->ScreenToOutputPixel( aPos ), rE.GetClicks(), rE.GetMode(), rE.GetButtons(), rE.GetModifier() );
375 }
376 
ImplNotifyKeyMouseCommandEventListeners(NotifyEvent & rNEvt)377 void Window::ImplNotifyKeyMouseCommandEventListeners( NotifyEvent& rNEvt )
378 {
379     if( rNEvt.GetType() == MouseNotifyEvent::COMMAND )
380     {
381         const CommandEvent* pCEvt = rNEvt.GetCommandEvent();
382         if ( pCEvt->GetCommand() != CommandEventId::ContextMenu )
383             // non context menu events are not to be notified up the chain
384             // so we return immediately
385             return;
386 
387         if ( mpWindowImpl->mbCompoundControl || ( rNEvt.GetWindow() == this ) )
388         {
389             // not interested: The event listeners are already called in ::Command,
390             // and calling them here a second time doesn't make sense
391             if ( rNEvt.GetWindow() != this )
392             {
393                 CommandEvent aCommandEvent;
394 
395                 if ( !pCEvt->IsMouseEvent() )
396                 {
397                     aCommandEvent = *pCEvt;
398                 }
399                 else
400                 {
401                     // the mouse event occurred in a different window, we need to translate the coordinates of
402                     // the mouse cursor within that window to the coordinates the mouse cursor would be in the
403                     // current window
404                     vcl::Window* pSource = rNEvt.GetWindow();
405                     Point aPos = pSource->OutputToScreenPixel( pCEvt->GetMousePosPixel() );
406                     aCommandEvent = CommandEvent( ScreenToOutputPixel( aPos ), pCEvt->GetCommand(), pCEvt->IsMouseEvent(), pCEvt->GetEventData() );
407                 }
408 
409                 CallEventListeners( VclEventId::WindowCommand, &aCommandEvent );
410             }
411         }
412     }
413 
414     // #82968# notify event listeners for mouse and key events separately and
415     // not in PreNotify ( as for focus listeners )
416     // this allows for processing those events internally first and pass it to
417     // the toolkit later
418 
419     VclPtr<vcl::Window> xWindow = this;
420 
421     if( rNEvt.GetType() == MouseNotifyEvent::MOUSEMOVE )
422     {
423         if ( mpWindowImpl->mbCompoundControl || ( rNEvt.GetWindow() == this ) )
424         {
425             if ( rNEvt.GetWindow() == this )
426                 CallEventListeners( VclEventId::WindowMouseMove, const_cast<MouseEvent *>(rNEvt.GetMouseEvent()) );
427             else
428             {
429                 MouseEvent aMouseEvent = ImplTranslateMouseEvent( *rNEvt.GetMouseEvent(), rNEvt.GetWindow(), this );
430                 CallEventListeners( VclEventId::WindowMouseMove, &aMouseEvent );
431             }
432         }
433     }
434     else if( rNEvt.GetType() == MouseNotifyEvent::MOUSEBUTTONUP )
435     {
436         if ( mpWindowImpl->mbCompoundControl || ( rNEvt.GetWindow() == this ) )
437         {
438             if ( rNEvt.GetWindow() == this )
439                 CallEventListeners( VclEventId::WindowMouseButtonUp, const_cast<MouseEvent *>(rNEvt.GetMouseEvent()) );
440             else
441             {
442                 MouseEvent aMouseEvent = ImplTranslateMouseEvent( *rNEvt.GetMouseEvent(), rNEvt.GetWindow(), this );
443                 CallEventListeners( VclEventId::WindowMouseButtonUp, &aMouseEvent );
444             }
445         }
446     }
447     else if( rNEvt.GetType() == MouseNotifyEvent::MOUSEBUTTONDOWN )
448     {
449         if ( mpWindowImpl->mbCompoundControl || ( rNEvt.GetWindow() == this ) )
450         {
451             if ( rNEvt.GetWindow() == this )
452                 CallEventListeners( VclEventId::WindowMouseButtonDown, const_cast<MouseEvent *>(rNEvt.GetMouseEvent()) );
453             else
454             {
455                 MouseEvent aMouseEvent = ImplTranslateMouseEvent( *rNEvt.GetMouseEvent(), rNEvt.GetWindow(), this );
456                 CallEventListeners( VclEventId::WindowMouseButtonDown, &aMouseEvent );
457             }
458         }
459     }
460     else if( rNEvt.GetType() == MouseNotifyEvent::KEYINPUT )
461     {
462         if ( mpWindowImpl->mbCompoundControl || ( rNEvt.GetWindow() == this ) )
463             CallEventListeners( VclEventId::WindowKeyInput, const_cast<KeyEvent *>(rNEvt.GetKeyEvent()) );
464     }
465     else if( rNEvt.GetType() == MouseNotifyEvent::KEYUP )
466     {
467         if ( mpWindowImpl->mbCompoundControl || ( rNEvt.GetWindow() == this ) )
468             CallEventListeners( VclEventId::WindowKeyUp, const_cast<KeyEvent *>(rNEvt.GetKeyEvent()) );
469     }
470 
471     if ( xWindow->isDisposed() )
472         return;
473 
474     // #106721# check if we're part of a compound control and notify
475     vcl::Window *pParent = ImplGetParent();
476     while( pParent )
477     {
478         if( pParent->IsCompoundControl() )
479         {
480             pParent->ImplNotifyKeyMouseCommandEventListeners( rNEvt );
481             break;
482         }
483         pParent = pParent->ImplGetParent();
484     }
485 }
486 
ImplCallInitShow()487 void Window::ImplCallInitShow()
488 {
489     mpWindowImpl->mbReallyShown   = true;
490     mpWindowImpl->mbInInitShow    = true;
491     CompatStateChanged( StateChangedType::InitShow );
492     mpWindowImpl->mbInInitShow    = false;
493 
494     vcl::Window* pWindow = mpWindowImpl->mpFirstOverlap;
495     while ( pWindow )
496     {
497         if ( pWindow->mpWindowImpl->mbVisible )
498             pWindow->ImplCallInitShow();
499         pWindow = pWindow->mpWindowImpl->mpNext;
500     }
501 
502     pWindow = mpWindowImpl->mpFirstChild;
503     while ( pWindow )
504     {
505         if ( pWindow->mpWindowImpl->mbVisible )
506             pWindow->ImplCallInitShow();
507         pWindow = pWindow->mpWindowImpl->mpNext;
508     }
509 }
510 
511 
ImplCallResize()512 void Window::ImplCallResize()
513 {
514     mpWindowImpl->mbCallResize = false;
515 
516     // Normally we avoid blanking on re-size unless people might notice:
517     if( GetBackground().IsGradient() )
518         Invalidate();
519 
520     Resize();
521 
522     // #88419# Most classes don't call the base class in Resize() and Move(),
523     // => Call ImpleResize/Move instead of Resize/Move directly...
524     CallEventListeners( VclEventId::WindowResize );
525 }
526 
ImplCallMove()527 void Window::ImplCallMove()
528 {
529     mpWindowImpl->mbCallMove = false;
530 
531     if( mpWindowImpl->mbFrame )
532     {
533         // update frame position
534         SalFrame *pParentFrame = nullptr;
535         vcl::Window *pParent = ImplGetParent();
536         while( pParent )
537         {
538             if( pParent->mpWindowImpl &&
539                 pParent->mpWindowImpl->mpFrame != mpWindowImpl->mpFrame )
540             {
541                 pParentFrame = pParent->mpWindowImpl->mpFrame;
542                 break;
543             }
544             pParent = pParent->GetParent();
545         }
546 
547         SalFrameGeometry g = mpWindowImpl->mpFrame->GetGeometry();
548         mpWindowImpl->maPos = Point( g.nX, g.nY );
549         if( pParentFrame )
550         {
551             g = pParentFrame->GetGeometry();
552             mpWindowImpl->maPos -= Point( g.nX, g.nY );
553         }
554         // the client window and all its subclients have the same position as the borderframe
555         // this is important for floating toolbars where the borderwindow is a floating window
556         // which has another borderwindow (ie the system floating window)
557         vcl::Window *pClientWin = mpWindowImpl->mpClientWindow;
558         while( pClientWin )
559         {
560             pClientWin->mpWindowImpl->maPos = mpWindowImpl->maPos;
561             pClientWin = pClientWin->mpWindowImpl->mpClientWindow;
562         }
563     }
564 
565     Move();
566 
567     CallEventListeners( VclEventId::WindowMove );
568 }
569 
ImplCallFocusChangeActivate(vcl::Window * pNewOverlapWindow,vcl::Window * pOldOverlapWindow)570 void Window::ImplCallFocusChangeActivate( vcl::Window* pNewOverlapWindow,
571                                           vcl::Window* pOldOverlapWindow )
572 {
573     ImplSVData* pSVData = ImplGetSVData();
574     vcl::Window*     pNewRealWindow;
575     vcl::Window*     pOldRealWindow;
576     bool bCallActivate = true;
577     bool bCallDeactivate = true;
578 
579     if (!pOldOverlapWindow)
580     {
581         return;
582     }
583 
584     pOldRealWindow = pOldOverlapWindow->ImplGetWindow();
585     if (!pNewOverlapWindow)
586     {
587         return;
588     }
589 
590     pNewRealWindow = pNewOverlapWindow->ImplGetWindow();
591     if ( (pOldRealWindow->GetType() != WindowType::FLOATINGWINDOW) ||
592          pOldRealWindow->GetActivateMode() != ActivateModeFlags::NONE )
593     {
594         if ( (pNewRealWindow->GetType() == WindowType::FLOATINGWINDOW) &&
595              pNewRealWindow->GetActivateMode() == ActivateModeFlags::NONE)
596         {
597             pSVData->mpWinData->mpLastDeacWin = pOldOverlapWindow;
598             bCallDeactivate = false;
599         }
600     }
601     else if ( (pNewRealWindow->GetType() != WindowType::FLOATINGWINDOW) ||
602               pNewRealWindow->GetActivateMode() != ActivateModeFlags::NONE )
603     {
604         if (pSVData->mpWinData->mpLastDeacWin)
605         {
606             if (pSVData->mpWinData->mpLastDeacWin.get() == pNewOverlapWindow)
607                 bCallActivate = false;
608             else
609             {
610                 vcl::Window* pLastRealWindow = pSVData->mpWinData->mpLastDeacWin->ImplGetWindow();
611                 pSVData->mpWinData->mpLastDeacWin->mpWindowImpl->mbActive = false;
612                 pSVData->mpWinData->mpLastDeacWin->Deactivate();
613                 if (pLastRealWindow != pSVData->mpWinData->mpLastDeacWin.get())
614                 {
615                     pLastRealWindow->mpWindowImpl->mbActive = true;
616                     pLastRealWindow->Activate();
617                 }
618             }
619             pSVData->mpWinData->mpLastDeacWin = nullptr;
620         }
621     }
622 
623     if ( bCallDeactivate )
624     {
625         if( pOldOverlapWindow->mpWindowImpl->mbActive )
626         {
627             pOldOverlapWindow->mpWindowImpl->mbActive = false;
628             pOldOverlapWindow->Deactivate();
629         }
630         if ( pOldRealWindow != pOldOverlapWindow )
631         {
632             if( pOldRealWindow->mpWindowImpl->mbActive )
633             {
634                 pOldRealWindow->mpWindowImpl->mbActive = false;
635                 pOldRealWindow->Deactivate();
636             }
637         }
638     }
639     if ( !bCallActivate || pNewOverlapWindow->mpWindowImpl->mbActive )
640         return;
641 
642     pNewOverlapWindow->mpWindowImpl->mbActive = true;
643     pNewOverlapWindow->Activate();
644 
645     if ( pNewRealWindow != pNewOverlapWindow )
646     {
647         if( ! pNewRealWindow->mpWindowImpl->mbActive )
648         {
649             pNewRealWindow->mpWindowImpl->mbActive = true;
650             pNewRealWindow->Activate();
651         }
652     }
653 }
654 
655 } /* namespace vcl */
656 
657 
NotifyEvent(MouseNotifyEvent nEventType,vcl::Window * pWindow,const void * pEvent)658 NotifyEvent::NotifyEvent( MouseNotifyEvent nEventType, vcl::Window* pWindow,
659                           const void* pEvent )
660 {
661     mpWindow    = pWindow;
662     mpData      = const_cast<void*>(pEvent);
663     mnEventType  = nEventType;
664 }
665 
666 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
667