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