/src/libreoffice/vcl/source/window/mouse.cxx
Line | Count | Source |
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 | | |
21 | | #include <config_feature_desktop.h> |
22 | | #include <config_vclplug.h> |
23 | | |
24 | | #include <tools/time.hxx> |
25 | | |
26 | | #include <LibreOfficeKit/LibreOfficeKitEnums.h> |
27 | | |
28 | | #include <vcl/ITiledRenderable.hxx> |
29 | | #include <vcl/dndlistenercontainer.hxx> |
30 | | #include <vcl/svapp.hxx> |
31 | | #include <vcl/window.hxx> |
32 | | #include <vcl/cursor.hxx> |
33 | | #include <vcl/sysdata.hxx> |
34 | | #include <vcl/event.hxx> |
35 | | |
36 | | #include <sal/types.h> |
37 | | |
38 | | #include <window.h> |
39 | | #include <svdata.hxx> |
40 | | #include <salobj.hxx> |
41 | | #include <salgdi.hxx> |
42 | | #include <salframe.hxx> |
43 | | #include <salinst.hxx> |
44 | | |
45 | | #include <dndeventdispatcher.hxx> |
46 | | |
47 | | #include <com/sun/star/datatransfer/dnd/XDragSource.hpp> |
48 | | #include <com/sun/star/datatransfer/dnd/XDropTarget.hpp> |
49 | | #include <com/sun/star/uno/XComponentContext.hpp> |
50 | | |
51 | | #include <comphelper/processfactory.hxx> |
52 | | |
53 | | using namespace ::com::sun::star::uno; |
54 | | |
55 | | namespace vcl { |
56 | | |
57 | | WindowHitTest Window::ImplHitTest( const Point& rFramePos ) |
58 | 0 | { |
59 | 0 | Point aFramePos( rFramePos ); |
60 | 0 | if( GetOutDev()->ImplIsAntiparallel() ) |
61 | 0 | { |
62 | 0 | const OutputDevice *pOutDev = GetOutDev(); |
63 | 0 | pOutDev->ReMirror( aFramePos ); |
64 | 0 | } |
65 | 0 | if ( !GetOutputRectPixel().Contains( aFramePos ) ) |
66 | 0 | return WindowHitTest::NONE; |
67 | 0 | if ( mpWindowImpl->mbWinRegion ) |
68 | 0 | { |
69 | 0 | Point aTempPos = aFramePos; |
70 | 0 | aTempPos.AdjustX( -GetOutDev()->mnOutOffX ); |
71 | 0 | aTempPos.AdjustY( -GetOutDev()->mnOutOffY ); |
72 | 0 | if ( !mpWindowImpl->maWinRegion.Contains( aTempPos ) ) |
73 | 0 | return WindowHitTest::NONE; |
74 | 0 | } |
75 | | |
76 | 0 | WindowHitTest nHitTest = WindowHitTest::Inside; |
77 | 0 | if ( mpWindowImpl->mbMouseTransparent ) |
78 | 0 | nHitTest |= WindowHitTest::Transparent; |
79 | 0 | return nHitTest; |
80 | 0 | } |
81 | | |
82 | | bool Window::ImplTestMousePointerSet() |
83 | 13.0k | { |
84 | | // as soon as mouse is captured, switch mouse-pointer |
85 | 13.0k | if ( IsMouseCaptured() ) |
86 | 0 | return true; |
87 | | |
88 | | // if the mouse is over the window, switch it |
89 | 13.0k | tools::Rectangle aClientRect( Point( 0, 0 ), GetOutputSizePixel() ); |
90 | 13.0k | return aClientRect.Contains( GetPointerPosPixel() ); |
91 | 13.0k | } |
92 | | |
93 | | PointerStyle Window::ImplGetMousePointer() const |
94 | 0 | { |
95 | 0 | PointerStyle ePointerStyle; |
96 | 0 | bool bWait = false; |
97 | |
|
98 | 0 | if ( IsEnabled() && IsInputEnabled() && ! IsInModalMode() ) |
99 | 0 | ePointerStyle = GetPointer(); |
100 | 0 | else |
101 | 0 | ePointerStyle = PointerStyle::Arrow; |
102 | |
|
103 | 0 | const vcl::Window* pWindow = this; |
104 | 0 | do |
105 | 0 | { |
106 | | // when the pointer is not visible stop the search, as |
107 | | // this status should not be overwritten |
108 | 0 | if ( pWindow->mpWindowImpl->mbNoPtrVisible ) |
109 | 0 | return PointerStyle::Null; |
110 | | |
111 | 0 | if ( !bWait ) |
112 | 0 | { |
113 | 0 | if ( pWindow->mpWindowImpl->mnWaitCount ) |
114 | 0 | { |
115 | 0 | ePointerStyle = PointerStyle::Wait; |
116 | 0 | bWait = true; |
117 | 0 | } |
118 | 0 | else |
119 | 0 | { |
120 | 0 | if ( pWindow->mpWindowImpl->mbChildPtrOverwrite ) |
121 | 0 | ePointerStyle = pWindow->GetPointer(); |
122 | 0 | } |
123 | 0 | } |
124 | |
|
125 | 0 | if ( pWindow->ImplIsOverlapWindow() ) |
126 | 0 | break; |
127 | | |
128 | 0 | pWindow = pWindow->ImplGetParent(); |
129 | 0 | } |
130 | 0 | while ( pWindow ); |
131 | | |
132 | 0 | return ePointerStyle; |
133 | 0 | } |
134 | | |
135 | | void Window::ImplCallMouseMove( sal_uInt16 nMouseCode, bool bModChanged ) |
136 | 0 | { |
137 | 0 | if ( !(mpWindowImpl->mpFrameData->mbMouseIn && mpWindowImpl->mpFrameWindow->mpWindowImpl->mbReallyVisible) ) |
138 | 0 | return; |
139 | | |
140 | 0 | sal_uInt64 nTime = tools::Time::GetSystemTicks(); |
141 | 0 | tools::Long nX = mpWindowImpl->mpFrameData->mnLastMouseX; |
142 | 0 | tools::Long nY = mpWindowImpl->mpFrameData->mnLastMouseY; |
143 | 0 | sal_uInt16 nCode = nMouseCode; |
144 | 0 | MouseEventModifiers nMode = mpWindowImpl->mpFrameData->mnMouseMode; |
145 | 0 | bool bLeave; |
146 | | // check for MouseLeave |
147 | 0 | bLeave = ((nX < 0) || (nY < 0) || |
148 | 0 | (nX >= mpWindowImpl->mpFrameWindow->GetOutDev()->mnOutWidth) || |
149 | 0 | (nY >= mpWindowImpl->mpFrameWindow->GetOutDev()->mnOutHeight)) && |
150 | 0 | !ImplGetSVData()->mpWinData->mpCaptureWin; |
151 | 0 | nMode |= MouseEventModifiers::SYNTHETIC; |
152 | 0 | if ( bModChanged ) |
153 | 0 | nMode |= MouseEventModifiers::MODIFIERCHANGED; |
154 | 0 | ImplHandleMouseEvent( mpWindowImpl->mpFrameWindow, NotifyEventType::MOUSEMOVE, bLeave, nX, nY, nTime, nCode, nMode ); |
155 | 0 | } |
156 | | |
157 | | void Window::ImplGenerateMouseMove() |
158 | 0 | { |
159 | 0 | if ( mpWindowImpl && mpWindowImpl->mpFrameData && |
160 | 0 | !mpWindowImpl->mpFrameData->mnMouseMoveId ) |
161 | 0 | mpWindowImpl->mpFrameData->mnMouseMoveId = Application::PostUserEvent( LINK( mpWindowImpl->mpFrameWindow, Window, ImplGenerateMouseMoveHdl ), nullptr, true ); |
162 | 0 | } |
163 | | |
164 | | IMPL_LINK_NOARG(Window, ImplGenerateMouseMoveHdl, void*, void) |
165 | 0 | { |
166 | 0 | mpWindowImpl->mpFrameData->mnMouseMoveId = nullptr; |
167 | 0 | vcl::Window* pCaptureWin = ImplGetSVData()->mpWinData->mpCaptureWin; |
168 | 0 | if( ! pCaptureWin || |
169 | 0 | (pCaptureWin->mpWindowImpl && pCaptureWin->mpWindowImpl->mpFrame == mpWindowImpl->mpFrame) |
170 | 0 | ) |
171 | 0 | { |
172 | 0 | ImplCallMouseMove( mpWindowImpl->mpFrameData->mnMouseCode ); |
173 | 0 | } |
174 | 0 | } |
175 | | |
176 | | void Window::ImplInvertFocus( const tools::Rectangle& rRect ) |
177 | 0 | { |
178 | 0 | InvertTracking( rRect, ShowTrackFlags::Small | ShowTrackFlags::TrackWindow ); |
179 | 0 | } |
180 | | |
181 | | static bool IsWindowFocused(const WindowImpl& rWinImpl) |
182 | 0 | { |
183 | 0 | if (rWinImpl.mpSysObj) |
184 | 0 | return true; |
185 | | |
186 | 0 | if (rWinImpl.mpFrameData->mbHasFocus) |
187 | 0 | return true; |
188 | | |
189 | 0 | if (rWinImpl.mbFakeFocusSet) |
190 | 0 | return true; |
191 | | |
192 | 0 | return false; |
193 | 0 | } |
194 | | |
195 | | void Window::ImplGrabFocus( GetFocusFlags nFlags ) |
196 | 0 | { |
197 | | // #143570# no focus for destructing windows |
198 | 0 | if( !mpWindowImpl || mpWindowImpl->mbInDispose ) |
199 | 0 | return; |
200 | | |
201 | | // some event listeners do really bad stuff |
202 | | // => prepare for the worst |
203 | 0 | VclPtr<vcl::Window> xWindow( this ); |
204 | | |
205 | | // Currently the client window should always get the focus |
206 | | // Should the border window at some point be focusable |
207 | | // we need to change all GrabFocus() instances in VCL, |
208 | | // e.g. in ToTop() |
209 | |
|
210 | 0 | if ( mpWindowImpl->mpClientWindow ) |
211 | 0 | { |
212 | | // For a lack of design we need a little hack here to |
213 | | // ensure that dialogs on close pass the focus back to |
214 | | // the correct window |
215 | 0 | if ( mpWindowImpl->mpLastFocusWindow && (mpWindowImpl->mpLastFocusWindow.get() != this) && |
216 | 0 | !(mpWindowImpl->mnDlgCtrlFlags & DialogControlFlags::WantFocus) && |
217 | 0 | mpWindowImpl->mpLastFocusWindow->IsEnabled() && |
218 | 0 | mpWindowImpl->mpLastFocusWindow->IsInputEnabled() && |
219 | 0 | ! mpWindowImpl->mpLastFocusWindow->IsInModalMode() |
220 | 0 | ) |
221 | 0 | mpWindowImpl->mpLastFocusWindow->GrabFocus(); |
222 | 0 | else |
223 | 0 | mpWindowImpl->mpClientWindow->GrabFocus(); |
224 | 0 | return; |
225 | 0 | } |
226 | 0 | else if ( mpWindowImpl->mbFrame ) |
227 | 0 | { |
228 | | // For a lack of design we need a little hack here to |
229 | | // ensure that dialogs on close pass the focus back to |
230 | | // the correct window |
231 | 0 | if ( mpWindowImpl->mpLastFocusWindow && (mpWindowImpl->mpLastFocusWindow.get() != this) && |
232 | 0 | !(mpWindowImpl->mnDlgCtrlFlags & DialogControlFlags::WantFocus) && |
233 | 0 | mpWindowImpl->mpLastFocusWindow->IsEnabled() && |
234 | 0 | mpWindowImpl->mpLastFocusWindow->IsInputEnabled() && |
235 | 0 | ! mpWindowImpl->mpLastFocusWindow->IsInModalMode() |
236 | 0 | ) |
237 | 0 | { |
238 | 0 | mpWindowImpl->mpLastFocusWindow->GrabFocus(); |
239 | 0 | return; |
240 | 0 | } |
241 | 0 | } |
242 | | |
243 | | // If the Window is disabled, then we don't change the focus |
244 | 0 | if ( !IsEnabled() || !IsInputEnabled() || IsInModalMode() ) |
245 | 0 | return; |
246 | | |
247 | | // we only need to set the focus if it is not already set |
248 | | // note: if some other frame is waiting for an asynchronous focus event |
249 | | // we also have to post an asynchronous focus event for this frame |
250 | | // which is done using ToTop |
251 | 0 | ImplSVData* pSVData = ImplGetSVData(); |
252 | |
|
253 | 0 | bool bAsyncFocusWaiting = false; |
254 | 0 | vcl::Window *pFrame = pSVData->maFrameData.mpFirstFrame; |
255 | 0 | while( pFrame && pFrame->mpWindowImpl && pFrame->mpWindowImpl->mpFrameData ) |
256 | 0 | { |
257 | 0 | if( pFrame != mpWindowImpl->mpFrameWindow.get() && pFrame->mpWindowImpl->mpFrameData->mnFocusId ) |
258 | 0 | { |
259 | 0 | bAsyncFocusWaiting = true; |
260 | 0 | break; |
261 | 0 | } |
262 | 0 | pFrame = pFrame->mpWindowImpl->mpFrameData->mpNextFrame; |
263 | 0 | } |
264 | |
|
265 | 0 | bool bHasFocus = IsWindowFocused(*mpWindowImpl); |
266 | |
|
267 | 0 | bool bMustNotGrabFocus = false; |
268 | | // #100242#, check parent hierarchy if some floater prohibits grab focus |
269 | |
|
270 | 0 | vcl::Window *pParent = this; |
271 | 0 | while( pParent ) |
272 | 0 | { |
273 | 0 | if ((pParent->GetStyle() & WB_SYSTEMFLOATWIN) && !(pParent->GetStyle() & WB_MOVEABLE)) |
274 | 0 | { |
275 | 0 | bMustNotGrabFocus = true; |
276 | 0 | break; |
277 | 0 | } |
278 | 0 | if (!pParent->mpWindowImpl) |
279 | 0 | break; |
280 | 0 | pParent = pParent->mpWindowImpl->mpParent; |
281 | 0 | } |
282 | |
|
283 | 0 | if ( !(( pSVData->mpWinData->mpFocusWin.get() != this && |
284 | 0 | !mpWindowImpl->mbInDispose ) || |
285 | 0 | ( bAsyncFocusWaiting && !bHasFocus && !bMustNotGrabFocus )) ) |
286 | 0 | return; |
287 | | |
288 | | // EndExtTextInput if it is not the same window |
289 | 0 | if (pSVData->mpWinData->mpExtTextInputWin |
290 | 0 | && (pSVData->mpWinData->mpExtTextInputWin.get() != this)) |
291 | 0 | pSVData->mpWinData->mpExtTextInputWin->EndExtTextInput(); |
292 | | |
293 | | // mark this windows as the last FocusWindow |
294 | 0 | vcl::Window* pOverlapWindow = ImplGetFirstOverlapWindow(); |
295 | 0 | if (pOverlapWindow->mpWindowImpl) |
296 | 0 | pOverlapWindow->mpWindowImpl->mpLastFocusWindow = this; |
297 | 0 | mpWindowImpl->mpFrameData->mpFocusWin = this; |
298 | |
|
299 | 0 | if( !bHasFocus ) |
300 | 0 | { |
301 | | // menu windows never get the system focus |
302 | | // the application will keep the focus |
303 | 0 | if( bMustNotGrabFocus ) |
304 | 0 | return; |
305 | 0 | else |
306 | 0 | { |
307 | | // here we already switch focus as ToTop() |
308 | | // should not give focus to another window |
309 | 0 | mpWindowImpl->mpFrame->ToTop( SalFrameToTop::GrabFocus | SalFrameToTop::GrabFocusOnly ); |
310 | 0 | return; |
311 | 0 | } |
312 | 0 | } |
313 | | |
314 | 0 | VclPtr<vcl::Window> pOldFocusWindow = pSVData->mpWinData->mpFocusWin; |
315 | |
|
316 | 0 | pSVData->mpWinData->mpFocusWin = this; |
317 | |
|
318 | 0 | if ( pOldFocusWindow && pOldFocusWindow->mpWindowImpl ) |
319 | 0 | { |
320 | | // Cursor hidden |
321 | 0 | if ( pOldFocusWindow->mpWindowImpl->mpCursor ) |
322 | 0 | pOldFocusWindow->mpWindowImpl->mpCursor->ImplHide(); |
323 | 0 | } |
324 | | |
325 | | // !!!!! due to old SV-Office Activate/Deactivate handling |
326 | | // !!!!! first as before |
327 | 0 | if ( pOldFocusWindow ) |
328 | 0 | { |
329 | | // remember Focus |
330 | 0 | vcl::Window* pOldOverlapWindow = pOldFocusWindow->ImplGetFirstOverlapWindow(); |
331 | 0 | vcl::Window* pNewOverlapWindow = ImplGetFirstOverlapWindow(); |
332 | 0 | if ( pOldOverlapWindow != pNewOverlapWindow ) |
333 | 0 | ImplCallFocusChangeActivate( pNewOverlapWindow, pOldOverlapWindow ); |
334 | 0 | } |
335 | 0 | else |
336 | 0 | { |
337 | 0 | vcl::Window* pNewOverlapWindow = ImplGetFirstOverlapWindow(); |
338 | 0 | if ( pNewOverlapWindow && pNewOverlapWindow->mpWindowImpl ) |
339 | 0 | { |
340 | 0 | vcl::Window* pNewRealWindow = pNewOverlapWindow->ImplGetWindow(); |
341 | 0 | pNewOverlapWindow->mpWindowImpl->mbActive = true; |
342 | 0 | pNewOverlapWindow->Activate(); |
343 | 0 | if ( pNewRealWindow != pNewOverlapWindow && pNewRealWindow && pNewRealWindow->mpWindowImpl ) |
344 | 0 | { |
345 | 0 | pNewRealWindow->mpWindowImpl->mbActive = true; |
346 | 0 | pNewRealWindow->Activate(); |
347 | 0 | } |
348 | 0 | } |
349 | 0 | } |
350 | | |
351 | | // call Get- and LoseFocus |
352 | 0 | if ( pOldFocusWindow && ! pOldFocusWindow->isDisposed() ) |
353 | 0 | { |
354 | 0 | NotifyEvent aNEvt( NotifyEventType::LOSEFOCUS, pOldFocusWindow ); |
355 | 0 | if ( !ImplCallPreNotify( aNEvt ) ) |
356 | 0 | pOldFocusWindow->CompatLoseFocus(); |
357 | 0 | pOldFocusWindow->ImplCallDeactivateListeners( this ); |
358 | 0 | } |
359 | |
|
360 | 0 | if (pSVData->mpWinData->mpFocusWin.get() == this) |
361 | 0 | { |
362 | 0 | if ( mpWindowImpl->mpSysObj ) |
363 | 0 | { |
364 | 0 | mpWindowImpl->mpFrameData->mpFocusWin = this; |
365 | 0 | if ( !mpWindowImpl->mpFrameData->mbInSysObjFocusHdl ) |
366 | 0 | mpWindowImpl->mpSysObj->GrabFocus(); |
367 | 0 | } |
368 | |
|
369 | 0 | if (pSVData->mpWinData->mpFocusWin.get() == this) |
370 | 0 | { |
371 | 0 | if ( mpWindowImpl->mpCursor ) |
372 | 0 | mpWindowImpl->mpCursor->ImplShow(); |
373 | 0 | mpWindowImpl->mbInFocusHdl = true; |
374 | 0 | mpWindowImpl->mnGetFocusFlags = nFlags; |
375 | | // if we're changing focus due to closing a popup floating window |
376 | | // notify the new focus window so it can restore the inner focus |
377 | | // eg, toolboxes can select their recent active item |
378 | 0 | if( pOldFocusWindow && |
379 | 0 | ! pOldFocusWindow->isDisposed() && |
380 | 0 | ( pOldFocusWindow->GetDialogControlFlags() & DialogControlFlags::FloatWinPopupModeEndCancel ) ) |
381 | 0 | mpWindowImpl->mnGetFocusFlags |= GetFocusFlags::FloatWinPopupModeEndCancel; |
382 | 0 | NotifyEvent aNEvt( NotifyEventType::GETFOCUS, this ); |
383 | 0 | if ( !ImplCallPreNotify( aNEvt ) && !xWindow->isDisposed() ) |
384 | 0 | CompatGetFocus(); |
385 | 0 | if( !xWindow->isDisposed() ) |
386 | 0 | { |
387 | 0 | if (pOldFocusWindow && pOldFocusWindow->isDisposed()) |
388 | 0 | pOldFocusWindow = nullptr; |
389 | 0 | ImplCallActivateListeners(pOldFocusWindow); |
390 | 0 | } |
391 | 0 | if( !xWindow->isDisposed() ) |
392 | 0 | { |
393 | 0 | mpWindowImpl->mnGetFocusFlags = GetFocusFlags::NONE; |
394 | 0 | mpWindowImpl->mbInFocusHdl = false; |
395 | 0 | } |
396 | 0 | } |
397 | 0 | } |
398 | |
|
399 | 0 | ImplNewInputContext(); |
400 | |
|
401 | 0 | } |
402 | | |
403 | | void Window::ImplGrabFocusToDocument( GetFocusFlags nFlags ) |
404 | 0 | { |
405 | 0 | vcl::Window *pWin = this; |
406 | 0 | while( pWin ) |
407 | 0 | { |
408 | 0 | if( !pWin->GetParent() ) |
409 | 0 | { |
410 | 0 | pWin->mpWindowImpl->mpFrame->GrabFocus(); |
411 | 0 | pWin->ImplGetFrameWindow()->GetWindow( GetWindowType::Client )->ImplGrabFocus(nFlags); |
412 | 0 | return; |
413 | 0 | } |
414 | 0 | pWin = pWin->GetParent(); |
415 | 0 | } |
416 | 0 | } |
417 | | |
418 | | void Window::MouseMove( const MouseEvent& rMEvt ) |
419 | 0 | { |
420 | 0 | NotifyEvent aNEvt( NotifyEventType::MOUSEMOVE, this, &rMEvt ); |
421 | 0 | EventNotify(aNEvt); |
422 | 0 | } |
423 | | |
424 | | void Window::MouseButtonDown( const MouseEvent& rMEvt ) |
425 | 0 | { |
426 | 0 | NotifyEvent aNEvt( NotifyEventType::MOUSEBUTTONDOWN, this, &rMEvt ); |
427 | 0 | if (!EventNotify(aNEvt) && mpWindowImpl) |
428 | 0 | mpWindowImpl->mbMouseButtonDown = true; |
429 | 0 | } |
430 | | |
431 | | void Window::MouseButtonUp( const MouseEvent& rMEvt ) |
432 | 0 | { |
433 | 0 | NotifyEvent aNEvt( NotifyEventType::MOUSEBUTTONUP, this, &rMEvt ); |
434 | 0 | if (!EventNotify(aNEvt) && mpWindowImpl) |
435 | 0 | mpWindowImpl->mbMouseButtonUp = true; |
436 | 0 | } |
437 | | |
438 | | void Window::SetMouseTransparent( bool bTransparent ) |
439 | 0 | { |
440 | |
|
441 | 0 | if ( mpWindowImpl->mpBorderWindow ) |
442 | 0 | mpWindowImpl->mpBorderWindow->SetMouseTransparent( bTransparent ); |
443 | |
|
444 | 0 | if( mpWindowImpl->mpSysObj ) |
445 | 0 | mpWindowImpl->mpSysObj->SetMouseTransparent( bTransparent ); |
446 | |
|
447 | 0 | mpWindowImpl->mbMouseTransparent = bTransparent; |
448 | 0 | } |
449 | | |
450 | | void Window::LocalStartDrag() |
451 | 0 | { |
452 | 0 | ImplGetFrameData()->mbDragging = true; |
453 | 0 | } |
454 | | |
455 | | void Window::CaptureMouse() |
456 | 0 | { |
457 | 0 | ImplSVData* pSVData = ImplGetSVData(); |
458 | | |
459 | | // possibly stop tracking |
460 | 0 | if (pSVData->mpWinData->mpTrackWin.get() != this) |
461 | 0 | { |
462 | 0 | if (pSVData->mpWinData->mpTrackWin) |
463 | 0 | pSVData->mpWinData->mpTrackWin->EndTracking(TrackingEventFlags::Cancel); |
464 | 0 | } |
465 | |
|
466 | 0 | if (pSVData->mpWinData->mpCaptureWin.get() != this) |
467 | 0 | { |
468 | 0 | pSVData->mpWinData->mpCaptureWin = this; |
469 | 0 | mpWindowImpl->mpFrame->CaptureMouse( true ); |
470 | 0 | } |
471 | 0 | } |
472 | | |
473 | | void Window::ReleaseMouse() |
474 | 0 | { |
475 | 0 | if (IsMouseCaptured()) |
476 | 0 | { |
477 | 0 | ImplSVData* pSVData = ImplGetSVData(); |
478 | 0 | pSVData->mpWinData->mpCaptureWin = nullptr; |
479 | 0 | if (mpWindowImpl && mpWindowImpl->mpFrame) |
480 | 0 | mpWindowImpl->mpFrame->CaptureMouse( false ); |
481 | 0 | ImplGenerateMouseMove(); |
482 | 0 | } |
483 | 0 | } |
484 | | |
485 | | bool Window::IsMouseCaptured() const |
486 | 119k | { |
487 | 119k | return (this == ImplGetSVData()->mpWinData->mpCaptureWin); |
488 | 119k | } |
489 | | |
490 | | void Window::SetPointer( PointerStyle nPointer ) |
491 | 4.26k | { |
492 | 4.26k | if ( mpWindowImpl->maPointer == nPointer ) |
493 | 0 | return; |
494 | | |
495 | 4.26k | mpWindowImpl->maPointer = nPointer; |
496 | | |
497 | | // possibly immediately move pointer |
498 | 4.26k | if ( !mpWindowImpl->mpFrameData->mbInMouseMove && ImplTestMousePointerSet() ) |
499 | 0 | mpWindowImpl->mpFrame->SetPointer( ImplGetMousePointer() ); |
500 | 4.26k | } |
501 | | |
502 | | void Window::EnableChildPointerOverwrite( bool bOverwrite ) |
503 | 0 | { |
504 | |
|
505 | 0 | if ( mpWindowImpl->mbChildPtrOverwrite == bOverwrite ) |
506 | 0 | return; |
507 | | |
508 | 0 | mpWindowImpl->mbChildPtrOverwrite = bOverwrite; |
509 | | |
510 | | // possibly immediately move pointer |
511 | 0 | if ( !mpWindowImpl->mpFrameData->mbInMouseMove && ImplTestMousePointerSet() ) |
512 | 0 | mpWindowImpl->mpFrame->SetPointer( ImplGetMousePointer() ); |
513 | 0 | } |
514 | | |
515 | | void Window::SetPointerPosPixel( const Point& rPos ) |
516 | 0 | { |
517 | 0 | Point aPos = OutputToScreenPixel( rPos ); |
518 | 0 | const OutputDevice *pOutDev = GetOutDev(); |
519 | 0 | if( pOutDev->HasMirroredGraphics() ) |
520 | 0 | { |
521 | 0 | if( !IsRTLEnabled() ) |
522 | 0 | { |
523 | 0 | pOutDev->ReMirror( aPos ); |
524 | 0 | } |
525 | | // mirroring is required here, SetPointerPos bypasses SalGraphics |
526 | 0 | aPos.setX( GetOutDev()->mpGraphics->mirror2( aPos.X(), *GetOutDev() ) ); |
527 | 0 | } |
528 | 0 | else if( GetOutDev()->ImplIsAntiparallel() ) |
529 | 0 | { |
530 | 0 | pOutDev->ReMirror( aPos ); |
531 | 0 | } |
532 | 0 | mpWindowImpl->mpFrame->SetPointerPos( aPos.X(), aPos.Y() ); |
533 | 0 | } |
534 | | |
535 | | void Window::SetLastMousePos(const Point& rPos) |
536 | 0 | { |
537 | | // Do this conversion, so when GetPointerPosPixel() calls |
538 | | // ScreenToOutputPixel(), we get back the original position. |
539 | 0 | Point aPos = OutputToScreenPixel(rPos); |
540 | 0 | mpWindowImpl->mpFrameData->mnLastMouseX = aPos.X(); |
541 | 0 | mpWindowImpl->mpFrameData->mnLastMouseY = aPos.Y(); |
542 | 0 | } |
543 | | |
544 | | Point Window::GetPointerPosPixel() |
545 | 17.3k | { |
546 | | |
547 | 17.3k | Point aPos( mpWindowImpl->mpFrameData->mnLastMouseX, mpWindowImpl->mpFrameData->mnLastMouseY ); |
548 | 17.3k | if( GetOutDev()->ImplIsAntiparallel() ) |
549 | 0 | { |
550 | 0 | const OutputDevice *pOutDev = GetOutDev(); |
551 | 0 | pOutDev->ReMirror( aPos ); |
552 | 0 | } |
553 | 17.3k | return ScreenToOutputPixel( aPos ); |
554 | 17.3k | } |
555 | | |
556 | | Point Window::GetLastPointerPosPixel() |
557 | 0 | { |
558 | |
|
559 | 0 | Point aPos( mpWindowImpl->mpFrameData->mnBeforeLastMouseX, mpWindowImpl->mpFrameData->mnBeforeLastMouseY ); |
560 | 0 | if( GetOutDev()->ImplIsAntiparallel() ) |
561 | 0 | { |
562 | 0 | const OutputDevice *pOutDev = GetOutDev(); |
563 | 0 | pOutDev->ReMirror( aPos ); |
564 | 0 | } |
565 | 0 | return ScreenToOutputPixel( aPos ); |
566 | 0 | } |
567 | | |
568 | | void Window::ShowPointer( bool bVisible ) |
569 | 0 | { |
570 | |
|
571 | 0 | if ( mpWindowImpl->mbNoPtrVisible != !bVisible ) |
572 | 0 | { |
573 | 0 | mpWindowImpl->mbNoPtrVisible = !bVisible; |
574 | | |
575 | | // possibly immediately move pointer |
576 | 0 | if ( !mpWindowImpl->mpFrameData->mbInMouseMove && ImplTestMousePointerSet() ) |
577 | 0 | mpWindowImpl->mpFrame->SetPointer( ImplGetMousePointer() ); |
578 | 0 | } |
579 | 0 | } |
580 | | |
581 | | Window::PointerState Window::GetPointerState() |
582 | 0 | { |
583 | 0 | PointerState aState; |
584 | 0 | aState.mnState = 0; |
585 | |
|
586 | 0 | if (mpWindowImpl->mpFrame) |
587 | 0 | { |
588 | 0 | SalFrame::SalPointerState aSalPointerState = mpWindowImpl->mpFrame->GetPointerState(); |
589 | 0 | if( GetOutDev()->ImplIsAntiparallel() ) |
590 | 0 | { |
591 | 0 | const OutputDevice *pOutDev = GetOutDev(); |
592 | 0 | pOutDev->ReMirror( aSalPointerState.maPos ); |
593 | 0 | } |
594 | 0 | aState.maPos = ScreenToOutputPixel( aSalPointerState.maPos ); |
595 | 0 | aState.mnState = aSalPointerState.mnState; |
596 | 0 | } |
597 | 0 | return aState; |
598 | 0 | } |
599 | | |
600 | | bool Window::IsMouseOver() const |
601 | 0 | { |
602 | 0 | return ImplGetWinData()->mbMouseOver; |
603 | 0 | } |
604 | | |
605 | | void Window::EnterWait() |
606 | 8.67k | { |
607 | | |
608 | 8.67k | mpWindowImpl->mnWaitCount++; |
609 | | |
610 | 8.67k | if ( mpWindowImpl->mnWaitCount == 1 ) |
611 | 4.41k | { |
612 | | // possibly immediately move pointer |
613 | 4.41k | if ( !mpWindowImpl->mpFrameData->mbInMouseMove && ImplTestMousePointerSet() ) |
614 | 0 | mpWindowImpl->mpFrame->SetPointer( ImplGetMousePointer() ); |
615 | 4.41k | } |
616 | 8.67k | } |
617 | | |
618 | | void Window::LeaveWait() |
619 | 8.67k | { |
620 | 8.67k | if( !mpWindowImpl ) |
621 | 0 | return; |
622 | | |
623 | 8.67k | if ( mpWindowImpl->mnWaitCount ) |
624 | 8.67k | { |
625 | 8.67k | mpWindowImpl->mnWaitCount--; |
626 | | |
627 | 8.67k | if ( !mpWindowImpl->mnWaitCount ) |
628 | 4.41k | { |
629 | | // possibly immediately move pointer |
630 | 4.41k | if ( !mpWindowImpl->mpFrameData->mbInMouseMove && ImplTestMousePointerSet() ) |
631 | 0 | mpWindowImpl->mpFrame->SetPointer( ImplGetMousePointer() ); |
632 | 4.41k | } |
633 | 8.67k | } |
634 | 8.67k | } |
635 | | |
636 | | bool Window::ImplStopDnd() |
637 | 0 | { |
638 | 0 | bool bRet = false; |
639 | 0 | if( mpWindowImpl->mpFrameData && mpWindowImpl->mpFrameData->mxDropTargetListener.is() ) |
640 | 0 | { |
641 | 0 | bRet = true; |
642 | 0 | mpWindowImpl->mpFrameData->mxDropTarget.clear(); |
643 | 0 | mpWindowImpl->mpFrameData->mxDragSource.clear(); |
644 | 0 | mpWindowImpl->mpFrameData->mxDropTargetListener.clear(); |
645 | 0 | } |
646 | |
|
647 | 0 | return bRet; |
648 | 0 | } |
649 | | |
650 | | void Window::ImplStartDnd() |
651 | 0 | { |
652 | 0 | GetDropTarget(); |
653 | 0 | } |
654 | | |
655 | | rtl::Reference<DNDListenerContainer> Window::GetDropTarget() |
656 | 37.6k | { |
657 | 37.6k | if( !mpWindowImpl ) |
658 | 0 | return {}; |
659 | | |
660 | 37.6k | if( ! mpWindowImpl->mxDNDListenerContainer.is() ) |
661 | 12.1k | { |
662 | 12.1k | sal_Int8 nDefaultActions = 0; |
663 | | |
664 | 12.1k | if( mpWindowImpl->mpFrameData ) |
665 | 12.1k | { |
666 | 12.1k | if( ! mpWindowImpl->mpFrameData->mxDropTarget.is() ) |
667 | 12.1k | { |
668 | | // initialization is done in GetDragSource |
669 | 12.1k | GetDragSource(); |
670 | 12.1k | } |
671 | | |
672 | 12.1k | if( mpWindowImpl->mpFrameData->mxDropTarget.is() ) |
673 | 0 | { |
674 | 0 | nDefaultActions = mpWindowImpl->mpFrameData->mxDropTarget->getDefaultActions(); |
675 | |
|
676 | 0 | if( ! mpWindowImpl->mpFrameData->mxDropTargetListener.is() ) |
677 | 0 | { |
678 | 0 | mpWindowImpl->mpFrameData->mxDropTargetListener = new DNDEventDispatcher( mpWindowImpl->mpFrameWindow ); |
679 | |
|
680 | 0 | try |
681 | 0 | { |
682 | 0 | mpWindowImpl->mpFrameData->mxDropTarget->addDropTargetListener( mpWindowImpl->mpFrameData->mxDropTargetListener ); |
683 | | |
684 | | // register also as drag gesture listener if directly supported by drag source |
685 | 0 | Reference< css::datatransfer::dnd::XDragGestureRecognizer > xDragGestureRecognizer( |
686 | 0 | mpWindowImpl->mpFrameData->mxDragSource, UNO_QUERY); |
687 | |
|
688 | 0 | if( xDragGestureRecognizer.is() ) |
689 | 0 | { |
690 | 0 | xDragGestureRecognizer->addDragGestureListener(mpWindowImpl->mpFrameData->mxDropTargetListener); |
691 | 0 | } |
692 | 0 | else |
693 | 0 | mpWindowImpl->mpFrameData->mbInternalDragGestureRecognizer = true; |
694 | |
|
695 | 0 | } |
696 | 0 | catch (const RuntimeException&) |
697 | 0 | { |
698 | | // release all instances |
699 | 0 | mpWindowImpl->mpFrameData->mxDropTarget.clear(); |
700 | 0 | mpWindowImpl->mpFrameData->mxDragSource.clear(); |
701 | 0 | } |
702 | 0 | } |
703 | 0 | } |
704 | | |
705 | 12.1k | } |
706 | | |
707 | 12.1k | mpWindowImpl->mxDNDListenerContainer = new DNDListenerContainer( nDefaultActions ); |
708 | 12.1k | } |
709 | | |
710 | | // this object is located in the same process, so there will be no runtime exception |
711 | 37.6k | return mpWindowImpl->mxDNDListenerContainer; |
712 | 37.6k | } |
713 | | |
714 | | Reference< css::datatransfer::dnd::XDragSource > Window::GetDragSource() |
715 | 12.1k | { |
716 | | #if HAVE_FEATURE_DESKTOP |
717 | | const SystemEnvData* pEnvData = GetSystemData(); |
718 | | if (!mpWindowImpl->mpFrameData || !pEnvData) |
719 | | return Reference<css::datatransfer::dnd::XDragSource>(); |
720 | | if (mpWindowImpl->mpFrameData->mxDragSource.is()) |
721 | | return mpWindowImpl->mpFrameData->mxDragSource; |
722 | | |
723 | | try |
724 | | { |
725 | | SalInstance* pInst = ImplGetSVData()->mpDefInst; |
726 | | mpWindowImpl->mpFrameData->mxDragSource = pInst->CreateDragSource(*pEnvData); |
727 | | mpWindowImpl->mpFrameData->mxDropTarget = pInst->CreateDropTarget(*pEnvData); |
728 | | } |
729 | | catch (const Exception&) |
730 | | { |
731 | | mpWindowImpl->mpFrameData->mxDropTarget.clear(); |
732 | | mpWindowImpl->mpFrameData->mxDragSource.clear(); |
733 | | } |
734 | | return mpWindowImpl->mpFrameData->mxDragSource; |
735 | | #else |
736 | 12.1k | return Reference< css::datatransfer::dnd::XDragSource > (); |
737 | 12.1k | #endif |
738 | 12.1k | } |
739 | | |
740 | | } /* namespace vcl */ |
741 | | |
742 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |