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