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