xref: /core/vcl/source/window/winproc.cxx (revision b6b26421)
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 <sal/config.h>
21 
22 #include <o3tl/safeint.hxx>
23 #include <tools/debug.hxx>
24 #include <tools/time.hxx>
25 #include <sal/log.hxx>
26 
27 #include <unotools/localedatawrapper.hxx>
28 
29 #include <dndeventdispatcher.hxx>
30 #include <comphelper/lok.hxx>
31 #include <vcl/QueueInfo.hxx>
32 #include <vcl/timer.hxx>
33 #include <vcl/event.hxx>
34 #include <vcl/GestureEventPan.hxx>
35 #include <vcl/GestureEventZoom.hxx>
36 #include <vcl/GestureEventRotate.hxx>
37 #include <vcl/settings.hxx>
38 #include <vcl/svapp.hxx>
39 #include <vcl/cursor.hxx>
40 #include <vcl/wrkwin.hxx>
41 #include <vcl/toolkit/floatwin.hxx>
42 #include <vcl/toolkit/dialog.hxx>
43 #include <vcl/toolkit/edit.hxx>
44 #include <vcl/help.hxx>
45 #include <vcl/dockwin.hxx>
46 #include <vcl/menu.hxx>
47 #include <vcl/virdev.hxx>
48 #include <vcl/uitest/logger.hxx>
49 #include <vcl/ptrstyle.hxx>
50 
51 #include <svdata.hxx>
52 #include <salwtype.hxx>
53 #include <salframe.hxx>
54 #include <accmgr.hxx>
55 #include <print.h>
56 #include <window.h>
57 #include <helpwin.hxx>
58 #include <brdwin.hxx>
59 #include <dndlistenercontainer.hxx>
60 
61 #include <com/sun/star/datatransfer/dnd/DNDConstants.hpp>
62 #include <com/sun/star/datatransfer/dnd/XDragSource.hpp>
63 #include <com/sun/star/awt/MouseEvent.hpp>
64 
65 #define IMPL_MIN_NEEDSYSWIN         49
66 
ImplCallPreNotify(NotifyEvent & rEvt)67 bool ImplCallPreNotify( NotifyEvent& rEvt )
68 {
69     return rEvt.GetWindow()->CompatPreNotify( rEvt );
70 }
71 
ImplHandleMouseFloatMode(vcl::Window * pChild,const Point & rMousePos,sal_uInt16 nCode,NotifyEventType nSVEvent,bool bMouseLeave)72 static bool ImplHandleMouseFloatMode( vcl::Window* pChild, const Point& rMousePos,
73                                       sal_uInt16 nCode, NotifyEventType nSVEvent,
74                                       bool bMouseLeave )
75 {
76     ImplSVData* pSVData = ImplGetSVData();
77 
78     if (pSVData->mpWinData->mpFirstFloat && !pSVData->mpWinData->mpCaptureWin
79         && !pSVData->mpWinData->mpFirstFloat->ImplIsFloatPopupModeWindow(pChild))
80     {
81         /*
82          *  #93895# since floats are system windows, coordinates have
83          *  to be converted to float relative for the hittest
84          */
85         bool            bHitTestInsideRect = false;
86         FloatingWindow* pFloat = pSVData->mpWinData->mpFirstFloat->ImplFloatHitTest( pChild, rMousePos, bHitTestInsideRect );
87         if ( nSVEvent == NotifyEventType::MOUSEMOVE )
88         {
89             if ( bMouseLeave )
90                 return true;
91 
92             if ( !pFloat || bHitTestInsideRect )
93             {
94                 if ( ImplGetSVHelpData().mpHelpWin && !ImplGetSVHelpData().mbKeyboardHelp )
95                     ImplDestroyHelpWindow( true );
96                 pChild->ImplGetFrame()->SetPointer( PointerStyle::Arrow );
97                 return true;
98             }
99         }
100         else
101         {
102             if ( nCode & MOUSE_LEFT )
103             {
104                 if ( nSVEvent == NotifyEventType::MOUSEBUTTONDOWN )
105                 {
106                     if ( !pFloat )
107                     {
108                         FloatingWindow* pLastLevelFloat = pSVData->mpWinData->mpFirstFloat->ImplFindLastLevelFloat();
109                         pLastLevelFloat->EndPopupMode( FloatWinPopupEndFlags::Cancel | FloatWinPopupEndFlags::CloseAll );
110                         return true;
111                     }
112                     else if ( bHitTestInsideRect )
113                     {
114                         pFloat->ImplSetMouseDown();
115                         return true;
116                     }
117                 }
118                 else
119                 {
120                     if ( pFloat )
121                     {
122                         if ( bHitTestInsideRect )
123                         {
124                             if ( pFloat->ImplIsMouseDown() )
125                                 pFloat->EndPopupMode( FloatWinPopupEndFlags::Cancel );
126                             return true;
127                         }
128                     }
129                     else
130                     {
131                         FloatingWindow* pLastLevelFloat = pSVData->mpWinData->mpFirstFloat->ImplFindLastLevelFloat();
132                         FloatWinPopupFlags nPopupFlags = pLastLevelFloat->GetPopupModeFlags();
133                         if ( !(nPopupFlags & FloatWinPopupFlags::NoMouseUpClose) )
134                         {
135                             pLastLevelFloat->EndPopupMode( FloatWinPopupEndFlags::Cancel | FloatWinPopupEndFlags::CloseAll );
136                             return true;
137                         }
138                     }
139                 }
140             }
141             else
142             {
143                 if ( !pFloat )
144                 {
145                     FloatingWindow* pLastLevelFloat = pSVData->mpWinData->mpFirstFloat->ImplFindLastLevelFloat();
146                     FloatWinPopupFlags nPopupFlags = pLastLevelFloat->GetPopupModeFlags();
147                     if ( nPopupFlags & FloatWinPopupFlags::AllMouseButtonClose )
148                     {
149                         if ( (nPopupFlags & FloatWinPopupFlags::NoMouseUpClose) &&
150                              (nSVEvent == NotifyEventType::MOUSEBUTTONUP) )
151                             return true;
152                         pLastLevelFloat->EndPopupMode( FloatWinPopupEndFlags::Cancel | FloatWinPopupEndFlags::CloseAll );
153                         return true;
154                     }
155                     else
156                         return true;
157                 }
158             }
159         }
160     }
161 
162     return false;
163 }
164 
ImplHandleMouseHelpRequest(vcl::Window * pChild,const Point & rMousePos)165 static void ImplHandleMouseHelpRequest( vcl::Window* pChild, const Point& rMousePos )
166 {
167     ImplSVHelpData& aHelpData = ImplGetSVHelpData();
168     if ( aHelpData.mpHelpWin &&
169          ( aHelpData.mpHelpWin->IsWindowOrChild( pChild ) ||
170            pChild->IsWindowOrChild( aHelpData.mpHelpWin ) ))
171         return;
172 
173     HelpEventMode nHelpMode = HelpEventMode::NONE;
174     if ( aHelpData.mbQuickHelp )
175         nHelpMode = HelpEventMode::QUICK;
176     if ( aHelpData.mbBalloonHelp )
177         nHelpMode |= HelpEventMode::BALLOON;
178     if ( !(bool(nHelpMode)) )
179         return;
180 
181     if ( pChild->IsInputEnabled() && !pChild->IsInModalMode() )
182     {
183         HelpEvent aHelpEvent( rMousePos, nHelpMode );
184         aHelpData.mbRequestingHelp = true;
185         pChild->RequestHelp( aHelpEvent );
186         aHelpData.mbRequestingHelp = false;
187     }
188     // #104172# do not kill keyboard activated tooltips
189     else if ( aHelpData.mpHelpWin && !aHelpData.mbKeyboardHelp)
190     {
191         ImplDestroyHelpWindow( true );
192     }
193 }
194 
ImplSetMousePointer(vcl::Window const * pChild)195 static void ImplSetMousePointer( vcl::Window const * pChild )
196 {
197     if ( ImplGetSVHelpData().mbExtHelpMode )
198         pChild->ImplGetFrame()->SetPointer( PointerStyle::Help );
199     else
200         pChild->ImplGetFrame()->SetPointer( pChild->ImplGetMousePointer() );
201 }
202 
ImplCallCommand(const VclPtr<vcl::Window> & pChild,CommandEventId nEvt,void const * pData=nullptr,bool bMouse=false,Point const * pPos=nullptr)203 static bool ImplCallCommand( const VclPtr<vcl::Window>& pChild, CommandEventId nEvt, void const * pData = nullptr,
204                              bool bMouse = false, Point const * pPos = nullptr )
205 {
206     Point aPos;
207     if ( pPos )
208         aPos = *pPos;
209     else
210     {
211         if( bMouse )
212             aPos = pChild->GetPointerPosPixel();
213         else
214         {
215             // simulate mouseposition at center of window
216             Size aSize( pChild->GetOutputSizePixel() );
217             aPos = Point( aSize.getWidth()/2, aSize.getHeight()/2 );
218         }
219     }
220 
221     CommandEvent    aCEvt( aPos, nEvt, bMouse, pData );
222     NotifyEvent     aNCmdEvt( NotifyEventType::COMMAND, pChild, &aCEvt );
223     bool bPreNotify = ImplCallPreNotify( aNCmdEvt );
224     if ( pChild->isDisposed() )
225         return false;
226     if ( !bPreNotify )
227     {
228         pChild->ImplGetWindowImpl()->mbCommand = false;
229         pChild->Command( aCEvt );
230 
231         if( pChild->isDisposed() )
232             return false;
233         pChild->ImplNotifyKeyMouseCommandEventListeners( aNCmdEvt );
234         if ( pChild->isDisposed() )
235             return false;
236         if ( pChild->ImplGetWindowImpl()->mbCommand )
237             return true;
238     }
239 
240     return false;
241 }
242 
243 /*  #i34277# delayed context menu activation;
244 *   necessary if there already was a popup menu running.
245 */
246 
247 namespace {
248 
249 struct ContextMenuEvent
250 {
251     VclPtr<vcl::Window>  pWindow;
252     Point           aChildPos;
253 };
254 
255 }
256 
ContextMenuEventLink(void * pCEvent,void *)257 static void ContextMenuEventLink( void* pCEvent, void* )
258 {
259     ContextMenuEvent* pEv = static_cast<ContextMenuEvent*>(pCEvent);
260 
261     if( ! pEv->pWindow->isDisposed() )
262     {
263         ImplCallCommand( pEv->pWindow, CommandEventId::ContextMenu, nullptr, true, &pEv->aChildPos );
264     }
265     delete pEv;
266 }
267 
ImplHandleMouseEvent(const VclPtr<vcl::Window> & xWindow,NotifyEventType nSVEvent,bool bMouseLeave,tools::Long nX,tools::Long nY,sal_uInt64 nMsgTime,sal_uInt16 nCode,MouseEventModifiers nMode)268 bool ImplHandleMouseEvent( const VclPtr<vcl::Window>& xWindow, NotifyEventType nSVEvent, bool bMouseLeave,
269                            tools::Long nX, tools::Long nY, sal_uInt64 nMsgTime,
270                            sal_uInt16 nCode, MouseEventModifiers nMode )
271 {
272     SAL_INFO( "vcl.debugevent",
273               "mouse event "
274                "(NotifyEventType " << static_cast<sal_uInt16>(nSVEvent) << ") "
275                "(MouseLeave " << bMouseLeave << ") "
276                "(X, Y " << nX << ", " << nY << ") "
277                "(Code " << nCode << ") "
278                "(Modifiers " << static_cast<sal_uInt16>(nMode) << ")");
279     ImplSVHelpData& aHelpData = ImplGetSVHelpData();
280     ImplSVData* pSVData = ImplGetSVData();
281     Point       aMousePos( nX, nY );
282     VclPtr<vcl::Window> pChild;
283     bool        bRet(false);
284     sal_uInt16  nClicks(0);
285     ImplFrameData* pWinFrameData = xWindow->ImplGetFrameData();
286     sal_uInt16      nOldCode = pWinFrameData->mnMouseCode;
287 
288     if (comphelper::LibreOfficeKit::isActive() && AllSettings::GetLayoutRTL()
289         && xWindow->GetOutDev() && !xWindow->GetOutDev()->ImplIsAntiparallel())
290     {
291         xWindow->GetOutDev()->ReMirror(aMousePos);
292         nX = aMousePos.X();
293         nY = aMousePos.Y();
294     }
295 
296     // we need a mousemove event, before we get a mousebuttondown or a
297     // mousebuttonup event
298     if ( (nSVEvent == NotifyEventType::MOUSEBUTTONDOWN) || (nSVEvent == NotifyEventType::MOUSEBUTTONUP) )
299     {
300         if ( (nSVEvent == NotifyEventType::MOUSEBUTTONUP) && aHelpData.mbExtHelpMode )
301             Help::EndExtHelp();
302         if ( aHelpData.mpHelpWin )
303         {
304             if( xWindow->ImplGetWindow() == aHelpData.mpHelpWin )
305             {
306                 ImplDestroyHelpWindow( false );
307                 return true; // xWindow is dead now - avoid crash!
308             }
309             else
310                 ImplDestroyHelpWindow( true );
311         }
312 
313         if ( (pWinFrameData->mnLastMouseX != nX) ||
314              (pWinFrameData->mnLastMouseY != nY) )
315         {
316             sal_uInt16 nMoveCode = nCode & ~(MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE);
317             ImplHandleMouseEvent(xWindow, NotifyEventType::MOUSEMOVE, false, nX, nY, nMsgTime, nMoveCode, nMode);
318         }
319     }
320 
321     // update frame data
322     pWinFrameData->mnBeforeLastMouseX = pWinFrameData->mnLastMouseX;
323     pWinFrameData->mnBeforeLastMouseY = pWinFrameData->mnLastMouseY;
324     pWinFrameData->mnLastMouseX = nX;
325     pWinFrameData->mnLastMouseY = nY;
326     pWinFrameData->mnMouseCode  = nCode;
327     MouseEventModifiers const nTmpMask = MouseEventModifiers::SYNTHETIC | MouseEventModifiers::MODIFIERCHANGED;
328     pWinFrameData->mnMouseMode  = nMode & ~nTmpMask;
329     if ( bMouseLeave )
330     {
331         pWinFrameData->mbMouseIn = false;
332         if ( ImplGetSVHelpData().mpHelpWin && !ImplGetSVHelpData().mbKeyboardHelp )
333         {
334             ImplDestroyHelpWindow( true );
335 
336             if ( xWindow->isDisposed() )
337                 return true; // xWindow is dead now - avoid crash! (#122045#)
338         }
339     }
340     else
341         pWinFrameData->mbMouseIn = true;
342 
343     DBG_ASSERT(!pSVData->mpWinData->mpTrackWin
344                    || (pSVData->mpWinData->mpTrackWin == pSVData->mpWinData->mpCaptureWin),
345                "ImplHandleMouseEvent: TrackWin != CaptureWin");
346 
347     // AutoScrollMode
348     if (pSVData->mpWinData->mpAutoScrollWin && (nSVEvent == NotifyEventType::MOUSEBUTTONDOWN))
349     {
350         pSVData->mpWinData->mpAutoScrollWin->EndAutoScroll();
351         return true;
352     }
353 
354     // find mouse window
355     if (pSVData->mpWinData->mpCaptureWin)
356     {
357         pChild = pSVData->mpWinData->mpCaptureWin;
358 
359         SAL_WARN_IF( xWindow != pChild->ImplGetFrameWindow(), "vcl",
360                     "ImplHandleMouseEvent: mouse event is not sent to capture window" );
361 
362         // java client cannot capture mouse correctly
363         if ( xWindow != pChild->ImplGetFrameWindow() )
364             return false;
365 
366         if ( bMouseLeave )
367             return false;
368     }
369     else
370     {
371         if ( bMouseLeave )
372             pChild = nullptr;
373         else
374             pChild = xWindow->ImplFindWindow( aMousePos );
375     }
376 
377     // test this because mouse events are buffered in the remote version
378     // and size may not be in sync
379     if ( !pChild && !bMouseLeave )
380         return false;
381 
382     // execute a few tests and catch the message or implement the status
383     if ( pChild )
384     {
385         if( pChild->GetOutDev()->ImplIsAntiparallel() )
386         {
387             // re-mirror frame pos at pChild
388             const OutputDevice *pChildWinOutDev = pChild->GetOutDev();
389             pChildWinOutDev->ReMirror( aMousePos );
390         }
391 
392         // no mouse messages to disabled windows
393         // #106845# if the window was disabled during capturing we have to pass the mouse events to release capturing
394         if (pSVData->mpWinData->mpCaptureWin.get() != pChild
395             && (!pChild->IsEnabled() || !pChild->IsInputEnabled() || pChild->IsInModalMode()))
396         {
397             ImplHandleMouseFloatMode( pChild, aMousePos, nCode, nSVEvent, bMouseLeave );
398             if ( nSVEvent == NotifyEventType::MOUSEMOVE )
399             {
400                 ImplHandleMouseHelpRequest( pChild, aMousePos );
401                 if( pWinFrameData->mpMouseMoveWin.get() != pChild )
402                     nMode |= MouseEventModifiers::ENTERWINDOW;
403             }
404 
405             // Call the hook also, if Window is disabled
406 
407             if ( nSVEvent == NotifyEventType::MOUSEBUTTONDOWN )
408                 return true;
409             else
410             {
411                 // Set normal MousePointer for disabled windows
412                 if ( nSVEvent == NotifyEventType::MOUSEMOVE )
413                     ImplSetMousePointer( pChild );
414 
415                 return false;
416             }
417         }
418 
419         // End ExtTextInput-Mode, if the user click in the same TopLevel Window
420         if (pSVData->mpWinData->mpExtTextInputWin
421             && ((nSVEvent == NotifyEventType::MOUSEBUTTONDOWN)
422                 || (nSVEvent == NotifyEventType::MOUSEBUTTONUP)))
423             pSVData->mpWinData->mpExtTextInputWin->EndExtTextInput();
424     }
425 
426     // determine mouse event data
427     if ( nSVEvent == NotifyEventType::MOUSEMOVE )
428     {
429         // check if MouseMove belongs to same window and if the
430         // status did not change
431         if ( pChild )
432         {
433             Point aChildMousePos = pChild->ScreenToOutputPixel( aMousePos );
434             if ( !bMouseLeave &&
435                  (pChild == pWinFrameData->mpMouseMoveWin) &&
436                  (aChildMousePos.X() == pWinFrameData->mnLastMouseWinX) &&
437                  (aChildMousePos.Y() == pWinFrameData->mnLastMouseWinY) &&
438                  (nOldCode == pWinFrameData->mnMouseCode) )
439             {
440                 // set mouse pointer anew, as it could have changed
441                 // due to the mode switch
442                 ImplSetMousePointer( pChild );
443                 return false;
444             }
445 
446             pWinFrameData->mnLastMouseWinX = aChildMousePos.X();
447             pWinFrameData->mnLastMouseWinY = aChildMousePos.Y();
448         }
449 
450         // mouse click
451         nClicks = pWinFrameData->mnClickCount;
452 
453         // call Start-Drag handler if required
454         // Warning: should be called before Move, as otherwise during
455         // fast mouse movements the applications move to the selection state
456         vcl::Window* pMouseDownWin = pWinFrameData->mpMouseDownWin;
457         if ( pMouseDownWin )
458         {
459             // check for matching StartDrag mode. We only compare
460             // the status of the mouse buttons, such that e. g. Mod1 can
461             // change immediately to the copy mode
462             const MouseSettings& rMSettings = pMouseDownWin->GetSettings().GetMouseSettings();
463             if ( (nCode & (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE)) ==
464                  (MouseSettings::GetStartDragCode() & (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE)) )
465             {
466                 if ( !pMouseDownWin->ImplGetFrameData()->mbStartDragCalled )
467                 {
468                     tools::Long nDragW  = rMSettings.GetStartDragWidth();
469                     tools::Long nDragH  = rMSettings.GetStartDragHeight();
470                     //long nMouseX = nX;
471                     //long nMouseY = nY;
472                     tools::Long nMouseX = aMousePos.X(); // #106074# use the possibly re-mirrored coordinates (RTL) ! nX,nY are unmodified !
473                     tools::Long nMouseY = aMousePos.Y();
474                     if ( (((nMouseX-nDragW) > pMouseDownWin->ImplGetFrameData()->mnFirstMouseX) ||
475                            ((nMouseX+nDragW) < pMouseDownWin->ImplGetFrameData()->mnFirstMouseX)) ||
476                          (((nMouseY-nDragH) > pMouseDownWin->ImplGetFrameData()->mnFirstMouseY) ||
477                            ((nMouseY+nDragH) < pMouseDownWin->ImplGetFrameData()->mnFirstMouseY)) )
478                     {
479                         pMouseDownWin->ImplGetFrameData()->mbStartDragCalled  = true;
480 
481                         // Check if drag source provides its own recognizer
482                         if( pMouseDownWin->ImplGetFrameData()->mbInternalDragGestureRecognizer )
483                         {
484                             // query DropTarget from child window
485                             css::uno::Reference< css::datatransfer::dnd::XDragGestureRecognizer > xDragGestureRecognizer(
486                                     pMouseDownWin->ImplGetWindowImpl()->mxDNDListenerContainer,
487                                     css::uno::UNO_QUERY );
488 
489                             if( xDragGestureRecognizer.is() )
490                             {
491                                 // retrieve mouse position relative to mouse down window
492                                 Point relLoc = pMouseDownWin->ScreenToOutputPixel( Point(
493                                     pMouseDownWin->ImplGetFrameData()->mnFirstMouseX,
494                                     pMouseDownWin->ImplGetFrameData()->mnFirstMouseY ) );
495 
496                                 // create a UNO mouse event out of the available data
497                                 css::awt::MouseEvent aMouseEvent( static_cast < css::uno::XInterface * > ( nullptr ),
498 #ifdef MACOSX
499                                     nCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_MOD3),
500 #else
501                                     nCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2),
502 #endif
503                                     nCode & (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE),
504                                     nMouseX,
505                                     nMouseY,
506                                     nClicks,
507                                     false );
508 
509                                 SolarMutexReleaser aReleaser;
510 
511                                 // FIXME: where do I get Action from ?
512                                 css::uno::Reference< css::datatransfer::dnd::XDragSource > xDragSource = pMouseDownWin->GetDragSource();
513 
514                                 if( xDragSource.is() )
515                                 {
516                                     static_cast < DNDListenerContainer * > ( xDragGestureRecognizer.get() )->fireDragGestureEvent( 0,
517                                         relLoc.X(), relLoc.Y(), xDragSource, css::uno::Any( aMouseEvent ) );
518                                 }
519                             }
520                         }
521                     }
522                 }
523             }
524             else
525                 pMouseDownWin->ImplGetFrameData()->mbStartDragCalled  = true;
526         }
527 
528         if (xWindow->isDisposed())
529             return true;
530         // test for mouseleave and mouseenter
531         VclPtr<vcl::Window> pMouseMoveWin = pWinFrameData->mpMouseMoveWin;
532         if ( pChild != pMouseMoveWin )
533         {
534             if ( pMouseMoveWin )
535             {
536                 Point       aLeaveMousePos = pMouseMoveWin->ScreenToOutputPixel( aMousePos );
537                 MouseEvent  aMLeaveEvt( aLeaveMousePos, nClicks, nMode | MouseEventModifiers::LEAVEWINDOW, nCode, nCode );
538                 NotifyEvent aNLeaveEvt( NotifyEventType::MOUSEMOVE, pMouseMoveWin, &aMLeaveEvt );
539                 pWinFrameData->mbInMouseMove = true;
540                 pMouseMoveWin->ImplGetWinData()->mbMouseOver = false;
541 
542                 // A MouseLeave can destroy this window
543                 if ( !ImplCallPreNotify( aNLeaveEvt ) )
544                 {
545                     pMouseMoveWin->MouseMove( aMLeaveEvt );
546                     if( !pMouseMoveWin->isDisposed() )
547                         aNLeaveEvt.GetWindow()->ImplNotifyKeyMouseCommandEventListeners( aNLeaveEvt );
548                 }
549 
550                 pWinFrameData->mpMouseMoveWin = nullptr;
551                 pWinFrameData->mbInMouseMove = false;
552 
553                 if ( pChild && pChild->isDisposed() )
554                     pChild = nullptr;
555                 if ( pMouseMoveWin->isDisposed() )
556                     return true;
557             }
558 
559             nMode |= MouseEventModifiers::ENTERWINDOW;
560         }
561         pWinFrameData->mpMouseMoveWin = pChild;
562         if( pChild )
563             pChild->ImplGetWinData()->mbMouseOver = true;
564 
565         // MouseLeave
566         if ( !pChild )
567             return false;
568     }
569     else
570     {
571         if (pChild)
572         {
573             // mouse click
574             if ( nSVEvent == NotifyEventType::MOUSEBUTTONDOWN )
575             {
576                 const MouseSettings& rMSettings = pChild->GetSettings().GetMouseSettings();
577                 sal_uInt64 nDblClkTime = rMSettings.GetDoubleClickTime();
578                 tools::Long    nDblClkW    = rMSettings.GetDoubleClickWidth();
579                 tools::Long    nDblClkH    = rMSettings.GetDoubleClickHeight();
580                 //long    nMouseX     = nX;
581                 //long    nMouseY     = nY;
582                 tools::Long nMouseX = aMousePos.X();   // #106074# use the possibly re-mirrored coordinates (RTL) ! nX,nY are unmodified !
583                 tools::Long nMouseY = aMousePos.Y();
584 
585                 if ( (pChild == pChild->ImplGetFrameData()->mpMouseDownWin) &&
586                      (nCode == pChild->ImplGetFrameData()->mnFirstMouseCode) &&
587                      ((nMsgTime-pChild->ImplGetFrameData()->mnMouseDownTime) < nDblClkTime) &&
588                      ((nMouseX-nDblClkW) <= pChild->ImplGetFrameData()->mnFirstMouseX) &&
589                      ((nMouseX+nDblClkW) >= pChild->ImplGetFrameData()->mnFirstMouseX) &&
590                      ((nMouseY-nDblClkH) <= pChild->ImplGetFrameData()->mnFirstMouseY) &&
591                      ((nMouseY+nDblClkH) >= pChild->ImplGetFrameData()->mnFirstMouseY) )
592                 {
593                     pChild->ImplGetFrameData()->mnClickCount++;
594                     pChild->ImplGetFrameData()->mbStartDragCalled  = true;
595                 }
596                 else
597                 {
598                     pChild->ImplGetFrameData()->mpMouseDownWin     = pChild;
599                     pChild->ImplGetFrameData()->mnClickCount       = 1;
600                     pChild->ImplGetFrameData()->mnFirstMouseX      = nMouseX;
601                     pChild->ImplGetFrameData()->mnFirstMouseY      = nMouseY;
602                     pChild->ImplGetFrameData()->mnFirstMouseCode   = nCode;
603                     pChild->ImplGetFrameData()->mbStartDragCalled  = (nCode & (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE)) !=
604                                                                      (MouseSettings::GetStartDragCode() & (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE));
605                 }
606                 pChild->ImplGetFrameData()->mnMouseDownTime = nMsgTime;
607             }
608             nClicks = pChild->ImplGetFrameData()->mnClickCount;
609         }
610 
611         pSVData->maAppData.mnLastInputTime = tools::Time::GetSystemTicks();
612     }
613 
614     SAL_WARN_IF( !pChild, "vcl", "ImplHandleMouseEvent: pChild == NULL" );
615 
616     if (!pChild)
617         return false;
618 
619     // create mouse event
620     Point aChildPos = pChild->ScreenToOutputPixel( aMousePos );
621     MouseEvent aMEvt( aChildPos, nClicks, nMode, nCode, nCode );
622 
623 
624     // tracking window gets the mouse events
625     if (pSVData->mpWinData->mpTrackWin)
626         pChild = pSVData->mpWinData->mpTrackWin;
627 
628     // handle FloatingMode
629     if (!pSVData->mpWinData->mpTrackWin && pSVData->mpWinData->mpFirstFloat)
630     {
631         if ( ImplHandleMouseFloatMode( pChild, aMousePos, nCode, nSVEvent, bMouseLeave ) )
632         {
633             if ( !pChild->isDisposed() )
634             {
635                 pChild->ImplGetFrameData()->mbStartDragCalled = true;
636             }
637             return true;
638         }
639     }
640 
641     // call handler
642     bool bCallHelpRequest = true;
643     SAL_WARN_IF( !pChild, "vcl", "ImplHandleMouseEvent: pChild is NULL" );
644 
645     if (!pChild)
646         return false;
647 
648     NotifyEvent aNEvt( nSVEvent, pChild, &aMEvt );
649     if ( nSVEvent == NotifyEventType::MOUSEMOVE )
650         pChild->ImplGetFrameData()->mbInMouseMove = true;
651 
652     // bring window into foreground on mouseclick
653     if ( nSVEvent == NotifyEventType::MOUSEBUTTONDOWN )
654     {
655         if (!pSVData->mpWinData->mpFirstFloat
656             && // totop for floating windows in popup would change the focus and would close them immediately
657             !(pChild->ImplGetFrameWindow()->GetStyle()
658               & WB_OWNERDRAWDECORATION)) // ownerdrawdecorated windows must never grab focus
659             pChild->ToTop();
660         if ( pChild->isDisposed() )
661             return true;
662     }
663 
664     if ( ImplCallPreNotify( aNEvt ) || pChild->isDisposed() )
665         bRet = true;
666     else
667     {
668         bRet = false;
669         if ( nSVEvent == NotifyEventType::MOUSEMOVE )
670         {
671             if (pSVData->mpWinData->mpTrackWin)
672             {
673                 TrackingEvent aTEvt( aMEvt );
674                 pChild->Tracking( aTEvt );
675                 if ( !pChild->isDisposed() )
676                 {
677                     // When ScrollRepeat, we restart the timer
678                     if (pSVData->mpWinData->mpTrackTimer
679                         && (pSVData->mpWinData->mnTrackFlags & StartTrackingFlags::ScrollRepeat))
680                         pSVData->mpWinData->mpTrackTimer->Start();
681                 }
682                 bCallHelpRequest = false;
683                 bRet = true;
684             }
685             else
686             {
687                 if( pChild->isDisposed() )
688                     bCallHelpRequest = false;
689                 else
690                 {
691                     // if the MouseMove handler changes the help window's visibility
692                     // the HelpRequest handler should not be called anymore
693                     vcl::Window* pOldHelpTextWin = ImplGetSVHelpData().mpHelpWin;
694                     pChild->MouseMove( aMEvt );
695                     if ( pOldHelpTextWin != ImplGetSVHelpData().mpHelpWin )
696                         bCallHelpRequest = false;
697                 }
698             }
699         }
700         else if ( nSVEvent == NotifyEventType::MOUSEBUTTONDOWN )
701         {
702             if ( pSVData->mpWinData->mpTrackWin )
703                 bRet = true;
704             else
705             {
706                 pChild->ImplGetWindowImpl()->mbMouseButtonDown = false;
707                 pChild->MouseButtonDown( aMEvt );
708             }
709         }
710         else
711         {
712             if (pSVData->mpWinData->mpTrackWin)
713             {
714                 pChild->EndTracking();
715                 bRet = true;
716             }
717             else
718             {
719                 pChild->ImplGetWindowImpl()->mbMouseButtonUp = false;
720                 pChild->MouseButtonUp( aMEvt );
721             }
722         }
723 
724         assert(aNEvt.GetWindow() == pChild);
725 
726         if (!pChild->isDisposed())
727             pChild->ImplNotifyKeyMouseCommandEventListeners( aNEvt );
728     }
729 
730     if (pChild->isDisposed())
731         return true;
732 
733     if ( nSVEvent == NotifyEventType::MOUSEMOVE )
734         pChild->ImplGetWindowImpl()->mpFrameData->mbInMouseMove = false;
735 
736     if ( nSVEvent == NotifyEventType::MOUSEMOVE )
737     {
738         if ( bCallHelpRequest && !ImplGetSVHelpData().mbKeyboardHelp )
739             ImplHandleMouseHelpRequest( pChild, pChild->OutputToScreenPixel( aMEvt.GetPosPixel() ) );
740         bRet = true;
741     }
742     else if ( !bRet )
743     {
744         if ( nSVEvent == NotifyEventType::MOUSEBUTTONDOWN )
745         {
746             if ( !pChild->ImplGetWindowImpl()->mbMouseButtonDown )
747                 bRet = true;
748         }
749         else
750         {
751             if ( !pChild->ImplGetWindowImpl()->mbMouseButtonUp )
752                 bRet = true;
753         }
754     }
755 
756     if ( nSVEvent == NotifyEventType::MOUSEMOVE )
757     {
758         // set new mouse pointer
759         if ( !bMouseLeave )
760             ImplSetMousePointer( pChild );
761     }
762     else if ( (nSVEvent == NotifyEventType::MOUSEBUTTONDOWN) || (nSVEvent == NotifyEventType::MOUSEBUTTONUP) )
763     {
764         // Command-Events
765         if ( /*!bRet &&*/ (nClicks == 1) && (nSVEvent == NotifyEventType::MOUSEBUTTONDOWN) &&
766              (nCode == MOUSE_MIDDLE) )
767         {
768             MouseMiddleButtonAction nMiddleAction = pChild->GetSettings().GetMouseSettings().GetMiddleButtonAction();
769             if ( nMiddleAction == MouseMiddleButtonAction::AutoScroll )
770                 bRet = !ImplCallCommand( pChild, CommandEventId::StartAutoScroll, nullptr, true, &aChildPos );
771             else if ( nMiddleAction == MouseMiddleButtonAction::PasteSelection )
772                 bRet = !ImplCallCommand( pChild, CommandEventId::PasteSelection, nullptr, true, &aChildPos );
773         }
774         else
775         {
776             // ContextMenu
777             if ( (nCode == MouseSettings::GetContextMenuCode()) &&
778                  (nClicks == MouseSettings::GetContextMenuClicks()) )
779             {
780                 bool bContextMenu = (nSVEvent == NotifyEventType::MOUSEBUTTONDOWN);
781                 if ( bContextMenu )
782                 {
783                     if( pSVData->maAppData.mpActivePopupMenu )
784                     {
785                         /*  #i34277# there already is a context menu open
786                         *   that was probably just closed with EndPopupMode.
787                         *   We need to give the eventual corresponding
788                         *   PopupMenu::Execute a chance to end properly.
789                         *   Therefore delay context menu command and
790                         *   issue only after popping one frame of the
791                         *   Yield stack.
792                         */
793                         ContextMenuEvent* pEv = new ContextMenuEvent;
794                         pEv->pWindow = pChild;
795                         pEv->aChildPos = aChildPos;
796                         Application::PostUserEvent( Link<void*,void>( pEv, ContextMenuEventLink ) );
797                     }
798                     else
799                         bRet = ! ImplCallCommand( pChild, CommandEventId::ContextMenu, nullptr, true, &aChildPos );
800                 }
801             }
802         }
803     }
804 
805     return bRet;
806 }
807 
ImplLOKHandleMouseEvent(const VclPtr<vcl::Window> & xWindow,NotifyEventType nEvent,bool,tools::Long nX,tools::Long nY,sal_uInt64,sal_uInt16 nCode,MouseEventModifiers nMode,sal_uInt16 nClicks)808 bool ImplLOKHandleMouseEvent(const VclPtr<vcl::Window>& xWindow, NotifyEventType nEvent, bool /*bMouseLeave*/,
809                              tools::Long nX, tools::Long nY, sal_uInt64 /*nMsgTime*/,
810                              sal_uInt16 nCode, MouseEventModifiers nMode, sal_uInt16 nClicks)
811 {
812     Point aMousePos(nX, nY);
813 
814     if (!xWindow)
815         return false;
816 
817     if (xWindow->isDisposed())
818         return false;
819 
820     ImplFrameData* pFrameData = xWindow->ImplGetFrameData();
821     if (!pFrameData)
822         return false;
823 
824     Point aWinPos = xWindow->ScreenToOutputPixel(aMousePos);
825 
826     pFrameData->mnLastMouseX = nX;
827     pFrameData->mnLastMouseY = nY;
828     pFrameData->mnClickCount = nClicks;
829     pFrameData->mnMouseCode = nCode;
830     pFrameData->mbMouseIn = false;
831 
832     vcl::Window* pDragWin = pFrameData->mpMouseDownWin;
833     if (pDragWin &&
834         nEvent == NotifyEventType::MOUSEMOVE &&
835         pFrameData->mbDragging)
836     {
837         css::uno::Reference<css::datatransfer::dnd::XDropTargetDragContext> xDropTargetDragContext =
838             new GenericDropTargetDragContext();
839         css::uno::Reference<css::datatransfer::dnd::XDropTarget> xDropTarget(
840             pDragWin->ImplGetWindowImpl()->mxDNDListenerContainer, css::uno::UNO_QUERY);
841 
842         if (!xDropTarget.is() ||
843             !xDropTargetDragContext.is() ||
844             (nCode & (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE)) !=
845             (MouseSettings::GetStartDragCode() & (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE)))
846         {
847             pFrameData->mbStartDragCalled = pFrameData->mbDragging = false;
848             return false;
849         }
850 
851         static_cast<DNDListenerContainer *>(xDropTarget.get())->fireDragOverEvent(
852             xDropTargetDragContext,
853             css::datatransfer::dnd::DNDConstants::ACTION_MOVE,
854             aWinPos.X(),
855             aWinPos.Y(),
856             (css::datatransfer::dnd::DNDConstants::ACTION_COPY |
857              css::datatransfer::dnd::DNDConstants::ACTION_MOVE |
858              css::datatransfer::dnd::DNDConstants::ACTION_LINK));
859 
860         return true;
861     }
862 
863     if (pDragWin &&
864         nEvent == NotifyEventType::MOUSEBUTTONUP &&
865         pFrameData->mbDragging)
866     {
867         css::uno::Reference<css::datatransfer::XTransferable> xTransfer;
868         css::uno::Reference<css::datatransfer::dnd::XDropTargetDropContext> xDropTargetDropContext =
869             new GenericDropTargetDropContext();
870         css::uno::Reference<css::datatransfer::dnd::XDropTarget> xDropTarget(
871             pDragWin->ImplGetWindowImpl()->mxDNDListenerContainer, css::uno::UNO_QUERY);
872 
873         if (!xDropTarget.is() || !xDropTargetDropContext.is())
874         {
875             pFrameData->mbStartDragCalled = pFrameData->mbDragging = false;
876             return false;
877         }
878 
879         Point dragOverPos = pDragWin->ScreenToOutputPixel(aMousePos);
880         static_cast<DNDListenerContainer *>(xDropTarget.get())->fireDropEvent(
881             xDropTargetDropContext,
882             css::datatransfer::dnd::DNDConstants::ACTION_MOVE,
883             dragOverPos.X(),
884             dragOverPos.Y(),
885             (css::datatransfer::dnd::DNDConstants::ACTION_COPY |
886              css::datatransfer::dnd::DNDConstants::ACTION_MOVE |
887              css::datatransfer::dnd::DNDConstants::ACTION_LINK),
888             xTransfer);
889 
890         pFrameData->mbStartDragCalled = pFrameData->mbDragging = false;
891         return true;
892     }
893 
894     if (pFrameData->mbDragging)
895     {
896         // wrong status, reset
897         pFrameData->mbStartDragCalled = pFrameData->mbDragging = false;
898         return false;
899     }
900 
901     vcl::Window* pDownWin = pFrameData->mpMouseDownWin;
902     if (pDownWin && nEvent == NotifyEventType::MOUSEMOVE)
903     {
904         const MouseSettings& aSettings = pDownWin->GetSettings().GetMouseSettings();
905         if ((nCode & (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE)) ==
906             (MouseSettings::GetStartDragCode() & (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE)) )
907         {
908             if (!pFrameData->mbStartDragCalled)
909             {
910                 tools::Long nDragWidth = aSettings.GetStartDragWidth();
911                 tools::Long nDragHeight = aSettings.GetStartDragHeight();
912                 tools::Long nMouseX = aMousePos.X();
913                 tools::Long nMouseY = aMousePos.Y();
914 
915                 if ((((nMouseX - nDragWidth) > pFrameData->mnFirstMouseX) ||
916                      ((nMouseX + nDragWidth) < pFrameData->mnFirstMouseX)) ||
917                     (((nMouseY - nDragHeight) > pFrameData->mnFirstMouseY) ||
918                      ((nMouseY + nDragHeight) < pFrameData->mnFirstMouseY)))
919                 {
920                     pFrameData->mbStartDragCalled  = true;
921 
922                     if (pFrameData->mbInternalDragGestureRecognizer)
923                     {
924                         // query DropTarget from child window
925                         css::uno::Reference< css::datatransfer::dnd::XDragGestureRecognizer > xDragGestureRecognizer(
926                             pDownWin->ImplGetWindowImpl()->mxDNDListenerContainer,
927                             css::uno::UNO_QUERY );
928 
929                         if (xDragGestureRecognizer.is())
930                         {
931                             // create a UNO mouse event out of the available data
932                             css::awt::MouseEvent aEvent(
933                                 static_cast < css::uno::XInterface * > ( nullptr ),
934  #ifdef MACOSX
935                                 nCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_MOD3),
936  #else
937                                 nCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2),
938  #endif
939                                 nCode & (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE),
940                                 nMouseX,
941                                 nMouseY,
942                                 nClicks,
943                                 false);
944                             css::uno::Reference< css::datatransfer::dnd::XDragSource > xDragSource =
945                                 pDownWin->GetDragSource();
946 
947                             if (xDragSource.is())
948                             {
949                                 static_cast<DNDListenerContainer *>(xDragGestureRecognizer.get())->
950                                     fireDragGestureEvent(
951                                         0,
952                                         aWinPos.X(),
953                                         aWinPos.Y(),
954                                         xDragSource,
955                                         css::uno::Any(aEvent));
956                             }
957                         }
958                     }
959                 }
960             }
961         }
962     }
963 
964     MouseEvent aMouseEvent(aWinPos, nClicks, nMode, nCode, nCode);
965     if (nEvent == NotifyEventType::MOUSEMOVE)
966     {
967         if (pFrameData->mpTrackWin)
968         {
969             TrackingEvent aTrackingEvent(aMouseEvent);
970             pFrameData->mpTrackWin->Tracking(aTrackingEvent);
971         }
972         else
973             xWindow->MouseMove(aMouseEvent);
974     }
975     else if (nEvent == NotifyEventType::MOUSEBUTTONDOWN &&
976         !pFrameData->mpTrackWin)
977     {
978         pFrameData->mpMouseDownWin = xWindow;
979         pFrameData->mnFirstMouseX = aMousePos.X();
980         pFrameData->mnFirstMouseY = aMousePos.Y();
981 
982         xWindow->MouseButtonDown(aMouseEvent);
983     }
984     else
985     {
986         if (pFrameData->mpTrackWin)
987         {
988             pFrameData->mpTrackWin->EndTracking();
989         }
990 
991         pFrameData->mpMouseDownWin = nullptr;
992         pFrameData->mpMouseMoveWin = nullptr;
993         pFrameData->mbStartDragCalled = false;
994         xWindow->MouseButtonUp(aMouseEvent);
995     }
996 
997     if (nEvent == NotifyEventType::MOUSEBUTTONDOWN)
998     {
999          // ContextMenu
1000          if ( (nCode == MouseSettings::GetContextMenuCode()) &&
1001               (nClicks == MouseSettings::GetContextMenuClicks()) )
1002          {
1003             ImplCallCommand(xWindow, CommandEventId::ContextMenu, nullptr, true, &aWinPos);
1004          }
1005     }
1006 
1007     return true;
1008 }
1009 
ImplGetKeyInputWindow(vcl::Window * pWindow)1010 static vcl::Window* ImplGetKeyInputWindow( vcl::Window* pWindow )
1011 {
1012     ImplSVData* pSVData = ImplGetSVData();
1013 
1014     // determine last input time
1015     pSVData->maAppData.mnLastInputTime = tools::Time::GetSystemTicks();
1016 
1017     // #127104# workaround for destroyed windows
1018     if( pWindow->ImplGetWindowImpl() == nullptr )
1019         return nullptr;
1020 
1021     // find window - is every time the window which has currently the
1022     // focus or the last time the focus.
1023 
1024     // the first floating window always has the focus, try it, or any parent floating windows, first
1025     vcl::Window* pChild = pSVData->mpWinData->mpFirstFloat;
1026     while (pChild)
1027     {
1028         if (pChild->ImplGetWindowImpl())
1029         {
1030             if (pChild->ImplGetWindowImpl()->mbFloatWin)
1031             {
1032                 if (static_cast<FloatingWindow *>(pChild)->GrabsFocus())
1033                     break;
1034             }
1035             else if (pChild->ImplGetWindowImpl()->mbDockWin)
1036             {
1037                 vcl::Window* pParent = pChild->GetWindow(GetWindowType::RealParent);
1038                 if (pParent && pParent->ImplGetWindowImpl()->mbFloatWin &&
1039                     static_cast<FloatingWindow *>(pParent)->GrabsFocus())
1040                     break;
1041             }
1042         }
1043         pChild = pChild->GetParent();
1044     }
1045 
1046     if (!pChild)
1047         pChild = pWindow;
1048 
1049     pChild = pChild->ImplGetWindowImpl() && pChild->ImplGetWindowImpl()->mpFrameData ? pChild->ImplGetWindowImpl()->mpFrameData->mpFocusWin.get() : nullptr;
1050 
1051     // no child - then no input
1052     if ( !pChild )
1053         return nullptr;
1054 
1055     // We call also KeyInput if we haven't the focus, because on Unix
1056     // system this is often the case when a Lookup Choice Window has
1057     // the focus - because this windows send the KeyInput directly to
1058     // the window without resetting the focus
1059 
1060     // no keyinput to disabled windows
1061     if ( !pChild->IsEnabled() || !pChild->IsInputEnabled() || pChild->IsInModalMode() )
1062         return nullptr;
1063 
1064     return pChild;
1065 }
1066 
ImplHandleKey(vcl::Window * pWindow,NotifyEventType nSVEvent,sal_uInt16 nKeyCode,sal_uInt16 nCharCode,sal_uInt16 nRepeat,bool bForward)1067 static bool ImplHandleKey( vcl::Window* pWindow, NotifyEventType nSVEvent,
1068                            sal_uInt16 nKeyCode, sal_uInt16 nCharCode, sal_uInt16 nRepeat, bool bForward )
1069 {
1070     ImplSVData* pSVData = ImplGetSVData();
1071     vcl::KeyCode aKeyCode( nKeyCode, nKeyCode );
1072     sal_uInt16 nEvCode = aKeyCode.GetCode();
1073 
1074     // allow application key listeners to remove the key event
1075     // but make sure we're not forwarding external KeyEvents, (ie where bForward is false)
1076     // because those are coming back from the listener itself and MUST be processed
1077     if( bForward )
1078     {
1079         VclEventId nVCLEvent;
1080         switch( nSVEvent )
1081         {
1082             case NotifyEventType::KEYINPUT:
1083                 nVCLEvent = VclEventId::WindowKeyInput;
1084                 break;
1085             case NotifyEventType::KEYUP:
1086                 nVCLEvent = VclEventId::WindowKeyUp;
1087                 break;
1088             default:
1089                 nVCLEvent = VclEventId::NONE;
1090                 break;
1091         }
1092         KeyEvent aKeyEvent(static_cast<sal_Unicode>(nCharCode), aKeyCode, nRepeat);
1093         if (nVCLEvent != VclEventId::NONE && Application::HandleKey(nVCLEvent, pWindow, &aKeyEvent))
1094             return true;
1095     }
1096 
1097     bool bCtrlF6 = (aKeyCode.GetCode() == KEY_F6) && aKeyCode.IsMod1();
1098 
1099     // determine last input time
1100     pSVData->maAppData.mnLastInputTime = tools::Time::GetSystemTicks();
1101 
1102     // handle tracking window
1103     if ( nSVEvent == NotifyEventType::KEYINPUT )
1104     {
1105         if ( ImplGetSVHelpData().mbExtHelpMode )
1106         {
1107             Help::EndExtHelp();
1108             if ( nEvCode == KEY_ESCAPE )
1109                 return true;
1110         }
1111         if ( ImplGetSVHelpData().mpHelpWin )
1112             ImplDestroyHelpWindow( false );
1113 
1114         // AutoScrollMode
1115         if (pSVData->mpWinData->mpAutoScrollWin)
1116         {
1117             pSVData->mpWinData->mpAutoScrollWin->EndAutoScroll();
1118             if ( nEvCode == KEY_ESCAPE )
1119                 return true;
1120         }
1121 
1122         if (pSVData->mpWinData->mpTrackWin)
1123         {
1124             sal_uInt16 nOrigCode = aKeyCode.GetCode();
1125 
1126             if ( nOrigCode == KEY_ESCAPE )
1127             {
1128                 pSVData->mpWinData->mpTrackWin->EndTracking( TrackingEventFlags::Cancel | TrackingEventFlags::Key );
1129                 if (pSVData->mpWinData->mpFirstFloat)
1130                 {
1131                     FloatingWindow* pLastLevelFloat = pSVData->mpWinData->mpFirstFloat->ImplFindLastLevelFloat();
1132                     if ( !(pLastLevelFloat->GetPopupModeFlags() & FloatWinPopupFlags::NoKeyClose) )
1133                     {
1134                         sal_uInt16 nEscCode = aKeyCode.GetCode();
1135 
1136                         if ( nEscCode == KEY_ESCAPE )
1137                             pLastLevelFloat->EndPopupMode( FloatWinPopupEndFlags::Cancel | FloatWinPopupEndFlags::CloseAll );
1138                     }
1139                 }
1140                 return true;
1141             }
1142             else if ( nOrigCode == KEY_RETURN )
1143             {
1144                 pSVData->mpWinData->mpTrackWin->EndTracking( TrackingEventFlags::Key );
1145                 return true;
1146             }
1147             else
1148                 return true;
1149         }
1150 
1151         // handle FloatingMode
1152         if (pSVData->mpWinData->mpFirstFloat)
1153         {
1154             FloatingWindow* pLastLevelFloat = pSVData->mpWinData->mpFirstFloat->ImplFindLastLevelFloat();
1155             if ( !(pLastLevelFloat->GetPopupModeFlags() & FloatWinPopupFlags::NoKeyClose) )
1156             {
1157                 sal_uInt16 nCode = aKeyCode.GetCode();
1158 
1159                 if ( (nCode == KEY_ESCAPE) || bCtrlF6)
1160                 {
1161                     pLastLevelFloat->EndPopupMode( FloatWinPopupEndFlags::Cancel | FloatWinPopupEndFlags::CloseAll );
1162                     if( !bCtrlF6 )
1163                         return true;
1164                 }
1165             }
1166         }
1167 
1168         // test for accel
1169         if ( pSVData->maAppData.mpAccelMgr )
1170         {
1171             if ( pSVData->maAppData.mpAccelMgr->IsAccelKey( aKeyCode ) )
1172                 return true;
1173         }
1174     }
1175 
1176     // find window
1177     VclPtr<vcl::Window> pChild = ImplGetKeyInputWindow( pWindow );
1178     if ( !pChild )
1179         return false;
1180 
1181     // #i1820# use locale specific decimal separator
1182     if (nEvCode == KEY_DECIMAL)
1183     {
1184         // tdf#138932: don't modify the meaning of the key for password box
1185         bool bPass = false;
1186         if (auto pEdit = dynamic_cast<Edit*>(pChild.get()))
1187             bPass = pEdit->IsPassword();
1188         if (!bPass && Application::GetSettings().GetMiscSettings().GetEnableLocalizedDecimalSep())
1189         {
1190             OUString aSep(pWindow->GetSettings().GetLocaleDataWrapper().getNumDecimalSep());
1191             nCharCode = static_cast<sal_uInt16>(aSep[0]);
1192         }
1193     }
1194 
1195     // RTL: mirror cursor keys
1196     if( (aKeyCode.GetCode() == KEY_LEFT || aKeyCode.GetCode() == KEY_RIGHT) &&
1197       pChild->IsRTLEnabled() && pChild->GetOutDev()->HasMirroredGraphics() )
1198         aKeyCode = vcl::KeyCode( aKeyCode.GetCode() == KEY_LEFT ? KEY_RIGHT : KEY_LEFT, aKeyCode.GetModifier() );
1199 
1200     KeyEvent    aKeyEvt( static_cast<sal_Unicode>(nCharCode), aKeyCode, nRepeat );
1201     NotifyEvent aNotifyEvt( nSVEvent, pChild, &aKeyEvt );
1202     bool bKeyPreNotify = ImplCallPreNotify( aNotifyEvt );
1203     bool bRet = true;
1204 
1205     if ( !bKeyPreNotify && !pChild->isDisposed() )
1206     {
1207         if ( nSVEvent == NotifyEventType::KEYINPUT )
1208         {
1209             UITestLogger::getInstance().logKeyInput(pChild, aKeyEvt);
1210             pChild->ImplGetWindowImpl()->mbKeyInput = false;
1211             pChild->KeyInput( aKeyEvt );
1212         }
1213         else
1214         {
1215             pChild->ImplGetWindowImpl()->mbKeyUp = false;
1216             pChild->KeyUp( aKeyEvt );
1217         }
1218         if( !pChild->isDisposed() )
1219             aNotifyEvt.GetWindow()->ImplNotifyKeyMouseCommandEventListeners( aNotifyEvt );
1220     }
1221 
1222     if ( pChild->isDisposed() )
1223         return true;
1224 
1225     if ( nSVEvent == NotifyEventType::KEYINPUT )
1226     {
1227         if ( !bKeyPreNotify && pChild->ImplGetWindowImpl()->mbKeyInput )
1228         {
1229             sal_uInt16 nCode = aKeyCode.GetCode();
1230 
1231             // #101999# is focus in or below toolbox
1232             bool bToolboxFocus=false;
1233             if( (nCode == KEY_F1) && aKeyCode.IsShift() )
1234             {
1235                 vcl::Window *pWin = pWindow->ImplGetWindowImpl()->mpFrameData->mpFocusWin;
1236                 while( pWin )
1237                 {
1238                     if( pWin->ImplGetWindowImpl()->mbToolBox )
1239                     {
1240                         bToolboxFocus = true;
1241                         break;
1242                     }
1243                     else
1244                         pWin = pWin->GetParent();
1245                 }
1246             }
1247 
1248             // ContextMenu
1249             if ( (nCode == KEY_CONTEXTMENU) || ((nCode == KEY_F10) && aKeyCode.IsShift() && !aKeyCode.IsMod1() && !aKeyCode.IsMod2() ) )
1250                 bRet = !ImplCallCommand( pChild, CommandEventId::ContextMenu );
1251             else if ( ( (nCode == KEY_F2) && aKeyCode.IsShift() ) || ( (nCode == KEY_F1) && aKeyCode.IsMod1() ) ||
1252                 // #101999# no active help when focus in toolbox, simulate BalloonHelp instead
1253                 ( (nCode == KEY_F1) && aKeyCode.IsShift() && bToolboxFocus ) )
1254             {
1255                 // TipHelp via Keyboard (Shift-F2 or Ctrl-F1)
1256                 // simulate mouseposition at center of window
1257 
1258                 Size aSize = pChild->GetOutDev()->GetOutputSize();
1259                 Point aPos( aSize.getWidth()/2, aSize.getHeight()/2 );
1260                 aPos = pChild->OutputToScreenPixel( aPos );
1261 
1262                 HelpEvent aHelpEvent( aPos, HelpEventMode::BALLOON );
1263                 aHelpEvent.SetKeyboardActivated( true );
1264                 ImplGetSVHelpData().mbSetKeyboardHelp = true;
1265                 pChild->RequestHelp( aHelpEvent );
1266                 ImplGetSVHelpData().mbSetKeyboardHelp = false;
1267             }
1268             else if ( (nCode == KEY_F1) || (nCode == KEY_HELP) )
1269             {
1270                 if ( !aKeyCode.GetModifier() )
1271                 {
1272                     if ( ImplGetSVHelpData().mbContextHelp )
1273                     {
1274                         Point       aMousePos = pChild->OutputToScreenPixel( pChild->GetPointerPosPixel() );
1275                         HelpEvent   aHelpEvent( aMousePos, HelpEventMode::CONTEXT );
1276                         pChild->RequestHelp( aHelpEvent );
1277                     }
1278                     else
1279                         bRet = false;
1280                 }
1281                 else if ( aKeyCode.IsShift() )
1282                 {
1283                     if ( ImplGetSVHelpData().mbExtHelp )
1284                         Help::StartExtHelp();
1285                     else
1286                         bRet = false;
1287                 }
1288             }
1289             else
1290                 bRet = false;
1291         }
1292     }
1293     else
1294     {
1295         if ( !bKeyPreNotify && pChild->ImplGetWindowImpl()->mbKeyUp )
1296             bRet = false;
1297     }
1298 
1299     // #105591# send keyinput to parent if we are a floating window and the key was not processed yet
1300     if( !bRet && pWindow->ImplGetWindowImpl() && pWindow->ImplGetWindowImpl()->mbFloatWin && pWindow->GetParent() && (pWindow->ImplGetWindowImpl()->mpFrame != pWindow->GetParent()->ImplGetWindowImpl()->mpFrame) )
1301     {
1302         pChild = pWindow->GetParent();
1303 
1304         // call handler
1305         NotifyEvent aNEvt( nSVEvent, pChild, &aKeyEvt );
1306         bool bPreNotify = ImplCallPreNotify( aNEvt );
1307         if ( pChild->isDisposed() )
1308             return true;
1309 
1310         if ( !bPreNotify )
1311         {
1312             if ( nSVEvent == NotifyEventType::KEYINPUT )
1313             {
1314                 pChild->ImplGetWindowImpl()->mbKeyInput = false;
1315                 pChild->KeyInput( aKeyEvt );
1316             }
1317             else
1318             {
1319                 pChild->ImplGetWindowImpl()->mbKeyUp = false;
1320                 pChild->KeyUp( aKeyEvt );
1321             }
1322 
1323             if( !pChild->isDisposed() )
1324                 aNEvt.GetWindow()->ImplNotifyKeyMouseCommandEventListeners( aNEvt );
1325             if ( pChild->isDisposed() )
1326                 return true;
1327         }
1328 
1329         if( bPreNotify || !pChild->ImplGetWindowImpl()->mbKeyInput )
1330             bRet = true;
1331     }
1332 
1333     return bRet;
1334 }
1335 
ImplHandleExtTextInput(vcl::Window * pWindow,const OUString & rText,const ExtTextInputAttr * pTextAttr,sal_Int32 nCursorPos,sal_uInt16 nCursorFlags)1336 static bool ImplHandleExtTextInput( vcl::Window* pWindow,
1337                                     const OUString& rText,
1338                                     const ExtTextInputAttr* pTextAttr,
1339                                     sal_Int32 nCursorPos, sal_uInt16 nCursorFlags )
1340 {
1341     ImplSVData* pSVData = ImplGetSVData();
1342     vcl::Window*     pChild = nullptr;
1343 
1344     int nTries = 200;
1345     while( nTries-- )
1346     {
1347         pChild = pSVData->mpWinData->mpExtTextInputWin;
1348         if ( !pChild )
1349         {
1350             pChild = ImplGetKeyInputWindow( pWindow );
1351             if ( !pChild )
1352                 return false;
1353         }
1354         if( !pChild->ImplGetWindowImpl()->mpFrameData->mnFocusId )
1355             break;
1356 
1357         if (comphelper::LibreOfficeKit::isActive())
1358         {
1359             SAL_WARN("vcl", "Failed to get ext text input context");
1360             break;
1361         }
1362         Application::Yield();
1363     }
1364 
1365     // If it is the first ExtTextInput call, we inform the information
1366     // and allocate the data, which we must store in this mode
1367     ImplWinData* pWinData = pChild->ImplGetWinData();
1368     if ( !pChild->ImplGetWindowImpl()->mbExtTextInput )
1369     {
1370         pChild->ImplGetWindowImpl()->mbExtTextInput = true;
1371         pWinData->mpExtOldText = OUString();
1372         pWinData->mpExtOldAttrAry.reset();
1373         pSVData->mpWinData->mpExtTextInputWin = pChild;
1374         ImplCallCommand( pChild, CommandEventId::StartExtTextInput );
1375     }
1376 
1377     // be aware of being recursively called in StartExtTextInput
1378     if ( !pChild->ImplGetWindowImpl()->mbExtTextInput )
1379         return false;
1380 
1381     // Test for changes
1382     bool bOnlyCursor = false;
1383     sal_Int32 nMinLen = std::min( pWinData->mpExtOldText->getLength(), rText.getLength() );
1384     sal_Int32 nDeltaStart = 0;
1385     while ( nDeltaStart < nMinLen )
1386     {
1387         if ( (*pWinData->mpExtOldText)[nDeltaStart] != rText[nDeltaStart] )
1388             break;
1389         nDeltaStart++;
1390     }
1391     if ( pWinData->mpExtOldAttrAry || pTextAttr )
1392     {
1393         if ( !pWinData->mpExtOldAttrAry || !pTextAttr )
1394             nDeltaStart = 0;
1395         else
1396         {
1397             sal_Int32 i = 0;
1398             while ( i < nDeltaStart )
1399             {
1400                 if ( pWinData->mpExtOldAttrAry[i] != pTextAttr[i] )
1401                 {
1402                     nDeltaStart = i;
1403                     break;
1404                 }
1405                 i++;
1406             }
1407         }
1408     }
1409     if ( (nDeltaStart >= nMinLen) &&
1410          (pWinData->mpExtOldText->getLength() == rText.getLength()) )
1411         bOnlyCursor = true;
1412 
1413     // Call Event and store the information
1414     CommandExtTextInputData aData( rText, pTextAttr,
1415                                    nCursorPos, nCursorFlags,
1416                                    bOnlyCursor );
1417     *pWinData->mpExtOldText = rText;
1418     pWinData->mpExtOldAttrAry.reset();
1419     if ( pTextAttr )
1420     {
1421         pWinData->mpExtOldAttrAry.reset( new ExtTextInputAttr[rText.getLength()] );
1422         memcpy( pWinData->mpExtOldAttrAry.get(), pTextAttr, rText.getLength()*sizeof( ExtTextInputAttr ) );
1423     }
1424     return !ImplCallCommand( pChild, CommandEventId::ExtTextInput, &aData );
1425 }
1426 
ImplHandleEndExtTextInput()1427 static bool ImplHandleEndExtTextInput()
1428 {
1429     ImplSVData* pSVData = ImplGetSVData();
1430     vcl::Window* pChild = pSVData->mpWinData->mpExtTextInputWin;
1431     bool bRet = false;
1432 
1433     if ( pChild )
1434     {
1435         pChild->ImplGetWindowImpl()->mbExtTextInput = false;
1436         pSVData->mpWinData->mpExtTextInputWin = nullptr;
1437         ImplWinData* pWinData = pChild->ImplGetWinData();
1438         pWinData->mpExtOldText.reset();
1439         pWinData->mpExtOldAttrAry.reset();
1440         bRet = !ImplCallCommand( pChild, CommandEventId::EndExtTextInput );
1441     }
1442 
1443     return bRet;
1444 }
1445 
ImplHandleExtTextInputPos(vcl::Window * pWindow,tools::Rectangle & rRect,tools::Long & rInputWidth,bool * pVertical)1446 static void ImplHandleExtTextInputPos( vcl::Window* pWindow,
1447                                        tools::Rectangle& rRect, tools::Long& rInputWidth,
1448                                        bool * pVertical )
1449 {
1450     ImplSVData* pSVData = ImplGetSVData();
1451     vcl::Window* pChild = pSVData->mpWinData->mpExtTextInputWin;
1452 
1453     if ( !pChild )
1454         pChild = ImplGetKeyInputWindow( pWindow );
1455     else
1456     {
1457         // Test, if the Window is related to the frame
1458         if ( !pWindow->ImplIsWindowOrChild( pChild ) )
1459             pChild = ImplGetKeyInputWindow( pWindow );
1460     }
1461 
1462     if ( pChild )
1463     {
1464         const OutputDevice *pChildOutDev = pChild->GetOutDev();
1465         ImplCallCommand( pChild, CommandEventId::CursorPos );
1466         const tools::Rectangle* pRect = pChild->GetCursorRect();
1467         if ( pRect )
1468             rRect = pChildOutDev->ImplLogicToDevicePixel( *pRect );
1469         else
1470         {
1471             vcl::Cursor* pCursor = pChild->GetCursor();
1472             if ( pCursor )
1473             {
1474                 Point aPos = pChildOutDev->ImplLogicToDevicePixel( pCursor->GetPos() );
1475                 Size aSize = pChild->LogicToPixel( pCursor->GetSize() );
1476                 if ( !aSize.Width() )
1477                     aSize.setWidth( pChild->GetSettings().GetStyleSettings().GetCursorSize() );
1478                 rRect = tools::Rectangle( aPos, aSize );
1479             }
1480             else
1481                 rRect = tools::Rectangle( Point( pChild->GetOutOffXPixel(), pChild->GetOutOffYPixel() ), Size() );
1482         }
1483         rInputWidth = pChild->GetOutDev()->ImplLogicWidthToDevicePixel( pChild->GetCursorExtTextInputWidth() );
1484         if ( !rInputWidth )
1485             rInputWidth = rRect.GetWidth();
1486     }
1487     if (pVertical != nullptr)
1488         *pVertical
1489             = pChild != nullptr && pChild->GetInputContext().GetFont().IsVertical();
1490 }
1491 
ImplHandleInputContextChange(vcl::Window * pWindow)1492 static bool ImplHandleInputContextChange( vcl::Window* pWindow )
1493 {
1494     vcl::Window* pChild = ImplGetKeyInputWindow( pWindow );
1495     CommandInputContextData aData;
1496     return !ImplCallCommand( pChild, CommandEventId::InputContextChange, &aData );
1497 }
1498 
ImplCallWheelCommand(const VclPtr<vcl::Window> & pWindow,const Point & rPos,const CommandWheelData * pWheelData)1499 static bool ImplCallWheelCommand( const VclPtr<vcl::Window>& pWindow, const Point& rPos,
1500                                   const CommandWheelData* pWheelData )
1501 {
1502     Point               aCmdMousePos = pWindow->ScreenToOutputPixel( rPos );
1503     CommandEvent        aCEvt( aCmdMousePos, CommandEventId::Wheel, true, pWheelData );
1504     NotifyEvent         aNCmdEvt( NotifyEventType::COMMAND, pWindow, &aCEvt );
1505     bool bPreNotify = ImplCallPreNotify( aNCmdEvt );
1506     if ( pWindow->isDisposed() )
1507         return false;
1508     if ( !bPreNotify )
1509     {
1510         pWindow->ImplGetWindowImpl()->mbCommand = false;
1511         pWindow->Command( aCEvt );
1512         if ( pWindow->isDisposed() )
1513             return false;
1514         if ( pWindow->ImplGetWindowImpl()->mbCommand )
1515             return true;
1516     }
1517     return false;
1518 }
1519 
acceptableWheelScrollTarget(const vcl::Window * pMouseWindow)1520 static bool acceptableWheelScrollTarget(const vcl::Window *pMouseWindow)
1521 {
1522     return (pMouseWindow && !pMouseWindow->isDisposed() && pMouseWindow->IsInputEnabled() && !pMouseWindow->IsInModalMode());
1523 }
1524 
1525 //If the last event at the same absolute screen position was handled by a
1526 //different window then reuse that window if the event occurs within 1/2 a
1527 //second, i.e. so scrolling down something like the calc sidebar that contains
1528 //widgets that respond to wheel events will continue to send the event to the
1529 //scrolling widget in favour of the widget that happens to end up under the
1530 //mouse.
shouldReusePreviousMouseWindow(const SalWheelMouseEvent & rPrevEvt,const SalWheelMouseEvent & rEvt)1531 static bool shouldReusePreviousMouseWindow(const SalWheelMouseEvent& rPrevEvt, const SalWheelMouseEvent& rEvt)
1532 {
1533     return (rEvt.mnX == rPrevEvt.mnX && rEvt.mnY == rPrevEvt.mnY && rEvt.mnTime-rPrevEvt.mnTime < 500/*ms*/);
1534 }
1535 
1536 namespace {
1537 
1538 class HandleGestureEventBase
1539 {
1540 protected:
1541     ImplSVData* m_pSVData;
1542     VclPtr<vcl::Window> m_pWindow;
1543     Point m_aMousePos;
1544 
1545 public:
HandleGestureEventBase(vcl::Window * pWindow,const Point & rMousePos)1546     HandleGestureEventBase(vcl::Window *pWindow, const Point &rMousePos)
1547         : m_pSVData(ImplGetSVData())
1548         , m_pWindow(pWindow)
1549         , m_aMousePos(rMousePos)
1550     {
1551     }
1552     bool Setup();
1553     vcl::Window* FindTarget();
1554     vcl::Window* Dispatch(vcl::Window* pTarget);
1555     virtual bool CallCommand(vcl::Window *pWindow, const Point &rMousePos) = 0;
~HandleGestureEventBase()1556     virtual ~HandleGestureEventBase() {}
1557 };
1558 
1559 }
1560 
Setup()1561 bool HandleGestureEventBase::Setup()
1562 {
1563 
1564     if (m_pSVData->mpWinData->mpAutoScrollWin)
1565         m_pSVData->mpWinData->mpAutoScrollWin->EndAutoScroll();
1566     if (ImplGetSVHelpData().mpHelpWin)
1567         ImplDestroyHelpWindow( true );
1568     return !m_pWindow->isDisposed();
1569 }
1570 
FindTarget()1571 vcl::Window* HandleGestureEventBase::FindTarget()
1572 {
1573     // first check any floating window ( eg. drop down listboxes)
1574     vcl::Window *pMouseWindow = nullptr;
1575 
1576     if (m_pSVData->mpWinData->mpFirstFloat && !m_pSVData->mpWinData->mpCaptureWin &&
1577          !m_pSVData->mpWinData->mpFirstFloat->ImplIsFloatPopupModeWindow( m_pWindow ) )
1578     {
1579         bool bHitTestInsideRect = false;
1580         pMouseWindow = m_pSVData->mpWinData->mpFirstFloat->ImplFloatHitTest( m_pWindow, m_aMousePos, bHitTestInsideRect );
1581         if (!pMouseWindow)
1582             pMouseWindow = m_pSVData->mpWinData->mpFirstFloat;
1583     }
1584     // then try the window directly beneath the mouse
1585     if( !pMouseWindow )
1586     {
1587         pMouseWindow = m_pWindow->ImplFindWindow( m_aMousePos );
1588     }
1589     else
1590     {
1591         // transform coordinates to float window frame coordinates
1592         pMouseWindow = pMouseWindow->ImplFindWindow(
1593                  pMouseWindow->OutputToScreenPixel(
1594                   pMouseWindow->AbsoluteScreenToOutputPixel(
1595                    m_pWindow->OutputToAbsoluteScreenPixel(
1596                     m_pWindow->ScreenToOutputPixel( m_aMousePos ) ) ) ) );
1597     }
1598 
1599     while (acceptableWheelScrollTarget(pMouseWindow))
1600     {
1601         if (pMouseWindow->IsEnabled())
1602             break;
1603         //try the parent if this one is disabled
1604         pMouseWindow = pMouseWindow->GetParent();
1605     }
1606 
1607     return pMouseWindow;
1608 }
1609 
Dispatch(vcl::Window * pMouseWindow)1610 vcl::Window *HandleGestureEventBase::Dispatch(vcl::Window* pMouseWindow)
1611 {
1612     vcl::Window *pDispatchedTo = nullptr;
1613 
1614     if (acceptableWheelScrollTarget(pMouseWindow) && pMouseWindow->IsEnabled())
1615     {
1616         // transform coordinates to float window frame coordinates
1617         Point aRelMousePos( pMouseWindow->OutputToScreenPixel(
1618                              pMouseWindow->AbsoluteScreenToOutputPixel(
1619                               m_pWindow->OutputToAbsoluteScreenPixel(
1620                                m_pWindow->ScreenToOutputPixel( m_aMousePos ) ) ) ) );
1621         bool bPropagate = CallCommand(pMouseWindow, aRelMousePos);
1622         if (!bPropagate)
1623             pDispatchedTo = pMouseWindow;
1624     }
1625 
1626     // if the command was not handled try the focus window
1627     if (!pDispatchedTo)
1628     {
1629         vcl::Window* pFocusWindow = m_pWindow->ImplGetWindowImpl()->mpFrameData->mpFocusWin;
1630         if ( pFocusWindow && (pFocusWindow != pMouseWindow) &&
1631              (pFocusWindow == m_pSVData->mpWinData->mpFocusWin) )
1632         {
1633             // no wheel-messages to disabled windows
1634             if ( pFocusWindow->IsEnabled() && pFocusWindow->IsInputEnabled() && ! pFocusWindow->IsInModalMode() )
1635             {
1636                 // transform coordinates to focus window frame coordinates
1637                 Point aRelMousePos( pFocusWindow->OutputToScreenPixel(
1638                                      pFocusWindow->AbsoluteScreenToOutputPixel(
1639                                       m_pWindow->OutputToAbsoluteScreenPixel(
1640                                        m_pWindow->ScreenToOutputPixel( m_aMousePos ) ) ) ) );
1641                 bool bPropagate = CallCommand(pFocusWindow, aRelMousePos);
1642                 if (!bPropagate)
1643                     pDispatchedTo = pMouseWindow;
1644             }
1645         }
1646     }
1647     return pDispatchedTo;
1648 }
1649 
1650 namespace {
1651 
1652 class HandleWheelEvent : public HandleGestureEventBase
1653 {
1654 private:
1655     CommandWheelData m_aWheelData;
1656 public:
HandleWheelEvent(vcl::Window * pWindow,const SalWheelMouseEvent & rEvt)1657     HandleWheelEvent(vcl::Window *pWindow, const SalWheelMouseEvent& rEvt)
1658         : HandleGestureEventBase(pWindow, Point(rEvt.mnX, rEvt.mnY))
1659     {
1660         CommandWheelMode nMode;
1661         sal_uInt16 nCode = rEvt.mnCode;
1662         bool bHorz = rEvt.mbHorz;
1663         bool bPixel = rEvt.mbDeltaIsPixel;
1664         if ( nCode & KEY_MOD1 )
1665             nMode = CommandWheelMode::ZOOM;
1666         else if ( nCode & KEY_MOD2 )
1667             nMode = CommandWheelMode::DATAZOOM;
1668         else
1669         {
1670             nMode = CommandWheelMode::SCROLL;
1671             // #i85450# interpret shift-wheel as horizontal wheel action
1672             if( (nCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_MOD3)) == KEY_SHIFT )
1673                 bHorz = true;
1674         }
1675 
1676         m_aWheelData = CommandWheelData(rEvt.mnDelta, rEvt.mnNotchDelta, rEvt.mnScrollLines, nMode, nCode, bHorz, bPixel);
1677 
1678     }
CallCommand(vcl::Window * pWindow,const Point & rMousePos)1679     virtual bool CallCommand(vcl::Window *pWindow, const Point &rMousePos) override
1680     {
1681         return ImplCallWheelCommand(pWindow, rMousePos, &m_aWheelData);
1682     }
1683     bool HandleEvent(const SalWheelMouseEvent& rEvt);
1684 };
1685 
1686 }
1687 
HandleEvent(const SalWheelMouseEvent & rEvt)1688 bool HandleWheelEvent::HandleEvent(const SalWheelMouseEvent& rEvt)
1689 {
1690     if (!Setup())
1691         return false;
1692 
1693     VclPtr<vcl::Window> xMouseWindow = FindTarget();
1694 
1695     ImplSVData* pSVData = ImplGetSVData();
1696 
1697     // avoid the problem that scrolling via wheel to this point brings a widget
1698     // under the mouse that also accepts wheel commands, so stick with the old
1699     // widget if the time gap is very small
1700     if (shouldReusePreviousMouseWindow(pSVData->mpWinData->maLastWheelEvent, rEvt) &&
1701         acceptableWheelScrollTarget(pSVData->mpWinData->mpLastWheelWindow))
1702     {
1703         xMouseWindow = pSVData->mpWinData->mpLastWheelWindow;
1704     }
1705 
1706     pSVData->mpWinData->maLastWheelEvent = rEvt;
1707 
1708     pSVData->mpWinData->mpLastWheelWindow = Dispatch(xMouseWindow);
1709 
1710     return pSVData->mpWinData->mpLastWheelWindow;
1711 }
1712 
1713 namespace {
1714 
1715 class HandleGestureEvent : public HandleGestureEventBase
1716 {
1717 public:
HandleGestureEvent(vcl::Window * pWindow,const Point & rMousePos)1718     HandleGestureEvent(vcl::Window *pWindow, const Point &rMousePos)
1719         : HandleGestureEventBase(pWindow, rMousePos)
1720     {
1721     }
1722     bool HandleEvent();
1723 };
1724 
1725 }
1726 
HandleEvent()1727 bool HandleGestureEvent::HandleEvent()
1728 {
1729     if (!Setup())
1730         return false;
1731 
1732     vcl::Window *pTarget = FindTarget();
1733 
1734     bool bHandled = Dispatch(pTarget) != nullptr;
1735     return bHandled;
1736 }
1737 
ImplHandleWheelEvent(vcl::Window * pWindow,const SalWheelMouseEvent & rEvt)1738 static bool ImplHandleWheelEvent(vcl::Window* pWindow, const SalWheelMouseEvent& rEvt)
1739 {
1740     HandleWheelEvent aHandler(pWindow, rEvt);
1741     return aHandler.HandleEvent(rEvt);
1742 }
1743 
1744 namespace {
1745 
1746 class HandleGestureSwipeEvent : public HandleGestureEvent
1747 {
1748 private:
1749     CommandGestureSwipeData m_aSwipeData;
1750 public:
HandleGestureSwipeEvent(vcl::Window * pWindow,const SalGestureSwipeEvent & rEvt)1751     HandleGestureSwipeEvent(vcl::Window *pWindow, const SalGestureSwipeEvent& rEvt)
1752         : HandleGestureEvent(pWindow, Point(rEvt.mnX, rEvt.mnY)),
1753           m_aSwipeData(rEvt.mnVelocityX)
1754     {
1755     }
CallCommand(vcl::Window * pWindow,const Point &)1756     virtual bool CallCommand(vcl::Window *pWindow, const Point &/*rMousePos*/) override
1757     {
1758         return ImplCallCommand(pWindow, CommandEventId::GestureSwipe, &m_aSwipeData);
1759     }
1760 };
1761 
1762 }
1763 
ImplHandleSwipe(vcl::Window * pWindow,const SalGestureSwipeEvent & rEvt)1764 static bool ImplHandleSwipe(vcl::Window *pWindow, const SalGestureSwipeEvent& rEvt)
1765 {
1766     HandleGestureSwipeEvent aHandler(pWindow, rEvt);
1767     return aHandler.HandleEvent();
1768 }
1769 
1770 namespace {
1771 
1772 class HandleGestureLongPressEvent : public HandleGestureEvent
1773 {
1774 private:
1775     CommandGestureLongPressData m_aLongPressData;
1776 public:
HandleGestureLongPressEvent(vcl::Window * pWindow,const SalGestureLongPressEvent & rEvt)1777     HandleGestureLongPressEvent(vcl::Window *pWindow, const SalGestureLongPressEvent& rEvt)
1778         : HandleGestureEvent(pWindow, Point(rEvt.mnX, rEvt.mnY)),
1779           m_aLongPressData(rEvt.mnX, rEvt.mnY)
1780     {
1781     }
CallCommand(vcl::Window * pWindow,const Point &)1782     virtual bool CallCommand(vcl::Window *pWindow, const Point &/*rMousePos*/) override
1783     {
1784         return ImplCallCommand(pWindow, CommandEventId::GestureLongPress, &m_aLongPressData);
1785     }
1786 };
1787 
1788 }
1789 
ImplHandleLongPress(vcl::Window * pWindow,const SalGestureLongPressEvent & rEvt)1790 static bool ImplHandleLongPress(vcl::Window *pWindow, const SalGestureLongPressEvent& rEvt)
1791 {
1792     HandleGestureLongPressEvent aHandler(pWindow, rEvt);
1793     return aHandler.HandleEvent();
1794 }
1795 
1796 namespace {
1797 
1798 class HandleGesturePanEvent : public HandleGestureEvent
1799 {
1800 private:
1801     CommandGesturePanData m_aGestureData;
1802 
1803 public:
HandleGesturePanEvent(vcl::Window * pWindow,const SalGestureEvent & rEvent)1804     HandleGesturePanEvent(vcl::Window* pWindow, const SalGestureEvent& rEvent)
1805         : HandleGestureEvent(pWindow, Point(rEvent.mnX, rEvent.mnY))
1806         , m_aGestureData(rEvent.mnX, rEvent.mnY, rEvent.meEventType, rEvent.mfOffset, rEvent.meOrientation)
1807     {
1808     }
1809 
CallCommand(vcl::Window * pWindow,const Point &)1810     virtual bool CallCommand(vcl::Window* pWindow, const Point& /*rMousePos*/) override
1811     {
1812         return ImplCallCommand(pWindow, CommandEventId::GesturePan, &m_aGestureData);
1813     }
1814 };
1815 
1816 }
1817 
ImplHandleGestureEvent(vcl::Window * pWindow,const SalGestureEvent & rEvent)1818 static bool ImplHandleGestureEvent(vcl::Window* pWindow, const SalGestureEvent& rEvent)
1819 {
1820     HandleGesturePanEvent aHandler(pWindow, rEvent);
1821     return aHandler.HandleEvent();
1822 }
1823 
1824 namespace {
1825 
1826 class HandleGestureZoomEvent : public HandleGestureEvent
1827 {
1828 private:
1829     CommandGestureZoomData m_aGestureData;
1830 
1831 public:
HandleGestureZoomEvent(vcl::Window * pWindow,const SalGestureZoomEvent & rEvent)1832     HandleGestureZoomEvent(vcl::Window* pWindow, const SalGestureZoomEvent& rEvent)
1833         : HandleGestureEvent(pWindow, Point(rEvent.mnX, rEvent.mnY))
1834         , m_aGestureData(rEvent.mnX, rEvent.mnY, rEvent.meEventType, rEvent.mfScaleDelta)
1835     {
1836     }
1837 
CallCommand(vcl::Window * pWindow,const Point &)1838     virtual bool CallCommand(vcl::Window* pWindow, const Point& /*rMousePos*/) override
1839     {
1840         return ImplCallCommand(pWindow, CommandEventId::GestureZoom, &m_aGestureData);
1841     }
1842 };
1843 
1844 }
1845 
ImplHandleGestureZoomEvent(vcl::Window * pWindow,const SalGestureZoomEvent & rEvent)1846 static bool ImplHandleGestureZoomEvent(vcl::Window* pWindow, const SalGestureZoomEvent& rEvent)
1847 {
1848     HandleGestureZoomEvent aHandler(pWindow, rEvent);
1849     return aHandler.HandleEvent();
1850 }
1851 
1852 namespace {
1853 
1854 class HandleGestureRotateEvent : public HandleGestureEvent
1855 {
1856 private:
1857     CommandGestureRotateData m_aGestureData;
1858 
1859 public:
HandleGestureRotateEvent(vcl::Window * pWindow,const SalGestureRotateEvent & rEvent)1860     HandleGestureRotateEvent(vcl::Window* pWindow, const SalGestureRotateEvent& rEvent)
1861         : HandleGestureEvent(pWindow, Point(rEvent.mnX, rEvent.mnY))
1862         , m_aGestureData(rEvent.mnX, rEvent.mnY, rEvent.meEventType, rEvent.mfAngleDelta)
1863     {
1864     }
1865 
CallCommand(vcl::Window * pWindow,const Point &)1866     virtual bool CallCommand(vcl::Window* pWindow, const Point& /*rMousePos*/) override
1867     {
1868         return ImplCallCommand(pWindow, CommandEventId::GestureRotate, &m_aGestureData);
1869     }
1870 };
1871 
1872 }
1873 
ImplHandleGestureRotateEvent(vcl::Window * pWindow,const SalGestureRotateEvent & rEvent)1874 static bool ImplHandleGestureRotateEvent(vcl::Window* pWindow, const SalGestureRotateEvent& rEvent)
1875 {
1876     HandleGestureRotateEvent aHandler(pWindow, rEvent);
1877     return aHandler.HandleEvent();
1878 }
1879 
ImplHandlePaint(vcl::Window * pWindow,const tools::Rectangle & rBoundRect,bool bImmediateUpdate)1880 static void ImplHandlePaint( vcl::Window* pWindow, const tools::Rectangle& rBoundRect, bool bImmediateUpdate )
1881 {
1882     // system paint events must be checked for re-mirroring
1883     pWindow->ImplGetWindowImpl()->mnPaintFlags |= ImplPaintFlags::CheckRtl;
1884 
1885     // trigger paint for all windows that live in the new paint region
1886     vcl::Region aRegion( rBoundRect );
1887     pWindow->ImplInvalidateOverlapFrameRegion( aRegion );
1888     if( bImmediateUpdate )
1889     {
1890         // #i87663# trigger possible pending resize notifications
1891         // (GetSizePixel does that for us)
1892         pWindow->GetSizePixel();
1893         // force drawing immediately
1894         pWindow->PaintImmediately();
1895     }
1896 }
1897 
KillOwnPopups(vcl::Window const * pWindow)1898 static void KillOwnPopups( vcl::Window const * pWindow )
1899 {
1900     ImplSVData* pSVData = ImplGetSVData();
1901     vcl::Window *pParent = pWindow->ImplGetWindowImpl()->mpFrameWindow;
1902     vcl::Window *pChild = pSVData->mpWinData->mpFirstFloat;
1903     if ( pChild && pParent->ImplIsWindowOrChild( pChild, true ) )
1904     {
1905         if (!(pSVData->mpWinData->mpFirstFloat->GetPopupModeFlags()
1906               & FloatWinPopupFlags::NoAppFocusClose))
1907             pSVData->mpWinData->mpFirstFloat->EndPopupMode(FloatWinPopupEndFlags::Cancel
1908                                                            | FloatWinPopupEndFlags::CloseAll);
1909     }
1910 }
1911 
ImplHandleResize(vcl::Window * pWindow,tools::Long nNewWidth,tools::Long nNewHeight)1912 void ImplHandleResize( vcl::Window* pWindow, tools::Long nNewWidth, tools::Long nNewHeight )
1913 {
1914     const bool bChanged = (nNewWidth != pWindow->GetOutputSizePixel().Width()) || (nNewHeight != pWindow->GetOutDev()->GetOutputHeightPixel());
1915     if (bChanged && pWindow->GetStyle() & (WB_MOVEABLE|WB_SIZEABLE))
1916     {
1917         KillOwnPopups( pWindow );
1918         if( pWindow->ImplGetWindow() != ImplGetSVHelpData().mpHelpWin )
1919             ImplDestroyHelpWindow( true );
1920     }
1921 
1922     if (
1923          (nNewWidth > 0 && nNewHeight > 0) ||
1924          pWindow->ImplGetWindow()->ImplGetWindowImpl()->mbAllResize
1925        )
1926     {
1927         if (bChanged)
1928         {
1929             pWindow->GetOutDev()->mnOutWidth  = nNewWidth;
1930             pWindow->GetOutDev()->mnOutHeight = nNewHeight;
1931             pWindow->ImplGetWindowImpl()->mbWaitSystemResize = false;
1932             if ( pWindow->IsReallyVisible() )
1933                 pWindow->ImplSetClipFlag();
1934             if ( pWindow->IsVisible() || pWindow->ImplGetWindow()->ImplGetWindowImpl()->mbAllResize ||
1935                 ( pWindow->ImplGetWindowImpl()->mbFrame && pWindow->ImplGetWindowImpl()->mpClientWindow ) )   // propagate resize for system border windows
1936             {
1937                 bool bStartTimer = true;
1938                 // use resize buffering for user resizes
1939                 // ownerdraw decorated windows and floating windows can be resized immediately (i.e. synchronously)
1940                 if( pWindow->ImplGetWindowImpl()->mbFrame && (pWindow->GetStyle() & WB_SIZEABLE)
1941                     && !(pWindow->GetStyle() & WB_OWNERDRAWDECORATION)  // synchronous resize for ownerdraw decorated windows (toolbars)
1942                     && !pWindow->ImplGetWindowImpl()->mbFloatWin )             // synchronous resize for floating windows, #i43799#
1943                 {
1944                     if( pWindow->ImplGetWindowImpl()->mpClientWindow )
1945                     {
1946                         // #i42750# presentation wants to be informed about resize
1947                         // as early as possible
1948                         WorkWindow* pWorkWindow = dynamic_cast<WorkWindow*>(pWindow->ImplGetWindowImpl()->mpClientWindow.get());
1949                         if( ! pWorkWindow || pWorkWindow->IsPresentationMode() )
1950                             bStartTimer = false;
1951                     }
1952                     else
1953                     {
1954                         WorkWindow* pWorkWindow = dynamic_cast<WorkWindow*>(pWindow);
1955                         if( ! pWorkWindow || pWorkWindow->IsPresentationMode() )
1956                             bStartTimer = false;
1957                     }
1958                 }
1959                 else
1960                     bStartTimer = false;
1961 
1962                 if( bStartTimer )
1963                     pWindow->ImplGetWindowImpl()->mpFrameData->maResizeIdle.Start();
1964                 else
1965                     pWindow->ImplCallResize(); // otherwise menus cannot be positioned
1966             }
1967             else
1968                 pWindow->ImplGetWindowImpl()->mbCallResize = true;
1969 
1970             if (pWindow->SupportsDoubleBuffering() && pWindow->ImplGetWindowImpl()->mbFrame)
1971             {
1972                 // Propagate resize for the frame's buffer.
1973                 pWindow->ImplGetWindowImpl()->mpFrameData->mpBuffer->SetOutputSizePixel(pWindow->GetOutputSizePixel());
1974             }
1975         }
1976     }
1977 
1978     pWindow->ImplGetWindowImpl()->mpFrameData->mbNeedSysWindow = (nNewWidth < IMPL_MIN_NEEDSYSWIN) ||
1979                                             (nNewHeight < IMPL_MIN_NEEDSYSWIN);
1980     bool bMinimized = (nNewWidth <= 0) || (nNewHeight <= 0);
1981     if( bMinimized != pWindow->ImplGetWindowImpl()->mpFrameData->mbMinimized )
1982         pWindow->ImplGetWindowImpl()->mpFrameWindow->ImplNotifyIconifiedState( bMinimized );
1983     pWindow->ImplGetWindowImpl()->mpFrameData->mbMinimized = bMinimized;
1984 }
1985 
ImplHandleMove(vcl::Window * pWindow)1986 static void ImplHandleMove( vcl::Window* pWindow )
1987 {
1988     if( pWindow->ImplGetWindowImpl()->mbFrame && pWindow->ImplIsFloatingWindow() && pWindow->IsReallyVisible() )
1989     {
1990         static_cast<FloatingWindow*>(pWindow)->EndPopupMode( FloatWinPopupEndFlags::TearOff );
1991         pWindow->ImplCallMove();
1992     }
1993 
1994     if( pWindow->GetStyle() & (WB_MOVEABLE|WB_SIZEABLE) )
1995     {
1996         KillOwnPopups( pWindow );
1997         if( pWindow->ImplGetWindow() != ImplGetSVHelpData().mpHelpWin )
1998             ImplDestroyHelpWindow( true );
1999     }
2000 
2001     if ( pWindow->IsVisible() )
2002         pWindow->ImplCallMove();
2003     else
2004         pWindow->ImplGetWindowImpl()->mbCallMove = true; // make sure the framepos will be updated on the next Show()
2005 
2006     if ( pWindow->ImplGetWindowImpl()->mbFrame && pWindow->ImplGetWindowImpl()->mpClientWindow )
2007         pWindow->ImplGetWindowImpl()->mpClientWindow->ImplCallMove();   // notify client to update geometry
2008 
2009 }
2010 
ImplHandleMoveResize(vcl::Window * pWindow,tools::Long nNewWidth,tools::Long nNewHeight)2011 static void ImplHandleMoveResize( vcl::Window* pWindow, tools::Long nNewWidth, tools::Long nNewHeight )
2012 {
2013     ImplHandleMove( pWindow );
2014     ImplHandleResize( pWindow, nNewWidth, nNewHeight );
2015 }
2016 
ImplActivateFloatingWindows(vcl::Window const * pWindow,bool bActive)2017 static void ImplActivateFloatingWindows( vcl::Window const * pWindow, bool bActive )
2018 {
2019     // First check all overlapping windows
2020     vcl::Window* pTempWindow = pWindow->ImplGetWindowImpl()->mpFirstOverlap;
2021     while ( pTempWindow )
2022     {
2023         if ( pTempWindow->GetActivateMode() == ActivateModeFlags::NONE )
2024         {
2025             if ( (pTempWindow->GetType() == WindowType::BORDERWINDOW) &&
2026                  (pTempWindow->ImplGetWindow()->GetType() == WindowType::FLOATINGWINDOW) )
2027                 static_cast<ImplBorderWindow*>(pTempWindow)->SetDisplayActive( bActive );
2028         }
2029 
2030         ImplActivateFloatingWindows( pTempWindow, bActive );
2031         pTempWindow = pTempWindow->ImplGetWindowImpl()->mpNext;
2032     }
2033 }
2034 
IMPL_LINK_NOARG(vcl::Window,ImplAsyncFocusHdl,void *,void)2035 IMPL_LINK_NOARG(vcl::Window, ImplAsyncFocusHdl, void*, void)
2036 {
2037     if (!ImplGetWindowImpl() || !ImplGetWindowImpl()->mpFrameData)
2038         return;
2039 
2040     ImplGetWindowImpl()->mpFrameData->mnFocusId = nullptr;
2041 
2042     // If the status has been preserved, because we got back the focus
2043     // in the meantime, we do nothing
2044     bool bHasFocus = ImplGetWindowImpl()->mpFrameData->mbHasFocus || ImplGetWindowImpl()->mpFrameData->mbSysObjFocus;
2045 
2046     // next execute the delayed functions
2047     if ( bHasFocus )
2048     {
2049         // redraw all floating windows inactive
2050         if ( ImplGetWindowImpl()->mpFrameData->mbStartFocusState != bHasFocus )
2051             ImplActivateFloatingWindows( this, bHasFocus );
2052 
2053         if ( ImplGetWindowImpl()->mpFrameData->mpFocusWin )
2054         {
2055             bool bHandled = false;
2056             if ( ImplGetWindowImpl()->mpFrameData->mpFocusWin->IsInputEnabled() &&
2057                  ! ImplGetWindowImpl()->mpFrameData->mpFocusWin->IsInModalMode() )
2058             {
2059                 if ( ImplGetWindowImpl()->mpFrameData->mpFocusWin->IsEnabled() )
2060                 {
2061                     ImplGetWindowImpl()->mpFrameData->mpFocusWin->GrabFocus();
2062                     bHandled = true;
2063                 }
2064                 else if( ImplGetWindowImpl()->mpFrameData->mpFocusWin->ImplHasDlgCtrl() )
2065                 {
2066                 // #109094# if the focus is restored to a disabled dialog control (was disabled meanwhile)
2067                 // try to move it to the next control
2068                     ImplGetWindowImpl()->mpFrameData->mpFocusWin->ImplDlgCtrlNextWindow();
2069                     bHandled = true;
2070                 }
2071             }
2072             if ( !bHandled )
2073             {
2074                 ImplSVData* pSVData = ImplGetSVData();
2075                 vcl::Window*     pTopLevelWindow = ImplGetWindowImpl()->mpFrameData->mpFocusWin->ImplGetFirstOverlapWindow();
2076 
2077                 if ((!pTopLevelWindow->IsInputEnabled() || pTopLevelWindow->IsInModalMode())
2078                     && !pSVData->mpWinData->mpExecuteDialogs.empty())
2079                     pSVData->mpWinData->mpExecuteDialogs.back()->ToTop(ToTopFlags::RestoreWhenMin | ToTopFlags::GrabFocusOnly);
2080                 else
2081                     pTopLevelWindow->GrabFocus();
2082             }
2083         }
2084         else
2085             GrabFocus();
2086     }
2087     else
2088     {
2089         vcl::Window* pFocusWin = ImplGetWindowImpl()->mpFrameData->mpFocusWin;
2090         if ( pFocusWin )
2091         {
2092             ImplSVData* pSVData = ImplGetSVData();
2093 
2094             if (pSVData->mpWinData->mpFocusWin == pFocusWin)
2095             {
2096                 // transfer the FocusWindow
2097                 vcl::Window* pOverlapWindow = pFocusWin->ImplGetFirstOverlapWindow();
2098                 if ( pOverlapWindow && pOverlapWindow->ImplGetWindowImpl() )
2099                     pOverlapWindow->ImplGetWindowImpl()->mpLastFocusWindow = pFocusWin;
2100                 pSVData->mpWinData->mpFocusWin = nullptr;
2101 
2102                 if ( pFocusWin->ImplGetWindowImpl() && pFocusWin->ImplGetWindowImpl()->mpCursor )
2103                     pFocusWin->ImplGetWindowImpl()->mpCursor->ImplHide();
2104 
2105                 // call the Deactivate
2106                 vcl::Window* pOldOverlapWindow = pFocusWin->ImplGetFirstOverlapWindow();
2107                 vcl::Window* pOldRealWindow = pOldOverlapWindow->ImplGetWindow();
2108 
2109                 if (pOldOverlapWindow && pOldOverlapWindow->ImplGetWindowImpl() &&
2110                     pOldRealWindow && pOldRealWindow->ImplGetWindowImpl())
2111                 {
2112                     pOldOverlapWindow->ImplGetWindowImpl()->mbActive = false;
2113                     pOldOverlapWindow->Deactivate();
2114                     if ( pOldRealWindow != pOldOverlapWindow )
2115                     {
2116                         pOldRealWindow->ImplGetWindowImpl()->mbActive = false;
2117                         pOldRealWindow->Deactivate();
2118                     }
2119                 }
2120 
2121                 // TrackingMode is ended in ImplHandleLoseFocus
2122 #ifdef _WIN32
2123                 // To avoid problems with the Unix IME
2124                 pFocusWin->EndExtTextInput();
2125 #endif
2126 
2127                 NotifyEvent aNEvt(NotifyEventType::LOSEFOCUS, pFocusWin);
2128                 if (!ImplCallPreNotify(aNEvt))
2129                     pFocusWin->CompatLoseFocus();
2130                 pFocusWin->ImplCallDeactivateListeners(nullptr);
2131             }
2132         }
2133 
2134         // Redraw all floating window inactive
2135         if ( ImplGetWindowImpl()->mpFrameData->mbStartFocusState != bHasFocus )
2136             ImplActivateFloatingWindows( this, bHasFocus );
2137     }
2138 }
2139 
ImplHandleGetFocus(vcl::Window * pWindow)2140 static void ImplHandleGetFocus( vcl::Window* pWindow )
2141 {
2142     if (!pWindow || !pWindow->ImplGetWindowImpl() || !pWindow->ImplGetWindowImpl()->mpFrameData)
2143         return;
2144 
2145     pWindow->ImplGetWindowImpl()->mpFrameData->mbHasFocus = true;
2146 
2147     // execute Focus-Events after a delay, such that SystemChildWindows
2148     // do not blink when they receive focus
2149     if ( !pWindow->ImplGetWindowImpl()->mpFrameData->mnFocusId )
2150     {
2151         pWindow->ImplGetWindowImpl()->mpFrameData->mbStartFocusState = !pWindow->ImplGetWindowImpl()->mpFrameData->mbHasFocus;
2152         pWindow->ImplGetWindowImpl()->mpFrameData->mnFocusId = Application::PostUserEvent( LINK( pWindow, vcl::Window, ImplAsyncFocusHdl ), nullptr, true);
2153         vcl::Window* pFocusWin = pWindow->ImplGetWindowImpl()->mpFrameData->mpFocusWin;
2154         if ( pFocusWin && pFocusWin->ImplGetWindowImpl()->mpCursor )
2155             pFocusWin->ImplGetWindowImpl()->mpCursor->ImplShow();
2156     }
2157 }
2158 
ImplHandleLoseFocus(vcl::Window * pWindow)2159 static void ImplHandleLoseFocus( vcl::Window* pWindow )
2160 {
2161     if (!pWindow)
2162         return;
2163 
2164     ImplSVData* pSVData = ImplGetSVData();
2165 
2166     // Abort the autoscroll if the frame loses focus
2167     if (pSVData->mpWinData->mpAutoScrollWin)
2168         pSVData->mpWinData->mpAutoScrollWin->EndAutoScroll();
2169 
2170     // Abort tracking if the frame loses focus
2171     if (pSVData->mpWinData->mpTrackWin)
2172     {
2173         if (pSVData->mpWinData->mpTrackWin->ImplGetWindowImpl() &&
2174             pSVData->mpWinData->mpTrackWin->ImplGetWindowImpl()->mpFrameWindow == pWindow)
2175             pSVData->mpWinData->mpTrackWin->EndTracking(TrackingEventFlags::Cancel);
2176     }
2177 
2178     if (pWindow->ImplGetWindowImpl() && pWindow->ImplGetWindowImpl()->mpFrameData)
2179     {
2180         pWindow->ImplGetWindowImpl()->mpFrameData->mbHasFocus = false;
2181 
2182         // execute Focus-Events after a delay, such that SystemChildWindows
2183         // do not flicker when they receive focus
2184         if ( !pWindow->ImplGetWindowImpl()->mpFrameData->mnFocusId )
2185         {
2186             pWindow->ImplGetWindowImpl()->mpFrameData->mbStartFocusState = !pWindow->ImplGetWindowImpl()->mpFrameData->mbHasFocus;
2187             pWindow->ImplGetWindowImpl()->mpFrameData->mnFocusId = Application::PostUserEvent( LINK( pWindow, vcl::Window, ImplAsyncFocusHdl ), nullptr, true );
2188         }
2189 
2190         vcl::Window* pFocusWin = pWindow->ImplGetWindowImpl()->mpFrameData->mpFocusWin;
2191         if ( pFocusWin && pFocusWin->ImplGetWindowImpl()->mpCursor )
2192             pFocusWin->ImplGetWindowImpl()->mpCursor->ImplHide();
2193     }
2194 
2195     // Make sure that no menu is visible when a toplevel window loses focus.
2196     VclPtr<FloatingWindow> pFirstFloat = pSVData->mpWinData->mpFirstFloat;
2197     if (pFirstFloat && pFirstFloat->IsMenuFloatingWindow() && !pWindow->GetParent())
2198     {
2199         pFirstFloat->EndPopupMode(FloatWinPopupEndFlags::Cancel | FloatWinPopupEndFlags::CloseAll);
2200     }
2201 }
2202 
2203 namespace {
2204 
2205 struct DelayedCloseEvent
2206 {
2207     VclPtr<vcl::Window> pWindow;
2208 };
2209 
2210 }
2211 
DelayedCloseEventLink(void * pCEvent,void *)2212 static void DelayedCloseEventLink( void* pCEvent, void* )
2213 {
2214     DelayedCloseEvent* pEv = static_cast<DelayedCloseEvent*>(pCEvent);
2215 
2216     if( ! pEv->pWindow->isDisposed() )
2217     {
2218         // dispatch to correct window type
2219         if( pEv->pWindow->IsSystemWindow() )
2220             static_cast<SystemWindow*>(pEv->pWindow.get())->Close();
2221         else if( pEv->pWindow->IsDockingWindow() )
2222             static_cast<DockingWindow*>(pEv->pWindow.get())->Close();
2223     }
2224     delete pEv;
2225 }
2226 
ImplHandleClose(const vcl::Window * pWindow)2227 static void ImplHandleClose( const vcl::Window* pWindow )
2228 {
2229     ImplSVData* pSVData = ImplGetSVData();
2230 
2231     bool bWasPopup = false;
2232     if( pWindow->ImplIsFloatingWindow() &&
2233         static_cast<const FloatingWindow*>(pWindow)->ImplIsInPrivatePopupMode() )
2234     {
2235         bWasPopup = true;
2236     }
2237 
2238     // on Close stop all floating modes and end popups
2239     if (pSVData->mpWinData->mpFirstFloat)
2240     {
2241         FloatingWindow* pLastLevelFloat;
2242         pLastLevelFloat = pSVData->mpWinData->mpFirstFloat->ImplFindLastLevelFloat();
2243         pLastLevelFloat->EndPopupMode( FloatWinPopupEndFlags::Cancel | FloatWinPopupEndFlags::CloseAll );
2244     }
2245     if ( ImplGetSVHelpData().mbExtHelpMode )
2246         Help::EndExtHelp();
2247     if ( ImplGetSVHelpData().mpHelpWin )
2248         ImplDestroyHelpWindow( false );
2249     // AutoScrollMode
2250     if (pSVData->mpWinData->mpAutoScrollWin)
2251         pSVData->mpWinData->mpAutoScrollWin->EndAutoScroll();
2252 
2253     if (pSVData->mpWinData->mpTrackWin)
2254         pSVData->mpWinData->mpTrackWin->EndTracking( TrackingEventFlags::Cancel | TrackingEventFlags::Key );
2255 
2256     if (bWasPopup)
2257         return;
2258 
2259     vcl::Window *pWin = pWindow->ImplGetWindow();
2260     SystemWindow* pSysWin = dynamic_cast<SystemWindow*>(pWin);
2261     if (pSysWin)
2262     {
2263         // See if the custom close handler is set.
2264         const Link<SystemWindow&,void>& rLink = pSysWin->GetCloseHdl();
2265         if (rLink.IsSet())
2266         {
2267             rLink.Call(*pSysWin);
2268             return;
2269         }
2270     }
2271 
2272     // check whether close is allowed
2273     if ( pWin->IsEnabled() && pWin->IsInputEnabled() && !pWin->IsInModalMode() )
2274     {
2275         DelayedCloseEvent* pEv = new DelayedCloseEvent;
2276         pEv->pWindow = pWin;
2277         Application::PostUserEvent( Link<void*,void>( pEv, DelayedCloseEventLink ) );
2278     }
2279 }
2280 
ImplHandleUserEvent(ImplSVEvent * pSVEvent)2281 static void ImplHandleUserEvent( ImplSVEvent* pSVEvent )
2282 {
2283     if ( pSVEvent )
2284     {
2285         if ( pSVEvent->mbCall )
2286         {
2287             pSVEvent->maLink.Call( pSVEvent->mpData );
2288         }
2289 
2290         delete pSVEvent;
2291     }
2292 }
2293 
ImplGetMouseMoveMode(SalMouseEvent const * pEvent)2294 MouseEventModifiers ImplGetMouseMoveMode( SalMouseEvent const * pEvent )
2295 {
2296     MouseEventModifiers nMode = MouseEventModifiers::NONE;
2297     if ( !pEvent->mnCode )
2298         nMode |= MouseEventModifiers::SIMPLEMOVE;
2299     if ( (pEvent->mnCode & MOUSE_LEFT) && !(pEvent->mnCode & KEY_MOD1) )
2300         nMode |= MouseEventModifiers::DRAGMOVE;
2301     if ( (pEvent->mnCode & MOUSE_LEFT) && (pEvent->mnCode & KEY_MOD1) )
2302         nMode |= MouseEventModifiers::DRAGCOPY;
2303     return nMode;
2304 }
2305 
ImplGetMouseButtonMode(SalMouseEvent const * pEvent)2306 MouseEventModifiers ImplGetMouseButtonMode( SalMouseEvent const * pEvent )
2307 {
2308     MouseEventModifiers nMode = MouseEventModifiers::NONE;
2309     if ( pEvent->mnButton == MOUSE_LEFT )
2310         nMode |= MouseEventModifiers::SIMPLECLICK;
2311     if ( (pEvent->mnButton == MOUSE_LEFT) && !(pEvent->mnCode & (MOUSE_MIDDLE | MOUSE_RIGHT)) )
2312         nMode |= MouseEventModifiers::SELECT;
2313     if ( (pEvent->mnButton == MOUSE_LEFT) && (pEvent->mnCode & KEY_MOD1) &&
2314          !(pEvent->mnCode & (MOUSE_MIDDLE | MOUSE_RIGHT | KEY_SHIFT)) )
2315         nMode |= MouseEventModifiers::MULTISELECT;
2316     if ( (pEvent->mnButton == MOUSE_LEFT) && (pEvent->mnCode & KEY_SHIFT) &&
2317          !(pEvent->mnCode & (MOUSE_MIDDLE | MOUSE_RIGHT | KEY_MOD1)) )
2318         nMode |= MouseEventModifiers::RANGESELECT;
2319     return nMode;
2320 }
2321 
ImplHandleSalMouseLeave(vcl::Window * pWindow,SalMouseEvent const * pEvent)2322 static bool ImplHandleSalMouseLeave( vcl::Window* pWindow, SalMouseEvent const * pEvent )
2323 {
2324     return ImplHandleMouseEvent( pWindow, NotifyEventType::MOUSEMOVE, true,
2325                                  pEvent->mnX, pEvent->mnY,
2326                                  pEvent->mnTime, pEvent->mnCode,
2327                                  ImplGetMouseMoveMode( pEvent ) );
2328 }
2329 
ImplHandleSalMouseMove(vcl::Window * pWindow,SalMouseEvent const * pEvent)2330 static bool ImplHandleSalMouseMove( vcl::Window* pWindow, SalMouseEvent const * pEvent )
2331 {
2332     return ImplHandleMouseEvent( pWindow, NotifyEventType::MOUSEMOVE, false,
2333                                  pEvent->mnX, pEvent->mnY,
2334                                  pEvent->mnTime, pEvent->mnCode,
2335                                  ImplGetMouseMoveMode( pEvent ) );
2336 }
2337 
ImplHandleSalMouseButtonDown(vcl::Window * pWindow,SalMouseEvent const * pEvent)2338 static bool ImplHandleSalMouseButtonDown( vcl::Window* pWindow, SalMouseEvent const * pEvent )
2339 {
2340     return ImplHandleMouseEvent( pWindow, NotifyEventType::MOUSEBUTTONDOWN, false,
2341                                  pEvent->mnX, pEvent->mnY,
2342                                  pEvent->mnTime,
2343 #ifdef MACOSX
2344                  pEvent->mnButton | (pEvent->mnCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_MOD3)),
2345 #else
2346                                  pEvent->mnButton | (pEvent->mnCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2)),
2347 #endif
2348                                  ImplGetMouseButtonMode( pEvent ) );
2349 }
2350 
ImplHandleSalMouseButtonUp(vcl::Window * pWindow,SalMouseEvent const * pEvent)2351 static bool ImplHandleSalMouseButtonUp( vcl::Window* pWindow, SalMouseEvent const * pEvent )
2352 {
2353     return ImplHandleMouseEvent( pWindow, NotifyEventType::MOUSEBUTTONUP, false,
2354                                  pEvent->mnX, pEvent->mnY,
2355                                  pEvent->mnTime,
2356 #ifdef MACOSX
2357                  pEvent->mnButton | (pEvent->mnCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_MOD3)),
2358 #else
2359                                  pEvent->mnButton | (pEvent->mnCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2)),
2360 #endif
2361                                  ImplGetMouseButtonMode( pEvent ) );
2362 }
2363 
ImplHandleMenuEvent(vcl::Window const * pWindow,SalMenuEvent * pEvent,SalEvent nEvent)2364 static bool ImplHandleMenuEvent( vcl::Window const * pWindow, SalMenuEvent* pEvent, SalEvent nEvent )
2365 {
2366     // Find SystemWindow and its Menubar and let it dispatch the command
2367     bool bRet = false;
2368     vcl::Window *pWin = pWindow->ImplGetWindowImpl()->mpFirstChild;
2369     while ( pWin )
2370     {
2371         if ( pWin->ImplGetWindowImpl()->mbSysWin )
2372             break;
2373         pWin = pWin->ImplGetWindowImpl()->mpNext;
2374     }
2375     if( pWin )
2376     {
2377         MenuBar *pMenuBar = static_cast<SystemWindow*>(pWin)->GetMenuBar();
2378         if( pMenuBar )
2379         {
2380             switch( nEvent )
2381             {
2382                 case SalEvent::MenuActivate:
2383                     pMenuBar->HandleMenuActivateEvent( static_cast<Menu*>(pEvent->mpMenu) );
2384                     bRet = true;
2385                     break;
2386                 case SalEvent::MenuDeactivate:
2387                     pMenuBar->HandleMenuDeActivateEvent( static_cast<Menu*>(pEvent->mpMenu) );
2388                     bRet = true;
2389                     break;
2390                 case SalEvent::MenuHighlight:
2391                     bRet = pMenuBar->HandleMenuHighlightEvent( static_cast<Menu*>(pEvent->mpMenu), pEvent->mnId );
2392                     break;
2393                 case SalEvent::MenuButtonCommand:
2394                     bRet = pMenuBar->HandleMenuButtonEvent( pEvent->mnId );
2395                     break;
2396                 case SalEvent::MenuCommand:
2397                     bRet = pMenuBar->HandleMenuCommandEvent( static_cast<Menu*>(pEvent->mpMenu), pEvent->mnId );
2398                     break;
2399                 default:
2400                     break;
2401             }
2402         }
2403     }
2404     return bRet;
2405 }
2406 
ImplHandleSalKeyMod(vcl::Window * pWindow,SalKeyModEvent const * pEvent)2407 static void ImplHandleSalKeyMod( vcl::Window* pWindow, SalKeyModEvent const * pEvent )
2408 {
2409     ImplSVData* pSVData = ImplGetSVData();
2410     vcl::Window* pTrackWin = pSVData->mpWinData->mpTrackWin;
2411     if ( pTrackWin )
2412         pWindow = pTrackWin;
2413 #ifdef MACOSX
2414     sal_uInt16 nOldCode = pWindow->ImplGetWindowImpl()->mpFrameData->mnMouseCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_MOD3);
2415 #else
2416     sal_uInt16 nOldCode = pWindow->ImplGetWindowImpl()->mpFrameData->mnMouseCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2);
2417 #endif
2418     sal_uInt16 nNewCode = pEvent->mnCode;
2419     if ( nOldCode != nNewCode )
2420     {
2421 #ifdef MACOSX
2422         nNewCode |= pWindow->ImplGetWindowImpl()->mpFrameData->mnMouseCode & ~(KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_MOD3);
2423 #else
2424         nNewCode |= pWindow->ImplGetWindowImpl()->mpFrameData->mnMouseCode & ~(KEY_SHIFT | KEY_MOD1 | KEY_MOD2);
2425 #endif
2426         pWindow->ImplGetWindowImpl()->mpFrameWindow->ImplCallMouseMove( nNewCode, true );
2427     }
2428 
2429     // #105224# send commandevent to allow special treatment of Ctrl-LeftShift/Ctrl-RightShift etc.
2430     // + auto-accelerator feature, tdf#92630
2431 
2432     // try to find a key input window...
2433     vcl::Window* pChild = ImplGetKeyInputWindow( pWindow );
2434     //...otherwise fail safe...
2435     if (!pChild)
2436         pChild = pWindow;
2437 
2438     CommandModKeyData data( pEvent->mnModKeyCode, pEvent->mbDown );
2439     ImplCallCommand( pChild, CommandEventId::ModKeyChange, &data );
2440 }
2441 
ImplHandleInputLanguageChange(vcl::Window * pWindow)2442 static void ImplHandleInputLanguageChange( vcl::Window* pWindow )
2443 {
2444     // find window
2445     vcl::Window* pChild = ImplGetKeyInputWindow( pWindow );
2446     if ( !pChild )
2447         return;
2448 
2449     ImplCallCommand( pChild, CommandEventId::InputLanguageChange );
2450 }
2451 
ImplHandleSalSettings(SalEvent nEvent)2452 static void ImplHandleSalSettings( SalEvent nEvent )
2453 {
2454     Application* pApp = GetpApp();
2455     if ( !pApp )
2456         return;
2457 
2458     if ( nEvent == SalEvent::SettingsChanged )
2459     {
2460         AllSettings aSettings = Application::GetSettings();
2461         Application::MergeSystemSettings( aSettings );
2462         pApp->OverrideSystemSettings( aSettings );
2463         Application::SetSettings( aSettings );
2464     }
2465     else
2466     {
2467         DataChangedEventType nType;
2468         switch ( nEvent )
2469         {
2470             case SalEvent::PrinterChanged:
2471                 ImplDeletePrnQueueList();
2472                 nType = DataChangedEventType::PRINTER;
2473                 break;
2474             case SalEvent::DisplayChanged:
2475                 nType = DataChangedEventType::DISPLAY;
2476                 break;
2477             case SalEvent::FontChanged:
2478                 OutputDevice::ImplUpdateAllFontData( true );
2479                 nType = DataChangedEventType::FONTS;
2480                 break;
2481             default:
2482                 nType = DataChangedEventType::NONE;
2483                 break;
2484         }
2485 
2486         if ( nType != DataChangedEventType::NONE )
2487         {
2488             DataChangedEvent aDCEvt( nType );
2489             Application::ImplCallEventListenersApplicationDataChanged(&aDCEvt);
2490             Application::NotifyAllWindows( aDCEvt );
2491         }
2492     }
2493 }
2494 
ImplHandleSalExtTextInputPos(vcl::Window * pWindow,SalExtTextInputPosEvent * pEvt)2495 static void ImplHandleSalExtTextInputPos( vcl::Window* pWindow, SalExtTextInputPosEvent* pEvt )
2496 {
2497     tools::Rectangle aCursorRect;
2498     ImplHandleExtTextInputPos( pWindow, aCursorRect, pEvt->mnExtWidth, &pEvt->mbVertical );
2499     if ( aCursorRect.IsEmpty() )
2500     {
2501         pEvt->mnX       = -1;
2502         pEvt->mnY       = -1;
2503         pEvt->mnWidth   = -1;
2504         pEvt->mnHeight  = -1;
2505     }
2506     else
2507     {
2508         pEvt->mnX       = aCursorRect.Left();
2509         pEvt->mnY       = aCursorRect.Top();
2510         pEvt->mnWidth   = aCursorRect.GetWidth();
2511         pEvt->mnHeight  = aCursorRect.GetHeight();
2512     }
2513 }
2514 
ImplHandleShowDialog(vcl::Window * pWindow,ShowDialogId nDialogId)2515 static bool ImplHandleShowDialog( vcl::Window* pWindow, ShowDialogId nDialogId )
2516 {
2517     if( ! pWindow )
2518         return false;
2519 
2520     if( pWindow->GetType() == WindowType::BORDERWINDOW )
2521     {
2522         vcl::Window* pWrkWin = pWindow->GetWindow( GetWindowType::Client );
2523         if( pWrkWin )
2524             pWindow = pWrkWin;
2525     }
2526     CommandDialogData aCmdData( nDialogId );
2527     return ImplCallCommand( pWindow, CommandEventId::ShowDialog, &aCmdData );
2528 }
2529 
ImplHandleSurroundingTextRequest(vcl::Window * pWindow,OUString & rText,Selection & rSelRange)2530 static void ImplHandleSurroundingTextRequest( vcl::Window *pWindow,
2531                           OUString& rText,
2532                           Selection &rSelRange )
2533 {
2534     vcl::Window* pChild = ImplGetKeyInputWindow( pWindow );
2535 
2536     if ( !pChild )
2537     {
2538         rText.clear();
2539         rSelRange.setMin( 0 );
2540         rSelRange.setMax( 0 );
2541     }
2542     else
2543     {
2544         rText = pChild->GetSurroundingText();
2545         Selection aSel = pChild->GetSurroundingTextSelection();
2546         rSelRange.setMin( aSel.Min() );
2547         rSelRange.setMax( aSel.Max() );
2548     }
2549 }
2550 
ImplHandleSalSurroundingTextRequest(vcl::Window * pWindow,SalSurroundingTextRequestEvent * pEvt)2551 static void ImplHandleSalSurroundingTextRequest( vcl::Window *pWindow,
2552                          SalSurroundingTextRequestEvent *pEvt )
2553 {
2554     Selection aSelRange;
2555     ImplHandleSurroundingTextRequest( pWindow, pEvt->maText, aSelRange );
2556 
2557     aSelRange.Normalize();
2558 
2559     if( aSelRange.Min() < 0 )
2560         pEvt->mnStart = 0;
2561     else if( aSelRange.Min() > pEvt->maText.getLength() )
2562         pEvt->mnStart = pEvt->maText.getLength();
2563     else
2564         pEvt->mnStart = aSelRange.Min();
2565 
2566     if( aSelRange.Max() < 0 )
2567         pEvt->mnStart = 0;
2568     else if( aSelRange.Max() > pEvt->maText.getLength() )
2569         pEvt->mnEnd = pEvt->maText.getLength();
2570     else
2571         pEvt->mnEnd = aSelRange.Max();
2572 }
2573 
ImplHandleSalDeleteSurroundingTextRequest(vcl::Window * pWindow,SalSurroundingTextSelectionChangeEvent * pEvt)2574 static void ImplHandleSalDeleteSurroundingTextRequest( vcl::Window *pWindow,
2575                          SalSurroundingTextSelectionChangeEvent *pEvt )
2576 {
2577     vcl::Window* pChild = ImplGetKeyInputWindow( pWindow );
2578 
2579     Selection aSelection(pEvt->mnStart, pEvt->mnEnd);
2580     if (pChild && pChild->DeleteSurroundingText(aSelection))
2581     {
2582         pEvt->mnStart = aSelection.Min();
2583         pEvt->mnEnd = aSelection.Max();
2584     }
2585     else
2586     {
2587         pEvt->mnStart = pEvt->mnEnd = SAL_MAX_UINT32;
2588     }
2589 }
2590 
ImplHandleSurroundingTextSelectionChange(vcl::Window * pWindow,sal_uLong nStart,sal_uLong nEnd)2591 static void ImplHandleSurroundingTextSelectionChange( vcl::Window *pWindow,
2592                               sal_uLong nStart,
2593                               sal_uLong nEnd )
2594 {
2595     vcl::Window* pChild = ImplGetKeyInputWindow( pWindow );
2596     if( pChild )
2597     {
2598         CommandSelectionChangeData data( nStart, nEnd );
2599         ImplCallCommand( pChild, CommandEventId::SelectionChange, &data );
2600     }
2601 }
2602 
ImplHandleStartReconversion(vcl::Window * pWindow)2603 static void ImplHandleStartReconversion( vcl::Window *pWindow )
2604 {
2605     vcl::Window* pChild = ImplGetKeyInputWindow( pWindow );
2606     if( pChild )
2607         ImplCallCommand( pChild, CommandEventId::PrepareReconversion );
2608 }
2609 
ImplHandleSalQueryCharPosition(vcl::Window * pWindow,SalQueryCharPositionEvent * pEvt)2610 static void ImplHandleSalQueryCharPosition( vcl::Window *pWindow,
2611                                             SalQueryCharPositionEvent *pEvt )
2612 {
2613     pEvt->mbValid = false;
2614     pEvt->mbVertical = false;
2615     pEvt->maCursorBound = AbsoluteScreenPixelRectangle();
2616 
2617     ImplSVData* pSVData = ImplGetSVData();
2618     vcl::Window* pChild = pSVData->mpWinData->mpExtTextInputWin;
2619 
2620     if ( !pChild )
2621         pChild = ImplGetKeyInputWindow( pWindow );
2622     else
2623     {
2624         // Test, if the Window is related to the frame
2625         if ( !pWindow->ImplIsWindowOrChild( pChild ) )
2626             pChild = ImplGetKeyInputWindow( pWindow );
2627     }
2628 
2629     if( !pChild )
2630         return;
2631 
2632     ImplCallCommand( pChild, CommandEventId::QueryCharPosition );
2633 
2634     ImplWinData* pWinData = pChild->ImplGetWinData();
2635     if ( !(pWinData->mpCompositionCharRects && pEvt->mnCharPos < o3tl::make_unsigned( pWinData->mnCompositionCharRects )) )
2636         return;
2637 
2638     const OutputDevice *pChildOutDev = pChild->GetOutDev();
2639     const tools::Rectangle& aRect = pWinData->mpCompositionCharRects[ pEvt->mnCharPos ];
2640     tools::Rectangle aDeviceRect = pChildOutDev->ImplLogicToDevicePixel( aRect );
2641     AbsoluteScreenPixelPoint aAbsScreenPos = pChild->OutputToAbsoluteScreenPixel( pChild->ScreenToOutputPixel(aDeviceRect.TopLeft()) );
2642     pEvt->maCursorBound = AbsoluteScreenPixelRectangle(aAbsScreenPos, aDeviceRect.GetSize());
2643     pEvt->mbVertical = pWinData->mbVertical;
2644     pEvt->mbValid = true;
2645 }
2646 
ImplWindowFrameProc(vcl::Window * _pWindow,SalEvent nEvent,const void * pEvent)2647 bool ImplWindowFrameProc( vcl::Window* _pWindow, SalEvent nEvent, const void* pEvent )
2648 {
2649     DBG_TESTSOLARMUTEX();
2650 
2651     // Ensure the window survives during this method.
2652     VclPtr<vcl::Window> pWindow( _pWindow );
2653 
2654     bool bRet = false;
2655 
2656     // #119709# for some unknown reason it is possible to receive events (in this case key events)
2657     // although the corresponding VCL window must have been destroyed already
2658     // at least ImplGetWindowImpl() was NULL in these cases, so check this here
2659     if( pWindow->ImplGetWindowImpl() == nullptr )
2660         return false;
2661 
2662     switch ( nEvent )
2663     {
2664         case SalEvent::MouseMove:
2665             bRet = ImplHandleSalMouseMove( pWindow, static_cast<SalMouseEvent const *>(pEvent) );
2666             break;
2667         case SalEvent::ExternalMouseMove:
2668         {
2669             MouseEvent const * pMouseEvt = static_cast<MouseEvent const *>(pEvent);
2670             SalMouseEvent   aSalMouseEvent;
2671 
2672             aSalMouseEvent.mnTime = tools::Time::GetSystemTicks();
2673             aSalMouseEvent.mnX = pMouseEvt->GetPosPixel().X();
2674             aSalMouseEvent.mnY = pMouseEvt->GetPosPixel().Y();
2675             aSalMouseEvent.mnButton = 0;
2676             aSalMouseEvent.mnCode = pMouseEvt->GetButtons() | pMouseEvt->GetModifier();
2677 
2678             bRet = ImplHandleSalMouseMove( pWindow, &aSalMouseEvent );
2679         }
2680         break;
2681         case SalEvent::MouseLeave:
2682             bRet = ImplHandleSalMouseLeave( pWindow, static_cast<SalMouseEvent const *>(pEvent) );
2683             break;
2684         case SalEvent::MouseButtonDown:
2685             bRet = ImplHandleSalMouseButtonDown( pWindow, static_cast<SalMouseEvent const *>(pEvent) );
2686             break;
2687         case SalEvent::ExternalMouseButtonDown:
2688         {
2689             MouseEvent const * pMouseEvt = static_cast<MouseEvent const *>(pEvent);
2690             SalMouseEvent   aSalMouseEvent;
2691 
2692             aSalMouseEvent.mnTime = tools::Time::GetSystemTicks();
2693             aSalMouseEvent.mnX = pMouseEvt->GetPosPixel().X();
2694             aSalMouseEvent.mnY = pMouseEvt->GetPosPixel().Y();
2695             aSalMouseEvent.mnButton = pMouseEvt->GetButtons();
2696             aSalMouseEvent.mnCode = pMouseEvt->GetButtons() | pMouseEvt->GetModifier();
2697 
2698             bRet = ImplHandleSalMouseButtonDown( pWindow, &aSalMouseEvent );
2699         }
2700         break;
2701         case SalEvent::MouseButtonUp:
2702             bRet = ImplHandleSalMouseButtonUp( pWindow, static_cast<SalMouseEvent const *>(pEvent) );
2703             break;
2704         case SalEvent::ExternalMouseButtonUp:
2705         {
2706             MouseEvent const * pMouseEvt = static_cast<MouseEvent const *>(pEvent);
2707             SalMouseEvent   aSalMouseEvent;
2708 
2709             aSalMouseEvent.mnTime = tools::Time::GetSystemTicks();
2710             aSalMouseEvent.mnX = pMouseEvt->GetPosPixel().X();
2711             aSalMouseEvent.mnY = pMouseEvt->GetPosPixel().Y();
2712             aSalMouseEvent.mnButton = pMouseEvt->GetButtons();
2713             aSalMouseEvent.mnCode = pMouseEvt->GetButtons() | pMouseEvt->GetModifier();
2714 
2715             bRet = ImplHandleSalMouseButtonUp( pWindow, &aSalMouseEvent );
2716         }
2717         break;
2718         case SalEvent::MouseActivate:
2719             bRet = false;
2720             break;
2721         case SalEvent::KeyInput:
2722             {
2723             SalKeyEvent const * pKeyEvt = static_cast<SalKeyEvent const *>(pEvent);
2724             bRet = ImplHandleKey( pWindow, NotifyEventType::KEYINPUT,
2725                 pKeyEvt->mnCode, pKeyEvt->mnCharCode, pKeyEvt->mnRepeat, true );
2726             }
2727             break;
2728         case SalEvent::ExternalKeyInput:
2729             {
2730             KeyEvent const * pKeyEvt = static_cast<KeyEvent const *>(pEvent);
2731             bRet = ImplHandleKey( pWindow, NotifyEventType::KEYINPUT,
2732                 pKeyEvt->GetKeyCode().GetFullCode(), pKeyEvt->GetCharCode(), pKeyEvt->GetRepeat(), false );
2733             }
2734             break;
2735         case SalEvent::KeyUp:
2736             {
2737             SalKeyEvent const * pKeyEvt = static_cast<SalKeyEvent const *>(pEvent);
2738             bRet = ImplHandleKey( pWindow, NotifyEventType::KEYUP,
2739                 pKeyEvt->mnCode, pKeyEvt->mnCharCode, pKeyEvt->mnRepeat, true );
2740             }
2741             break;
2742         case SalEvent::ExternalKeyUp:
2743             {
2744             KeyEvent const * pKeyEvt = static_cast<KeyEvent const *>(pEvent);
2745             bRet = ImplHandleKey( pWindow, NotifyEventType::KEYUP,
2746                 pKeyEvt->GetKeyCode().GetFullCode(), pKeyEvt->GetCharCode(), pKeyEvt->GetRepeat(), false );
2747             }
2748             break;
2749         case SalEvent::KeyModChange:
2750             ImplHandleSalKeyMod( pWindow, static_cast<SalKeyModEvent const *>(pEvent) );
2751             break;
2752 
2753         case SalEvent::InputLanguageChange:
2754             ImplHandleInputLanguageChange( pWindow );
2755             break;
2756 
2757         case SalEvent::MenuActivate:
2758         case SalEvent::MenuDeactivate:
2759         case SalEvent::MenuHighlight:
2760         case SalEvent::MenuCommand:
2761         case SalEvent::MenuButtonCommand:
2762             bRet = ImplHandleMenuEvent( pWindow, const_cast<SalMenuEvent *>(static_cast<SalMenuEvent const *>(pEvent)), nEvent );
2763             break;
2764 
2765         case SalEvent::WheelMouse:
2766             bRet = ImplHandleWheelEvent( pWindow, *static_cast<const SalWheelMouseEvent*>(pEvent));
2767             break;
2768 
2769         case SalEvent::Paint:
2770             {
2771             SalPaintEvent const * pPaintEvt = static_cast<SalPaintEvent const *>(pEvent);
2772 
2773             if( AllSettings::GetLayoutRTL() )
2774             {
2775                 SalFrame* pSalFrame = pWindow->ImplGetWindowImpl()->mpFrame;
2776                 const_cast<SalPaintEvent *>(pPaintEvt)->mnBoundX = pSalFrame->maGeometry.width() - pPaintEvt->mnBoundWidth - pPaintEvt->mnBoundX;
2777             }
2778 
2779             tools::Rectangle aBoundRect( Point( pPaintEvt->mnBoundX, pPaintEvt->mnBoundY ),
2780                                   Size( pPaintEvt->mnBoundWidth, pPaintEvt->mnBoundHeight ) );
2781             ImplHandlePaint( pWindow, aBoundRect, pPaintEvt->mbImmediateUpdate );
2782             }
2783             break;
2784 
2785         case SalEvent::Move:
2786             ImplHandleMove( pWindow );
2787             break;
2788 
2789         case SalEvent::Resize:
2790             {
2791             tools::Long nNewWidth;
2792             tools::Long nNewHeight;
2793             pWindow->ImplGetWindowImpl()->mpFrame->GetClientSize( nNewWidth, nNewHeight );
2794             ImplHandleResize( pWindow, nNewWidth, nNewHeight );
2795             }
2796             break;
2797 
2798         case SalEvent::MoveResize:
2799             {
2800             SalFrameGeometry g = pWindow->ImplGetWindowImpl()->mpFrame->GetGeometry();
2801             ImplHandleMoveResize(pWindow, g.width(), g.height());
2802             }
2803             break;
2804 
2805         case SalEvent::ClosePopups:
2806             {
2807             KillOwnPopups( pWindow );
2808             }
2809             break;
2810 
2811         case SalEvent::GetFocus:
2812             ImplHandleGetFocus( pWindow );
2813             break;
2814         case SalEvent::LoseFocus:
2815             ImplHandleLoseFocus( pWindow );
2816             break;
2817 
2818         case SalEvent::Close:
2819             ImplHandleClose( pWindow );
2820             break;
2821 
2822         case SalEvent::Shutdown:
2823             {
2824                 static bool bInQueryExit = false;
2825                 if( !bInQueryExit )
2826                 {
2827                     bInQueryExit = true;
2828                     if ( GetpApp()->QueryExit() )
2829                     {
2830                         // end the message loop
2831                         Application::Quit();
2832                         return false;
2833                     }
2834                     else
2835                     {
2836                         bInQueryExit = false;
2837                         return true;
2838                     }
2839                 }
2840                 return false;
2841             }
2842 
2843         case SalEvent::SettingsChanged:
2844         case SalEvent::PrinterChanged:
2845         case SalEvent::DisplayChanged:
2846         case SalEvent::FontChanged:
2847             ImplHandleSalSettings( nEvent );
2848             break;
2849 
2850         case SalEvent::UserEvent:
2851             ImplHandleUserEvent( const_cast<ImplSVEvent *>(static_cast<ImplSVEvent const *>(pEvent)) );
2852             break;
2853 
2854         case SalEvent::ExtTextInput:
2855             {
2856             SalExtTextInputEvent const * pEvt = static_cast<SalExtTextInputEvent const *>(pEvent);
2857             bRet = ImplHandleExtTextInput( pWindow,
2858                                            pEvt->maText, pEvt->mpTextAttr,
2859                                            pEvt->mnCursorPos, pEvt->mnCursorFlags );
2860             }
2861             break;
2862         case SalEvent::EndExtTextInput:
2863             bRet = ImplHandleEndExtTextInput();
2864             break;
2865         case SalEvent::ExtTextInputPos:
2866             ImplHandleSalExtTextInputPos( pWindow, const_cast<SalExtTextInputPosEvent *>(static_cast<SalExtTextInputPosEvent const *>(pEvent)) );
2867             break;
2868         case SalEvent::InputContextChange:
2869             bRet = ImplHandleInputContextChange( pWindow );
2870             break;
2871         case SalEvent::ShowDialog:
2872             {
2873                 ShowDialogId nLOKWindowId = static_cast<ShowDialogId>(reinterpret_cast<sal_IntPtr>(pEvent));
2874                 bRet = ImplHandleShowDialog( pWindow, nLOKWindowId );
2875             }
2876             break;
2877         case SalEvent::SurroundingTextRequest:
2878             ImplHandleSalSurroundingTextRequest( pWindow, const_cast<SalSurroundingTextRequestEvent *>(static_cast<SalSurroundingTextRequestEvent const *>(pEvent)) );
2879             break;
2880         case SalEvent::DeleteSurroundingTextRequest:
2881             ImplHandleSalDeleteSurroundingTextRequest( pWindow, const_cast<SalSurroundingTextSelectionChangeEvent *>(static_cast<SalSurroundingTextSelectionChangeEvent const *>(pEvent)) );
2882             break;
2883         case SalEvent::SurroundingTextSelectionChange:
2884         {
2885             SalSurroundingTextSelectionChangeEvent const * pEvt
2886              = static_cast<SalSurroundingTextSelectionChangeEvent const *>(pEvent);
2887             ImplHandleSurroundingTextSelectionChange( pWindow,
2888                               pEvt->mnStart,
2889                               pEvt->mnEnd );
2890             [[fallthrough]]; // TODO: Fallthrough really intended?
2891         }
2892         case SalEvent::StartReconversion:
2893             ImplHandleStartReconversion( pWindow );
2894             break;
2895 
2896         case SalEvent::QueryCharPosition:
2897             ImplHandleSalQueryCharPosition( pWindow, const_cast<SalQueryCharPositionEvent *>(static_cast<SalQueryCharPositionEvent const *>(pEvent)) );
2898             break;
2899 
2900         case SalEvent::GestureSwipe:
2901             bRet = ImplHandleSwipe(pWindow, *static_cast<const SalGestureSwipeEvent*>(pEvent));
2902             break;
2903 
2904         case SalEvent::GestureLongPress:
2905             bRet = ImplHandleLongPress(pWindow, *static_cast<const SalGestureLongPressEvent*>(pEvent));
2906             break;
2907 
2908         case SalEvent::ExternalGesture:
2909         {
2910             auto const * pGestureEvent = static_cast<GestureEventPan const *>(pEvent);
2911 
2912             SalGestureEvent aSalGestureEvent;
2913             aSalGestureEvent.mfOffset = pGestureEvent->mnOffset;
2914             aSalGestureEvent.mnX = pGestureEvent->mnX;
2915             aSalGestureEvent.mnY = pGestureEvent->mnY;
2916             aSalGestureEvent.meEventType = pGestureEvent->meEventType;
2917             aSalGestureEvent.meOrientation = pGestureEvent->meOrientation;
2918 
2919             bRet = ImplHandleGestureEvent(pWindow, aSalGestureEvent);
2920         }
2921         break;
2922         case SalEvent::GesturePan:
2923         {
2924             auto const * aSalGestureEvent = static_cast<SalGestureEvent const *>(pEvent);
2925             bRet = ImplHandleGestureEvent(pWindow, *aSalGestureEvent);
2926         }
2927         break;
2928         case SalEvent::GestureZoom:
2929         {
2930             const auto * pGestureEvent = static_cast<SalGestureZoomEvent const *>(pEvent);
2931             bRet = ImplHandleGestureZoomEvent(pWindow, *pGestureEvent);
2932         }
2933         break;
2934         case SalEvent::GestureRotate:
2935         {
2936             const auto * pGestureEvent = static_cast<SalGestureRotateEvent const *>(pEvent);
2937             bRet = ImplHandleGestureRotateEvent(pWindow, *pGestureEvent);
2938         }
2939         break;
2940         default:
2941             SAL_WARN( "vcl.layout", "ImplWindowFrameProc(): unknown event (" << static_cast<int>(nEvent) << ")" );
2942             break;
2943     }
2944 
2945     return bRet;
2946 }
2947 
2948 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
2949