bump product version to 6.4.0.3
[LibreOffice.git] / vcl / source / window / winproc.cxx
blob424b8b6cdbfa4dd0f2e554db463f603b0f724e44
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <tools/debug.hxx>
21 #include <tools/time.hxx>
22 #include <sal/log.hxx>
24 #include <unotools/localedatawrapper.hxx>
26 #include <comphelper/lok.hxx>
27 #include <vcl/timer.hxx>
28 #include <vcl/event.hxx>
29 #include <vcl/GestureEvent.hxx>
30 #include <vcl/settings.hxx>
31 #include <vcl/svapp.hxx>
32 #include <vcl/cursor.hxx>
33 #include <vcl/wrkwin.hxx>
34 #include <vcl/floatwin.hxx>
35 #include <vcl/dialog.hxx>
36 #include <vcl/help.hxx>
37 #include <vcl/dockwin.hxx>
38 #include <vcl/menu.hxx>
39 #include <vcl/virdev.hxx>
40 #include <vcl/uitest/logger.hxx>
41 #include <vcl/ptrstyle.hxx>
43 #include <svdata.hxx>
44 #include <salwtype.hxx>
45 #include <salframe.hxx>
46 #include <accmgr.hxx>
47 #include <print.h>
48 #include <window.h>
49 #include <helpwin.hxx>
50 #include <brdwin.hxx>
51 #include <dndlistenercontainer.hxx>
53 #include <com/sun/star/datatransfer/dnd/XDragSource.hpp>
54 #include <com/sun/star/awt/MouseEvent.hpp>
56 #define IMPL_MIN_NEEDSYSWIN 49
58 bool ImplCallPreNotify( NotifyEvent& rEvt )
60 return rEvt.GetWindow()->CompatPreNotify( rEvt );
63 static bool ImplHandleMouseFloatMode( vcl::Window* pChild, const Point& rMousePos,
64 sal_uInt16 nCode, MouseNotifyEvent nSVEvent,
65 bool bMouseLeave )
67 ImplSVData* pSVData = ImplGetSVData();
69 if ( pSVData->maWinData.mpFirstFloat && !pSVData->maWinData.mpCaptureWin &&
70 !pSVData->maWinData.mpFirstFloat->ImplIsFloatPopupModeWindow( pChild ) )
73 * #93895# since floats are system windows, coordinates have
74 * to be converted to float relative for the hittest
76 bool bHitTestInsideRect = false;
77 FloatingWindow* pFloat = pSVData->maWinData.mpFirstFloat->ImplFloatHitTest( pChild, rMousePos, bHitTestInsideRect );
78 FloatingWindow* pLastLevelFloat;
79 FloatWinPopupFlags nPopupFlags;
80 if ( nSVEvent == MouseNotifyEvent::MOUSEMOVE )
82 if ( bMouseLeave )
83 return true;
85 if ( !pFloat || bHitTestInsideRect )
87 if ( pSVData->maHelpData.mpHelpWin && !pSVData->maHelpData.mbKeyboardHelp )
88 ImplDestroyHelpWindow( true );
89 pChild->ImplGetFrame()->SetPointer( PointerStyle::Arrow );
90 return true;
93 else
95 if ( nCode & MOUSE_LEFT )
97 if ( nSVEvent == MouseNotifyEvent::MOUSEBUTTONDOWN )
99 if ( !pFloat )
101 pLastLevelFloat = pSVData->maWinData.mpFirstFloat->ImplFindLastLevelFloat();
102 pLastLevelFloat->EndPopupMode( FloatWinPopupEndFlags::Cancel | FloatWinPopupEndFlags::CloseAll );
103 return true;
105 else if ( bHitTestInsideRect )
107 pFloat->ImplSetMouseDown();
108 return true;
111 else
113 if ( pFloat )
115 if ( bHitTestInsideRect )
117 if ( pFloat->ImplIsMouseDown() )
118 pFloat->EndPopupMode( FloatWinPopupEndFlags::Cancel );
119 return true;
122 else
124 pLastLevelFloat = pSVData->maWinData.mpFirstFloat->ImplFindLastLevelFloat();
125 nPopupFlags = pLastLevelFloat->GetPopupModeFlags();
126 if ( !(nPopupFlags & FloatWinPopupFlags::NoMouseUpClose) )
128 pLastLevelFloat->EndPopupMode( FloatWinPopupEndFlags::Cancel | FloatWinPopupEndFlags::CloseAll );
129 return true;
134 else
136 if ( !pFloat )
138 pLastLevelFloat = pSVData->maWinData.mpFirstFloat->ImplFindLastLevelFloat();
139 nPopupFlags = pLastLevelFloat->GetPopupModeFlags();
140 if ( nPopupFlags & FloatWinPopupFlags::AllMouseButtonClose )
142 if ( (nPopupFlags & FloatWinPopupFlags::NoMouseUpClose) &&
143 (nSVEvent == MouseNotifyEvent::MOUSEBUTTONUP) )
144 return true;
145 pLastLevelFloat->EndPopupMode( FloatWinPopupEndFlags::Cancel | FloatWinPopupEndFlags::CloseAll );
146 return true;
148 else
149 return true;
155 return false;
158 static void ImplHandleMouseHelpRequest( vcl::Window* pChild, const Point& rMousePos )
160 if (comphelper::LibreOfficeKit::isActive())
161 return;
163 ImplSVData* pSVData = ImplGetSVData();
164 if ( !pSVData->maHelpData.mpHelpWin ||
165 !( pSVData->maHelpData.mpHelpWin->IsWindowOrChild( pChild ) ||
166 pChild->IsWindowOrChild( pSVData->maHelpData.mpHelpWin ) ) )
168 HelpEventMode nHelpMode = HelpEventMode::NONE;
169 if ( pSVData->maHelpData.mbQuickHelp )
170 nHelpMode = HelpEventMode::QUICK;
171 if ( pSVData->maHelpData.mbBalloonHelp )
172 nHelpMode |= HelpEventMode::BALLOON;
173 if ( bool(nHelpMode) )
175 if ( pChild->IsInputEnabled() && !pChild->IsInModalMode() )
177 HelpEvent aHelpEvent( rMousePos, nHelpMode );
178 pSVData->maHelpData.mbRequestingHelp = true;
179 pChild->RequestHelp( aHelpEvent );
180 pSVData->maHelpData.mbRequestingHelp = false;
182 // #104172# do not kill keyboard activated tooltips
183 else if ( pSVData->maHelpData.mpHelpWin && !pSVData->maHelpData.mbKeyboardHelp)
185 ImplDestroyHelpWindow( true );
191 static void ImplSetMousePointer( vcl::Window const * pChild )
193 ImplSVData* pSVData = ImplGetSVData();
194 if ( pSVData->maHelpData.mbExtHelpMode )
195 pChild->ImplGetFrame()->SetPointer( PointerStyle::Help );
196 else
197 pChild->ImplGetFrame()->SetPointer( pChild->ImplGetMousePointer() );
200 static bool ImplCallCommand( const VclPtr<vcl::Window>& pChild, CommandEventId nEvt, void const * pData = nullptr,
201 bool bMouse = false, Point const * pPos = nullptr )
203 Point aPos;
204 if ( pPos )
205 aPos = *pPos;
206 else
208 if( bMouse )
209 aPos = pChild->GetPointerPosPixel();
210 else
212 // simulate mouseposition at center of window
213 Size aSize( pChild->GetOutputSizePixel() );
214 aPos = Point( aSize.getWidth()/2, aSize.getHeight()/2 );
218 CommandEvent aCEvt( aPos, nEvt, bMouse, pData );
219 NotifyEvent aNCmdEvt( MouseNotifyEvent::COMMAND, pChild, &aCEvt );
220 bool bPreNotify = ImplCallPreNotify( aNCmdEvt );
221 if ( pChild->IsDisposed() )
222 return false;
223 if ( !bPreNotify )
225 pChild->ImplGetWindowImpl()->mbCommand = false;
226 pChild->Command( aCEvt );
228 if( pChild->IsDisposed() )
229 return false;
230 pChild->ImplNotifyKeyMouseCommandEventListeners( aNCmdEvt );
231 if ( pChild->IsDisposed() )
232 return false;
233 if ( pChild->ImplGetWindowImpl()->mbCommand )
234 return true;
237 return false;
240 /* #i34277# delayed context menu activation;
241 * necessary if there already was a popup menu running.
244 struct ContextMenuEvent
246 VclPtr<vcl::Window> pWindow;
247 Point aChildPos;
250 static void ContextMenuEventLink( void* pCEvent, void* )
252 ContextMenuEvent* pEv = static_cast<ContextMenuEvent*>(pCEvent);
254 if( ! pEv->pWindow->IsDisposed() )
256 ImplCallCommand( pEv->pWindow, CommandEventId::ContextMenu, nullptr, true, &pEv->aChildPos );
258 delete pEv;
261 bool ImplHandleMouseEvent( const VclPtr<vcl::Window>& xWindow, MouseNotifyEvent nSVEvent, bool bMouseLeave,
262 long nX, long nY, sal_uInt64 nMsgTime,
263 sal_uInt16 nCode, MouseEventModifiers nMode )
265 ImplSVData* pSVData = ImplGetSVData();
266 Point aMousePos( nX, nY );
267 VclPtr<vcl::Window> pChild;
268 bool bRet(false);
269 sal_uInt16 nClicks(0);
270 ImplFrameData* pWinFrameData = xWindow->ImplGetFrameData();
271 sal_uInt16 nOldCode = pWinFrameData->mnMouseCode;
273 // we need a mousemove event, before we get a mousebuttondown or a
274 // mousebuttonup event
275 if ( (nSVEvent == MouseNotifyEvent::MOUSEBUTTONDOWN) || (nSVEvent == MouseNotifyEvent::MOUSEBUTTONUP) )
277 if ( (nSVEvent == MouseNotifyEvent::MOUSEBUTTONUP) && pSVData->maHelpData.mbExtHelpMode )
278 Help::EndExtHelp();
279 if ( pSVData->maHelpData.mpHelpWin )
281 if( xWindow->ImplGetWindow() == pSVData->maHelpData.mpHelpWin )
283 ImplDestroyHelpWindow( false );
284 return true; // xWindow is dead now - avoid crash!
286 else
287 ImplDestroyHelpWindow( true );
290 if ( (pWinFrameData->mnLastMouseX != nX) ||
291 (pWinFrameData->mnLastMouseY != nY) )
293 sal_uInt16 nMoveCode = nCode & ~(MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE);
294 ImplHandleMouseEvent(xWindow, MouseNotifyEvent::MOUSEMOVE, false, nX, nY, nMsgTime, nMoveCode, nMode);
298 // update frame data
299 pWinFrameData->mnBeforeLastMouseX = pWinFrameData->mnLastMouseX;
300 pWinFrameData->mnBeforeLastMouseY = pWinFrameData->mnLastMouseY;
301 pWinFrameData->mnLastMouseX = nX;
302 pWinFrameData->mnLastMouseY = nY;
303 pWinFrameData->mnMouseCode = nCode;
304 MouseEventModifiers const nTmpMask = MouseEventModifiers::SYNTHETIC | MouseEventModifiers::MODIFIERCHANGED;
305 pWinFrameData->mnMouseMode = nMode & ~nTmpMask;
306 if ( bMouseLeave )
308 pWinFrameData->mbMouseIn = false;
309 if ( pSVData->maHelpData.mpHelpWin && !pSVData->maHelpData.mbKeyboardHelp )
311 ImplDestroyHelpWindow( true );
313 if ( xWindow->IsDisposed() )
314 return true; // xWindow is dead now - avoid crash! (#122045#)
317 else
318 pWinFrameData->mbMouseIn = true;
320 DBG_ASSERT( !pSVData->maWinData.mpTrackWin ||
321 (pSVData->maWinData.mpTrackWin == pSVData->maWinData.mpCaptureWin),
322 "ImplHandleMouseEvent: TrackWin != CaptureWin" );
324 // AutoScrollMode
325 if ( pSVData->maWinData.mpAutoScrollWin && (nSVEvent == MouseNotifyEvent::MOUSEBUTTONDOWN) )
327 pSVData->maWinData.mpAutoScrollWin->EndAutoScroll();
328 return true;
331 // find mouse window
332 if ( pSVData->maWinData.mpCaptureWin )
334 pChild = pSVData->maWinData.mpCaptureWin;
336 SAL_WARN_IF( xWindow != pChild->ImplGetFrameWindow(), "vcl",
337 "ImplHandleMouseEvent: mouse event is not sent to capture window" );
339 // java client cannot capture mouse correctly
340 if ( xWindow != pChild->ImplGetFrameWindow() )
341 return false;
343 if ( bMouseLeave )
344 return false;
346 else
348 if ( bMouseLeave )
349 pChild = nullptr;
350 else
351 pChild = xWindow->ImplFindWindow( aMousePos );
354 // test this because mouse events are buffered in the remote version
355 // and size may not be in sync
356 if ( !pChild && !bMouseLeave )
357 return false;
359 // execute a few tests and catch the message or implement the status
360 if ( pChild )
362 if( pChild->ImplIsAntiparallel() )
364 // re-mirror frame pos at pChild
365 const OutputDevice *pChildWinOutDev = pChild->GetOutDev();
366 pChildWinOutDev->ReMirror( aMousePos );
369 // no mouse messages to disabled windows
370 // #106845# if the window was disabled during capturing we have to pass the mouse events to release capturing
371 if ( pSVData->maWinData.mpCaptureWin.get() != pChild && (!pChild->IsEnabled() || !pChild->IsInputEnabled() || pChild->IsInModalMode() ) )
373 ImplHandleMouseFloatMode( pChild, aMousePos, nCode, nSVEvent, bMouseLeave );
374 if ( nSVEvent == MouseNotifyEvent::MOUSEMOVE )
376 ImplHandleMouseHelpRequest( pChild, aMousePos );
377 if( pWinFrameData->mpMouseMoveWin.get() != pChild )
378 nMode |= MouseEventModifiers::ENTERWINDOW;
381 // Call the hook also, if Window is disabled
382 Point aChildPos = pChild->ImplFrameToOutput( aMousePos );
383 MouseEvent aMEvt( aChildPos, pWinFrameData->mnClickCount, nMode, nCode, nCode );
384 NotifyEvent aNEvt( nSVEvent, pChild, &aMEvt );
386 if( pChild->IsCallHandlersOnInputDisabled() )
388 pWinFrameData->mpMouseMoveWin = pChild;
389 pChild->ImplNotifyKeyMouseCommandEventListeners( aNEvt );
392 if ( nSVEvent == MouseNotifyEvent::MOUSEBUTTONDOWN )
393 return true;
394 else
396 // Set normal MousePointer for disabled windows
397 if ( nSVEvent == MouseNotifyEvent::MOUSEMOVE )
398 ImplSetMousePointer( pChild );
400 return false;
404 // End ExtTextInput-Mode, if the user click in the same TopLevel Window
405 if ( pSVData->maWinData.mpExtTextInputWin &&
406 ((nSVEvent == MouseNotifyEvent::MOUSEBUTTONDOWN) ||
407 (nSVEvent == MouseNotifyEvent::MOUSEBUTTONUP)) )
408 pSVData->maWinData.mpExtTextInputWin->EndExtTextInput();
411 // determine mouse event data
412 if ( nSVEvent == MouseNotifyEvent::MOUSEMOVE )
414 // check if MouseMove belongs to same window and if the
415 // status did not change
416 if ( pChild )
418 Point aChildMousePos = pChild->ImplFrameToOutput( aMousePos );
419 if ( !bMouseLeave &&
420 (pChild == pWinFrameData->mpMouseMoveWin) &&
421 (aChildMousePos.X() == pWinFrameData->mnLastMouseWinX) &&
422 (aChildMousePos.Y() == pWinFrameData->mnLastMouseWinY) &&
423 (nOldCode == pWinFrameData->mnMouseCode) )
425 // set mouse pointer anew, as it could have changed
426 // due to the mode switch
427 ImplSetMousePointer( pChild );
428 return false;
431 pWinFrameData->mnLastMouseWinX = aChildMousePos.X();
432 pWinFrameData->mnLastMouseWinY = aChildMousePos.Y();
435 // mouse click
436 nClicks = pWinFrameData->mnClickCount;
438 // call Start-Drag handler if required
439 // Warning: should be called before Move, as otherwise during
440 // fast mouse movements the applications move to the selection state
441 vcl::Window* pMouseDownWin = pWinFrameData->mpMouseDownWin;
442 if ( pMouseDownWin )
444 // check for matching StartDrag mode. We only compare
445 // the status of the mouse buttons, such that e. g. Mod1 can
446 // change immediately to the copy mode
447 const MouseSettings& rMSettings = pMouseDownWin->GetSettings().GetMouseSettings();
448 if ( (nCode & (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE)) ==
449 (MouseSettings::GetStartDragCode() & (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE)) )
451 if ( !pMouseDownWin->ImplGetFrameData()->mbStartDragCalled )
453 long nDragW = rMSettings.GetStartDragWidth();
454 long nDragH = rMSettings.GetStartDragHeight();
455 //long nMouseX = nX;
456 //long nMouseY = nY;
457 long nMouseX = aMousePos.X(); // #106074# use the possibly re-mirrored coordinates (RTL) ! nX,nY are unmodified !
458 long nMouseY = aMousePos.Y();
459 if ( !(((nMouseX-nDragW) <= pMouseDownWin->ImplGetFrameData()->mnFirstMouseX) &&
460 ((nMouseX+nDragW) >= pMouseDownWin->ImplGetFrameData()->mnFirstMouseX)) ||
461 !(((nMouseY-nDragH) <= pMouseDownWin->ImplGetFrameData()->mnFirstMouseY) &&
462 ((nMouseY+nDragH) >= pMouseDownWin->ImplGetFrameData()->mnFirstMouseY)) )
464 pMouseDownWin->ImplGetFrameData()->mbStartDragCalled = true;
466 // Check if drag source provides its own recognizer
467 if( pMouseDownWin->ImplGetFrameData()->mbInternalDragGestureRecognizer )
469 // query DropTarget from child window
470 css::uno::Reference< css::datatransfer::dnd::XDragGestureRecognizer > xDragGestureRecognizer(
471 pMouseDownWin->ImplGetWindowImpl()->mxDNDListenerContainer,
472 css::uno::UNO_QUERY );
474 if( xDragGestureRecognizer.is() )
476 // retrieve mouse position relative to mouse down window
477 Point relLoc = pMouseDownWin->ImplFrameToOutput( Point(
478 pMouseDownWin->ImplGetFrameData()->mnFirstMouseX,
479 pMouseDownWin->ImplGetFrameData()->mnFirstMouseY ) );
481 // create a UNO mouse event out of the available data
482 css::awt::MouseEvent aMouseEvent( static_cast < css::uno::XInterface * > ( nullptr ),
483 #ifdef MACOSX
484 nCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_MOD3),
485 #else
486 nCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2),
487 #endif
488 nCode & (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE),
489 nMouseX,
490 nMouseY,
491 nClicks,
492 false );
494 SolarMutexReleaser aReleaser;
496 // FIXME: where do I get Action from ?
497 css::uno::Reference< css::datatransfer::dnd::XDragSource > xDragSource = pMouseDownWin->GetDragSource();
499 if( xDragSource.is() )
501 static_cast < DNDListenerContainer * > ( xDragGestureRecognizer.get() )->fireDragGestureEvent( 0,
502 relLoc.X(), relLoc.Y(), xDragSource, css::uno::makeAny( aMouseEvent ) );
509 else
510 pMouseDownWin->ImplGetFrameData()->mbStartDragCalled = true;
513 // test for mouseleave and mouseenter
514 VclPtr<vcl::Window> pMouseMoveWin = pWinFrameData->mpMouseMoveWin;
515 if ( pChild != pMouseMoveWin )
517 if ( pMouseMoveWin )
519 Point aLeaveMousePos = pMouseMoveWin->ImplFrameToOutput( aMousePos );
520 MouseEvent aMLeaveEvt( aLeaveMousePos, nClicks, nMode | MouseEventModifiers::LEAVEWINDOW, nCode, nCode );
521 NotifyEvent aNLeaveEvt( MouseNotifyEvent::MOUSEMOVE, pMouseMoveWin, &aMLeaveEvt );
522 pWinFrameData->mbInMouseMove = true;
523 pMouseMoveWin->ImplGetWinData()->mbMouseOver = false;
525 // A MouseLeave can destroy this window
526 if ( !ImplCallPreNotify( aNLeaveEvt ) )
528 pMouseMoveWin->MouseMove( aMLeaveEvt );
529 if( !pMouseMoveWin->IsDisposed() )
530 aNLeaveEvt.GetWindow()->ImplNotifyKeyMouseCommandEventListeners( aNLeaveEvt );
533 pWinFrameData->mpMouseMoveWin = nullptr;
534 pWinFrameData->mbInMouseMove = false;
536 if ( pChild && pChild->IsDisposed() )
537 pChild = nullptr;
538 if ( pMouseMoveWin->IsDisposed() )
539 return true;
542 nMode |= MouseEventModifiers::ENTERWINDOW;
544 pWinFrameData->mpMouseMoveWin = pChild;
545 if( pChild )
546 pChild->ImplGetWinData()->mbMouseOver = true;
548 // MouseLeave
549 if ( !pChild )
550 return false;
552 else
554 if (pChild)
556 // mouse click
557 if ( nSVEvent == MouseNotifyEvent::MOUSEBUTTONDOWN )
559 const MouseSettings& rMSettings = pChild->GetSettings().GetMouseSettings();
560 sal_uInt64 nDblClkTime = rMSettings.GetDoubleClickTime();
561 long nDblClkW = rMSettings.GetDoubleClickWidth();
562 long nDblClkH = rMSettings.GetDoubleClickHeight();
563 //long nMouseX = nX;
564 //long nMouseY = nY;
565 long nMouseX = aMousePos.X(); // #106074# use the possibly re-mirrored coordinates (RTL) ! nX,nY are unmodified !
566 long nMouseY = aMousePos.Y();
568 if ( (pChild == pChild->ImplGetFrameData()->mpMouseDownWin) &&
569 (nCode == pChild->ImplGetFrameData()->mnFirstMouseCode) &&
570 ((nMsgTime-pChild->ImplGetFrameData()->mnMouseDownTime) < nDblClkTime) &&
571 ((nMouseX-nDblClkW) <= pChild->ImplGetFrameData()->mnFirstMouseX) &&
572 ((nMouseX+nDblClkW) >= pChild->ImplGetFrameData()->mnFirstMouseX) &&
573 ((nMouseY-nDblClkH) <= pChild->ImplGetFrameData()->mnFirstMouseY) &&
574 ((nMouseY+nDblClkH) >= pChild->ImplGetFrameData()->mnFirstMouseY) )
576 pChild->ImplGetFrameData()->mnClickCount++;
577 pChild->ImplGetFrameData()->mbStartDragCalled = true;
579 else
581 pChild->ImplGetFrameData()->mpMouseDownWin = pChild;
582 pChild->ImplGetFrameData()->mnClickCount = 1;
583 pChild->ImplGetFrameData()->mnFirstMouseX = nMouseX;
584 pChild->ImplGetFrameData()->mnFirstMouseY = nMouseY;
585 pChild->ImplGetFrameData()->mnFirstMouseCode = nCode;
586 pChild->ImplGetFrameData()->mbStartDragCalled = (nCode & (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE)) !=
587 (MouseSettings::GetStartDragCode() & (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE));
589 pChild->ImplGetFrameData()->mnMouseDownTime = nMsgTime;
591 nClicks = pChild->ImplGetFrameData()->mnClickCount;
594 pSVData->maAppData.mnLastInputTime = tools::Time::GetSystemTicks();
597 SAL_WARN_IF( !pChild, "vcl", "ImplHandleMouseEvent: pChild == NULL" );
599 if (!pChild)
600 return false;
602 // create mouse event
603 Point aChildPos = pChild->ImplFrameToOutput( aMousePos );
604 MouseEvent aMEvt( aChildPos, nClicks, nMode, nCode, nCode );
607 // tracking window gets the mouse events
608 if ( pSVData->maWinData.mpTrackWin )
609 pChild = pSVData->maWinData.mpTrackWin;
611 // handle FloatingMode
612 if ( !pSVData->maWinData.mpTrackWin && pSVData->maWinData.mpFirstFloat )
614 if ( ImplHandleMouseFloatMode( pChild, aMousePos, nCode, nSVEvent, bMouseLeave ) )
616 if ( !pChild->IsDisposed() )
618 pChild->ImplGetFrameData()->mbStartDragCalled = true;
620 return true;
624 // call handler
625 bool bCallHelpRequest = true;
626 SAL_WARN_IF( !pChild, "vcl", "ImplHandleMouseEvent: pChild is NULL" );
628 if (!pChild)
629 return false;
631 NotifyEvent aNEvt( nSVEvent, pChild, &aMEvt );
632 if ( nSVEvent == MouseNotifyEvent::MOUSEMOVE )
633 pChild->ImplGetFrameData()->mbInMouseMove = true;
635 // bring window into foreground on mouseclick
636 if ( nSVEvent == MouseNotifyEvent::MOUSEBUTTONDOWN )
638 if( !pSVData->maWinData.mpFirstFloat && // totop for floating windows in popup would change the focus and would close them immediately
639 !(pChild->ImplGetFrameWindow()->GetStyle() & WB_OWNERDRAWDECORATION) ) // ownerdrawdecorated windows must never grab focus
640 pChild->ToTop();
641 if ( pChild->IsDisposed() )
642 return true;
645 if ( ImplCallPreNotify( aNEvt ) || pChild->IsDisposed() )
646 bRet = true;
647 else
649 bRet = false;
650 if ( nSVEvent == MouseNotifyEvent::MOUSEMOVE )
652 if ( pSVData->maWinData.mpTrackWin )
654 TrackingEvent aTEvt( aMEvt );
655 pChild->Tracking( aTEvt );
656 if ( !pChild->IsDisposed() )
658 // When ScrollRepeat, we restart the timer
659 if ( pSVData->maWinData.mpTrackTimer &&
660 (pSVData->maWinData.mnTrackFlags & StartTrackingFlags::ScrollRepeat) )
661 pSVData->maWinData.mpTrackTimer->Start();
663 bCallHelpRequest = false;
664 bRet = true;
666 else
668 // Auto-ToTop
669 if ( !pSVData->maWinData.mpCaptureWin &&
670 (pChild->GetSettings().GetMouseSettings().GetOptions() & MouseSettingsOptions::AutoFocus) )
671 pChild->ToTop( ToTopFlags::NoGrabFocus );
673 if( pChild->IsDisposed() )
674 bCallHelpRequest = false;
675 else
677 // if the MouseMove handler changes the help window's visibility
678 // the HelpRequest handler should not be called anymore
679 vcl::Window* pOldHelpTextWin = pSVData->maHelpData.mpHelpWin;
680 pChild->MouseMove( aMEvt );
681 if ( pOldHelpTextWin != pSVData->maHelpData.mpHelpWin )
682 bCallHelpRequest = false;
686 else if ( nSVEvent == MouseNotifyEvent::MOUSEBUTTONDOWN )
688 if ( pSVData->maWinData.mpTrackWin )
689 bRet = true;
690 else
692 pChild->ImplGetWindowImpl()->mbMouseButtonDown = false;
693 pChild->MouseButtonDown( aMEvt );
696 else
698 if ( pSVData->maWinData.mpTrackWin )
700 pChild->EndTracking();
701 bRet = true;
703 else
705 pChild->ImplGetWindowImpl()->mbMouseButtonUp = false;
706 pChild->MouseButtonUp( aMEvt );
710 assert(aNEvt.GetWindow() == pChild);
712 if (!pChild->IsDisposed())
713 pChild->ImplNotifyKeyMouseCommandEventListeners( aNEvt );
716 if (pChild->IsDisposed())
717 return true;
719 if ( nSVEvent == MouseNotifyEvent::MOUSEMOVE )
720 pChild->ImplGetWindowImpl()->mpFrameData->mbInMouseMove = false;
722 if ( nSVEvent == MouseNotifyEvent::MOUSEMOVE )
724 if ( bCallHelpRequest && !pSVData->maHelpData.mbKeyboardHelp )
725 ImplHandleMouseHelpRequest( pChild, pChild->OutputToScreenPixel( aMEvt.GetPosPixel() ) );
726 bRet = true;
728 else if ( !bRet )
730 if ( nSVEvent == MouseNotifyEvent::MOUSEBUTTONDOWN )
732 if ( !pChild->ImplGetWindowImpl()->mbMouseButtonDown )
733 bRet = true;
735 else
737 if ( !pChild->ImplGetWindowImpl()->mbMouseButtonUp )
738 bRet = true;
742 if ( nSVEvent == MouseNotifyEvent::MOUSEMOVE )
744 // set new mouse pointer
745 if ( !bMouseLeave )
746 ImplSetMousePointer( pChild );
748 else if ( (nSVEvent == MouseNotifyEvent::MOUSEBUTTONDOWN) || (nSVEvent == MouseNotifyEvent::MOUSEBUTTONUP) )
750 // Command-Events
751 if ( /*!bRet &&*/ (nClicks == 1) && (nSVEvent == MouseNotifyEvent::MOUSEBUTTONDOWN) &&
752 (nCode == MOUSE_MIDDLE) )
754 MouseMiddleButtonAction nMiddleAction = pChild->GetSettings().GetMouseSettings().GetMiddleButtonAction();
755 if ( nMiddleAction == MouseMiddleButtonAction::AutoScroll )
756 bRet = !ImplCallCommand( pChild, CommandEventId::StartAutoScroll, nullptr, true, &aChildPos );
757 else if ( nMiddleAction == MouseMiddleButtonAction::PasteSelection )
758 bRet = !ImplCallCommand( pChild, CommandEventId::PasteSelection, nullptr, true, &aChildPos );
760 else
762 // ContextMenu
763 if ( (nCode == MouseSettings::GetContextMenuCode()) &&
764 (nClicks == MouseSettings::GetContextMenuClicks()) )
766 bool bContextMenu = (nSVEvent == MouseNotifyEvent::MOUSEBUTTONDOWN);
767 if ( bContextMenu )
769 if( pSVData->maAppData.mpActivePopupMenu )
771 /* #i34277# there already is a context menu open
772 * that was probably just closed with EndPopupMode.
773 * We need to give the eventual corresponding
774 * PopupMenu::Execute a chance to end properly.
775 * Therefore delay context menu command and
776 * issue only after popping one frame of the
777 * Yield stack.
779 ContextMenuEvent* pEv = new ContextMenuEvent;
780 pEv->pWindow = pChild;
781 pEv->aChildPos = aChildPos;
782 Application::PostUserEvent( Link<void*,void>( pEv, ContextMenuEventLink ) );
784 else
785 bRet = ! ImplCallCommand( pChild, CommandEventId::ContextMenu, nullptr, true, &aChildPos );
791 return bRet;
794 static vcl::Window* ImplGetKeyInputWindow( vcl::Window* pWindow )
796 ImplSVData* pSVData = ImplGetSVData();
798 // determine last input time
799 pSVData->maAppData.mnLastInputTime = tools::Time::GetSystemTicks();
801 // #127104# workaround for destroyed windows
802 if( pWindow->ImplGetWindowImpl() == nullptr )
803 return nullptr;
805 // find window - is every time the window which has currently the
806 // focus or the last time the focus.
808 // the first floating window always has the focus, try it, or any parent floating windows, first
809 vcl::Window* pChild = pSVData->maWinData.mpFirstFloat;
810 while (pChild)
812 if (pChild->ImplGetWindowImpl()->mbFloatWin)
814 if (static_cast<FloatingWindow *>(pChild)->GrabsFocus())
815 break;
817 else if (pChild->ImplGetWindowImpl()->mbDockWin)
819 vcl::Window* pParent = pChild->GetWindow(GetWindowType::RealParent);
820 if (pParent && pParent->ImplGetWindowImpl()->mbFloatWin &&
821 static_cast<FloatingWindow *>(pParent)->GrabsFocus())
822 break;
824 pChild = pChild->GetParent();
827 if (!pChild)
828 pChild = pWindow;
830 pChild = pChild->ImplGetWindowImpl()->mpFrameData->mpFocusWin;
832 // no child - then no input
833 if ( !pChild )
834 return nullptr;
836 // We call also KeyInput if we haven't the focus, because on Unix
837 // system this is often the case when a Lookup Choice Window has
838 // the focus - because this windows send the KeyInput directly to
839 // the window without resetting the focus
840 SAL_WARN_IF( pChild != pSVData->maWinData.mpFocusWin, "vcl",
841 "ImplHandleKey: Keyboard-Input is sent to a frame without focus" );
843 // no keyinput to disabled windows
844 if ( !pChild->IsEnabled() || !pChild->IsInputEnabled() || pChild->IsInModalMode() )
845 return nullptr;
847 return pChild;
850 static bool ImplHandleKey( vcl::Window* pWindow, MouseNotifyEvent nSVEvent,
851 sal_uInt16 nKeyCode, sal_uInt16 nCharCode, sal_uInt16 nRepeat, bool bForward )
853 ImplSVData* pSVData = ImplGetSVData();
854 vcl::KeyCode aKeyCode( nKeyCode, nKeyCode );
855 sal_uInt16 nEvCode = aKeyCode.GetCode();
857 // allow application key listeners to remove the key event
858 // but make sure we're not forwarding external KeyEvents, (ie where bForward is false)
859 // because those are coming back from the listener itself and MUST be processed
860 if( bForward )
862 VclEventId nVCLEvent;
863 switch( nSVEvent )
865 case MouseNotifyEvent::KEYINPUT:
866 nVCLEvent = VclEventId::WindowKeyInput;
867 break;
868 case MouseNotifyEvent::KEYUP:
869 nVCLEvent = VclEventId::WindowKeyUp;
870 break;
871 default:
872 nVCLEvent = VclEventId::NONE;
873 break;
875 KeyEvent aKeyEvent(static_cast<sal_Unicode>(nCharCode), aKeyCode, nRepeat);
876 if (nVCLEvent != VclEventId::NONE && Application::HandleKey(nVCLEvent, pWindow, &aKeyEvent))
877 return true;
880 // #i1820# use locale specific decimal separator
881 if( nEvCode == KEY_DECIMAL )
883 if( Application::GetSettings().GetMiscSettings().GetEnableLocalizedDecimalSep() )
885 OUString aSep( pWindow->GetSettings().GetLocaleDataWrapper().getNumDecimalSep() );
886 nCharCode = static_cast<sal_uInt16>(aSep[0]);
890 bool bCtrlF6 = (aKeyCode.GetCode() == KEY_F6) && aKeyCode.IsMod1();
892 // determine last input time
893 pSVData->maAppData.mnLastInputTime = tools::Time::GetSystemTicks();
895 // handle tracking window
896 if ( nSVEvent == MouseNotifyEvent::KEYINPUT )
898 if ( pSVData->maHelpData.mbExtHelpMode )
900 Help::EndExtHelp();
901 if ( nEvCode == KEY_ESCAPE )
902 return true;
904 if ( pSVData->maHelpData.mpHelpWin )
905 ImplDestroyHelpWindow( false );
907 // AutoScrollMode
908 if ( pSVData->maWinData.mpAutoScrollWin )
910 pSVData->maWinData.mpAutoScrollWin->EndAutoScroll();
911 if ( nEvCode == KEY_ESCAPE )
912 return true;
915 if ( pSVData->maWinData.mpTrackWin )
917 sal_uInt16 nOrigCode = aKeyCode.GetCode();
919 if ( nOrigCode == KEY_ESCAPE )
921 pSVData->maWinData.mpTrackWin->EndTracking( TrackingEventFlags::Cancel | TrackingEventFlags::Key );
922 if ( pSVData->maWinData.mpFirstFloat )
924 FloatingWindow* pLastLevelFloat = pSVData->maWinData.mpFirstFloat->ImplFindLastLevelFloat();
925 if ( !(pLastLevelFloat->GetPopupModeFlags() & FloatWinPopupFlags::NoKeyClose) )
927 sal_uInt16 nEscCode = aKeyCode.GetCode();
929 if ( nEscCode == KEY_ESCAPE )
930 pLastLevelFloat->EndPopupMode( FloatWinPopupEndFlags::Cancel | FloatWinPopupEndFlags::CloseAll );
933 return true;
935 else if ( nOrigCode == KEY_RETURN )
937 pSVData->maWinData.mpTrackWin->EndTracking( TrackingEventFlags::Key );
938 return true;
940 else
941 return true;
944 // handle FloatingMode
945 if ( pSVData->maWinData.mpFirstFloat )
947 FloatingWindow* pLastLevelFloat = pSVData->maWinData.mpFirstFloat->ImplFindLastLevelFloat();
948 if ( !(pLastLevelFloat->GetPopupModeFlags() & FloatWinPopupFlags::NoKeyClose) )
950 sal_uInt16 nCode = aKeyCode.GetCode();
952 if ( (nCode == KEY_ESCAPE) || bCtrlF6)
954 pLastLevelFloat->EndPopupMode( FloatWinPopupEndFlags::Cancel | FloatWinPopupEndFlags::CloseAll );
955 if( !bCtrlF6 )
956 return true;
961 // test for accel
962 if ( pSVData->maAppData.mpAccelMgr )
964 if ( pSVData->maAppData.mpAccelMgr->IsAccelKey( aKeyCode ) )
965 return true;
969 // find window
970 VclPtr<vcl::Window> pChild = ImplGetKeyInputWindow( pWindow );
971 if ( !pChild )
972 return false;
974 // RTL: mirror cursor keys
975 const OutputDevice *pChildOutDev = pChild->GetOutDev();
976 if( (aKeyCode.GetCode() == KEY_LEFT || aKeyCode.GetCode() == KEY_RIGHT) &&
977 pChildOutDev->HasMirroredGraphics() && pChild->IsRTLEnabled() )
978 aKeyCode = vcl::KeyCode( aKeyCode.GetCode() == KEY_LEFT ? KEY_RIGHT : KEY_LEFT, aKeyCode.GetModifier() );
980 KeyEvent aKeyEvt( static_cast<sal_Unicode>(nCharCode), aKeyCode, nRepeat );
981 NotifyEvent aNotifyEvt( nSVEvent, pChild, &aKeyEvt );
982 bool bKeyPreNotify = ImplCallPreNotify( aNotifyEvt );
983 bool bRet = true;
985 if ( !bKeyPreNotify && !pChild->IsDisposed() )
987 if ( nSVEvent == MouseNotifyEvent::KEYINPUT )
989 UITestLogger::getInstance().logKeyInput(pChild, aKeyEvt);
990 pChild->ImplGetWindowImpl()->mbKeyInput = false;
991 pChild->KeyInput( aKeyEvt );
993 else
995 pChild->ImplGetWindowImpl()->mbKeyUp = false;
996 pChild->KeyUp( aKeyEvt );
998 if( !pChild->IsDisposed() )
999 aNotifyEvt.GetWindow()->ImplNotifyKeyMouseCommandEventListeners( aNotifyEvt );
1002 if ( pChild->IsDisposed() )
1003 return true;
1005 if ( nSVEvent == MouseNotifyEvent::KEYINPUT )
1007 if ( !bKeyPreNotify && pChild->ImplGetWindowImpl()->mbKeyInput )
1009 sal_uInt16 nCode = aKeyCode.GetCode();
1011 // #101999# is focus in or below toolbox
1012 bool bToolboxFocus=false;
1013 if( (nCode == KEY_F1) && aKeyCode.IsShift() )
1015 vcl::Window *pWin = pWindow->ImplGetWindowImpl()->mpFrameData->mpFocusWin;
1016 while( pWin )
1018 if( pWin->ImplGetWindowImpl()->mbToolBox )
1020 bToolboxFocus = true;
1021 break;
1023 else
1024 pWin = pWin->GetParent();
1028 // ContextMenu
1029 if ( (nCode == KEY_CONTEXTMENU) || ((nCode == KEY_F10) && aKeyCode.IsShift() && !aKeyCode.IsMod1() && !aKeyCode.IsMod2() ) )
1030 bRet = !ImplCallCommand( pChild, CommandEventId::ContextMenu );
1031 else if ( ( (nCode == KEY_F2) && aKeyCode.IsShift() ) || ( (nCode == KEY_F1) && aKeyCode.IsMod1() ) ||
1032 // #101999# no active help when focus in toolbox, simulate BalloonHelp instead
1033 ( (nCode == KEY_F1) && aKeyCode.IsShift() && bToolboxFocus ) )
1035 // TipHelp via Keyboard (Shift-F2 or Ctrl-F1)
1036 // simulate mouseposition at center of window
1038 Size aSize = pChild->GetOutputSize();
1039 Point aPos( aSize.getWidth()/2, aSize.getHeight()/2 );
1040 aPos = pChild->OutputToScreenPixel( aPos );
1042 HelpEvent aHelpEvent( aPos, HelpEventMode::BALLOON );
1043 aHelpEvent.SetKeyboardActivated( true );
1044 pSVData->maHelpData.mbSetKeyboardHelp = true;
1045 pChild->RequestHelp( aHelpEvent );
1046 pSVData->maHelpData.mbSetKeyboardHelp = false;
1048 else if ( (nCode == KEY_F1) || (nCode == KEY_HELP) )
1050 if ( !aKeyCode.GetModifier() )
1052 if ( pSVData->maHelpData.mbContextHelp )
1054 Point aMousePos = pChild->OutputToScreenPixel( pChild->GetPointerPosPixel() );
1055 HelpEvent aHelpEvent( aMousePos, HelpEventMode::CONTEXT );
1056 pChild->RequestHelp( aHelpEvent );
1058 else
1059 bRet = false;
1061 else if ( aKeyCode.IsShift() )
1063 if ( pSVData->maHelpData.mbExtHelp )
1064 Help::StartExtHelp();
1065 else
1066 bRet = false;
1069 else
1070 bRet = false;
1073 else
1075 if ( !bKeyPreNotify && pChild->ImplGetWindowImpl()->mbKeyUp )
1076 bRet = false;
1079 // #105591# send keyinput to parent if we are a floating window and the key was not processed yet
1080 if( !bRet && pWindow->ImplGetWindowImpl() && pWindow->ImplGetWindowImpl()->mbFloatWin && pWindow->GetParent() && (pWindow->ImplGetWindowImpl()->mpFrame != pWindow->GetParent()->ImplGetWindowImpl()->mpFrame) )
1082 pChild = pWindow->GetParent();
1084 // call handler
1085 NotifyEvent aNEvt( nSVEvent, pChild, &aKeyEvt );
1086 bool bPreNotify = ImplCallPreNotify( aNEvt );
1087 if ( pChild->IsDisposed() )
1088 return true;
1090 if ( !bPreNotify )
1092 if ( nSVEvent == MouseNotifyEvent::KEYINPUT )
1094 pChild->ImplGetWindowImpl()->mbKeyInput = false;
1095 pChild->KeyInput( aKeyEvt );
1097 else
1099 pChild->ImplGetWindowImpl()->mbKeyUp = false;
1100 pChild->KeyUp( aKeyEvt );
1103 if( !pChild->IsDisposed() )
1104 aNEvt.GetWindow()->ImplNotifyKeyMouseCommandEventListeners( aNEvt );
1105 if ( pChild->IsDisposed() )
1106 return true;
1109 if( bPreNotify || !pChild->ImplGetWindowImpl()->mbKeyInput )
1110 bRet = true;
1113 return bRet;
1116 static bool ImplHandleExtTextInput( vcl::Window* pWindow,
1117 const OUString& rText,
1118 const ExtTextInputAttr* pTextAttr,
1119 sal_Int32 nCursorPos, sal_uInt16 nCursorFlags )
1121 ImplSVData* pSVData = ImplGetSVData();
1122 vcl::Window* pChild = nullptr;
1124 int nTries = 200;
1125 while( nTries-- )
1127 pChild = pSVData->maWinData.mpExtTextInputWin;
1128 if ( !pChild )
1130 pChild = ImplGetKeyInputWindow( pWindow );
1131 if ( !pChild )
1132 return false;
1134 if( !pChild->ImplGetWindowImpl()->mpFrameData->mnFocusId )
1135 break;
1137 if (comphelper::LibreOfficeKit::isActive())
1139 SAL_WARN("vcl", "Failed to get ext text input context");
1140 break;
1142 Application::Yield();
1145 // If it is the first ExtTextInput call, we inform the information
1146 // and allocate the data, which we must store in this mode
1147 ImplWinData* pWinData = pChild->ImplGetWinData();
1148 if ( !pChild->ImplGetWindowImpl()->mbExtTextInput )
1150 pChild->ImplGetWindowImpl()->mbExtTextInput = true;
1151 pWinData->mpExtOldText = OUString();
1152 pWinData->mpExtOldAttrAry.reset();
1153 pSVData->maWinData.mpExtTextInputWin = pChild;
1154 ImplCallCommand( pChild, CommandEventId::StartExtTextInput );
1157 // be aware of being recursively called in StartExtTextInput
1158 if ( !pChild->ImplGetWindowImpl()->mbExtTextInput )
1159 return false;
1161 // Test for changes
1162 bool bOnlyCursor = false;
1163 sal_Int32 nMinLen = std::min( pWinData->mpExtOldText->getLength(), rText.getLength() );
1164 sal_Int32 nDeltaStart = 0;
1165 while ( nDeltaStart < nMinLen )
1167 if ( (*pWinData->mpExtOldText)[nDeltaStart] != rText[nDeltaStart] )
1168 break;
1169 nDeltaStart++;
1171 if ( pWinData->mpExtOldAttrAry || pTextAttr )
1173 if ( !pWinData->mpExtOldAttrAry || !pTextAttr )
1174 nDeltaStart = 0;
1175 else
1177 sal_Int32 i = 0;
1178 while ( i < nDeltaStart )
1180 if ( pWinData->mpExtOldAttrAry[i] != pTextAttr[i] )
1182 nDeltaStart = i;
1183 break;
1185 i++;
1189 if ( (nDeltaStart >= nMinLen) &&
1190 (pWinData->mpExtOldText->getLength() == rText.getLength()) )
1191 bOnlyCursor = true;
1193 // Call Event and store the information
1194 CommandExtTextInputData aData( rText, pTextAttr,
1195 nCursorPos, nCursorFlags,
1196 bOnlyCursor );
1197 *pWinData->mpExtOldText = rText;
1198 pWinData->mpExtOldAttrAry.reset();
1199 if ( pTextAttr )
1201 pWinData->mpExtOldAttrAry.reset( new ExtTextInputAttr[rText.getLength()] );
1202 memcpy( pWinData->mpExtOldAttrAry.get(), pTextAttr, rText.getLength()*sizeof( ExtTextInputAttr ) );
1204 return !ImplCallCommand( pChild, CommandEventId::ExtTextInput, &aData );
1207 static bool ImplHandleEndExtTextInput()
1209 ImplSVData* pSVData = ImplGetSVData();
1210 vcl::Window* pChild = pSVData->maWinData.mpExtTextInputWin;
1211 bool bRet = false;
1213 if ( pChild )
1215 pChild->ImplGetWindowImpl()->mbExtTextInput = false;
1216 pSVData->maWinData.mpExtTextInputWin = nullptr;
1217 ImplWinData* pWinData = pChild->ImplGetWinData();
1218 pWinData->mpExtOldText.reset();
1219 pWinData->mpExtOldAttrAry.reset();
1220 bRet = !ImplCallCommand( pChild, CommandEventId::EndExtTextInput );
1223 return bRet;
1226 static void ImplHandleExtTextInputPos( vcl::Window* pWindow,
1227 tools::Rectangle& rRect, long& rInputWidth,
1228 bool * pVertical )
1230 ImplSVData* pSVData = ImplGetSVData();
1231 vcl::Window* pChild = pSVData->maWinData.mpExtTextInputWin;
1233 if ( !pChild )
1234 pChild = ImplGetKeyInputWindow( pWindow );
1235 else
1237 // Test, if the Window is related to the frame
1238 if ( !pWindow->ImplIsWindowOrChild( pChild ) )
1239 pChild = ImplGetKeyInputWindow( pWindow );
1242 if ( pChild )
1244 const OutputDevice *pChildOutDev = pChild->GetOutDev();
1245 ImplCallCommand( pChild, CommandEventId::CursorPos );
1246 const tools::Rectangle* pRect = pChild->GetCursorRect();
1247 if ( pRect )
1248 rRect = pChildOutDev->ImplLogicToDevicePixel( *pRect );
1249 else
1251 vcl::Cursor* pCursor = pChild->GetCursor();
1252 if ( pCursor )
1254 Point aPos = pChildOutDev->ImplLogicToDevicePixel( pCursor->GetPos() );
1255 Size aSize = pChild->LogicToPixel( pCursor->GetSize() );
1256 if ( !aSize.Width() )
1257 aSize.setWidth( pChild->GetSettings().GetStyleSettings().GetCursorSize() );
1258 rRect = tools::Rectangle( aPos, aSize );
1260 else
1261 rRect = tools::Rectangle( Point( pChild->GetOutOffXPixel(), pChild->GetOutOffYPixel() ), Size() );
1263 rInputWidth = pChild->ImplLogicWidthToDevicePixel( pChild->GetCursorExtTextInputWidth() );
1264 if ( !rInputWidth )
1265 rInputWidth = rRect.GetWidth();
1267 if (pVertical != nullptr)
1268 *pVertical
1269 = pChild != nullptr && pChild->GetInputContext().GetFont().IsVertical();
1272 static bool ImplHandleInputContextChange( vcl::Window* pWindow )
1274 vcl::Window* pChild = ImplGetKeyInputWindow( pWindow );
1275 CommandInputContextData aData;
1276 return !ImplCallCommand( pChild, CommandEventId::InputContextChange, &aData );
1279 static bool ImplCallWheelCommand( const VclPtr<vcl::Window>& pWindow, const Point& rPos,
1280 const CommandWheelData* pWheelData )
1282 Point aCmdMousePos = pWindow->ImplFrameToOutput( rPos );
1283 CommandEvent aCEvt( aCmdMousePos, CommandEventId::Wheel, true, pWheelData );
1284 NotifyEvent aNCmdEvt( MouseNotifyEvent::COMMAND, pWindow, &aCEvt );
1285 bool bPreNotify = ImplCallPreNotify( aNCmdEvt );
1286 if ( pWindow->IsDisposed() )
1287 return false;
1288 if ( !bPreNotify )
1290 pWindow->ImplGetWindowImpl()->mbCommand = false;
1291 pWindow->Command( aCEvt );
1292 if ( pWindow->IsDisposed() )
1293 return false;
1294 if ( pWindow->ImplGetWindowImpl()->mbCommand )
1295 return true;
1297 return false;
1300 static bool acceptableWheelScrollTarget(const vcl::Window *pMouseWindow)
1302 return (pMouseWindow && !pMouseWindow->isDisposed() && pMouseWindow->IsInputEnabled() && !pMouseWindow->IsInModalMode());
1305 //If the last event at the same absolute screen position was handled by a
1306 //different window then reuse that window if the event occurs within 1/2 a
1307 //second, i.e. so scrolling down something like the calc sidebar that contains
1308 //widgets that respond to wheel events will continue to send the event to the
1309 //scrolling widget in favour of the widget that happens to end up under the
1310 //mouse.
1311 static bool shouldReusePreviousMouseWindow(const SalWheelMouseEvent& rPrevEvt, const SalWheelMouseEvent& rEvt)
1313 return (rEvt.mnX == rPrevEvt.mnX && rEvt.mnY == rPrevEvt.mnY && rEvt.mnTime-rPrevEvt.mnTime < 500/*ms*/);
1316 class HandleGestureEventBase
1318 protected:
1319 ImplSVData* m_pSVData;
1320 VclPtr<vcl::Window> m_pWindow;
1321 Point const m_aMousePos;
1323 public:
1324 HandleGestureEventBase(vcl::Window *pWindow, const Point &rMousePos)
1325 : m_pSVData(ImplGetSVData())
1326 , m_pWindow(pWindow)
1327 , m_aMousePos(rMousePos)
1330 bool Setup();
1331 vcl::Window* FindTarget();
1332 vcl::Window* Dispatch(vcl::Window* pTarget);
1333 virtual bool CallCommand(vcl::Window *pWindow, const Point &rMousePos) = 0;
1334 virtual ~HandleGestureEventBase() {}
1337 bool HandleGestureEventBase::Setup()
1340 if (m_pSVData->maWinData.mpAutoScrollWin)
1341 m_pSVData->maWinData.mpAutoScrollWin->EndAutoScroll();
1342 if (m_pSVData->maHelpData.mpHelpWin)
1343 ImplDestroyHelpWindow( true );
1344 return !m_pWindow->IsDisposed();
1347 vcl::Window* HandleGestureEventBase::FindTarget()
1349 // first check any floating window ( eg. drop down listboxes)
1350 vcl::Window *pMouseWindow = nullptr;
1352 if (m_pSVData->maWinData.mpFirstFloat && !m_pSVData->maWinData.mpCaptureWin &&
1353 !m_pSVData->maWinData.mpFirstFloat->ImplIsFloatPopupModeWindow( m_pWindow ) )
1355 bool bHitTestInsideRect = false;
1356 pMouseWindow = m_pSVData->maWinData.mpFirstFloat->ImplFloatHitTest( m_pWindow, m_aMousePos, bHitTestInsideRect );
1357 if (!pMouseWindow)
1358 pMouseWindow = m_pSVData->maWinData.mpFirstFloat;
1360 // then try the window directly beneath the mouse
1361 if( !pMouseWindow )
1363 pMouseWindow = m_pWindow->ImplFindWindow( m_aMousePos );
1365 else
1367 // transform coordinates to float window frame coordinates
1368 pMouseWindow = pMouseWindow->ImplFindWindow(
1369 pMouseWindow->OutputToScreenPixel(
1370 pMouseWindow->AbsoluteScreenToOutputPixel(
1371 m_pWindow->OutputToAbsoluteScreenPixel(
1372 m_pWindow->ScreenToOutputPixel( m_aMousePos ) ) ) ) );
1375 while (acceptableWheelScrollTarget(pMouseWindow))
1377 if (pMouseWindow->IsEnabled())
1378 break;
1379 //try the parent if this one is disabled
1380 pMouseWindow = pMouseWindow->GetParent();
1383 return pMouseWindow;
1386 vcl::Window *HandleGestureEventBase::Dispatch(vcl::Window* pMouseWindow)
1388 vcl::Window *pDispatchedTo = nullptr;
1390 if (acceptableWheelScrollTarget(pMouseWindow) && pMouseWindow->IsEnabled())
1392 // transform coordinates to float window frame coordinates
1393 Point aRelMousePos( pMouseWindow->OutputToScreenPixel(
1394 pMouseWindow->AbsoluteScreenToOutputPixel(
1395 m_pWindow->OutputToAbsoluteScreenPixel(
1396 m_pWindow->ScreenToOutputPixel( m_aMousePos ) ) ) ) );
1397 bool bPropogate = CallCommand(pMouseWindow, aRelMousePos);
1398 if (!bPropogate)
1399 pDispatchedTo = pMouseWindow;
1402 // if the command was not handled try the focus window
1403 if (!pDispatchedTo)
1405 vcl::Window* pFocusWindow = m_pWindow->ImplGetWindowImpl()->mpFrameData->mpFocusWin;
1406 if ( pFocusWindow && (pFocusWindow != pMouseWindow) &&
1407 (pFocusWindow == m_pSVData->maWinData.mpFocusWin) )
1409 // no wheel-messages to disabled windows
1410 if ( pFocusWindow->IsEnabled() && pFocusWindow->IsInputEnabled() && ! pFocusWindow->IsInModalMode() )
1412 // transform coordinates to focus window frame coordinates
1413 Point aRelMousePos( pFocusWindow->OutputToScreenPixel(
1414 pFocusWindow->AbsoluteScreenToOutputPixel(
1415 m_pWindow->OutputToAbsoluteScreenPixel(
1416 m_pWindow->ScreenToOutputPixel( m_aMousePos ) ) ) ) );
1417 bool bPropogate = CallCommand(pFocusWindow, aRelMousePos);
1418 if (!bPropogate)
1419 pDispatchedTo = pMouseWindow;
1423 return pDispatchedTo;
1426 class HandleWheelEvent : public HandleGestureEventBase
1428 private:
1429 CommandWheelData m_aWheelData;
1430 public:
1431 HandleWheelEvent(vcl::Window *pWindow, const SalWheelMouseEvent& rEvt)
1432 : HandleGestureEventBase(pWindow, Point(rEvt.mnX, rEvt.mnY))
1434 CommandWheelMode nMode;
1435 sal_uInt16 nCode = rEvt.mnCode;
1436 bool bHorz = rEvt.mbHorz;
1437 bool bPixel = rEvt.mbDeltaIsPixel;
1438 if ( nCode & KEY_MOD1 )
1439 nMode = CommandWheelMode::ZOOM;
1440 else if ( nCode & KEY_MOD2 )
1441 nMode = CommandWheelMode::DATAZOOM;
1442 else
1444 nMode = CommandWheelMode::SCROLL;
1445 // #i85450# interpret shift-wheel as horizontal wheel action
1446 if( (nCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_MOD3)) == KEY_SHIFT )
1447 bHorz = true;
1450 m_aWheelData = CommandWheelData(rEvt.mnDelta, rEvt.mnNotchDelta, rEvt.mnScrollLines, nMode, nCode, bHorz, bPixel);
1453 virtual bool CallCommand(vcl::Window *pWindow, const Point &rMousePos) override
1455 return ImplCallWheelCommand(pWindow, rMousePos, &m_aWheelData);
1457 bool HandleEvent(const SalWheelMouseEvent& rEvt);
1460 bool HandleWheelEvent::HandleEvent(const SalWheelMouseEvent& rEvt)
1462 if (!Setup())
1463 return false;
1465 VclPtr<vcl::Window> xMouseWindow = FindTarget();
1467 ImplSVData* pSVData = ImplGetSVData();
1469 // avoid the problem that scrolling via wheel to this point brings a widget
1470 // under the mouse that also accepts wheel commands, so stick with the old
1471 // widget if the time gap is very small
1472 if (shouldReusePreviousMouseWindow(pSVData->maWinData.maLastWheelEvent, rEvt) &&
1473 acceptableWheelScrollTarget(pSVData->maWinData.mpLastWheelWindow))
1475 xMouseWindow = pSVData->maWinData.mpLastWheelWindow;
1478 pSVData->maWinData.maLastWheelEvent = rEvt;
1480 pSVData->maWinData.mpLastWheelWindow = Dispatch(xMouseWindow);
1482 return pSVData->maWinData.mpLastWheelWindow.get();
1485 class HandleGestureEvent : public HandleGestureEventBase
1487 public:
1488 HandleGestureEvent(vcl::Window *pWindow, const Point &rMousePos)
1489 : HandleGestureEventBase(pWindow, rMousePos)
1492 bool HandleEvent();
1495 bool HandleGestureEvent::HandleEvent()
1497 if (!Setup())
1498 return false;
1500 vcl::Window *pTarget = FindTarget();
1502 bool bHandled = Dispatch(pTarget) != nullptr;
1503 return bHandled;
1506 static bool ImplHandleWheelEvent(vcl::Window* pWindow, const SalWheelMouseEvent& rEvt)
1508 HandleWheelEvent aHandler(pWindow, rEvt);
1509 return aHandler.HandleEvent(rEvt);
1512 class HandleSwipeEvent : public HandleGestureEvent
1514 private:
1515 CommandSwipeData m_aSwipeData;
1516 public:
1517 HandleSwipeEvent(vcl::Window *pWindow, const SalSwipeEvent& rEvt)
1518 : HandleGestureEvent(pWindow, Point(rEvt.mnX, rEvt.mnY)),
1519 m_aSwipeData(rEvt.mnVelocityX)
1522 virtual bool CallCommand(vcl::Window *pWindow, const Point &/*rMousePos*/) override
1524 return ImplCallCommand(pWindow, CommandEventId::Swipe, &m_aSwipeData);
1528 static bool ImplHandleSwipe(vcl::Window *pWindow, const SalSwipeEvent& rEvt)
1530 HandleSwipeEvent aHandler(pWindow, rEvt);
1531 return aHandler.HandleEvent();
1534 class HandleLongPressEvent : public HandleGestureEvent
1536 private:
1537 CommandLongPressData m_aLongPressData;
1538 public:
1539 HandleLongPressEvent(vcl::Window *pWindow, const SalLongPressEvent& rEvt)
1540 : HandleGestureEvent(pWindow, Point(rEvt.mnX, rEvt.mnY)),
1541 m_aLongPressData(rEvt.mnX, rEvt.mnY)
1544 virtual bool CallCommand(vcl::Window *pWindow, const Point &/*rMousePos*/) override
1546 return ImplCallCommand(pWindow, CommandEventId::LongPress, &m_aLongPressData);
1550 static bool ImplHandleLongPress(vcl::Window *pWindow, const SalLongPressEvent& rEvt)
1552 HandleLongPressEvent aHandler(pWindow, rEvt);
1553 return aHandler.HandleEvent();
1556 class HandleGeneralGestureEvent : public HandleGestureEvent
1558 private:
1559 CommandGestureData m_aGestureData;
1561 public:
1562 HandleGeneralGestureEvent(vcl::Window* pWindow, const SalGestureEvent& rEvent)
1563 : HandleGestureEvent(pWindow, Point(rEvent.mnX, rEvent.mnY))
1564 , m_aGestureData(rEvent.mnX, rEvent.mnY, rEvent.meEventType, rEvent.mfOffset, rEvent.meOrientation)
1568 virtual bool CallCommand(vcl::Window* pWindow, const Point& /*rMousePos*/) override
1570 return ImplCallCommand(pWindow, CommandEventId::Gesture, &m_aGestureData);
1574 static bool ImplHandleGestureEvent(vcl::Window* pWindow, const SalGestureEvent& rEvent)
1576 HandleGeneralGestureEvent aHandler(pWindow, rEvent);
1577 return aHandler.HandleEvent();
1580 static void ImplHandlePaint( vcl::Window* pWindow, const tools::Rectangle& rBoundRect, bool bImmediateUpdate )
1582 // system paint events must be checked for re-mirroring
1583 pWindow->ImplGetWindowImpl()->mnPaintFlags |= ImplPaintFlags::CheckRtl;
1585 // trigger paint for all windows that live in the new paint region
1586 vcl::Region aRegion( rBoundRect );
1587 pWindow->ImplInvalidateOverlapFrameRegion( aRegion );
1588 if( bImmediateUpdate )
1590 // #i87663# trigger possible pending resize notifications
1591 // (GetSizePixel does that for us)
1592 pWindow->GetSizePixel();
1593 // force drawing immediately
1594 pWindow->Update();
1598 static void KillOwnPopups( vcl::Window const * pWindow )
1600 ImplSVData* pSVData = ImplGetSVData();
1601 vcl::Window *pParent = pWindow->ImplGetWindowImpl()->mpFrameWindow;
1602 vcl::Window *pChild = pSVData->maWinData.mpFirstFloat;
1603 if ( pChild && pParent->ImplIsWindowOrChild( pChild, true ) )
1605 if ( !(pSVData->maWinData.mpFirstFloat->GetPopupModeFlags() & FloatWinPopupFlags::NoAppFocusClose) )
1606 pSVData->maWinData.mpFirstFloat->EndPopupMode( FloatWinPopupEndFlags::Cancel | FloatWinPopupEndFlags::CloseAll );
1610 void ImplHandleResize( vcl::Window* pWindow, long nNewWidth, long nNewHeight )
1612 const bool bChanged = (nNewWidth != pWindow->GetOutputWidthPixel()) || (nNewHeight != pWindow->GetOutputHeightPixel());
1613 if (bChanged && pWindow->GetStyle() & (WB_MOVEABLE|WB_SIZEABLE))
1615 KillOwnPopups( pWindow );
1616 if( pWindow->ImplGetWindow() != ImplGetSVData()->maHelpData.mpHelpWin )
1617 ImplDestroyHelpWindow( true );
1620 if (
1621 (nNewWidth > 0 && nNewHeight > 0) ||
1622 pWindow->ImplGetWindow()->ImplGetWindowImpl()->mbAllResize
1625 if (bChanged)
1627 pWindow->mnOutWidth = nNewWidth;
1628 pWindow->mnOutHeight = nNewHeight;
1629 pWindow->ImplGetWindowImpl()->mbWaitSystemResize = false;
1630 if ( pWindow->IsReallyVisible() )
1631 pWindow->ImplSetClipFlag();
1632 if ( pWindow->IsVisible() || pWindow->ImplGetWindow()->ImplGetWindowImpl()->mbAllResize ||
1633 ( pWindow->ImplGetWindowImpl()->mbFrame && pWindow->ImplGetWindowImpl()->mpClientWindow ) ) // propagate resize for system border windows
1635 bool bStartTimer = true;
1636 // use resize buffering for user resizes
1637 // ownerdraw decorated windows and floating windows can be resized immediately (i.e. synchronously)
1638 if( pWindow->ImplGetWindowImpl()->mbFrame && (pWindow->GetStyle() & WB_SIZEABLE)
1639 && !(pWindow->GetStyle() & WB_OWNERDRAWDECORATION) // synchronous resize for ownerdraw decorated windows (toolbars)
1640 && !pWindow->ImplGetWindowImpl()->mbFloatWin ) // synchronous resize for floating windows, #i43799#
1642 if( pWindow->ImplGetWindowImpl()->mpClientWindow )
1644 // #i42750# presentation wants to be informed about resize
1645 // as early as possible
1646 WorkWindow* pWorkWindow = dynamic_cast<WorkWindow*>(pWindow->ImplGetWindowImpl()->mpClientWindow.get());
1647 if( ! pWorkWindow || pWorkWindow->IsPresentationMode() )
1648 bStartTimer = false;
1650 else
1652 WorkWindow* pWorkWindow = dynamic_cast<WorkWindow*>(pWindow);
1653 if( ! pWorkWindow || pWorkWindow->IsPresentationMode() )
1654 bStartTimer = false;
1657 else
1658 bStartTimer = false;
1660 if( bStartTimer )
1661 pWindow->ImplGetWindowImpl()->mpFrameData->maResizeIdle.Start();
1662 else
1663 pWindow->ImplCallResize(); // otherwise menus cannot be positioned
1665 else
1666 pWindow->ImplGetWindowImpl()->mbCallResize = true;
1668 if (pWindow->SupportsDoubleBuffering() && pWindow->ImplGetWindowImpl()->mbFrame)
1670 // Propagate resize for the frame's buffer.
1671 pWindow->ImplGetWindowImpl()->mpFrameData->mpBuffer->SetOutputSizePixel(pWindow->GetOutputSizePixel());
1676 pWindow->ImplGetWindowImpl()->mpFrameData->mbNeedSysWindow = (nNewWidth < IMPL_MIN_NEEDSYSWIN) ||
1677 (nNewHeight < IMPL_MIN_NEEDSYSWIN);
1678 bool bMinimized = (nNewWidth <= 0) || (nNewHeight <= 0);
1679 if( bMinimized != pWindow->ImplGetWindowImpl()->mpFrameData->mbMinimized )
1680 pWindow->ImplGetWindowImpl()->mpFrameWindow->ImplNotifyIconifiedState( bMinimized );
1681 pWindow->ImplGetWindowImpl()->mpFrameData->mbMinimized = bMinimized;
1684 static void ImplHandleMove( vcl::Window* pWindow )
1686 if( pWindow->ImplGetWindowImpl()->mbFrame && pWindow->ImplIsFloatingWindow() && pWindow->IsReallyVisible() )
1688 static_cast<FloatingWindow*>(pWindow)->EndPopupMode( FloatWinPopupEndFlags::TearOff );
1689 pWindow->ImplCallMove();
1692 if( pWindow->GetStyle() & (WB_MOVEABLE|WB_SIZEABLE) )
1694 KillOwnPopups( pWindow );
1695 if( pWindow->ImplGetWindow() != ImplGetSVData()->maHelpData.mpHelpWin )
1696 ImplDestroyHelpWindow( true );
1699 if ( pWindow->IsVisible() )
1700 pWindow->ImplCallMove();
1701 else
1702 pWindow->ImplGetWindowImpl()->mbCallMove = true; // make sure the framepos will be updated on the next Show()
1704 if ( pWindow->ImplGetWindowImpl()->mbFrame && pWindow->ImplGetWindowImpl()->mpClientWindow )
1705 pWindow->ImplGetWindowImpl()->mpClientWindow->ImplCallMove(); // notify client to update geometry
1709 static void ImplHandleMoveResize( vcl::Window* pWindow, long nNewWidth, long nNewHeight )
1711 ImplHandleMove( pWindow );
1712 ImplHandleResize( pWindow, nNewWidth, nNewHeight );
1715 static void ImplActivateFloatingWindows( vcl::Window const * pWindow, bool bActive )
1717 // First check all overlapping windows
1718 vcl::Window* pTempWindow = pWindow->ImplGetWindowImpl()->mpFirstOverlap;
1719 while ( pTempWindow )
1721 if ( pTempWindow->GetActivateMode() == ActivateModeFlags::NONE )
1723 if ( (pTempWindow->GetType() == WindowType::BORDERWINDOW) &&
1724 (pTempWindow->ImplGetWindow()->GetType() == WindowType::FLOATINGWINDOW) )
1725 static_cast<ImplBorderWindow*>(pTempWindow)->SetDisplayActive( bActive );
1728 ImplActivateFloatingWindows( pTempWindow, bActive );
1729 pTempWindow = pTempWindow->ImplGetWindowImpl()->mpNext;
1733 IMPL_LINK_NOARG(vcl::Window, ImplAsyncFocusHdl, void*, void)
1735 ImplGetWindowImpl()->mpFrameData->mnFocusId = nullptr;
1737 // If the status has been preserved, because we got back the focus
1738 // in the meantime, we do nothing
1739 bool bHasFocus = ImplGetWindowImpl()->mpFrameData->mbHasFocus || ImplGetWindowImpl()->mpFrameData->mbSysObjFocus;
1741 // next execute the delayed functions
1742 if ( bHasFocus )
1744 // redraw all floating windows inactive
1745 if ( ImplGetWindowImpl()->mpFrameData->mbStartFocusState != bHasFocus )
1746 ImplActivateFloatingWindows( this, bHasFocus );
1748 if ( ImplGetWindowImpl()->mpFrameData->mpFocusWin )
1750 bool bHandled = false;
1751 if ( ImplGetWindowImpl()->mpFrameData->mpFocusWin->IsInputEnabled() &&
1752 ! ImplGetWindowImpl()->mpFrameData->mpFocusWin->IsInModalMode() )
1754 if ( ImplGetWindowImpl()->mpFrameData->mpFocusWin->IsEnabled() )
1756 ImplGetWindowImpl()->mpFrameData->mpFocusWin->GrabFocus();
1757 bHandled = true;
1759 else if( ImplGetWindowImpl()->mpFrameData->mpFocusWin->ImplHasDlgCtrl() )
1761 // #109094# if the focus is restored to a disabled dialog control (was disabled meanwhile)
1762 // try to move it to the next control
1763 ImplGetWindowImpl()->mpFrameData->mpFocusWin->ImplDlgCtrlNextWindow();
1764 bHandled = true;
1767 if ( !bHandled )
1769 ImplSVData* pSVData = ImplGetSVData();
1770 vcl::Window* pTopLevelWindow = ImplGetWindowImpl()->mpFrameData->mpFocusWin->ImplGetFirstOverlapWindow();
1772 if ((!pTopLevelWindow->IsInputEnabled() || pTopLevelWindow->IsInModalMode()) && !pSVData->maWinData.mpExecuteDialogs.empty())
1773 pSVData->maWinData.mpExecuteDialogs.back()->ToTop(ToTopFlags::RestoreWhenMin | ToTopFlags::GrabFocusOnly);
1774 else
1775 pTopLevelWindow->GrabFocus();
1778 else
1779 GrabFocus();
1781 else
1783 vcl::Window* pFocusWin = ImplGetWindowImpl()->mpFrameData->mpFocusWin;
1784 if ( pFocusWin )
1786 ImplSVData* pSVData = ImplGetSVData();
1788 if ( pSVData->maWinData.mpFocusWin == pFocusWin )
1790 // transfer the FocusWindow
1791 vcl::Window* pOverlapWindow = pFocusWin->ImplGetFirstOverlapWindow();
1792 pOverlapWindow->ImplGetWindowImpl()->mpLastFocusWindow = pFocusWin;
1793 pSVData->maWinData.mpFocusWin = nullptr;
1795 if ( pFocusWin->ImplGetWindowImpl()->mpCursor )
1796 pFocusWin->ImplGetWindowImpl()->mpCursor->ImplHide();
1798 // call the Deactivate
1799 vcl::Window* pOldOverlapWindow = pFocusWin->ImplGetFirstOverlapWindow();
1800 vcl::Window* pOldRealWindow = pOldOverlapWindow->ImplGetWindow();
1802 pOldOverlapWindow->ImplGetWindowImpl()->mbActive = false;
1803 pOldOverlapWindow->Deactivate();
1804 if ( pOldRealWindow != pOldOverlapWindow )
1806 pOldRealWindow->ImplGetWindowImpl()->mbActive = false;
1807 pOldRealWindow->Deactivate();
1810 // TrackingMode is ended in ImplHandleLoseFocus
1811 #ifdef _WIN32
1812 // To avoid problems with the Unix IME
1813 pFocusWin->EndExtTextInput();
1814 #endif
1816 NotifyEvent aNEvt(MouseNotifyEvent::LOSEFOCUS, pFocusWin);
1817 if (!ImplCallPreNotify(aNEvt))
1818 pFocusWin->CompatLoseFocus();
1819 pFocusWin->ImplCallDeactivateListeners(nullptr);
1823 // Redraw all floating window inactive
1824 if ( ImplGetWindowImpl()->mpFrameData->mbStartFocusState != bHasFocus )
1825 ImplActivateFloatingWindows( this, bHasFocus );
1829 static void ImplHandleGetFocus( vcl::Window* pWindow )
1831 pWindow->ImplGetWindowImpl()->mpFrameData->mbHasFocus = true;
1833 // execute Focus-Events after a delay, such that SystemChildWindows
1834 // do not blink when they receive focus
1835 if ( !pWindow->ImplGetWindowImpl()->mpFrameData->mnFocusId )
1837 pWindow->ImplGetWindowImpl()->mpFrameData->mbStartFocusState = !pWindow->ImplGetWindowImpl()->mpFrameData->mbHasFocus;
1838 pWindow->ImplGetWindowImpl()->mpFrameData->mnFocusId = Application::PostUserEvent( LINK( pWindow, vcl::Window, ImplAsyncFocusHdl ), nullptr, true);
1839 vcl::Window* pFocusWin = pWindow->ImplGetWindowImpl()->mpFrameData->mpFocusWin;
1840 if ( pFocusWin && pFocusWin->ImplGetWindowImpl()->mpCursor )
1841 pFocusWin->ImplGetWindowImpl()->mpCursor->ImplShow();
1845 static void ImplHandleLoseFocus( vcl::Window* pWindow )
1847 ImplSVData* pSVData = ImplGetSVData();
1849 // Abort the autoscroll if the frame loses focus
1850 if ( pSVData->maWinData.mpAutoScrollWin )
1851 pSVData->maWinData.mpAutoScrollWin->EndAutoScroll();
1853 // Abort tracking if the frame loses focus
1854 if ( pSVData->maWinData.mpTrackWin )
1856 if ( pSVData->maWinData.mpTrackWin->ImplGetWindowImpl()->mpFrameWindow == pWindow )
1857 pSVData->maWinData.mpTrackWin->EndTracking( TrackingEventFlags::Cancel );
1860 pWindow->ImplGetWindowImpl()->mpFrameData->mbHasFocus = false;
1862 // execute Focus-Events after a delay, such that SystemChildWindows
1863 // do not flicker when they receive focus
1864 if ( !pWindow->ImplGetWindowImpl()->mpFrameData->mnFocusId )
1866 pWindow->ImplGetWindowImpl()->mpFrameData->mbStartFocusState = !pWindow->ImplGetWindowImpl()->mpFrameData->mbHasFocus;
1867 pWindow->ImplGetWindowImpl()->mpFrameData->mnFocusId = Application::PostUserEvent( LINK( pWindow, vcl::Window, ImplAsyncFocusHdl ), nullptr, true );
1870 vcl::Window* pFocusWin = pWindow->ImplGetWindowImpl()->mpFrameData->mpFocusWin;
1871 if ( pFocusWin && pFocusWin->ImplGetWindowImpl()->mpCursor )
1872 pFocusWin->ImplGetWindowImpl()->mpCursor->ImplHide();
1874 // Make sure that no menu is visible when a toplevel window loses focus.
1875 VclPtr<FloatingWindow> pFirstFloat = pSVData->maWinData.mpFirstFloat;
1876 if (pFirstFloat && !pWindow->GetParent())
1877 pFirstFloat->EndPopupMode(FloatWinPopupEndFlags::Cancel | FloatWinPopupEndFlags::CloseAll);
1880 struct DelayedCloseEvent
1882 VclPtr<vcl::Window> pWindow;
1885 static void DelayedCloseEventLink( void* pCEvent, void* )
1887 DelayedCloseEvent* pEv = static_cast<DelayedCloseEvent*>(pCEvent);
1889 if( ! pEv->pWindow->IsDisposed() )
1891 // dispatch to correct window type
1892 if( pEv->pWindow->IsSystemWindow() )
1893 static_cast<SystemWindow*>(pEv->pWindow.get())->Close();
1894 else if( pEv->pWindow->IsDockingWindow() )
1895 static_cast<DockingWindow*>(pEv->pWindow.get())->Close();
1897 delete pEv;
1900 static void ImplHandleClose( const vcl::Window* pWindow )
1902 ImplSVData* pSVData = ImplGetSVData();
1904 bool bWasPopup = false;
1905 if( pWindow->ImplIsFloatingWindow() &&
1906 static_cast<const FloatingWindow*>(pWindow)->ImplIsInPrivatePopupMode() )
1908 bWasPopup = true;
1911 // on Close stop all floating modes and end popups
1912 if ( pSVData->maWinData.mpFirstFloat )
1914 FloatingWindow* pLastLevelFloat;
1915 pLastLevelFloat = pSVData->maWinData.mpFirstFloat->ImplFindLastLevelFloat();
1916 pLastLevelFloat->EndPopupMode( FloatWinPopupEndFlags::Cancel | FloatWinPopupEndFlags::CloseAll );
1918 if ( pSVData->maHelpData.mbExtHelpMode )
1919 Help::EndExtHelp();
1920 if ( pSVData->maHelpData.mpHelpWin )
1921 ImplDestroyHelpWindow( false );
1922 // AutoScrollMode
1923 if ( pSVData->maWinData.mpAutoScrollWin )
1924 pSVData->maWinData.mpAutoScrollWin->EndAutoScroll();
1926 if ( pSVData->maWinData.mpTrackWin )
1927 pSVData->maWinData.mpTrackWin->EndTracking( TrackingEventFlags::Cancel | TrackingEventFlags::Key );
1929 if (bWasPopup)
1930 return;
1932 vcl::Window *pWin = pWindow->ImplGetWindow();
1933 SystemWindow* pSysWin = dynamic_cast<SystemWindow*>(pWin);
1934 if (pSysWin)
1936 // See if the custom close handler is set.
1937 const Link<SystemWindow&,void>& rLink = pSysWin->GetCloseHdl();
1938 if (rLink.IsSet())
1940 rLink.Call(*pSysWin);
1941 return;
1945 // check whether close is allowed
1946 if ( pWin->IsEnabled() && pWin->IsInputEnabled() && !pWin->IsInModalMode() )
1948 DelayedCloseEvent* pEv = new DelayedCloseEvent;
1949 pEv->pWindow = pWin;
1950 Application::PostUserEvent( Link<void*,void>( pEv, DelayedCloseEventLink ) );
1954 static void ImplHandleUserEvent( ImplSVEvent* pSVEvent )
1956 if ( pSVEvent )
1958 if ( pSVEvent->mbCall )
1960 pSVEvent->maLink.Call( pSVEvent->mpData );
1963 delete pSVEvent;
1967 static MouseEventModifiers ImplGetMouseMoveMode( SalMouseEvent const * pEvent )
1969 MouseEventModifiers nMode = MouseEventModifiers::NONE;
1970 if ( !pEvent->mnCode )
1971 nMode |= MouseEventModifiers::SIMPLEMOVE;
1972 if ( (pEvent->mnCode & MOUSE_LEFT) && !(pEvent->mnCode & KEY_MOD1) )
1973 nMode |= MouseEventModifiers::DRAGMOVE;
1974 if ( (pEvent->mnCode & MOUSE_LEFT) && (pEvent->mnCode & KEY_MOD1) )
1975 nMode |= MouseEventModifiers::DRAGCOPY;
1976 return nMode;
1979 static MouseEventModifiers ImplGetMouseButtonMode( SalMouseEvent const * pEvent )
1981 MouseEventModifiers nMode = MouseEventModifiers::NONE;
1982 if ( pEvent->mnButton == MOUSE_LEFT )
1983 nMode |= MouseEventModifiers::SIMPLECLICK;
1984 if ( (pEvent->mnButton == MOUSE_LEFT) && !(pEvent->mnCode & (MOUSE_MIDDLE | MOUSE_RIGHT)) )
1985 nMode |= MouseEventModifiers::SELECT;
1986 if ( (pEvent->mnButton == MOUSE_LEFT) && (pEvent->mnCode & KEY_MOD1) &&
1987 !(pEvent->mnCode & (MOUSE_MIDDLE | MOUSE_RIGHT | KEY_SHIFT)) )
1988 nMode |= MouseEventModifiers::MULTISELECT;
1989 if ( (pEvent->mnButton == MOUSE_LEFT) && (pEvent->mnCode & KEY_SHIFT) &&
1990 !(pEvent->mnCode & (MOUSE_MIDDLE | MOUSE_RIGHT | KEY_MOD1)) )
1991 nMode |= MouseEventModifiers::RANGESELECT;
1992 return nMode;
1995 static bool ImplHandleSalMouseLeave( vcl::Window* pWindow, SalMouseEvent const * pEvent )
1997 return ImplHandleMouseEvent( pWindow, MouseNotifyEvent::MOUSEMOVE, true,
1998 pEvent->mnX, pEvent->mnY,
1999 pEvent->mnTime, pEvent->mnCode,
2000 ImplGetMouseMoveMode( pEvent ) );
2003 static bool ImplHandleSalMouseMove( vcl::Window* pWindow, SalMouseEvent const * pEvent )
2005 return ImplHandleMouseEvent( pWindow, MouseNotifyEvent::MOUSEMOVE, false,
2006 pEvent->mnX, pEvent->mnY,
2007 pEvent->mnTime, pEvent->mnCode,
2008 ImplGetMouseMoveMode( pEvent ) );
2011 static bool ImplHandleSalMouseButtonDown( vcl::Window* pWindow, SalMouseEvent const * pEvent )
2013 return ImplHandleMouseEvent( pWindow, MouseNotifyEvent::MOUSEBUTTONDOWN, false,
2014 pEvent->mnX, pEvent->mnY,
2015 pEvent->mnTime,
2016 #ifdef MACOSX
2017 pEvent->mnButton | (pEvent->mnCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_MOD3)),
2018 #else
2019 pEvent->mnButton | (pEvent->mnCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2)),
2020 #endif
2021 ImplGetMouseButtonMode( pEvent ) );
2024 static bool ImplHandleSalMouseButtonUp( vcl::Window* pWindow, SalMouseEvent const * pEvent )
2026 return ImplHandleMouseEvent( pWindow, MouseNotifyEvent::MOUSEBUTTONUP, false,
2027 pEvent->mnX, pEvent->mnY,
2028 pEvent->mnTime,
2029 #ifdef MACOSX
2030 pEvent->mnButton | (pEvent->mnCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_MOD3)),
2031 #else
2032 pEvent->mnButton | (pEvent->mnCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2)),
2033 #endif
2034 ImplGetMouseButtonMode( pEvent ) );
2037 static bool ImplHandleMenuEvent( vcl::Window const * pWindow, SalMenuEvent* pEvent, SalEvent nEvent )
2039 // Find SystemWindow and its Menubar and let it dispatch the command
2040 bool bRet = false;
2041 vcl::Window *pWin = pWindow->ImplGetWindowImpl()->mpFirstChild;
2042 while ( pWin )
2044 if ( pWin->ImplGetWindowImpl()->mbSysWin )
2045 break;
2046 pWin = pWin->ImplGetWindowImpl()->mpNext;
2048 if( pWin )
2050 MenuBar *pMenuBar = static_cast<SystemWindow*>(pWin)->GetMenuBar();
2051 if( pMenuBar )
2053 switch( nEvent )
2055 case SalEvent::MenuActivate:
2056 pMenuBar->HandleMenuActivateEvent( static_cast<Menu*>(pEvent->mpMenu) );
2057 bRet = true;
2058 break;
2059 case SalEvent::MenuDeactivate:
2060 pMenuBar->HandleMenuDeActivateEvent( static_cast<Menu*>(pEvent->mpMenu) );
2061 bRet = true;
2062 break;
2063 case SalEvent::MenuHighlight:
2064 bRet = pMenuBar->HandleMenuHighlightEvent( static_cast<Menu*>(pEvent->mpMenu), pEvent->mnId );
2065 break;
2066 case SalEvent::MenuButtonCommand:
2067 bRet = pMenuBar->HandleMenuButtonEvent( pEvent->mnId );
2068 break;
2069 case SalEvent::MenuCommand:
2070 bRet = pMenuBar->HandleMenuCommandEvent( static_cast<Menu*>(pEvent->mpMenu), pEvent->mnId );
2071 break;
2072 default:
2073 break;
2077 return bRet;
2080 static void ImplHandleSalKeyMod( vcl::Window* pWindow, SalKeyModEvent const * pEvent )
2082 ImplSVData* pSVData = ImplGetSVData();
2083 vcl::Window* pTrackWin = pSVData->maWinData.mpTrackWin;
2084 if ( pTrackWin )
2085 pWindow = pTrackWin;
2086 #ifdef MACOSX
2087 sal_uInt16 nOldCode = pWindow->ImplGetWindowImpl()->mpFrameData->mnMouseCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_MOD3);
2088 #else
2089 sal_uInt16 nOldCode = pWindow->ImplGetWindowImpl()->mpFrameData->mnMouseCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2);
2090 #endif
2091 sal_uInt16 nNewCode = pEvent->mnCode;
2092 if ( nOldCode != nNewCode )
2094 #ifdef MACOSX
2095 nNewCode |= pWindow->ImplGetWindowImpl()->mpFrameData->mnMouseCode & ~(KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_MOD3);
2096 #else
2097 nNewCode |= pWindow->ImplGetWindowImpl()->mpFrameData->mnMouseCode & ~(KEY_SHIFT | KEY_MOD1 | KEY_MOD2);
2098 #endif
2099 pWindow->ImplGetWindowImpl()->mpFrameWindow->ImplCallMouseMove( nNewCode, true );
2102 // #105224# send commandevent to allow special treatment of Ctrl-LeftShift/Ctrl-RightShift etc.
2103 // + auto-accelerator feature, tdf#92630
2105 // try to find a key input window...
2106 vcl::Window* pChild = ImplGetKeyInputWindow( pWindow );
2107 //...otherwise fail safe...
2108 if (!pChild)
2109 pChild = pWindow;
2111 CommandModKeyData data( pEvent->mnModKeyCode, pEvent->mbDown );
2112 ImplCallCommand( pChild, CommandEventId::ModKeyChange, &data );
2115 static void ImplHandleInputLanguageChange( vcl::Window* pWindow )
2117 // find window
2118 vcl::Window* pChild = ImplGetKeyInputWindow( pWindow );
2119 if ( !pChild )
2120 return;
2122 ImplCallCommand( pChild, CommandEventId::InputLanguageChange );
2125 static void ImplHandleSalSettings( SalEvent nEvent )
2127 Application* pApp = GetpApp();
2128 if ( !pApp )
2129 return;
2131 if ( nEvent == SalEvent::SettingsChanged )
2133 AllSettings aSettings = Application::GetSettings();
2134 Application::MergeSystemSettings( aSettings );
2135 pApp->OverrideSystemSettings( aSettings );
2136 Application::SetSettings( aSettings );
2138 else
2140 DataChangedEventType nType;
2141 switch ( nEvent )
2143 case SalEvent::PrinterChanged:
2144 ImplDeletePrnQueueList();
2145 nType = DataChangedEventType::PRINTER;
2146 break;
2147 case SalEvent::DisplayChanged:
2148 nType = DataChangedEventType::DISPLAY;
2149 break;
2150 case SalEvent::FontChanged:
2151 OutputDevice::ImplUpdateAllFontData( true );
2152 nType = DataChangedEventType::FONTS;
2153 break;
2154 default:
2155 nType = DataChangedEventType::NONE;
2156 break;
2159 if ( nType != DataChangedEventType::NONE )
2161 DataChangedEvent aDCEvt( nType );
2162 Application::ImplCallEventListenersApplicationDataChanged(&aDCEvt);
2163 Application::NotifyAllWindows( aDCEvt );
2168 static void ImplHandleSalExtTextInputPos( vcl::Window* pWindow, SalExtTextInputPosEvent* pEvt )
2170 tools::Rectangle aCursorRect;
2171 ImplHandleExtTextInputPos( pWindow, aCursorRect, pEvt->mnExtWidth, &pEvt->mbVertical );
2172 if ( aCursorRect.IsEmpty() )
2174 pEvt->mnX = -1;
2175 pEvt->mnY = -1;
2176 pEvt->mnWidth = -1;
2177 pEvt->mnHeight = -1;
2179 else
2181 pEvt->mnX = aCursorRect.Left();
2182 pEvt->mnY = aCursorRect.Top();
2183 pEvt->mnWidth = aCursorRect.GetWidth();
2184 pEvt->mnHeight = aCursorRect.GetHeight();
2188 static bool ImplHandleShowDialog( vcl::Window* pWindow, ShowDialogId nDialogId )
2190 if( ! pWindow )
2191 return false;
2193 if( pWindow->GetType() == WindowType::BORDERWINDOW )
2195 vcl::Window* pWrkWin = pWindow->GetWindow( GetWindowType::Client );
2196 if( pWrkWin )
2197 pWindow = pWrkWin;
2199 CommandDialogData aCmdData( nDialogId );
2200 return ImplCallCommand( pWindow, CommandEventId::ShowDialog, &aCmdData );
2203 static void ImplHandleSurroundingTextRequest( vcl::Window *pWindow,
2204 OUString& rText,
2205 Selection &rSelRange )
2207 vcl::Window* pChild = ImplGetKeyInputWindow( pWindow );
2209 if ( !pChild )
2211 rText.clear();
2212 rSelRange.setMin( 0 );
2213 rSelRange.setMax( 0 );
2215 else
2217 rText = pChild->GetSurroundingText();
2218 Selection aSel = pChild->GetSurroundingTextSelection();
2219 rSelRange.setMin( aSel.Min() );
2220 rSelRange.setMax( aSel.Max() );
2224 static void ImplHandleSalSurroundingTextRequest( vcl::Window *pWindow,
2225 SalSurroundingTextRequestEvent *pEvt )
2227 Selection aSelRange;
2228 ImplHandleSurroundingTextRequest( pWindow, pEvt->maText, aSelRange );
2230 aSelRange.Justify();
2232 if( aSelRange.Min() < 0 )
2233 pEvt->mnStart = 0;
2234 else if( aSelRange.Min() > pEvt->maText.getLength() )
2235 pEvt->mnStart = pEvt->maText.getLength();
2236 else
2237 pEvt->mnStart = aSelRange.Min();
2239 if( aSelRange.Max() < 0 )
2240 pEvt->mnStart = 0;
2241 else if( aSelRange.Max() > pEvt->maText.getLength() )
2242 pEvt->mnEnd = pEvt->maText.getLength();
2243 else
2244 pEvt->mnEnd = aSelRange.Max();
2247 static void ImplHandleSurroundingTextSelectionChange( vcl::Window *pWindow,
2248 sal_uLong nStart,
2249 sal_uLong nEnd )
2251 vcl::Window* pChild = ImplGetKeyInputWindow( pWindow );
2252 if( pChild )
2254 CommandSelectionChangeData data( nStart, nEnd );
2255 ImplCallCommand( pChild, CommandEventId::SelectionChange, &data );
2259 static void ImplHandleStartReconversion( vcl::Window *pWindow )
2261 vcl::Window* pChild = ImplGetKeyInputWindow( pWindow );
2262 if( pChild )
2263 ImplCallCommand( pChild, CommandEventId::PrepareReconversion );
2266 static void ImplHandleSalQueryCharPosition( vcl::Window *pWindow,
2267 SalQueryCharPositionEvent *pEvt )
2269 pEvt->mbValid = false;
2270 pEvt->mbVertical = false;
2271 pEvt->mnCursorBoundX = 0;
2272 pEvt->mnCursorBoundY = 0;
2273 pEvt->mnCursorBoundWidth = 0;
2274 pEvt->mnCursorBoundHeight = 0;
2276 ImplSVData* pSVData = ImplGetSVData();
2277 vcl::Window* pChild = pSVData->maWinData.mpExtTextInputWin;
2279 if ( !pChild )
2280 pChild = ImplGetKeyInputWindow( pWindow );
2281 else
2283 // Test, if the Window is related to the frame
2284 if ( !pWindow->ImplIsWindowOrChild( pChild ) )
2285 pChild = ImplGetKeyInputWindow( pWindow );
2288 if( pChild )
2290 ImplCallCommand( pChild, CommandEventId::QueryCharPosition );
2292 ImplWinData* pWinData = pChild->ImplGetWinData();
2293 if ( pWinData->mpCompositionCharRects && pEvt->mnCharPos < static_cast<sal_uLong>( pWinData->mnCompositionCharRects ) )
2295 const OutputDevice *pChildOutDev = pChild->GetOutDev();
2296 const tools::Rectangle& aRect = pWinData->mpCompositionCharRects[ pEvt->mnCharPos ];
2297 tools::Rectangle aDeviceRect = pChildOutDev->ImplLogicToDevicePixel( aRect );
2298 Point aAbsScreenPos = pChild->OutputToAbsoluteScreenPixel( pChild->ScreenToOutputPixel(aDeviceRect.TopLeft()) );
2299 pEvt->mnCursorBoundX = aAbsScreenPos.X();
2300 pEvt->mnCursorBoundY = aAbsScreenPos.Y();
2301 pEvt->mnCursorBoundWidth = aDeviceRect.GetWidth();
2302 pEvt->mnCursorBoundHeight = aDeviceRect.GetHeight();
2303 pEvt->mbVertical = pWinData->mbVertical;
2304 pEvt->mbValid = true;
2309 bool ImplWindowFrameProc( vcl::Window* _pWindow, SalEvent nEvent, const void* pEvent )
2311 DBG_TESTSOLARMUTEX();
2313 // Ensure the window survives during this method.
2314 VclPtr<vcl::Window> pWindow( _pWindow );
2316 bool bRet = false;
2318 // #119709# for some unknown reason it is possible to receive events (in this case key events)
2319 // although the corresponding VCL window must have been destroyed already
2320 // at least ImplGetWindowImpl() was NULL in these cases, so check this here
2321 if( pWindow->ImplGetWindowImpl() == nullptr )
2322 return false;
2324 switch ( nEvent )
2326 case SalEvent::MouseMove:
2327 bRet = ImplHandleSalMouseMove( pWindow, static_cast<SalMouseEvent const *>(pEvent) );
2328 break;
2329 case SalEvent::ExternalMouseMove:
2331 MouseEvent const * pMouseEvt = static_cast<MouseEvent const *>(pEvent);
2332 SalMouseEvent aSalMouseEvent;
2334 aSalMouseEvent.mnTime = tools::Time::GetSystemTicks();
2335 aSalMouseEvent.mnX = pMouseEvt->GetPosPixel().X();
2336 aSalMouseEvent.mnY = pMouseEvt->GetPosPixel().Y();
2337 aSalMouseEvent.mnButton = 0;
2338 aSalMouseEvent.mnCode = pMouseEvt->GetButtons() | pMouseEvt->GetModifier();
2340 bRet = ImplHandleSalMouseMove( pWindow, &aSalMouseEvent );
2342 break;
2343 case SalEvent::MouseLeave:
2344 bRet = ImplHandleSalMouseLeave( pWindow, static_cast<SalMouseEvent const *>(pEvent) );
2345 break;
2346 case SalEvent::MouseButtonDown:
2347 bRet = ImplHandleSalMouseButtonDown( pWindow, static_cast<SalMouseEvent const *>(pEvent) );
2348 break;
2349 case SalEvent::ExternalMouseButtonDown:
2351 MouseEvent const * pMouseEvt = static_cast<MouseEvent const *>(pEvent);
2352 SalMouseEvent aSalMouseEvent;
2354 aSalMouseEvent.mnTime = tools::Time::GetSystemTicks();
2355 aSalMouseEvent.mnX = pMouseEvt->GetPosPixel().X();
2356 aSalMouseEvent.mnY = pMouseEvt->GetPosPixel().Y();
2357 aSalMouseEvent.mnButton = pMouseEvt->GetButtons();
2358 aSalMouseEvent.mnCode = pMouseEvt->GetButtons() | pMouseEvt->GetModifier();
2360 bRet = ImplHandleSalMouseButtonDown( pWindow, &aSalMouseEvent );
2362 break;
2363 case SalEvent::MouseButtonUp:
2364 bRet = ImplHandleSalMouseButtonUp( pWindow, static_cast<SalMouseEvent const *>(pEvent) );
2365 break;
2366 case SalEvent::ExternalMouseButtonUp:
2368 MouseEvent const * pMouseEvt = static_cast<MouseEvent const *>(pEvent);
2369 SalMouseEvent aSalMouseEvent;
2371 aSalMouseEvent.mnTime = tools::Time::GetSystemTicks();
2372 aSalMouseEvent.mnX = pMouseEvt->GetPosPixel().X();
2373 aSalMouseEvent.mnY = pMouseEvt->GetPosPixel().Y();
2374 aSalMouseEvent.mnButton = pMouseEvt->GetButtons();
2375 aSalMouseEvent.mnCode = pMouseEvt->GetButtons() | pMouseEvt->GetModifier();
2377 bRet = ImplHandleSalMouseButtonUp( pWindow, &aSalMouseEvent );
2379 break;
2380 case SalEvent::MouseActivate:
2381 bRet = false;
2382 break;
2383 case SalEvent::KeyInput:
2385 SalKeyEvent const * pKeyEvt = static_cast<SalKeyEvent const *>(pEvent);
2386 bRet = ImplHandleKey( pWindow, MouseNotifyEvent::KEYINPUT,
2387 pKeyEvt->mnCode, pKeyEvt->mnCharCode, pKeyEvt->mnRepeat, true );
2389 break;
2390 case SalEvent::ExternalKeyInput:
2392 KeyEvent const * pKeyEvt = static_cast<KeyEvent const *>(pEvent);
2393 bRet = ImplHandleKey( pWindow, MouseNotifyEvent::KEYINPUT,
2394 pKeyEvt->GetKeyCode().GetFullCode(), pKeyEvt->GetCharCode(), pKeyEvt->GetRepeat(), false );
2396 break;
2397 case SalEvent::KeyUp:
2399 SalKeyEvent const * pKeyEvt = static_cast<SalKeyEvent const *>(pEvent);
2400 bRet = ImplHandleKey( pWindow, MouseNotifyEvent::KEYUP,
2401 pKeyEvt->mnCode, pKeyEvt->mnCharCode, pKeyEvt->mnRepeat, true );
2403 break;
2404 case SalEvent::ExternalKeyUp:
2406 KeyEvent const * pKeyEvt = static_cast<KeyEvent const *>(pEvent);
2407 bRet = ImplHandleKey( pWindow, MouseNotifyEvent::KEYUP,
2408 pKeyEvt->GetKeyCode().GetFullCode(), pKeyEvt->GetCharCode(), pKeyEvt->GetRepeat(), false );
2410 break;
2411 case SalEvent::KeyModChange:
2412 ImplHandleSalKeyMod( pWindow, static_cast<SalKeyModEvent const *>(pEvent) );
2413 break;
2415 case SalEvent::InputLanguageChange:
2416 ImplHandleInputLanguageChange( pWindow );
2417 break;
2419 case SalEvent::MenuActivate:
2420 case SalEvent::MenuDeactivate:
2421 case SalEvent::MenuHighlight:
2422 case SalEvent::MenuCommand:
2423 case SalEvent::MenuButtonCommand:
2424 bRet = ImplHandleMenuEvent( pWindow, const_cast<SalMenuEvent *>(static_cast<SalMenuEvent const *>(pEvent)), nEvent );
2425 break;
2427 case SalEvent::WheelMouse:
2428 bRet = ImplHandleWheelEvent( pWindow, *static_cast<const SalWheelMouseEvent*>(pEvent));
2429 break;
2431 case SalEvent::Paint:
2433 SalPaintEvent const * pPaintEvt = static_cast<SalPaintEvent const *>(pEvent);
2435 if( AllSettings::GetLayoutRTL() )
2437 SalFrame* pSalFrame = pWindow->ImplGetWindowImpl()->mpFrame;
2438 const_cast<SalPaintEvent *>(pPaintEvt)->mnBoundX = pSalFrame->maGeometry.nWidth-pPaintEvt->mnBoundWidth-pPaintEvt->mnBoundX;
2441 tools::Rectangle aBoundRect( Point( pPaintEvt->mnBoundX, pPaintEvt->mnBoundY ),
2442 Size( pPaintEvt->mnBoundWidth, pPaintEvt->mnBoundHeight ) );
2443 ImplHandlePaint( pWindow, aBoundRect, pPaintEvt->mbImmediateUpdate );
2445 break;
2447 case SalEvent::Move:
2448 ImplHandleMove( pWindow );
2449 break;
2451 case SalEvent::Resize:
2453 long nNewWidth;
2454 long nNewHeight;
2455 pWindow->ImplGetWindowImpl()->mpFrame->GetClientSize( nNewWidth, nNewHeight );
2456 ImplHandleResize( pWindow, nNewWidth, nNewHeight );
2458 break;
2460 case SalEvent::MoveResize:
2462 SalFrameGeometry g = pWindow->ImplGetWindowImpl()->mpFrame->GetGeometry();
2463 ImplHandleMoveResize( pWindow, g.nWidth, g.nHeight );
2465 break;
2467 case SalEvent::ClosePopups:
2469 KillOwnPopups( pWindow );
2471 break;
2473 case SalEvent::GetFocus:
2474 ImplHandleGetFocus( pWindow );
2475 break;
2476 case SalEvent::LoseFocus:
2477 ImplHandleLoseFocus( pWindow );
2478 break;
2480 case SalEvent::Close:
2481 ImplHandleClose( pWindow );
2482 break;
2484 case SalEvent::Shutdown:
2486 static bool bInQueryExit = false;
2487 if( !bInQueryExit )
2489 bInQueryExit = true;
2490 if ( GetpApp()->QueryExit() )
2492 // end the message loop
2493 Application::Quit();
2494 return false;
2496 else
2498 bInQueryExit = false;
2499 return true;
2502 return false;
2505 case SalEvent::SettingsChanged:
2506 case SalEvent::PrinterChanged:
2507 case SalEvent::DisplayChanged:
2508 case SalEvent::FontChanged:
2509 ImplHandleSalSettings( nEvent );
2510 break;
2512 case SalEvent::UserEvent:
2513 ImplHandleUserEvent( const_cast<ImplSVEvent *>(static_cast<ImplSVEvent const *>(pEvent)) );
2514 break;
2516 case SalEvent::ExtTextInput:
2518 SalExtTextInputEvent const * pEvt = static_cast<SalExtTextInputEvent const *>(pEvent);
2519 bRet = ImplHandleExtTextInput( pWindow,
2520 pEvt->maText, pEvt->mpTextAttr,
2521 pEvt->mnCursorPos, pEvt->mnCursorFlags );
2523 break;
2524 case SalEvent::EndExtTextInput:
2525 bRet = ImplHandleEndExtTextInput();
2526 break;
2527 case SalEvent::ExtTextInputPos:
2528 ImplHandleSalExtTextInputPos( pWindow, const_cast<SalExtTextInputPosEvent *>(static_cast<SalExtTextInputPosEvent const *>(pEvent)) );
2529 break;
2530 case SalEvent::InputContextChange:
2531 bRet = ImplHandleInputContextChange( pWindow );
2532 break;
2533 case SalEvent::ShowDialog:
2535 ShowDialogId nLOKWindowId = static_cast<ShowDialogId>(reinterpret_cast<sal_IntPtr>(pEvent));
2536 bRet = ImplHandleShowDialog( pWindow, nLOKWindowId );
2538 break;
2539 case SalEvent::SurroundingTextRequest:
2540 ImplHandleSalSurroundingTextRequest( pWindow, const_cast<SalSurroundingTextRequestEvent *>(static_cast<SalSurroundingTextRequestEvent const *>(pEvent)) );
2541 break;
2542 case SalEvent::SurroundingTextSelectionChange:
2544 SalSurroundingTextSelectionChangeEvent const * pEvt
2545 = static_cast<SalSurroundingTextSelectionChangeEvent const *>(pEvent);
2546 ImplHandleSurroundingTextSelectionChange( pWindow,
2547 pEvt->mnStart,
2548 pEvt->mnEnd );
2549 [[fallthrough]]; // TODO: Fallthrough really intended?
2551 case SalEvent::StartReconversion:
2552 ImplHandleStartReconversion( pWindow );
2553 break;
2555 case SalEvent::QueryCharPosition:
2556 ImplHandleSalQueryCharPosition( pWindow, const_cast<SalQueryCharPositionEvent *>(static_cast<SalQueryCharPositionEvent const *>(pEvent)) );
2557 break;
2559 case SalEvent::Swipe:
2560 bRet = ImplHandleSwipe(pWindow, *static_cast<const SalSwipeEvent*>(pEvent));
2561 break;
2563 case SalEvent::LongPress:
2564 bRet = ImplHandleLongPress(pWindow, *static_cast<const SalLongPressEvent*>(pEvent));
2565 break;
2567 case SalEvent::ExternalGesture:
2569 auto const * pGestureEvent = static_cast<GestureEvent const *>(pEvent);
2571 SalGestureEvent aSalGestureEvent;
2572 aSalGestureEvent.mfOffset = pGestureEvent->mnOffset;
2573 aSalGestureEvent.mnX = pGestureEvent->mnX;
2574 aSalGestureEvent.mnY = pGestureEvent->mnY;
2575 aSalGestureEvent.meEventType = pGestureEvent->meEventType;
2576 aSalGestureEvent.meOrientation = pGestureEvent->meOrientation;
2578 bRet = ImplHandleGestureEvent(pWindow, aSalGestureEvent);
2580 break;
2581 case SalEvent::Gesture:
2583 auto const * aSalGestureEvent = static_cast<SalGestureEvent const *>(pEvent);
2584 bRet = ImplHandleGestureEvent(pWindow, *aSalGestureEvent);
2586 break;
2587 default:
2588 SAL_WARN( "vcl.layout", "ImplWindowFrameProc(): unknown event (" << static_cast<int>(nEvent) << ")" );
2589 break;
2592 return bRet;
2595 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */