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