build fix: no comphelper/profilezone.hxx in this branch
[LibreOffice.git] / vcl / source / window / winproc.cxx
blobf184555a75f95de22264ac459a82c9cb90f10bae
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>
23 #include <unotools/localedatawrapper.hxx>
25 #include <comphelper/lok.hxx>
26 #include <vcl/i18nhelp.hxx>
27 #include <vcl/unohelp.hxx>
28 #include <vcl/timer.hxx>
29 #include <vcl/event.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/lazydelete.hxx>
41 #include <touch/touch.h>
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 <salgdi.hxx>
52 #include "dndlistenercontainer.hxx"
54 #include <com/sun/star/datatransfer/dnd/XDragSource.hpp>
55 #include <com/sun/star/awt/MouseEvent.hpp>
57 #define IMPL_MIN_NEEDSYSWIN 49
59 bool ImplCallPreNotify( NotifyEvent& rEvt )
61 return Application::CallEventHooks( rEvt )
62 || rEvt.GetWindow()->CompatPreNotify( rEvt );
65 static bool ImplHandleMouseFloatMode( vcl::Window* pChild, const Point& rMousePos,
66 sal_uInt16 nCode, MouseNotifyEvent nSVEvent,
67 bool bMouseLeave )
69 ImplSVData* pSVData = ImplGetSVData();
71 if ( pSVData->maWinData.mpFirstFloat && !pSVData->maWinData.mpCaptureWin &&
72 !pSVData->maWinData.mpFirstFloat->ImplIsFloatPopupModeWindow( pChild ) )
75 * #93895# since floats are system windows, coordinates have
76 * to be converted to float relative for the hittest
78 HitTest nHitTest = HITTEST_OUTSIDE;
79 FloatingWindow* pFloat = pSVData->maWinData.mpFirstFloat->ImplFloatHitTest( pChild, rMousePos, nHitTest );
80 FloatingWindow* pLastLevelFloat;
81 FloatWinPopupFlags nPopupFlags;
82 if ( nSVEvent == MouseNotifyEvent::MOUSEMOVE )
84 if ( bMouseLeave )
85 return true;
87 if ( !pFloat || (nHitTest == HITTEST_RECT) )
89 if ( pSVData->maHelpData.mpHelpWin && !pSVData->maHelpData.mbKeyboardHelp )
90 ImplDestroyHelpWindow( true );
91 pChild->ImplGetFrame()->SetPointer( PointerStyle::Arrow );
92 return true;
95 else
97 if ( nCode & MOUSE_LEFT )
99 if ( nSVEvent == MouseNotifyEvent::MOUSEBUTTONDOWN )
101 if ( !pFloat )
103 pLastLevelFloat = pSVData->maWinData.mpFirstFloat->ImplFindLastLevelFloat();
104 pLastLevelFloat->EndPopupMode( FloatWinPopupEndFlags::Cancel | FloatWinPopupEndFlags::CloseAll );
105 return true;
107 else if ( nHitTest == HITTEST_RECT )
109 pFloat->ImplSetMouseDown();
110 return true;
113 else
115 if ( pFloat )
117 if ( nHitTest == HITTEST_RECT )
119 if ( pFloat->ImplIsMouseDown() )
120 pFloat->EndPopupMode( FloatWinPopupEndFlags::Cancel );
121 return true;
124 else
126 pLastLevelFloat = pSVData->maWinData.mpFirstFloat->ImplFindLastLevelFloat();
127 nPopupFlags = pLastLevelFloat->GetPopupModeFlags();
128 if ( !(nPopupFlags & FloatWinPopupFlags::NoMouseUpClose) )
130 pLastLevelFloat->EndPopupMode( FloatWinPopupEndFlags::Cancel | FloatWinPopupEndFlags::CloseAll );
131 return true;
136 else
138 if ( !pFloat )
140 pLastLevelFloat = pSVData->maWinData.mpFirstFloat->ImplFindLastLevelFloat();
141 nPopupFlags = pLastLevelFloat->GetPopupModeFlags();
142 if ( nPopupFlags & FloatWinPopupFlags::AllMouseButtonClose )
144 if ( (nPopupFlags & FloatWinPopupFlags::NoMouseUpClose) &&
145 (nSVEvent == MouseNotifyEvent::MOUSEBUTTONUP) )
146 return true;
147 pLastLevelFloat->EndPopupMode( FloatWinPopupEndFlags::Cancel | FloatWinPopupEndFlags::CloseAll );
148 return true;
150 else
151 return true;
157 return false;
160 static void ImplHandleMouseHelpRequest( vcl::Window* pChild, const Point& rMousePos )
162 if (comphelper::LibreOfficeKit::isActive())
163 return;
165 ImplSVData* pSVData = ImplGetSVData();
166 if ( !pSVData->maHelpData.mpHelpWin ||
167 !( pSVData->maHelpData.mpHelpWin->IsWindowOrChild( pChild ) ||
168 pChild->IsWindowOrChild( pSVData->maHelpData.mpHelpWin ) ) )
170 HelpEventMode nHelpMode = HelpEventMode::NONE;
171 if ( pSVData->maHelpData.mbQuickHelp )
172 nHelpMode = HelpEventMode::QUICK;
173 if ( pSVData->maHelpData.mbBalloonHelp )
174 nHelpMode |= HelpEventMode::BALLOON;
175 if ( bool(nHelpMode) )
177 if ( pChild->IsInputEnabled() && !pChild->IsInModalMode() )
179 HelpEvent aHelpEvent( rMousePos, nHelpMode );
180 pSVData->maHelpData.mbRequestingHelp = true;
181 pChild->RequestHelp( aHelpEvent );
182 pSVData->maHelpData.mbRequestingHelp = false;
184 // #104172# do not kill keyboard activated tooltips
185 else if ( pSVData->maHelpData.mpHelpWin && !pSVData->maHelpData.mbKeyboardHelp)
187 ImplDestroyHelpWindow( true );
193 static void ImplSetMousePointer( vcl::Window* pChild )
195 ImplSVData* pSVData = ImplGetSVData();
196 if ( pSVData->maHelpData.mbExtHelpMode )
197 pChild->ImplGetFrame()->SetPointer( PointerStyle::Help );
198 else
199 pChild->ImplGetFrame()->SetPointer( pChild->ImplGetMousePointer() );
202 static bool ImplCallCommand( const VclPtr<vcl::Window>& pChild, CommandEventId nEvt, void* pData = nullptr,
203 bool bMouse = false, Point* pPos = nullptr )
205 Point aPos;
206 if ( pPos )
207 aPos = *pPos;
208 else
210 if( bMouse )
211 aPos = pChild->GetPointerPosPixel();
212 else
214 // simulate mouseposition at center of window
215 Size aSize( pChild->GetOutputSizePixel() );
216 aPos = Point( aSize.getWidth()/2, aSize.getHeight()/2 );
220 CommandEvent aCEvt( aPos, nEvt, bMouse, pData );
221 NotifyEvent aNCmdEvt( MouseNotifyEvent::COMMAND, pChild, &aCEvt );
222 bool bPreNotify = ImplCallPreNotify( aNCmdEvt );
223 if ( pChild->IsDisposed() )
224 return false;
225 if ( !bPreNotify )
227 pChild->ImplGetWindowImpl()->mbCommand = false;
228 pChild->Command( aCEvt );
230 if( pChild->IsDisposed() )
231 return false;
232 pChild->ImplNotifyKeyMouseCommandEventListeners( aNCmdEvt );
233 if ( pChild->IsDisposed() )
234 return false;
235 if ( pChild->ImplGetWindowImpl()->mbCommand )
236 return true;
239 return false;
242 /* #i34277# delayed context menu activation;
243 * necessary if there already was a popup menu running.
246 struct ContextMenuEvent
248 VclPtr<vcl::Window> pWindow;
249 Point aChildPos;
252 static void ContextMenuEventLink( void* pCEvent, void* )
254 ContextMenuEvent* pEv = static_cast<ContextMenuEvent*>(pCEvent);
256 if( ! pEv->pWindow->IsDisposed() )
258 ImplCallCommand( pEv->pWindow, CommandEventId::ContextMenu, nullptr, true, &pEv->aChildPos );
260 delete pEv;
263 bool ImplHandleMouseEvent( const VclPtr<vcl::Window>& xWindow, MouseNotifyEvent nSVEvent, bool bMouseLeave,
264 long nX, long nY, sal_uInt64 nMsgTime,
265 sal_uInt16 nCode, MouseEventModifiers nMode )
267 ImplSVData* pSVData = ImplGetSVData();
268 Point aMousePos( nX, nY );
269 VclPtr<vcl::Window> pChild;
270 bool bRet(false);
271 sal_uInt16 nClicks(0);
272 ImplFrameData* pWinFrameData = xWindow->ImplGetFrameData();
273 sal_uInt16 nOldCode = pWinFrameData->mnMouseCode;
275 // we need a mousemove event, before we get a mousebuttondown or a
276 // mousebuttonup event
277 if ( (nSVEvent == MouseNotifyEvent::MOUSEBUTTONDOWN) || (nSVEvent == MouseNotifyEvent::MOUSEBUTTONUP) )
279 if ( (nSVEvent == MouseNotifyEvent::MOUSEBUTTONUP) && pSVData->maHelpData.mbExtHelpMode )
280 Help::EndExtHelp();
281 if ( pSVData->maHelpData.mpHelpWin )
283 if( xWindow->ImplGetWindow() == pSVData->maHelpData.mpHelpWin )
285 ImplDestroyHelpWindow( false );
286 return true; // xWindow is dead now - avoid crash!
288 else
289 ImplDestroyHelpWindow( true );
292 if ( (pWinFrameData->mnLastMouseX != nX) ||
293 (pWinFrameData->mnLastMouseY != nY) )
295 sal_uInt16 nMoveCode = nCode & ~(MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE);
296 ImplHandleMouseEvent(xWindow, MouseNotifyEvent::MOUSEMOVE, false, nX, nY, nMsgTime, nMoveCode, nMode);
300 // update frame data
301 pWinFrameData->mnBeforeLastMouseX = pWinFrameData->mnLastMouseX;
302 pWinFrameData->mnBeforeLastMouseY = pWinFrameData->mnLastMouseY;
303 pWinFrameData->mnLastMouseX = nX;
304 pWinFrameData->mnLastMouseY = nY;
305 pWinFrameData->mnMouseCode = nCode;
306 MouseEventModifiers nTmpMask = MouseEventModifiers::SYNTHETIC | MouseEventModifiers::MODIFIERCHANGED;
307 pWinFrameData->mnMouseMode = nMode & ~nTmpMask;
308 if ( bMouseLeave )
310 pWinFrameData->mbMouseIn = false;
311 if ( pSVData->maHelpData.mpHelpWin && !pSVData->maHelpData.mbKeyboardHelp )
313 ImplDestroyHelpWindow( true );
315 if ( xWindow->IsDisposed() )
316 return true; // xWindow is dead now - avoid crash! (#122045#)
319 else
320 pWinFrameData->mbMouseIn = true;
322 DBG_ASSERT( !pSVData->maWinData.mpTrackWin ||
323 (pSVData->maWinData.mpTrackWin == pSVData->maWinData.mpCaptureWin),
324 "ImplHandleMouseEvent: TrackWin != CaptureWin" );
326 // AutoScrollMode
327 if ( pSVData->maWinData.mpAutoScrollWin && (nSVEvent == MouseNotifyEvent::MOUSEBUTTONDOWN) )
329 pSVData->maWinData.mpAutoScrollWin->EndAutoScroll();
330 return true;
333 // find mouse window
334 if ( pSVData->maWinData.mpCaptureWin )
336 pChild = pSVData->maWinData.mpCaptureWin;
338 SAL_WARN_IF( xWindow != pChild->ImplGetFrameWindow(), "vcl",
339 "ImplHandleMouseEvent: mouse event is not sent to capture window" );
341 // java client cannot capture mouse correctly
342 if ( xWindow != pChild->ImplGetFrameWindow() )
343 return false;
345 if ( bMouseLeave )
346 return false;
348 else
350 if ( bMouseLeave )
351 pChild = nullptr;
352 else
353 pChild = xWindow->ImplFindWindow( aMousePos );
356 // test this because mouse events are buffered in the remote version
357 // and size may not be in sync
358 if ( !pChild && !bMouseLeave )
359 return false;
361 // execute a few tests and catch the message or implement the status
362 if ( pChild )
364 if( pChild->ImplIsAntiparallel() )
366 // - RTL - re-mirror frame pos at pChild
367 const OutputDevice *pChildWinOutDev = pChild->GetOutDev();
368 pChildWinOutDev->ReMirror( aMousePos );
371 // no mouse messages to disabled windows
372 // #106845# if the window was disabled during capturing we have to pass the mouse events to release capturing
373 if ( pSVData->maWinData.mpCaptureWin.get() != pChild && (!pChild->IsEnabled() || !pChild->IsInputEnabled() || pChild->IsInModalMode() ) )
375 ImplHandleMouseFloatMode( pChild, aMousePos, nCode, nSVEvent, bMouseLeave );
376 if ( nSVEvent == MouseNotifyEvent::MOUSEMOVE )
378 ImplHandleMouseHelpRequest( pChild, aMousePos );
379 if( pWinFrameData->mpMouseMoveWin.get() != pChild )
380 nMode |= MouseEventModifiers::ENTERWINDOW;
383 // Call the hook also, if Window is disabled
384 Point aChildPos = pChild->ImplFrameToOutput( aMousePos );
385 MouseEvent aMEvt( aChildPos, pWinFrameData->mnClickCount, nMode, nCode, nCode );
386 NotifyEvent aNEvt( nSVEvent, pChild, &aMEvt );
387 Application::CallEventHooks( aNEvt );
389 if( pChild->IsCallHandlersOnInputDisabled() )
391 pWinFrameData->mpMouseMoveWin = pChild;
392 pChild->ImplNotifyKeyMouseCommandEventListeners( aNEvt );
395 if ( nSVEvent == MouseNotifyEvent::MOUSEBUTTONDOWN )
396 return true;
397 else
399 // Set normal MousePointer for disabled windows
400 if ( nSVEvent == MouseNotifyEvent::MOUSEMOVE )
401 ImplSetMousePointer( pChild );
403 return false;
407 // End ExtTextInput-Mode, if the user click in the same TopLevel Window
408 if ( pSVData->maWinData.mpExtTextInputWin &&
409 ((nSVEvent == MouseNotifyEvent::MOUSEBUTTONDOWN) ||
410 (nSVEvent == MouseNotifyEvent::MOUSEBUTTONUP)) )
411 pSVData->maWinData.mpExtTextInputWin->EndExtTextInput();
414 // determine mouse event data
415 if ( nSVEvent == MouseNotifyEvent::MOUSEMOVE )
417 // check if MouseMove belongs to same window and if the
418 // status did not change
419 if ( pChild )
421 Point aChildMousePos = pChild->ImplFrameToOutput( aMousePos );
422 if ( !bMouseLeave &&
423 (pChild == pWinFrameData->mpMouseMoveWin) &&
424 (aChildMousePos.X() == pWinFrameData->mnLastMouseWinX) &&
425 (aChildMousePos.Y() == pWinFrameData->mnLastMouseWinY) &&
426 (nOldCode == pWinFrameData->mnMouseCode) )
428 // set mouse pointer anew, as it could have changed
429 // due to the mode switch
430 ImplSetMousePointer( pChild );
431 return false;
434 pWinFrameData->mnLastMouseWinX = aChildMousePos.X();
435 pWinFrameData->mnLastMouseWinY = aChildMousePos.Y();
438 // mouse click
439 nClicks = pWinFrameData->mnClickCount;
441 // call Start-Drag handler if required
442 // Warning: should be called before Move, as otherwise during
443 // fast mouse movements the applications move to the selection state
444 vcl::Window* pMouseDownWin = pWinFrameData->mpMouseDownWin;
445 if ( pMouseDownWin )
447 // check for matching StartDrag mode. We only compare
448 // the status of the mouse buttons, such that e. g. Mod1 can
449 // change immediately to the copy mode
450 const MouseSettings& rMSettings = pMouseDownWin->GetSettings().GetMouseSettings();
451 if ( (nCode & (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE)) ==
452 (rMSettings.GetStartDragCode() & (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE)) )
454 if ( !pMouseDownWin->ImplGetFrameData()->mbStartDragCalled )
456 long nDragW = rMSettings.GetStartDragWidth();
457 long nDragH = rMSettings.GetStartDragHeight();
458 //long nMouseX = nX;
459 //long nMouseY = nY;
460 long nMouseX = aMousePos.X(); // #106074# use the possibly re-mirrored coordinates (RTL) ! nX,nY are unmodified !
461 long nMouseY = aMousePos.Y();
462 if ( !(((nMouseX-nDragW) <= pMouseDownWin->ImplGetFrameData()->mnFirstMouseX) &&
463 ((nMouseX+nDragW) >= pMouseDownWin->ImplGetFrameData()->mnFirstMouseX)) ||
464 !(((nMouseY-nDragH) <= pMouseDownWin->ImplGetFrameData()->mnFirstMouseY) &&
465 ((nMouseY+nDragH) >= pMouseDownWin->ImplGetFrameData()->mnFirstMouseY)) )
467 pMouseDownWin->ImplGetFrameData()->mbStartDragCalled = true;
469 // Check if drag source provides it's own recognizer
470 if( pMouseDownWin->ImplGetFrameData()->mbInternalDragGestureRecognizer )
472 // query DropTarget from child window
473 css::uno::Reference< css::datatransfer::dnd::XDragGestureRecognizer > xDragGestureRecognizer =
474 css::uno::Reference< css::datatransfer::dnd::XDragGestureRecognizer > ( pMouseDownWin->ImplGetWindowImpl()->mxDNDListenerContainer,
475 css::uno::UNO_QUERY );
477 if( xDragGestureRecognizer.is() )
479 // retrieve mouse position relative to mouse down window
480 Point relLoc = pMouseDownWin->ImplFrameToOutput( Point(
481 pMouseDownWin->ImplGetFrameData()->mnFirstMouseX,
482 pMouseDownWin->ImplGetFrameData()->mnFirstMouseY ) );
484 // create a uno mouse event out of the available data
485 css::awt::MouseEvent aMouseEvent( static_cast < css::uno::XInterface * > ( nullptr ),
486 #ifdef MACOSX
487 nCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_MOD3),
488 #else
489 nCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2),
490 #endif
491 nCode & (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE),
492 nMouseX,
493 nMouseY,
494 nClicks,
495 false );
497 SolarMutexReleaser aReleaser;
499 // FIXME: where do I get Action from ?
500 css::uno::Reference< css::datatransfer::dnd::XDragSource > xDragSource = pMouseDownWin->GetDragSource();
502 if( xDragSource.is() )
504 static_cast < DNDListenerContainer * > ( xDragGestureRecognizer.get() )->fireDragGestureEvent( 0,
505 relLoc.X(), relLoc.Y(), xDragSource, css::uno::makeAny( aMouseEvent ) );
512 else
513 pMouseDownWin->ImplGetFrameData()->mbStartDragCalled = true;
516 // test for mouseleave and mouseenter
517 VclPtr<vcl::Window> pMouseMoveWin = pWinFrameData->mpMouseMoveWin;
518 if ( pChild != pMouseMoveWin )
520 if ( pMouseMoveWin )
522 Point aLeaveMousePos = pMouseMoveWin->ImplFrameToOutput( aMousePos );
523 MouseEvent aMLeaveEvt( aLeaveMousePos, nClicks, nMode | MouseEventModifiers::LEAVEWINDOW, nCode, nCode );
524 NotifyEvent aNLeaveEvt( MouseNotifyEvent::MOUSEMOVE, pMouseMoveWin, &aMLeaveEvt );
525 pWinFrameData->mbInMouseMove = true;
526 pMouseMoveWin->ImplGetWinData()->mbMouseOver = false;
528 // A MouseLeave can destroy this window
529 if ( !ImplCallPreNotify( aNLeaveEvt ) )
531 pMouseMoveWin->MouseMove( aMLeaveEvt );
532 if( !pMouseMoveWin->IsDisposed() )
533 aNLeaveEvt.GetWindow()->ImplNotifyKeyMouseCommandEventListeners( aNLeaveEvt );
536 pWinFrameData->mpMouseMoveWin = nullptr;
537 pWinFrameData->mbInMouseMove = false;
539 if ( pChild )
541 if ( pChild->IsDisposed() )
542 pChild = nullptr;
544 if ( pMouseMoveWin->IsDisposed() )
545 return true;
548 nMode |= MouseEventModifiers::ENTERWINDOW;
550 pWinFrameData->mpMouseMoveWin = pChild;
551 if( pChild )
552 pChild->ImplGetWinData()->mbMouseOver = true;
554 // MouseLeave
555 if ( !pChild )
556 return false;
558 else
560 if (pChild)
562 // mouse click
563 if ( nSVEvent == MouseNotifyEvent::MOUSEBUTTONDOWN )
565 const MouseSettings& rMSettings = pChild->GetSettings().GetMouseSettings();
566 sal_uInt64 nDblClkTime = rMSettings.GetDoubleClickTime();
567 long nDblClkW = rMSettings.GetDoubleClickWidth();
568 long nDblClkH = rMSettings.GetDoubleClickHeight();
569 //long nMouseX = nX;
570 //long nMouseY = nY;
571 long nMouseX = aMousePos.X(); // #106074# use the possibly re-mirrored coordinates (RTL) ! nX,nY are unmodified !
572 long nMouseY = aMousePos.Y();
574 if ( (pChild == pChild->ImplGetFrameData()->mpMouseDownWin) &&
575 (nCode == pChild->ImplGetFrameData()->mnFirstMouseCode) &&
576 ((nMsgTime-pChild->ImplGetFrameData()->mnMouseDownTime) < nDblClkTime) &&
577 ((nMouseX-nDblClkW) <= pChild->ImplGetFrameData()->mnFirstMouseX) &&
578 ((nMouseX+nDblClkW) >= pChild->ImplGetFrameData()->mnFirstMouseX) &&
579 ((nMouseY-nDblClkH) <= pChild->ImplGetFrameData()->mnFirstMouseY) &&
580 ((nMouseY+nDblClkH) >= pChild->ImplGetFrameData()->mnFirstMouseY) )
582 pChild->ImplGetFrameData()->mnClickCount++;
583 pChild->ImplGetFrameData()->mbStartDragCalled = true;
585 else
587 pChild->ImplGetFrameData()->mpMouseDownWin = pChild;
588 pChild->ImplGetFrameData()->mnClickCount = 1;
589 pChild->ImplGetFrameData()->mnFirstMouseX = nMouseX;
590 pChild->ImplGetFrameData()->mnFirstMouseY = nMouseY;
591 pChild->ImplGetFrameData()->mnFirstMouseCode = nCode;
592 pChild->ImplGetFrameData()->mbStartDragCalled = !((nCode & (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE)) ==
593 (rMSettings.GetStartDragCode() & (MOUSE_LEFT | MOUSE_RIGHT | MOUSE_MIDDLE)));
595 pChild->ImplGetFrameData()->mnMouseDownTime = nMsgTime;
597 nClicks = pChild->ImplGetFrameData()->mnClickCount;
600 pSVData->maAppData.mnLastInputTime = tools::Time::GetSystemTicks();
603 SAL_WARN_IF( !pChild, "vcl", "ImplHandleMouseEvent: pChild == NULL" );
605 if (!pChild)
606 return false;
608 // create mouse event
609 Point aChildPos = pChild->ImplFrameToOutput( aMousePos );
610 MouseEvent aMEvt( aChildPos, nClicks, nMode, nCode, nCode );
613 // tracking window gets the mouse events
614 if ( pSVData->maWinData.mpTrackWin )
615 pChild = pSVData->maWinData.mpTrackWin;
617 // handle FloatingMode
618 if ( !pSVData->maWinData.mpTrackWin && pSVData->maWinData.mpFirstFloat )
620 if ( ImplHandleMouseFloatMode( pChild, aMousePos, nCode, nSVEvent, bMouseLeave ) )
622 if ( !pChild->IsDisposed() )
624 pChild->ImplGetFrameData()->mbStartDragCalled = true;
626 return true;
630 // call handler
631 bool bDrag = false;
632 bool bCallHelpRequest = true;
633 SAL_WARN_IF( !pChild, "vcl", "ImplHandleMouseEvent: pChild is NULL" );
635 if (!pChild)
636 return false;
638 NotifyEvent aNEvt( nSVEvent, pChild, &aMEvt );
639 if ( nSVEvent == MouseNotifyEvent::MOUSEMOVE )
640 pChild->ImplGetFrameData()->mbInMouseMove = true;
642 // bring window into foreground on mouseclick
643 if ( nSVEvent == MouseNotifyEvent::MOUSEBUTTONDOWN )
645 if( !pSVData->maWinData.mpFirstFloat && // totop for floating windows in popup would change the focus and would close them immediately
646 !(pChild->ImplGetFrameWindow()->GetStyle() & WB_OWNERDRAWDECORATION) ) // ownerdrawdecorated windows must never grab focus
647 pChild->ToTop();
648 if ( pChild->IsDisposed() )
649 return true;
652 if ( ImplCallPreNotify( aNEvt ) || pChild->IsDisposed() )
653 bRet = true;
654 else
656 bRet = false;
657 if ( nSVEvent == MouseNotifyEvent::MOUSEMOVE )
659 if ( pSVData->maWinData.mpTrackWin )
661 TrackingEvent aTEvt( aMEvt );
662 pChild->Tracking( aTEvt );
663 if ( !pChild->IsDisposed() )
665 // When ScrollRepeat, we restart the timer
666 if ( pSVData->maWinData.mpTrackTimer &&
667 (pSVData->maWinData.mnTrackFlags & StartTrackingFlags::ScrollRepeat) )
668 pSVData->maWinData.mpTrackTimer->Start();
670 bCallHelpRequest = false;
671 bRet = true;
673 else
675 // Auto-ToTop
676 if ( !pSVData->maWinData.mpCaptureWin &&
677 (pChild->GetSettings().GetMouseSettings().GetOptions() & MouseSettingsOptions::AutoFocus) )
678 pChild->ToTop( ToTopFlags::NoGrabFocus );
680 if( pChild->IsDisposed() )
681 bCallHelpRequest = false;
682 else
684 // if the MouseMove handler changes the help window's visibility
685 // the HelpRequest handler should not be called anymore
686 vcl::Window* pOldHelpTextWin = pSVData->maHelpData.mpHelpWin;
687 pChild->ImplGetWindowImpl()->mbMouseMove = false;
688 pChild->MouseMove( aMEvt );
689 if ( pOldHelpTextWin != pSVData->maHelpData.mpHelpWin )
690 bCallHelpRequest = false;
694 else if ( nSVEvent == MouseNotifyEvent::MOUSEBUTTONDOWN )
696 if ( pSVData->maWinData.mpTrackWin &&
697 !(pSVData->maWinData.mnTrackFlags & StartTrackingFlags::MouseButtonDown) )
698 bRet = true;
699 else
701 pChild->ImplGetWindowImpl()->mbMouseButtonDown = false;
702 pChild->MouseButtonDown( aMEvt );
705 else
707 if ( pSVData->maWinData.mpTrackWin )
709 pChild->EndTracking();
710 bRet = true;
712 else
714 pChild->ImplGetWindowImpl()->mbMouseButtonUp = false;
715 pChild->MouseButtonUp( aMEvt );
719 assert(aNEvt.GetWindow() == pChild);
721 if (!pChild->IsDisposed())
722 pChild->ImplNotifyKeyMouseCommandEventListeners( aNEvt );
725 if (pChild->IsDisposed())
726 return true;
728 if ( nSVEvent == MouseNotifyEvent::MOUSEMOVE )
729 pChild->ImplGetWindowImpl()->mpFrameData->mbInMouseMove = false;
731 if ( nSVEvent == MouseNotifyEvent::MOUSEMOVE )
733 if ( bCallHelpRequest && !pSVData->maHelpData.mbKeyboardHelp )
734 ImplHandleMouseHelpRequest( pChild, pChild->OutputToScreenPixel( aMEvt.GetPosPixel() ) );
735 bRet = true;
737 else if ( !bRet )
739 if ( nSVEvent == MouseNotifyEvent::MOUSEBUTTONDOWN )
741 if ( !pChild->ImplGetWindowImpl()->mbMouseButtonDown )
742 bRet = true;
744 else
746 if ( !pChild->ImplGetWindowImpl()->mbMouseButtonUp )
747 bRet = true;
751 if ( nSVEvent == MouseNotifyEvent::MOUSEMOVE )
753 // set new mouse pointer
754 if ( !bMouseLeave )
755 ImplSetMousePointer( pChild );
757 else if ( (nSVEvent == MouseNotifyEvent::MOUSEBUTTONDOWN) || (nSVEvent == MouseNotifyEvent::MOUSEBUTTONUP) )
759 if ( !bDrag )
761 // Command-Events
762 if ( /*!bRet &&*/ (nClicks == 1) && (nSVEvent == MouseNotifyEvent::MOUSEBUTTONDOWN) &&
763 (nCode == MOUSE_MIDDLE) )
765 MouseMiddleButtonAction nMiddleAction = pChild->GetSettings().GetMouseSettings().GetMiddleButtonAction();
766 if ( nMiddleAction == MouseMiddleButtonAction::AutoScroll )
767 bRet = !ImplCallCommand( pChild, CommandEventId::StartAutoScroll, nullptr, true, &aChildPos );
768 else if ( nMiddleAction == MouseMiddleButtonAction::PasteSelection )
769 bRet = !ImplCallCommand( pChild, CommandEventId::PasteSelection, nullptr, true, &aChildPos );
771 else
773 // ContextMenu
774 const MouseSettings& rMSettings = pChild->GetSettings().GetMouseSettings();
775 if ( (nCode == rMSettings.GetContextMenuCode()) &&
776 (nClicks == rMSettings.GetContextMenuClicks()) )
778 bool bContextMenu = (nSVEvent == MouseNotifyEvent::MOUSEBUTTONDOWN);
779 if ( bContextMenu )
781 if( pSVData->maAppData.mpActivePopupMenu )
783 /* #i34277# there already is a context menu open
784 * that was probably just closed with EndPopupMode.
785 * We need to give the eventual corresponding
786 * PopupMenu::Execute a chance to end properly.
787 * Therefore delay context menu command and
788 * issue only after popping one frame of the
789 * Yield stack.
791 ContextMenuEvent* pEv = new ContextMenuEvent;
792 pEv->pWindow = pChild;
793 pEv->aChildPos = aChildPos;
794 Application::PostUserEvent( Link<void*,void>( pEv, ContextMenuEventLink ) );
796 else
797 bRet = ! ImplCallCommand( pChild, CommandEventId::ContextMenu, nullptr, true, &aChildPos );
804 return bRet;
807 static vcl::Window* ImplGetKeyInputWindow( vcl::Window* pWindow )
809 ImplSVData* pSVData = ImplGetSVData();
811 // determine last input time
812 pSVData->maAppData.mnLastInputTime = tools::Time::GetSystemTicks();
814 // #127104# workaround for destroyed windows
815 if( pWindow->ImplGetWindowImpl() == nullptr )
816 return nullptr;
818 // find window - is every time the window which has currently the
819 // focus or the last time the focus.
821 // the first floating window always has the focus, try it, or any parent floating windows, first
822 vcl::Window* pChild = pSVData->maWinData.mpFirstFloat;
823 while (pChild)
825 if (pChild->ImplGetWindowImpl()->mbFloatWin)
827 if (static_cast<FloatingWindow *>(pChild)->GrabsFocus())
828 break;
830 pChild = pChild->GetParent();
833 if (!pChild)
834 pChild = pWindow;
836 pChild = pChild->ImplGetWindowImpl()->mpFrameData->mpFocusWin;
838 // no child - than no input
839 if ( !pChild )
840 return nullptr;
842 // We call also KeyInput if we haven't the focus, because on Unix
843 // system this is often the case when a Lookup Choice Window has
844 // the focus - because this windows send the KeyInput directly to
845 // the window without resetting the focus
846 SAL_WARN_IF( pChild != pSVData->maWinData.mpFocusWin, "vcl",
847 "ImplHandleKey: Keyboard-Input is sent to a frame without focus" );
849 // no keyinput to disabled windows
850 if ( !pChild->IsEnabled() || !pChild->IsInputEnabled() || pChild->IsInModalMode() )
851 return nullptr;
853 return pChild;
856 static bool ImplHandleKey( vcl::Window* pWindow, MouseNotifyEvent nSVEvent,
857 sal_uInt16 nKeyCode, sal_uInt16 nCharCode, sal_uInt16 nRepeat, bool bForward )
859 ImplSVData* pSVData = ImplGetSVData();
860 vcl::KeyCode aKeyCode( nKeyCode, nKeyCode );
861 sal_uInt16 nEvCode = aKeyCode.GetCode();
863 // allow application key listeners to remove the key event
864 // but make sure we're not forwarding external KeyEvents, (ie where bForward is false)
865 // because those are coming back from the listener itself and MUST be processed
866 KeyEvent aKeyEvent( (sal_Unicode)nCharCode, aKeyCode, nRepeat );
867 if( bForward )
869 sal_uInt16 nVCLEvent;
870 switch( nSVEvent )
872 case MouseNotifyEvent::KEYINPUT:
873 nVCLEvent = VCLEVENT_WINDOW_KEYINPUT;
874 break;
875 case MouseNotifyEvent::KEYUP:
876 nVCLEvent = VCLEVENT_WINDOW_KEYUP;
877 break;
878 default:
879 nVCLEvent = 0;
880 break;
882 if( nVCLEvent && Application::HandleKey( nVCLEvent, pWindow, &aKeyEvent ) )
883 return true;
886 // #i1820# use locale specific decimal separator
887 if( nEvCode == KEY_DECIMAL )
889 if( Application::GetSettings().GetMiscSettings().GetEnableLocalizedDecimalSep() )
891 OUString aSep( pWindow->GetSettings().GetLocaleDataWrapper().getNumDecimalSep() );
892 nCharCode = (sal_uInt16) aSep[0];
896 bool bCtrlF6 = (aKeyCode.GetCode() == KEY_F6) && aKeyCode.IsMod1();
898 // determine last input time
899 pSVData->maAppData.mnLastInputTime = tools::Time::GetSystemTicks();
901 // handle tracking window
902 if ( nSVEvent == MouseNotifyEvent::KEYINPUT )
904 if ( pSVData->maHelpData.mbExtHelpMode )
906 Help::EndExtHelp();
907 if ( nEvCode == KEY_ESCAPE )
908 return true;
910 if ( pSVData->maHelpData.mpHelpWin )
911 ImplDestroyHelpWindow( false );
913 // AutoScrollMode
914 if ( pSVData->maWinData.mpAutoScrollWin )
916 pSVData->maWinData.mpAutoScrollWin->EndAutoScroll();
917 if ( nEvCode == KEY_ESCAPE )
918 return true;
921 if ( pSVData->maWinData.mpTrackWin )
923 sal_uInt16 nOrigCode = aKeyCode.GetCode();
925 if ( (nOrigCode == KEY_ESCAPE) && !(pSVData->maWinData.mnTrackFlags & StartTrackingFlags::NoKeyCancel) )
927 pSVData->maWinData.mpTrackWin->EndTracking( TrackingEventFlags::Cancel | TrackingEventFlags::Key );
928 if ( pSVData->maWinData.mpFirstFloat )
930 FloatingWindow* pLastLevelFloat = pSVData->maWinData.mpFirstFloat->ImplFindLastLevelFloat();
931 if ( !(pLastLevelFloat->GetPopupModeFlags() & FloatWinPopupFlags::NoKeyClose) )
933 sal_uInt16 nEscCode = aKeyCode.GetCode();
935 if ( nEscCode == KEY_ESCAPE )
936 pLastLevelFloat->EndPopupMode( FloatWinPopupEndFlags::Cancel | FloatWinPopupEndFlags::CloseAll );
939 return true;
941 else if ( nOrigCode == KEY_RETURN )
943 pSVData->maWinData.mpTrackWin->EndTracking( TrackingEventFlags::Key );
944 return true;
946 else if ( !(pSVData->maWinData.mnTrackFlags & StartTrackingFlags::KeyInput) )
947 return true;
950 // handle FloatingMode
951 if ( pSVData->maWinData.mpFirstFloat )
953 FloatingWindow* pLastLevelFloat = pSVData->maWinData.mpFirstFloat->ImplFindLastLevelFloat();
954 if ( !(pLastLevelFloat->GetPopupModeFlags() & FloatWinPopupFlags::NoKeyClose) )
956 sal_uInt16 nCode = aKeyCode.GetCode();
958 if ( (nCode == KEY_ESCAPE) || bCtrlF6)
960 pLastLevelFloat->EndPopupMode( FloatWinPopupEndFlags::Cancel | FloatWinPopupEndFlags::CloseAll );
961 if( !bCtrlF6 )
962 return true;
967 // test for accel
968 if ( pSVData->maAppData.mpAccelMgr )
970 if ( pSVData->maAppData.mpAccelMgr->IsAccelKey( aKeyCode, nRepeat ) )
971 return true;
975 // find window
976 VclPtr<vcl::Window> pChild = ImplGetKeyInputWindow( pWindow );
977 if ( !pChild )
978 return false;
980 // --- RTL --- mirror cursor keys
981 const OutputDevice *pChildOutDev = pChild->GetOutDev();
982 if( (aKeyCode.GetCode() == KEY_LEFT || aKeyCode.GetCode() == KEY_RIGHT) &&
983 pChildOutDev->HasMirroredGraphics() && pChild->IsRTLEnabled() )
984 aKeyCode = vcl::KeyCode( aKeyCode.GetCode() == KEY_LEFT ? KEY_RIGHT : KEY_LEFT, aKeyCode.GetModifier() );
986 KeyEvent aKeyEvt( (sal_Unicode)nCharCode, aKeyCode, nRepeat );
987 NotifyEvent aNotifyEvt( nSVEvent, pChild, &aKeyEvt );
988 bool bKeyPreNotify = ImplCallPreNotify( aNotifyEvt );
989 bool bRet = true;
991 if ( !bKeyPreNotify && !pChild->IsDisposed() )
993 if ( nSVEvent == MouseNotifyEvent::KEYINPUT )
995 pChild->ImplGetWindowImpl()->mbKeyInput = false;
996 pChild->KeyInput( aKeyEvt );
998 else
1000 pChild->ImplGetWindowImpl()->mbKeyUp = false;
1001 pChild->KeyUp( aKeyEvt );
1003 if( !pChild->IsDisposed() )
1004 aNotifyEvt.GetWindow()->ImplNotifyKeyMouseCommandEventListeners( aNotifyEvt );
1007 if ( pChild->IsDisposed() )
1008 return true;
1010 if ( nSVEvent == MouseNotifyEvent::KEYINPUT )
1012 if ( !bKeyPreNotify && pChild->ImplGetWindowImpl()->mbKeyInput )
1014 sal_uInt16 nCode = aKeyCode.GetCode();
1016 // #101999# is focus in or below toolbox
1017 bool bToolboxFocus=false;
1018 if( (nCode == KEY_F1) && aKeyCode.IsShift() )
1020 vcl::Window *pWin = pWindow->ImplGetWindowImpl()->mpFrameData->mpFocusWin;
1021 while( pWin )
1023 if( pWin->ImplGetWindowImpl()->mbToolBox )
1025 bToolboxFocus = true;
1026 break;
1028 else
1029 pWin = pWin->GetParent();
1033 // ContextMenu
1034 if ( (nCode == KEY_CONTEXTMENU) || ((nCode == KEY_F10) && aKeyCode.IsShift() && !aKeyCode.IsMod1() && !aKeyCode.IsMod2() ) )
1035 bRet = !ImplCallCommand( pChild, CommandEventId::ContextMenu );
1036 else if ( ( (nCode == KEY_F2) && aKeyCode.IsShift() ) || ( (nCode == KEY_F1) && aKeyCode.IsMod1() ) ||
1037 // #101999# no active help when focus in toolbox, simulate BallonHelp instead
1038 ( (nCode == KEY_F1) && aKeyCode.IsShift() && bToolboxFocus ) )
1040 // TipHelp via Keyboard (Shift-F2 or Ctrl-F1)
1041 // simulate mouseposition at center of window
1043 Size aSize = pChild->GetOutputSize();
1044 Point aPos = Point( aSize.getWidth()/2, aSize.getHeight()/2 );
1045 aPos = pChild->OutputToScreenPixel( aPos );
1047 HelpEvent aHelpEvent( aPos, HelpEventMode::BALLOON );
1048 aHelpEvent.SetKeyboardActivated( true );
1049 pSVData->maHelpData.mbSetKeyboardHelp = true;
1050 pChild->RequestHelp( aHelpEvent );
1051 pSVData->maHelpData.mbSetKeyboardHelp = false;
1053 else if ( (nCode == KEY_F1) || (nCode == KEY_HELP) )
1055 if ( !aKeyCode.GetModifier() )
1057 if ( pSVData->maHelpData.mbContextHelp )
1059 Point aMousePos = pChild->OutputToScreenPixel( pChild->GetPointerPosPixel() );
1060 HelpEvent aHelpEvent( aMousePos, HelpEventMode::CONTEXT );
1061 pChild->RequestHelp( aHelpEvent );
1063 else
1064 bRet = false;
1066 else if ( aKeyCode.IsShift() )
1068 if ( pSVData->maHelpData.mbExtHelp )
1069 Help::StartExtHelp();
1070 else
1071 bRet = false;
1074 else
1076 if ( ImplCallHotKey( aKeyCode ) )
1077 bRet = true;
1078 else
1079 bRet = false;
1083 else
1085 if ( !bKeyPreNotify && pChild->ImplGetWindowImpl()->mbKeyUp )
1086 bRet = false;
1089 // #105591# send keyinput to parent if we are a floating window and the key was not processed yet
1090 if( !bRet && pWindow->ImplGetWindowImpl()->mbFloatWin && pWindow->GetParent() && (pWindow->ImplGetWindowImpl()->mpFrame != pWindow->GetParent()->ImplGetWindowImpl()->mpFrame) )
1092 pChild = pWindow->GetParent();
1094 // call handler
1095 KeyEvent aKEvt( (sal_Unicode)nCharCode, aKeyCode, nRepeat );
1096 NotifyEvent aNEvt( nSVEvent, pChild, &aKEvt );
1097 bool bPreNotify = ImplCallPreNotify( aNEvt );
1098 if ( pChild->IsDisposed() )
1099 return true;
1101 if ( !bPreNotify )
1103 if ( nSVEvent == MouseNotifyEvent::KEYINPUT )
1105 pChild->ImplGetWindowImpl()->mbKeyInput = false;
1106 pChild->KeyInput( aKEvt );
1108 else
1110 pChild->ImplGetWindowImpl()->mbKeyUp = false;
1111 pChild->KeyUp( aKEvt );
1114 if( !pChild->IsDisposed() )
1115 aNEvt.GetWindow()->ImplNotifyKeyMouseCommandEventListeners( aNEvt );
1116 if ( pChild->IsDisposed() )
1117 return true;
1120 if( bPreNotify || !pChild->ImplGetWindowImpl()->mbKeyInput )
1121 bRet = true;
1124 return bRet;
1127 static bool ImplHandleExtTextInput( vcl::Window* pWindow,
1128 const OUString& rText,
1129 const ExtTextInputAttr* pTextAttr,
1130 sal_Int32 nCursorPos, sal_uInt16 nCursorFlags )
1132 ImplSVData* pSVData = ImplGetSVData();
1133 vcl::Window* pChild = nullptr;
1135 int nTries = 200;
1136 while( nTries-- )
1138 pChild = pSVData->maWinData.mpExtTextInputWin;
1139 if ( !pChild )
1141 pChild = ImplGetKeyInputWindow( pWindow );
1142 if ( !pChild )
1143 return false;
1145 if( !pChild->ImplGetWindowImpl()->mpFrameData->mnFocusId )
1146 break;
1147 Application::Yield();
1150 // If it is the first ExtTextInput call, we inform the information
1151 // and allocate the data, which we must store in this mode
1152 ImplWinData* pWinData = pChild->ImplGetWinData();
1153 if ( !pChild->ImplGetWindowImpl()->mbExtTextInput )
1155 pChild->ImplGetWindowImpl()->mbExtTextInput = true;
1156 pWinData->mpExtOldText = new OUString;
1157 if ( pWinData->mpExtOldAttrAry )
1159 delete [] pWinData->mpExtOldAttrAry;
1160 pWinData->mpExtOldAttrAry = nullptr;
1162 pSVData->maWinData.mpExtTextInputWin = pChild;
1163 ImplCallCommand( pChild, CommandEventId::StartExtTextInput );
1166 // be aware of being recursively called in StartExtTextInput
1167 if ( !pChild->ImplGetWindowImpl()->mbExtTextInput )
1168 return false;
1170 // Test for changes
1171 bool bOnlyCursor = false;
1172 sal_Int32 nMinLen = std::min( pWinData->mpExtOldText->getLength(), rText.getLength() );
1173 sal_Int32 nDeltaStart = 0;
1174 while ( nDeltaStart < nMinLen )
1176 if ( (*pWinData->mpExtOldText)[nDeltaStart] != rText[nDeltaStart] )
1177 break;
1178 nDeltaStart++;
1180 if ( pWinData->mpExtOldAttrAry || pTextAttr )
1182 if ( !pWinData->mpExtOldAttrAry || !pTextAttr )
1183 nDeltaStart = 0;
1184 else
1186 sal_Int32 i = 0;
1187 while ( i < nDeltaStart )
1189 if ( pWinData->mpExtOldAttrAry[i] != pTextAttr[i] )
1191 nDeltaStart = i;
1192 break;
1194 i++;
1198 if ( (nDeltaStart >= nMinLen) &&
1199 (pWinData->mpExtOldText->getLength() == rText.getLength()) )
1200 bOnlyCursor = true;
1202 // Call Event and store the information
1203 CommandExtTextInputData aData( rText, pTextAttr,
1204 nCursorPos, nCursorFlags,
1205 bOnlyCursor );
1206 *pWinData->mpExtOldText = rText;
1207 if ( pWinData->mpExtOldAttrAry )
1209 delete [] pWinData->mpExtOldAttrAry;
1210 pWinData->mpExtOldAttrAry = nullptr;
1212 if ( pTextAttr )
1214 pWinData->mpExtOldAttrAry = new ExtTextInputAttr[rText.getLength()];
1215 memcpy( pWinData->mpExtOldAttrAry, pTextAttr, rText.getLength()*sizeof( ExtTextInputAttr ) );
1217 return !ImplCallCommand( pChild, CommandEventId::ExtTextInput, &aData );
1220 static bool ImplHandleEndExtTextInput( vcl::Window* /* pWindow */ )
1222 ImplSVData* pSVData = ImplGetSVData();
1223 vcl::Window* pChild = pSVData->maWinData.mpExtTextInputWin;
1224 bool bRet = false;
1226 if ( pChild )
1228 pChild->ImplGetWindowImpl()->mbExtTextInput = false;
1229 pSVData->maWinData.mpExtTextInputWin = nullptr;
1230 ImplWinData* pWinData = pChild->ImplGetWinData();
1231 if ( pWinData->mpExtOldText )
1233 delete pWinData->mpExtOldText;
1234 pWinData->mpExtOldText = nullptr;
1236 if ( pWinData->mpExtOldAttrAry )
1238 delete [] pWinData->mpExtOldAttrAry;
1239 pWinData->mpExtOldAttrAry = nullptr;
1241 bRet = !ImplCallCommand( pChild, CommandEventId::EndExtTextInput );
1244 return bRet;
1247 static void ImplHandleExtTextInputPos( vcl::Window* pWindow,
1248 Rectangle& rRect, long& rInputWidth,
1249 bool * pVertical )
1251 ImplSVData* pSVData = ImplGetSVData();
1252 vcl::Window* pChild = pSVData->maWinData.mpExtTextInputWin;
1254 if ( !pChild )
1255 pChild = ImplGetKeyInputWindow( pWindow );
1256 else
1258 // Test, if the Window is related to the frame
1259 if ( !pWindow->ImplIsWindowOrChild( pChild ) )
1260 pChild = ImplGetKeyInputWindow( pWindow );
1263 if ( pChild )
1265 const OutputDevice *pChildOutDev = pChild->GetOutDev();
1266 ImplCallCommand( pChild, CommandEventId::CursorPos );
1267 const Rectangle* pRect = pChild->GetCursorRect();
1268 if ( pRect )
1269 rRect = pChildOutDev->ImplLogicToDevicePixel( *pRect );
1270 else
1272 vcl::Cursor* pCursor = pChild->GetCursor();
1273 if ( pCursor )
1275 Point aPos = pChildOutDev->ImplLogicToDevicePixel( pCursor->GetPos() );
1276 Size aSize = pChild->LogicToPixel( pCursor->GetSize() );
1277 if ( !aSize.Width() )
1278 aSize.Width() = pChild->GetSettings().GetStyleSettings().GetCursorSize();
1279 rRect = Rectangle( aPos, aSize );
1281 else
1282 rRect = Rectangle( Point( pChild->GetOutOffXPixel(), pChild->GetOutOffYPixel() ), Size() );
1284 rInputWidth = pChild->ImplLogicWidthToDevicePixel( pChild->GetCursorExtTextInputWidth() );
1285 if ( !rInputWidth )
1286 rInputWidth = rRect.GetWidth();
1288 if (pVertical != nullptr)
1289 *pVertical
1290 = pChild != nullptr && pChild->GetInputContext().GetFont().IsVertical();
1293 static bool ImplHandleInputContextChange( vcl::Window* pWindow, LanguageType eNewLang )
1295 vcl::Window* pChild = ImplGetKeyInputWindow( pWindow );
1296 CommandInputContextData aData( eNewLang );
1297 return !ImplCallCommand( pChild, CommandEventId::InputContextChange, &aData );
1300 static bool ImplCallWheelCommand( const VclPtr<vcl::Window>& pWindow, const Point& rPos,
1301 const CommandWheelData* pWheelData )
1303 Point aCmdMousePos = pWindow->ImplFrameToOutput( rPos );
1304 CommandEvent aCEvt( aCmdMousePos, CommandEventId::Wheel, true, pWheelData );
1305 NotifyEvent aNCmdEvt( MouseNotifyEvent::COMMAND, pWindow, &aCEvt );
1306 bool bPreNotify = ImplCallPreNotify( aNCmdEvt );
1307 if ( pWindow->IsDisposed() )
1308 return false;
1309 if ( !bPreNotify )
1311 pWindow->ImplGetWindowImpl()->mbCommand = false;
1312 pWindow->Command( aCEvt );
1313 if ( pWindow->IsDisposed() )
1314 return false;
1315 if ( pWindow->ImplGetWindowImpl()->mbCommand )
1316 return true;
1318 return false;
1321 static bool acceptableWheelScrollTarget(const vcl::Window *pMouseWindow)
1323 return (pMouseWindow && !pMouseWindow->isDisposed() && pMouseWindow->IsInputEnabled() && !pMouseWindow->IsInModalMode());
1326 //If the last event at the same absolute screen position was handled by a
1327 //different window then reuse that window if the event occurs within 1/2 a
1328 //second, i.e. so scrolling down something like the calc sidebar that contains
1329 //widgets that respond to wheel events will continue to send the event to the
1330 //scrolling widget in favour of the widget that happens to end up under the
1331 //mouse.
1332 static bool shouldReusePreviousMouseWindow(const SalWheelMouseEvent& rPrevEvt, const SalWheelMouseEvent& rEvt)
1334 return (rEvt.mnX == rPrevEvt.mnX && rEvt.mnY == rPrevEvt.mnY && rEvt.mnTime-rPrevEvt.mnTime < 500/*ms*/);
1337 class HandleGestureEventBase
1339 protected:
1340 ImplSVData* m_pSVData;
1341 VclPtr<vcl::Window> m_pWindow;
1342 Point m_aMousePos;
1344 public:
1345 HandleGestureEventBase(vcl::Window *pWindow, const Point &rMousePos)
1346 : m_pSVData(ImplGetSVData())
1347 , m_pWindow(pWindow)
1348 , m_aMousePos(rMousePos)
1351 bool Setup();
1352 vcl::Window* FindTarget();
1353 vcl::Window* Dispatch(vcl::Window* pTarget);
1354 virtual bool CallCommand(vcl::Window *pWindow, const Point &rMousePos) = 0;
1355 virtual ~HandleGestureEventBase() {}
1358 bool HandleGestureEventBase::Setup()
1361 if (m_pSVData->maWinData.mpAutoScrollWin)
1362 m_pSVData->maWinData.mpAutoScrollWin->EndAutoScroll();
1363 if (m_pSVData->maHelpData.mpHelpWin)
1364 ImplDestroyHelpWindow( true );
1365 if (m_pWindow->IsDisposed())
1366 return false;
1367 return true;
1370 vcl::Window* HandleGestureEventBase::FindTarget()
1372 // first check any floating window ( eg. drop down listboxes)
1373 vcl::Window *pMouseWindow = nullptr;
1375 if (m_pSVData->maWinData.mpFirstFloat && !m_pSVData->maWinData.mpCaptureWin &&
1376 !m_pSVData->maWinData.mpFirstFloat->ImplIsFloatPopupModeWindow( m_pWindow ) )
1378 HitTest nHitTest = HITTEST_OUTSIDE;
1379 pMouseWindow = m_pSVData->maWinData.mpFirstFloat->ImplFloatHitTest( m_pWindow, m_aMousePos, nHitTest );
1380 if (!pMouseWindow)
1381 pMouseWindow = m_pSVData->maWinData.mpFirstFloat;
1383 // then try the window directly beneath the mouse
1384 if( !pMouseWindow )
1386 pMouseWindow = m_pWindow->ImplFindWindow( m_aMousePos );
1388 else
1390 // transform coordinates to float window frame coordinates
1391 pMouseWindow = pMouseWindow->ImplFindWindow(
1392 pMouseWindow->OutputToScreenPixel(
1393 pMouseWindow->AbsoluteScreenToOutputPixel(
1394 m_pWindow->OutputToAbsoluteScreenPixel(
1395 m_pWindow->ScreenToOutputPixel( m_aMousePos ) ) ) ) );
1398 while (acceptableWheelScrollTarget(pMouseWindow))
1400 if (pMouseWindow->IsEnabled())
1401 break;
1402 //try the parent if this one is disabled
1403 pMouseWindow = pMouseWindow->GetParent();
1406 return pMouseWindow;
1409 vcl::Window *HandleGestureEventBase::Dispatch(vcl::Window* pMouseWindow)
1411 vcl::Window *pDispatchedTo = nullptr;
1413 if (acceptableWheelScrollTarget(pMouseWindow) && pMouseWindow->IsEnabled())
1415 // transform coordinates to float window frame coordinates
1416 Point aRelMousePos( pMouseWindow->OutputToScreenPixel(
1417 pMouseWindow->AbsoluteScreenToOutputPixel(
1418 m_pWindow->OutputToAbsoluteScreenPixel(
1419 m_pWindow->ScreenToOutputPixel( m_aMousePos ) ) ) ) );
1420 bool bPropogate = CallCommand(pMouseWindow, aRelMousePos);
1421 if (!bPropogate)
1422 pDispatchedTo = pMouseWindow;
1425 // if the command was not handled try the focus window
1426 if (!pDispatchedTo)
1428 vcl::Window* pFocusWindow = m_pWindow->ImplGetWindowImpl()->mpFrameData->mpFocusWin;
1429 if ( pFocusWindow && (pFocusWindow != pMouseWindow) &&
1430 (pFocusWindow == m_pSVData->maWinData.mpFocusWin) )
1432 // no wheel-messages to disabled windows
1433 if ( pFocusWindow->IsEnabled() && pFocusWindow->IsInputEnabled() && ! pFocusWindow->IsInModalMode() )
1435 // transform coordinates to focus window frame coordinates
1436 Point aRelMousePos( pFocusWindow->OutputToScreenPixel(
1437 pFocusWindow->AbsoluteScreenToOutputPixel(
1438 m_pWindow->OutputToAbsoluteScreenPixel(
1439 m_pWindow->ScreenToOutputPixel( m_aMousePos ) ) ) ) );
1440 bool bPropogate = CallCommand(pFocusWindow, aRelMousePos);
1441 if (!bPropogate)
1442 pDispatchedTo = pMouseWindow;
1446 return pDispatchedTo;
1449 class HandleWheelEvent : public HandleGestureEventBase
1451 private:
1452 CommandWheelData m_aWheelData;
1453 public:
1454 HandleWheelEvent(vcl::Window *pWindow, const SalWheelMouseEvent& rEvt, bool bScaleDirectly)
1455 : HandleGestureEventBase(pWindow, Point(rEvt.mnX, rEvt.mnY))
1457 CommandWheelMode nMode;
1458 sal_uInt16 nCode = rEvt.mnCode;
1459 bool bHorz = rEvt.mbHorz;
1460 bool bPixel = rEvt.mbDeltaIsPixel;
1461 if (bScaleDirectly)
1462 nMode = CommandWheelMode::ZOOM_SCALE;
1463 else if ( nCode & KEY_MOD1 )
1464 nMode = CommandWheelMode::ZOOM;
1465 else if ( nCode & KEY_MOD2 )
1466 nMode = CommandWheelMode::DATAZOOM;
1467 else
1469 nMode = CommandWheelMode::SCROLL;
1470 // #i85450# interpret shift-wheel as horizontal wheel action
1471 if( (nCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_MOD3)) == KEY_SHIFT )
1472 bHorz = true;
1475 m_aWheelData = CommandWheelData(rEvt.mnDelta, rEvt.mnNotchDelta, rEvt.mnScrollLines, nMode, nCode, bHorz, bPixel);
1478 virtual bool CallCommand(vcl::Window *pWindow, const Point &rMousePos) override
1480 return ImplCallWheelCommand(pWindow, rMousePos, &m_aWheelData);
1482 bool HandleEvent(const SalWheelMouseEvent& rEvt);
1485 bool HandleWheelEvent::HandleEvent(const SalWheelMouseEvent& rEvt)
1487 if (!Setup())
1488 return false;
1490 VclPtr<vcl::Window> xMouseWindow = FindTarget();
1492 ImplSVData* pSVData = ImplGetSVData();
1494 // avoid the problem that scrolling via wheel to this point brings a widget
1495 // under the mouse that also accepts wheel commands, so stick with the old
1496 // widget if the time gap is very small
1497 if (shouldReusePreviousMouseWindow(pSVData->maWinData.maLastWheelEvent, rEvt) &&
1498 acceptableWheelScrollTarget(pSVData->maWinData.mpLastWheelWindow))
1500 xMouseWindow = pSVData->maWinData.mpLastWheelWindow;
1503 pSVData->maWinData.maLastWheelEvent = rEvt;
1505 pSVData->maWinData.mpLastWheelWindow = Dispatch(xMouseWindow);
1507 return pSVData->maWinData.mpLastWheelWindow.get();
1510 class HandleGestureEvent : public HandleGestureEventBase
1512 public:
1513 HandleGestureEvent(vcl::Window *pWindow, const Point &rMousePos)
1514 : HandleGestureEventBase(pWindow, rMousePos)
1517 bool HandleEvent();
1520 bool HandleGestureEvent::HandleEvent()
1522 if (!Setup())
1523 return false;
1525 vcl::Window *pTarget = FindTarget();
1527 bool bHandled = Dispatch(pTarget) != nullptr;
1528 return bHandled;
1531 static bool ImplHandleWheelEvent( vcl::Window* pWindow, const SalWheelMouseEvent& rEvt, bool scaleDirectly = false )
1533 HandleWheelEvent aHandler(pWindow, rEvt, scaleDirectly);
1534 return aHandler.HandleEvent(rEvt);
1537 class HandleSwipeEvent : public HandleGestureEvent
1539 private:
1540 CommandSwipeData m_aSwipeData;
1541 public:
1542 HandleSwipeEvent(vcl::Window *pWindow, const SalSwipeEvent& rEvt)
1543 : HandleGestureEvent(pWindow, Point(rEvt.mnX, rEvt.mnY))
1545 m_aSwipeData = CommandSwipeData(rEvt.mnVelocityX);
1547 virtual bool CallCommand(vcl::Window *pWindow, const Point &/*rMousePos*/) override
1549 return ImplCallCommand(pWindow, CommandEventId::Swipe, &m_aSwipeData);
1553 static bool ImplHandleSwipe(vcl::Window *pWindow, const SalSwipeEvent& rEvt)
1555 HandleSwipeEvent aHandler(pWindow, rEvt);
1556 return aHandler.HandleEvent();
1559 class HandleLongPressEvent : public HandleGestureEvent
1561 private:
1562 CommandLongPressData m_aLongPressData;
1563 public:
1564 HandleLongPressEvent(vcl::Window *pWindow, const SalLongPressEvent& rEvt)
1565 : HandleGestureEvent(pWindow, Point(rEvt.mnX, rEvt.mnY))
1567 m_aLongPressData = CommandLongPressData(rEvt.mnX, rEvt.mnY);
1569 virtual bool CallCommand(vcl::Window *pWindow, const Point &/*rMousePos*/) override
1571 return ImplCallCommand(pWindow, CommandEventId::LongPress, &m_aLongPressData);
1575 static bool ImplHandleLongPress(vcl::Window *pWindow, const SalLongPressEvent& rEvt)
1577 HandleLongPressEvent aHandler(pWindow, rEvt);
1578 return aHandler.HandleEvent();
1581 #define IMPL_PAINT_CHECKRTL ((sal_uInt16)0x0020)
1583 static void ImplHandlePaint( vcl::Window* pWindow, const Rectangle& rBoundRect, bool bImmediateUpdate )
1585 // system paint events must be checked for re-mirroring
1586 pWindow->ImplGetWindowImpl()->mnPaintFlags |= IMPL_PAINT_CHECKRTL;
1588 // trigger paint for all windows that live in the new paint region
1589 vcl::Region aRegion( rBoundRect );
1590 pWindow->ImplInvalidateOverlapFrameRegion( aRegion );
1591 if( bImmediateUpdate )
1593 // #i87663# trigger possible pending resize notifications
1594 // (GetSizePixel does that for us)
1595 pWindow->GetSizePixel();
1596 // force drawing immediately
1597 pWindow->Update();
1601 static void KillOwnPopups( vcl::Window* pWindow )
1603 ImplSVData* pSVData = ImplGetSVData();
1604 vcl::Window *pParent = pWindow->ImplGetWindowImpl()->mpFrameWindow;
1605 vcl::Window *pChild = pSVData->maWinData.mpFirstFloat;
1606 if ( pChild && pParent->ImplIsWindowOrChild( pChild, true ) )
1608 if ( !(pSVData->maWinData.mpFirstFloat->GetPopupModeFlags() & FloatWinPopupFlags::NoAppFocusClose) )
1609 pSVData->maWinData.mpFirstFloat->EndPopupMode( FloatWinPopupEndFlags::Cancel | FloatWinPopupEndFlags::CloseAll );
1613 void ImplHandleResize( vcl::Window* pWindow, long nNewWidth, long nNewHeight )
1615 if( pWindow->GetStyle() & (WB_MOVEABLE|WB_SIZEABLE) )
1617 KillOwnPopups( pWindow );
1618 if( pWindow->ImplGetWindow() != ImplGetSVData()->maHelpData.mpHelpWin )
1619 ImplDestroyHelpWindow( true );
1622 if (
1623 (nNewWidth > 0 && nNewHeight > 0) ||
1624 pWindow->ImplGetWindow()->ImplGetWindowImpl()->mbAllResize
1627 if ( (nNewWidth != pWindow->GetOutputWidthPixel()) || (nNewHeight != pWindow->GetOutputHeightPixel()) )
1629 pWindow->mnOutWidth = nNewWidth;
1630 pWindow->mnOutHeight = nNewHeight;
1631 pWindow->ImplGetWindowImpl()->mbWaitSystemResize = false;
1632 if ( pWindow->IsReallyVisible() )
1633 pWindow->ImplSetClipFlag();
1634 if ( pWindow->IsVisible() || pWindow->ImplGetWindow()->ImplGetWindowImpl()->mbAllResize ||
1635 ( pWindow->ImplGetWindowImpl()->mbFrame && pWindow->ImplGetWindowImpl()->mpClientWindow ) ) // propagate resize for system border windows
1637 bool bStartTimer = true;
1638 // use resize buffering for user resizes
1639 // ownerdraw decorated windows and floating windows can be resized immediately (i.e. synchronously)
1640 if( pWindow->ImplGetWindowImpl()->mbFrame && (pWindow->GetStyle() & WB_SIZEABLE)
1641 && !(pWindow->GetStyle() & WB_OWNERDRAWDECORATION) // synchronous resize for ownerdraw decorated windows (toolbars)
1642 && !pWindow->ImplGetWindowImpl()->mbFloatWin ) // synchronous resize for floating windows, #i43799#
1644 if( pWindow->ImplGetWindowImpl()->mpClientWindow )
1646 // #i42750# presentation wants to be informed about resize
1647 // as early as possible
1648 WorkWindow* pWorkWindow = dynamic_cast<WorkWindow*>(pWindow->ImplGetWindowImpl()->mpClientWindow.get());
1649 if( ! pWorkWindow || pWorkWindow->IsPresentationMode() )
1650 bStartTimer = false;
1652 else
1654 WorkWindow* pWorkWindow = dynamic_cast<WorkWindow*>(pWindow);
1655 if( ! pWorkWindow || pWorkWindow->IsPresentationMode() )
1656 bStartTimer = false;
1659 else
1660 bStartTimer = false;
1662 if( bStartTimer )
1663 pWindow->ImplGetWindowImpl()->mpFrameData->maResizeIdle.Start();
1664 else
1665 pWindow->ImplCallResize(); // otherwise menus cannot be positioned
1667 else
1668 pWindow->ImplGetWindowImpl()->mbCallResize = true;
1670 if (pWindow->SupportsDoubleBuffering() && pWindow->ImplGetWindowImpl()->mbFrame)
1672 // Propagate resize for the frame's buffer.
1673 pWindow->ImplGetWindowImpl()->mpFrameData->mpBuffer->SetOutputSizePixel(pWindow->GetOutputSizePixel());
1678 pWindow->ImplGetWindowImpl()->mpFrameData->mbNeedSysWindow = (nNewWidth < IMPL_MIN_NEEDSYSWIN) ||
1679 (nNewHeight < IMPL_MIN_NEEDSYSWIN);
1680 bool bMinimized = (nNewWidth <= 0) || (nNewHeight <= 0);
1681 if( bMinimized != pWindow->ImplGetWindowImpl()->mpFrameData->mbMinimized )
1682 pWindow->ImplGetWindowImpl()->mpFrameWindow->ImplNotifyIconifiedState( bMinimized );
1683 pWindow->ImplGetWindowImpl()->mpFrameData->mbMinimized = bMinimized;
1686 static void ImplHandleMove( vcl::Window* pWindow )
1688 if( pWindow->ImplGetWindowImpl()->mbFrame && pWindow->ImplIsFloatingWindow() && pWindow->IsReallyVisible() )
1690 static_cast<FloatingWindow*>(pWindow)->EndPopupMode( FloatWinPopupEndFlags::TearOff );
1691 pWindow->ImplCallMove();
1694 if( pWindow->GetStyle() & (WB_MOVEABLE|WB_SIZEABLE) )
1696 KillOwnPopups( pWindow );
1697 if( pWindow->ImplGetWindow() != ImplGetSVData()->maHelpData.mpHelpWin )
1698 ImplDestroyHelpWindow( true );
1701 if ( pWindow->IsVisible() )
1702 pWindow->ImplCallMove();
1703 else
1704 pWindow->ImplGetWindowImpl()->mbCallMove = true; // make sure the framepos will be updated on the next Show()
1706 if ( pWindow->ImplGetWindowImpl()->mbFrame && pWindow->ImplGetWindowImpl()->mpClientWindow )
1707 pWindow->ImplGetWindowImpl()->mpClientWindow->ImplCallMove(); // notify client to update geometry
1711 static void ImplHandleMoveResize( vcl::Window* pWindow, long nNewWidth, long nNewHeight )
1713 ImplHandleMove( pWindow );
1714 ImplHandleResize( pWindow, nNewWidth, nNewHeight );
1717 static void ImplActivateFloatingWindows( vcl::Window* pWindow, bool bActive )
1719 // First check all overlapping windows
1720 vcl::Window* pTempWindow = pWindow->ImplGetWindowImpl()->mpFirstOverlap;
1721 while ( pTempWindow )
1723 if ( pTempWindow->GetActivateMode() == ActivateModeFlags::NONE )
1725 if ( (pTempWindow->GetType() == WINDOW_BORDERWINDOW) &&
1726 (pTempWindow->ImplGetWindow()->GetType() == WINDOW_FLOATINGWINDOW) )
1727 static_cast<ImplBorderWindow*>(pTempWindow)->SetDisplayActive( bActive );
1730 ImplActivateFloatingWindows( pTempWindow, bActive );
1731 pTempWindow = pTempWindow->ImplGetWindowImpl()->mpNext;
1735 IMPL_LINK_NOARG(vcl::Window, ImplAsyncFocusHdl, void*, void)
1737 ImplGetWindowImpl()->mpFrameData->mnFocusId = nullptr;
1739 // If the status has been preserved, because we got back the focus
1740 // in the meantime, we do nothing
1741 bool bHasFocus = ImplGetWindowImpl()->mpFrameData->mbHasFocus || ImplGetWindowImpl()->mpFrameData->mbSysObjFocus;
1743 // next execute the delayed functions
1744 if ( bHasFocus )
1746 // redraw all floating windows inactive
1747 if ( ImplGetWindowImpl()->mpFrameData->mbStartFocusState != bHasFocus )
1748 ImplActivateFloatingWindows( this, bHasFocus );
1750 if ( ImplGetWindowImpl()->mpFrameData->mpFocusWin )
1752 bool bHandled = false;
1753 if ( ImplGetWindowImpl()->mpFrameData->mpFocusWin->IsInputEnabled() &&
1754 ! ImplGetWindowImpl()->mpFrameData->mpFocusWin->IsInModalMode() )
1756 if ( ImplGetWindowImpl()->mpFrameData->mpFocusWin->IsEnabled() )
1758 ImplGetWindowImpl()->mpFrameData->mpFocusWin->GrabFocus();
1759 bHandled = true;
1761 else if( ImplGetWindowImpl()->mpFrameData->mpFocusWin->ImplHasDlgCtrl() )
1763 // #109094# if the focus is restored to a disabled dialog control (was disabled meanwhile)
1764 // try to move it to the next control
1765 ImplGetWindowImpl()->mpFrameData->mpFocusWin->ImplDlgCtrlNextWindow();
1766 bHandled = true;
1769 if ( !bHandled )
1771 ImplSVData* pSVData = ImplGetSVData();
1772 vcl::Window* pTopLevelWindow = ImplGetWindowImpl()->mpFrameData->mpFocusWin->ImplGetFirstOverlapWindow();
1773 if ( ( ! pTopLevelWindow->IsInputEnabled() || pTopLevelWindow->IsInModalMode() )
1774 && pSVData->maWinData.mpLastExecuteDlg )
1775 pSVData->maWinData.mpLastExecuteDlg->ToTop( ToTopFlags::RestoreWhenMin | ToTopFlags::GrabFocusOnly);
1776 else
1777 pTopLevelWindow->GrabFocus();
1780 else
1781 GrabFocus();
1783 else
1785 vcl::Window* pFocusWin = ImplGetWindowImpl()->mpFrameData->mpFocusWin;
1786 if ( pFocusWin )
1788 ImplSVData* pSVData = ImplGetSVData();
1790 if ( pSVData->maWinData.mpFocusWin == pFocusWin )
1792 // transfer the FocusWindow
1793 vcl::Window* pOverlapWindow = pFocusWin->ImplGetFirstOverlapWindow();
1794 pOverlapWindow->ImplGetWindowImpl()->mpLastFocusWindow = pFocusWin;
1795 pSVData->maWinData.mpFocusWin = nullptr;
1797 if ( pFocusWin->ImplGetWindowImpl()->mpCursor )
1798 pFocusWin->ImplGetWindowImpl()->mpCursor->ImplHide();
1800 // call the Deactivate
1801 vcl::Window* pOldFocusWindow = pFocusWin;
1802 if ( pOldFocusWindow )
1804 vcl::Window* pOldOverlapWindow = pOldFocusWindow->ImplGetFirstOverlapWindow();
1805 vcl::Window* pOldRealWindow = pOldOverlapWindow->ImplGetWindow();
1807 pOldOverlapWindow->ImplGetWindowImpl()->mbActive = false;
1808 pOldOverlapWindow->Deactivate();
1809 if ( pOldRealWindow != pOldOverlapWindow )
1811 pOldRealWindow->ImplGetWindowImpl()->mbActive = false;
1812 pOldRealWindow->Deactivate();
1816 // TrackingMode is ended in ImplHandleLoseFocus
1817 #ifdef _WIN32
1818 // To avoid problems with the Unix IME
1819 pFocusWin->EndExtTextInput();
1820 #endif
1822 NotifyEvent aNEvt(MouseNotifyEvent::LOSEFOCUS, pFocusWin);
1823 if (!ImplCallPreNotify(aNEvt))
1824 pFocusWin->CompatLoseFocus();
1825 pFocusWin->ImplCallDeactivateListeners(nullptr);
1829 // Redraw all floating window inactive
1830 if ( ImplGetWindowImpl()->mpFrameData->mbStartFocusState != bHasFocus )
1831 ImplActivateFloatingWindows( this, bHasFocus );
1835 static void ImplHandleGetFocus( vcl::Window* pWindow )
1837 pWindow->ImplGetWindowImpl()->mpFrameData->mbHasFocus = true;
1839 // execute Focus-Events after a delay, such that SystemChildWindows
1840 // do not blink when they receive focus
1841 if ( !pWindow->ImplGetWindowImpl()->mpFrameData->mnFocusId )
1843 pWindow->ImplGetWindowImpl()->mpFrameData->mbStartFocusState = !pWindow->ImplGetWindowImpl()->mpFrameData->mbHasFocus;
1844 pWindow->ImplGetWindowImpl()->mpFrameData->mnFocusId = Application::PostUserEvent( LINK( pWindow, vcl::Window, ImplAsyncFocusHdl ), nullptr, true);
1845 vcl::Window* pFocusWin = pWindow->ImplGetWindowImpl()->mpFrameData->mpFocusWin;
1846 if ( pFocusWin && pFocusWin->ImplGetWindowImpl()->mpCursor )
1847 pFocusWin->ImplGetWindowImpl()->mpCursor->ImplShow();
1851 static void ImplHandleLoseFocus( vcl::Window* pWindow )
1853 ImplSVData* pSVData = ImplGetSVData();
1855 // Abort the autoscroll if the frame loses focus
1856 if ( pSVData->maWinData.mpAutoScrollWin )
1857 pSVData->maWinData.mpAutoScrollWin->EndAutoScroll();
1859 // Abort tracking if the frame loses focus
1860 if ( pSVData->maWinData.mpTrackWin )
1862 if ( pSVData->maWinData.mpTrackWin->ImplGetWindowImpl()->mpFrameWindow == pWindow )
1863 pSVData->maWinData.mpTrackWin->EndTracking( TrackingEventFlags::Cancel );
1866 pWindow->ImplGetWindowImpl()->mpFrameData->mbHasFocus = false;
1868 // execute Focus-Events after a delay, such that SystemChildWindows
1869 // do not flicker when they receive focus
1870 if ( !pWindow->ImplGetWindowImpl()->mpFrameData->mnFocusId )
1872 pWindow->ImplGetWindowImpl()->mpFrameData->mbStartFocusState = !pWindow->ImplGetWindowImpl()->mpFrameData->mbHasFocus;
1873 pWindow->ImplGetWindowImpl()->mpFrameData->mnFocusId = Application::PostUserEvent( LINK( pWindow, vcl::Window, ImplAsyncFocusHdl ), nullptr, true );
1876 vcl::Window* pFocusWin = pWindow->ImplGetWindowImpl()->mpFrameData->mpFocusWin;
1877 if ( pFocusWin && pFocusWin->ImplGetWindowImpl()->mpCursor )
1878 pFocusWin->ImplGetWindowImpl()->mpCursor->ImplHide();
1881 struct DelayedCloseEvent
1883 VclPtr<vcl::Window> pWindow;
1886 static void DelayedCloseEventLink( void* pCEvent, void* )
1888 DelayedCloseEvent* pEv = static_cast<DelayedCloseEvent*>(pCEvent);
1890 if( ! pEv->pWindow->IsDisposed() )
1892 // dispatch to correct window type
1893 if( pEv->pWindow->IsSystemWindow() )
1894 static_cast<SystemWindow*>(pEv->pWindow.get())->Close();
1895 else if( pEv->pWindow->IsDockingWindow() )
1896 static_cast<DockingWindow*>(pEv->pWindow.get())->Close();
1898 delete pEv;
1901 void ImplHandleClose( vcl::Window* pWindow )
1903 ImplSVData* pSVData = ImplGetSVData();
1905 bool bWasPopup = false;
1906 if( pWindow->ImplIsFloatingWindow() &&
1907 static_cast<FloatingWindow*>(pWindow)->ImplIsInPrivatePopupMode() )
1909 bWasPopup = true;
1912 // on Close stop all floating modes and end popups
1913 if ( pSVData->maWinData.mpFirstFloat )
1915 FloatingWindow* pLastLevelFloat;
1916 pLastLevelFloat = pSVData->maWinData.mpFirstFloat->ImplFindLastLevelFloat();
1917 pLastLevelFloat->EndPopupMode( FloatWinPopupEndFlags::Cancel | FloatWinPopupEndFlags::CloseAll );
1919 if ( pSVData->maHelpData.mbExtHelpMode )
1920 Help::EndExtHelp();
1921 if ( pSVData->maHelpData.mpHelpWin )
1922 ImplDestroyHelpWindow( false );
1923 // AutoScrollMode
1924 if ( pSVData->maWinData.mpAutoScrollWin )
1925 pSVData->maWinData.mpAutoScrollWin->EndAutoScroll();
1927 if ( pSVData->maWinData.mpTrackWin )
1928 pSVData->maWinData.mpTrackWin->EndTracking( TrackingEventFlags::Cancel | TrackingEventFlags::Key );
1930 if (bWasPopup)
1931 return;
1933 vcl::Window *pWin = pWindow->ImplGetWindow();
1934 SystemWindow* pSysWin = dynamic_cast<SystemWindow*>(pWin);
1935 if (pSysWin)
1937 // See if the custom close handler is set.
1938 const Link<SystemWindow&,void>& rLink = pSysWin->GetCloseHdl();
1939 if (rLink.IsSet())
1941 rLink.Call(*pSysWin);
1942 return;
1946 // check whether close is allowed
1947 if ( pWin->IsEnabled() && pWin->IsInputEnabled() && !pWin->IsInModalMode() )
1949 DelayedCloseEvent* pEv = new DelayedCloseEvent;
1950 pEv->pWindow = pWin;
1951 Application::PostUserEvent( Link<void*,void>( pEv, DelayedCloseEventLink ) );
1955 static void ImplHandleUserEvent( ImplSVEvent* pSVEvent )
1957 if ( pSVEvent )
1959 if ( pSVEvent->mbCall )
1961 pSVEvent->maLink.Call( pSVEvent->mpData );
1964 delete pSVEvent;
1968 static MouseEventModifiers ImplGetMouseMoveMode( SalMouseEvent* pEvent )
1970 MouseEventModifiers nMode = MouseEventModifiers::NONE;
1971 if ( !pEvent->mnCode )
1972 nMode |= MouseEventModifiers::SIMPLEMOVE;
1973 if ( (pEvent->mnCode & MOUSE_LEFT) && !(pEvent->mnCode & KEY_MOD1) )
1974 nMode |= MouseEventModifiers::DRAGMOVE;
1975 if ( (pEvent->mnCode & MOUSE_LEFT) && (pEvent->mnCode & KEY_MOD1) )
1976 nMode |= MouseEventModifiers::DRAGCOPY;
1977 return nMode;
1980 static MouseEventModifiers ImplGetMouseButtonMode( SalMouseEvent* pEvent )
1982 MouseEventModifiers nMode = MouseEventModifiers::NONE;
1983 if ( pEvent->mnButton == MOUSE_LEFT )
1984 nMode |= MouseEventModifiers::SIMPLECLICK;
1985 if ( (pEvent->mnButton == MOUSE_LEFT) && !(pEvent->mnCode & (MOUSE_MIDDLE | MOUSE_RIGHT)) )
1986 nMode |= MouseEventModifiers::SELECT;
1987 if ( (pEvent->mnButton == MOUSE_LEFT) && (pEvent->mnCode & KEY_MOD1) &&
1988 !(pEvent->mnCode & (MOUSE_MIDDLE | MOUSE_RIGHT | KEY_SHIFT)) )
1989 nMode |= MouseEventModifiers::MULTISELECT;
1990 if ( (pEvent->mnButton == MOUSE_LEFT) && (pEvent->mnCode & KEY_SHIFT) &&
1991 !(pEvent->mnCode & (MOUSE_MIDDLE | MOUSE_RIGHT | KEY_MOD1)) )
1992 nMode |= MouseEventModifiers::RANGESELECT;
1993 return nMode;
1996 inline bool ImplHandleSalMouseLeave( vcl::Window* pWindow, SalMouseEvent* pEvent )
1998 return ImplHandleMouseEvent( pWindow, MouseNotifyEvent::MOUSEMOVE, true,
1999 pEvent->mnX, pEvent->mnY,
2000 pEvent->mnTime, pEvent->mnCode,
2001 ImplGetMouseMoveMode( pEvent ) );
2004 inline bool ImplHandleSalMouseMove( vcl::Window* pWindow, SalMouseEvent* pEvent )
2006 return ImplHandleMouseEvent( pWindow, MouseNotifyEvent::MOUSEMOVE, false,
2007 pEvent->mnX, pEvent->mnY,
2008 pEvent->mnTime, pEvent->mnCode,
2009 ImplGetMouseMoveMode( pEvent ) );
2012 inline bool ImplHandleSalMouseButtonDown( vcl::Window* pWindow, SalMouseEvent* pEvent )
2014 return ImplHandleMouseEvent( pWindow, MouseNotifyEvent::MOUSEBUTTONDOWN, false,
2015 pEvent->mnX, pEvent->mnY,
2016 pEvent->mnTime,
2017 #ifdef MACOSX
2018 pEvent->mnButton | (pEvent->mnCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_MOD3)),
2019 #else
2020 pEvent->mnButton | (pEvent->mnCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2)),
2021 #endif
2022 ImplGetMouseButtonMode( pEvent ) );
2025 inline bool ImplHandleSalMouseButtonUp( vcl::Window* pWindow, SalMouseEvent* pEvent )
2027 return ImplHandleMouseEvent( pWindow, MouseNotifyEvent::MOUSEBUTTONUP, false,
2028 pEvent->mnX, pEvent->mnY,
2029 pEvent->mnTime,
2030 #ifdef MACOSX
2031 pEvent->mnButton | (pEvent->mnCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_MOD3)),
2032 #else
2033 pEvent->mnButton | (pEvent->mnCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2)),
2034 #endif
2035 ImplGetMouseButtonMode( pEvent ) );
2038 static bool ImplHandleMenuEvent( vcl::Window* pWindow, SalMenuEvent* pEvent, SalEvent nEvent )
2040 // Find SystemWindow and its Menubar and let it dispatch the command
2041 bool bRet = false;
2042 vcl::Window *pWin = pWindow->ImplGetWindowImpl()->mpFirstChild;
2043 while ( pWin )
2045 if ( pWin->ImplGetWindowImpl()->mbSysWin )
2046 break;
2047 pWin = pWin->ImplGetWindowImpl()->mpNext;
2049 if( pWin )
2051 MenuBar *pMenuBar = static_cast<SystemWindow*>(pWin)->GetMenuBar();
2052 if( pMenuBar )
2054 switch( nEvent )
2056 case SalEvent::MenuActivate:
2057 bRet = pMenuBar->HandleMenuActivateEvent( static_cast<Menu*>(pEvent->mpMenu) );
2058 break;
2059 case SalEvent::MenuDeactivate:
2060 bRet = pMenuBar->HandleMenuDeActivateEvent( static_cast<Menu*>(pEvent->mpMenu) );
2061 break;
2062 case SalEvent::MenuHighlight:
2063 bRet = pMenuBar->HandleMenuHighlightEvent( static_cast<Menu*>(pEvent->mpMenu), pEvent->mnId );
2064 break;
2065 case SalEvent::MenuButtonCommand:
2066 bRet = pMenuBar->HandleMenuButtonEvent( static_cast<Menu*>(pEvent->mpMenu), pEvent->mnId );
2067 break;
2068 case SalEvent::MenuCommand:
2069 bRet = pMenuBar->HandleMenuCommandEvent( static_cast<Menu*>(pEvent->mpMenu), pEvent->mnId );
2070 break;
2071 default:
2072 break;
2076 return bRet;
2079 static void ImplHandleSalKeyMod( vcl::Window* pWindow, SalKeyModEvent* pEvent )
2081 ImplSVData* pSVData = ImplGetSVData();
2082 vcl::Window* pTrackWin = pSVData->maWinData.mpTrackWin;
2083 if ( pTrackWin )
2084 pWindow = pTrackWin;
2085 #ifdef MACOSX
2086 sal_uInt16 nOldCode = pWindow->ImplGetWindowImpl()->mpFrameData->mnMouseCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_MOD3);
2087 #else
2088 sal_uInt16 nOldCode = pWindow->ImplGetWindowImpl()->mpFrameData->mnMouseCode & (KEY_SHIFT | KEY_MOD1 | KEY_MOD2);
2089 #endif
2090 sal_uInt16 nNewCode = pEvent->mnCode;
2091 if ( nOldCode != nNewCode )
2093 #ifdef MACOSX
2094 nNewCode |= pWindow->ImplGetWindowImpl()->mpFrameData->mnMouseCode & ~(KEY_SHIFT | KEY_MOD1 | KEY_MOD2 | KEY_MOD3);
2095 #else
2096 nNewCode |= pWindow->ImplGetWindowImpl()->mpFrameData->mnMouseCode & ~(KEY_SHIFT | KEY_MOD1 | KEY_MOD2);
2097 #endif
2098 pWindow->ImplGetWindowImpl()->mpFrameWindow->ImplCallMouseMove( nNewCode, true );
2101 // #105224# send commandevent to allow special treatment of Ctrl-LeftShift/Ctrl-RightShift etc.
2102 // + auto-accelerator feature, tdf#92630
2104 // find window
2105 vcl::Window* pChild = ImplGetKeyInputWindow( pWindow );
2106 if ( !pChild )
2107 return;
2109 CommandModKeyData data( pEvent->mnModKeyCode, pEvent->mbDown );
2110 ImplCallCommand( pChild, CommandEventId::ModKeyChange, &data );
2113 static void ImplHandleInputLanguageChange( vcl::Window* pWindow )
2115 // find window
2116 vcl::Window* pChild = ImplGetKeyInputWindow( pWindow );
2117 if ( !pChild )
2118 return;
2120 ImplCallCommand( pChild, CommandEventId::InputLanguageChange );
2123 static void ImplHandleSalSettings( SalEvent nEvent )
2125 Application* pApp = GetpApp();
2126 if ( !pApp )
2127 return;
2129 if ( nEvent == SalEvent::SettingsChanged )
2131 AllSettings aSettings = Application::GetSettings();
2132 Application::MergeSystemSettings( aSettings );
2133 pApp->OverrideSystemSettings( aSettings );
2134 Application::SetSettings( aSettings );
2136 else
2138 DataChangedEventType nType;
2139 switch ( nEvent )
2141 case SalEvent::PrinterChanged:
2142 ImplDeletePrnQueueList();
2143 nType = DataChangedEventType::PRINTER;
2144 break;
2145 case SalEvent::DisplayChanged:
2146 nType = DataChangedEventType::DISPLAY;
2147 break;
2148 case SalEvent::FontChanged:
2149 OutputDevice::ImplUpdateAllFontData( true );
2150 nType = DataChangedEventType::FONTS;
2151 break;
2152 default:
2153 nType = DataChangedEventType::NONE;
2154 break;
2157 if ( nType != DataChangedEventType::NONE )
2159 DataChangedEvent aDCEvt( nType );
2160 Application::NotifyAllWindows( aDCEvt );
2165 static void ImplHandleSalExtTextInputPos( vcl::Window* pWindow, SalExtTextInputPosEvent* pEvt )
2167 Rectangle aCursorRect;
2168 ImplHandleExtTextInputPos( pWindow, aCursorRect, pEvt->mnExtWidth, &pEvt->mbVertical );
2169 if ( aCursorRect.IsEmpty() )
2171 pEvt->mnX = -1;
2172 pEvt->mnY = -1;
2173 pEvt->mnWidth = -1;
2174 pEvt->mnHeight = -1;
2176 else
2178 pEvt->mnX = aCursorRect.Left();
2179 pEvt->mnY = aCursorRect.Top();
2180 pEvt->mnWidth = aCursorRect.GetWidth();
2181 pEvt->mnHeight = aCursorRect.GetHeight();
2185 static bool ImplHandleShowDialog( vcl::Window* pWindow, ShowDialogId nDialogId )
2187 if( ! pWindow )
2188 return false;
2190 if( pWindow->GetType() == WINDOW_BORDERWINDOW )
2192 vcl::Window* pWrkWin = pWindow->GetWindow( GetWindowType::Client );
2193 if( pWrkWin )
2194 pWindow = pWrkWin;
2196 CommandDialogData aCmdData( nDialogId );
2197 return ImplCallCommand( pWindow, CommandEventId::ShowDialog, &aCmdData );
2200 static void ImplHandleSurroundingTextRequest( vcl::Window *pWindow,
2201 OUString& rText,
2202 Selection &rSelRange )
2204 vcl::Window* pChild = ImplGetKeyInputWindow( pWindow );
2206 if ( !pChild )
2208 rText.clear();
2209 rSelRange.setMin( 0 );
2210 rSelRange.setMax( 0 );
2212 else
2214 rText = pChild->GetSurroundingText();
2215 Selection aSel = pChild->GetSurroundingTextSelection();
2216 rSelRange.setMin( aSel.Min() );
2217 rSelRange.setMax( aSel.Max() );
2221 static void ImplHandleSalSurroundingTextRequest( vcl::Window *pWindow,
2222 SalSurroundingTextRequestEvent *pEvt )
2224 Selection aSelRange;
2225 ImplHandleSurroundingTextRequest( pWindow, pEvt->maText, aSelRange );
2227 aSelRange.Justify();
2229 if( aSelRange.Min() < 0 )
2230 pEvt->mnStart = 0;
2231 else if( aSelRange.Min() > pEvt->maText.getLength() )
2232 pEvt->mnStart = pEvt->maText.getLength();
2233 else
2234 pEvt->mnStart = aSelRange.Min();
2236 if( aSelRange.Max() < 0 )
2237 pEvt->mnStart = 0;
2238 else if( aSelRange.Max() > pEvt->maText.getLength() )
2239 pEvt->mnEnd = pEvt->maText.getLength();
2240 else
2241 pEvt->mnEnd = aSelRange.Max();
2244 static void ImplHandleSurroundingTextSelectionChange( vcl::Window *pWindow,
2245 sal_uLong nStart,
2246 sal_uLong nEnd )
2248 vcl::Window* pChild = ImplGetKeyInputWindow( pWindow );
2249 if( pChild )
2251 CommandSelectionChangeData data( nStart, nEnd );
2252 ImplCallCommand( pChild, CommandEventId::SelectionChange, &data );
2256 static void ImplHandleStartReconversion( vcl::Window *pWindow )
2258 vcl::Window* pChild = ImplGetKeyInputWindow( pWindow );
2259 if( pChild )
2260 ImplCallCommand( pChild, CommandEventId::PrepareReconversion );
2263 static void ImplHandleSalQueryCharPosition( vcl::Window *pWindow,
2264 SalQueryCharPositionEvent *pEvt )
2266 pEvt->mbValid = false;
2267 pEvt->mbVertical = false;
2268 pEvt->mnCursorBoundX = 0;
2269 pEvt->mnCursorBoundY = 0;
2270 pEvt->mnCursorBoundWidth = 0;
2271 pEvt->mnCursorBoundHeight = 0;
2273 ImplSVData* pSVData = ImplGetSVData();
2274 vcl::Window* pChild = pSVData->maWinData.mpExtTextInputWin;
2276 if ( !pChild )
2277 pChild = ImplGetKeyInputWindow( pWindow );
2278 else
2280 // Test, if the Window is related to the frame
2281 if ( !pWindow->ImplIsWindowOrChild( pChild ) )
2282 pChild = ImplGetKeyInputWindow( pWindow );
2285 if( pChild )
2287 ImplCallCommand( pChild, CommandEventId::QueryCharPosition );
2289 ImplWinData* pWinData = pChild->ImplGetWinData();
2290 if ( pWinData->mpCompositionCharRects && pEvt->mnCharPos < static_cast<sal_uLong>( pWinData->mnCompositionCharRects ) )
2292 const OutputDevice *pChildOutDev = pChild->GetOutDev();
2293 const Rectangle& aRect = pWinData->mpCompositionCharRects[ pEvt->mnCharPos ];
2294 Rectangle aDeviceRect = pChildOutDev->ImplLogicToDevicePixel( aRect );
2295 Point aAbsScreenPos = pChild->OutputToAbsoluteScreenPixel( pChild->ScreenToOutputPixel(aDeviceRect.TopLeft()) );
2296 pEvt->mnCursorBoundX = aAbsScreenPos.X();
2297 pEvt->mnCursorBoundY = aAbsScreenPos.Y();
2298 pEvt->mnCursorBoundWidth = aDeviceRect.GetWidth();
2299 pEvt->mnCursorBoundHeight = aDeviceRect.GetHeight();
2300 pEvt->mbVertical = pWinData->mbVertical;
2301 pEvt->mbValid = true;
2306 bool ImplWindowFrameProc( vcl::Window* _pWindow, SalEvent nEvent, const void* pEvent )
2308 DBG_TESTSOLARMUTEX();
2310 // Ensure the window survives during this method.
2311 VclPtr<vcl::Window> pWindow( _pWindow );
2313 bool bRet = false;
2315 // #119709# for some unknown reason it is possible to receive events (in this case key events)
2316 // although the corresponding VCL window must have been destroyed already
2317 // at least ImplGetWindowImpl() was NULL in these cases, so check this here
2318 if( pWindow->ImplGetWindowImpl() == nullptr )
2319 return false;
2321 switch ( nEvent )
2323 case SalEvent::MouseMove:
2324 bRet = ImplHandleSalMouseMove( pWindow, const_cast<SalMouseEvent *>(static_cast<SalMouseEvent const *>(pEvent)) );
2325 break;
2326 case SalEvent::ExternalMouseMove:
2328 MouseEvent const * pMouseEvt = static_cast<MouseEvent const *>(pEvent);
2329 SalMouseEvent aSalMouseEvent;
2331 aSalMouseEvent.mnTime = tools::Time::GetSystemTicks();
2332 aSalMouseEvent.mnX = pMouseEvt->GetPosPixel().X();
2333 aSalMouseEvent.mnY = pMouseEvt->GetPosPixel().Y();
2334 aSalMouseEvent.mnButton = 0;
2335 aSalMouseEvent.mnCode = pMouseEvt->GetButtons() | pMouseEvt->GetModifier();
2337 bRet = ImplHandleSalMouseMove( pWindow, &aSalMouseEvent );
2339 break;
2340 case SalEvent::MouseLeave:
2341 bRet = ImplHandleSalMouseLeave( pWindow, const_cast<SalMouseEvent *>(static_cast<SalMouseEvent const *>(pEvent)) );
2342 break;
2343 case SalEvent::MouseButtonDown:
2344 bRet = ImplHandleSalMouseButtonDown( pWindow, const_cast<SalMouseEvent *>(static_cast<SalMouseEvent const *>(pEvent)) );
2345 break;
2346 case SalEvent::ExternalMouseButtonDown:
2348 MouseEvent const * pMouseEvt = static_cast<MouseEvent const *>(pEvent);
2349 SalMouseEvent aSalMouseEvent;
2351 aSalMouseEvent.mnTime = tools::Time::GetSystemTicks();
2352 aSalMouseEvent.mnX = pMouseEvt->GetPosPixel().X();
2353 aSalMouseEvent.mnY = pMouseEvt->GetPosPixel().Y();
2354 aSalMouseEvent.mnButton = pMouseEvt->GetButtons();
2355 aSalMouseEvent.mnCode = pMouseEvt->GetButtons() | pMouseEvt->GetModifier();
2357 bRet = ImplHandleSalMouseButtonDown( pWindow, &aSalMouseEvent );
2359 break;
2360 case SalEvent::MouseButtonUp:
2361 bRet = ImplHandleSalMouseButtonUp( pWindow, const_cast<SalMouseEvent *>(static_cast<SalMouseEvent const *>(pEvent)) );
2362 break;
2363 case SalEvent::ExternalMouseButtonUp:
2365 MouseEvent const * pMouseEvt = static_cast<MouseEvent const *>(pEvent);
2366 SalMouseEvent aSalMouseEvent;
2368 aSalMouseEvent.mnTime = tools::Time::GetSystemTicks();
2369 aSalMouseEvent.mnX = pMouseEvt->GetPosPixel().X();
2370 aSalMouseEvent.mnY = pMouseEvt->GetPosPixel().Y();
2371 aSalMouseEvent.mnButton = pMouseEvt->GetButtons();
2372 aSalMouseEvent.mnCode = pMouseEvt->GetButtons() | pMouseEvt->GetModifier();
2374 bRet = ImplHandleSalMouseButtonUp( pWindow, &aSalMouseEvent );
2376 break;
2377 case SalEvent::MouseActivate:
2378 bRet = false;
2379 break;
2380 case SalEvent::KeyInput:
2382 SalKeyEvent const * pKeyEvt = static_cast<SalKeyEvent const *>(pEvent);
2383 bRet = ImplHandleKey( pWindow, MouseNotifyEvent::KEYINPUT,
2384 pKeyEvt->mnCode, pKeyEvt->mnCharCode, pKeyEvt->mnRepeat, true );
2386 break;
2387 case SalEvent::ExternalKeyInput:
2389 KeyEvent const * pKeyEvt = static_cast<KeyEvent const *>(pEvent);
2390 bRet = ImplHandleKey( pWindow, MouseNotifyEvent::KEYINPUT,
2391 pKeyEvt->GetKeyCode().GetFullCode(), pKeyEvt->GetCharCode(), pKeyEvt->GetRepeat(), false );
2393 break;
2394 case SalEvent::KeyUp:
2396 SalKeyEvent const * pKeyEvt = static_cast<SalKeyEvent const *>(pEvent);
2397 bRet = ImplHandleKey( pWindow, MouseNotifyEvent::KEYUP,
2398 pKeyEvt->mnCode, pKeyEvt->mnCharCode, pKeyEvt->mnRepeat, true );
2400 break;
2401 case SalEvent::ExternalKeyUp:
2403 KeyEvent const * pKeyEvt = static_cast<KeyEvent const *>(pEvent);
2404 bRet = ImplHandleKey( pWindow, MouseNotifyEvent::KEYUP,
2405 pKeyEvt->GetKeyCode().GetFullCode(), pKeyEvt->GetCharCode(), pKeyEvt->GetRepeat(), false );
2407 break;
2408 case SalEvent::KeyModChange:
2409 ImplHandleSalKeyMod( pWindow, const_cast<SalKeyModEvent *>(static_cast<SalKeyModEvent const *>(pEvent)) );
2410 break;
2412 case SalEvent::InputLanguageChange:
2413 ImplHandleInputLanguageChange( pWindow );
2414 break;
2416 case SalEvent::MenuActivate:
2417 case SalEvent::MenuDeactivate:
2418 case SalEvent::MenuHighlight:
2419 case SalEvent::MenuCommand:
2420 case SalEvent::MenuButtonCommand:
2421 bRet = ImplHandleMenuEvent( pWindow, const_cast<SalMenuEvent *>(static_cast<SalMenuEvent const *>(pEvent)), nEvent );
2422 break;
2424 case SalEvent::WheelMouse:
2425 bRet = ImplHandleWheelEvent( pWindow, *static_cast<const SalWheelMouseEvent*>(pEvent));
2426 break;
2428 case SalEvent::Paint:
2430 SalPaintEvent const * pPaintEvt = static_cast<SalPaintEvent const *>(pEvent);
2432 if( AllSettings::GetLayoutRTL() )
2434 // --- RTL --- (mirror paint rect)
2435 SalFrame* pSalFrame = pWindow->ImplGetWindowImpl()->mpFrame;
2436 const_cast<SalPaintEvent *>(pPaintEvt)->mnBoundX = pSalFrame->maGeometry.nWidth-pPaintEvt->mnBoundWidth-pPaintEvt->mnBoundX;
2439 Rectangle aBoundRect( Point( pPaintEvt->mnBoundX, pPaintEvt->mnBoundY ),
2440 Size( pPaintEvt->mnBoundWidth, pPaintEvt->mnBoundHeight ) );
2441 ImplHandlePaint( pWindow, aBoundRect, pPaintEvt->mbImmediateUpdate );
2443 break;
2445 case SalEvent::Move:
2446 ImplHandleMove( pWindow );
2447 break;
2449 case SalEvent::Resize:
2451 long nNewWidth;
2452 long nNewHeight;
2453 pWindow->ImplGetWindowImpl()->mpFrame->GetClientSize( nNewWidth, nNewHeight );
2454 ImplHandleResize( pWindow, nNewWidth, nNewHeight );
2456 break;
2458 case SalEvent::MoveResize:
2460 SalFrameGeometry g = pWindow->ImplGetWindowImpl()->mpFrame->GetGeometry();
2461 ImplHandleMoveResize( pWindow, g.nWidth, g.nHeight );
2463 break;
2465 case SalEvent::ClosePopups:
2467 KillOwnPopups( pWindow );
2469 break;
2471 case SalEvent::GetFocus:
2472 ImplHandleGetFocus( pWindow );
2473 break;
2474 case SalEvent::LoseFocus:
2475 ImplHandleLoseFocus( pWindow );
2476 break;
2478 case SalEvent::Close:
2479 ImplHandleClose( pWindow );
2480 break;
2482 case SalEvent::Shutdown:
2484 static bool bInQueryExit = false;
2485 if( !bInQueryExit )
2487 bInQueryExit = true;
2488 if ( GetpApp()->QueryExit() )
2490 // end the message loop
2491 Application::Quit();
2492 return false;
2494 else
2496 bInQueryExit = false;
2497 return true;
2500 return false;
2503 case SalEvent::SettingsChanged:
2504 case SalEvent::PrinterChanged:
2505 case SalEvent::DisplayChanged:
2506 case SalEvent::FontChanged:
2507 ImplHandleSalSettings( nEvent );
2508 break;
2510 case SalEvent::UserEvent:
2511 ImplHandleUserEvent( const_cast<ImplSVEvent *>(static_cast<ImplSVEvent const *>(pEvent)) );
2512 break;
2514 case SalEvent::ExtTextInput:
2516 SalExtTextInputEvent const * pEvt = static_cast<SalExtTextInputEvent const *>(pEvent);
2517 bRet = ImplHandleExtTextInput( pWindow,
2518 pEvt->maText, pEvt->mpTextAttr,
2519 pEvt->mnCursorPos, pEvt->mnCursorFlags );
2521 break;
2522 case SalEvent::EndExtTextInput:
2523 bRet = ImplHandleEndExtTextInput( pWindow );
2524 break;
2525 case SalEvent::ExtTextInputPos:
2526 ImplHandleSalExtTextInputPos( pWindow, const_cast<SalExtTextInputPosEvent *>(static_cast<SalExtTextInputPosEvent const *>(pEvent)) );
2527 break;
2528 case SalEvent::InputContextChange:
2529 bRet = ImplHandleInputContextChange( pWindow, static_cast<SalInputContextChangeEvent const *>(pEvent)->meLanguage );
2530 break;
2531 case SalEvent::ShowDialog:
2533 ShowDialogId nLOKWindowId = static_cast<ShowDialogId>(reinterpret_cast<sal_IntPtr>(pEvent));
2534 bRet = ImplHandleShowDialog( pWindow, nLOKWindowId );
2536 break;
2537 case SalEvent::SurroundingTextRequest:
2538 ImplHandleSalSurroundingTextRequest( pWindow, const_cast<SalSurroundingTextRequestEvent *>(static_cast<SalSurroundingTextRequestEvent const *>(pEvent)) );
2539 break;
2540 case SalEvent::SurroundingTextSelectionChange:
2542 SalSurroundingTextSelectionChangeEvent const * pEvt
2543 = static_cast<SalSurroundingTextSelectionChangeEvent const *>(pEvent);
2544 ImplHandleSurroundingTextSelectionChange( pWindow,
2545 pEvt->mnStart,
2546 pEvt->mnEnd );
2547 SAL_FALLTHROUGH; // TODO: Fallthrough really intended?
2549 case SalEvent::StartReconversion:
2550 ImplHandleStartReconversion( pWindow );
2551 break;
2552 case SalEvent::ExternalZoom:
2554 SalWheelMouseEvent aSalWheelMouseEvent;
2555 aSalWheelMouseEvent.mnTime = tools::Time::GetSystemTicks();
2556 aSalWheelMouseEvent.mnX = 0;
2557 aSalWheelMouseEvent.mnY = 0;
2558 // Pass on the scale as a percentage * 100 of current zoom factor
2559 // so to assure zoom granularity
2560 aSalWheelMouseEvent.mnDelta = long(MOBILE_ZOOM_SCALE_MULTIPLIER);
2561 // Other SalWheelMouseEvent fields ignored when the
2562 // scaleDirectly parameter to ImplHandleWheelEvent() is
2563 // true.
2564 bRet = ImplHandleWheelEvent( pWindow, aSalWheelMouseEvent, true );
2566 break;
2567 case SalEvent::ExternalScroll:
2569 SalWheelMouseEvent aSalWheelMouseEvent;
2570 aSalWheelMouseEvent.mnTime = tools::Time::GetSystemTicks();
2571 aSalWheelMouseEvent.mbDeltaIsPixel = true;
2572 // event location holds delta values instead
2573 aSalWheelMouseEvent.mnX = 0;
2574 aSalWheelMouseEvent.mnY = 0;
2575 aSalWheelMouseEvent.mnScrollLines = 0;
2576 if (aSalWheelMouseEvent.mnX != 0 || aSalWheelMouseEvent.mnY != 0)
2578 bRet = ImplHandleWheelEvent( pWindow, aSalWheelMouseEvent );
2581 break;
2582 case SalEvent::QueryCharPosition:
2583 ImplHandleSalQueryCharPosition( pWindow, const_cast<SalQueryCharPositionEvent *>(static_cast<SalQueryCharPositionEvent const *>(pEvent)) );
2584 break;
2586 case SalEvent::Swipe:
2587 bRet = ImplHandleSwipe(pWindow, *static_cast<const SalSwipeEvent*>(pEvent));
2588 break;
2590 case SalEvent::LongPress:
2591 bRet = ImplHandleLongPress(pWindow, *static_cast<const SalLongPressEvent*>(pEvent));
2592 break;
2595 default:
2596 SAL_WARN( "vcl.layout", "ImplWindowFrameProc(): unknown event (" << (int)nEvent << ")" );
2597 break;
2600 return bRet;
2603 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */