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