build fix: no comphelper/profilezone.hxx in this branch
[LibreOffice.git] / vcl / source / window / mouse.cxx
blobaca2627c5f192b17625c487d998a274894950d03
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <config_features.h>
23 #include <tools/time.hxx>
25 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
27 #include <vcl/ITiledRenderable.hxx>
28 #include <vcl/svapp.hxx>
29 #include <vcl/salgtype.hxx>
30 #include <vcl/window.hxx>
31 #include <vcl/floatwin.hxx>
32 #include <vcl/cursor.hxx>
33 #include <vcl/sysdata.hxx>
35 #include <sal/types.h>
37 #include <window.h>
38 #include <outdev.h>
39 #include <svdata.hxx>
40 #include <salobj.hxx>
41 #include <salgdi.hxx>
42 #include <salframe.hxx>
44 #include "dndlistenercontainer.hxx"
45 #include "dndeventdispatcher.hxx"
47 #include <com/sun/star/datatransfer/dnd/XDragSource.hpp>
48 #include <com/sun/star/datatransfer/dnd/XDropTarget.hpp>
50 #include <comphelper/processfactory.hxx>
52 using namespace ::com::sun::star::uno;
54 namespace vcl {
56 WindowHitTest Window::ImplHitTest( const Point& rFramePos )
58 Point aFramePos( rFramePos );
59 if( ImplIsAntiparallel() )
61 // - RTL - re-mirror frame pos at this window
62 const OutputDevice *pOutDev = GetOutDev();
63 pOutDev->ReMirror( aFramePos );
65 Rectangle aRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) );
66 if ( !aRect.IsInside( aFramePos ) )
67 return WindowHitTest::NONE;
68 if ( mpWindowImpl->mbWinRegion )
70 Point aTempPos = aFramePos;
71 aTempPos.X() -= mnOutOffX;
72 aTempPos.Y() -= mnOutOffY;
73 if ( !mpWindowImpl->maWinRegion.IsInside( aTempPos ) )
74 return WindowHitTest::NONE;
77 WindowHitTest nHitTest = WindowHitTest::Inside;
78 if ( mpWindowImpl->mbMouseTransparent )
79 nHitTest |= WindowHitTest::Transparent;
80 return nHitTest;
83 bool Window::ImplTestMousePointerSet()
85 // as soon as mouse is captured, switch mouse-pointer
86 if ( IsMouseCaptured() )
87 return true;
89 // if the mouse is over the window, switch it
90 Rectangle aClientRect( Point( 0, 0 ), GetOutputSizePixel() );
91 if ( aClientRect.IsInside( GetPointerPosPixel() ) )
92 return true;
94 return false;
97 PointerStyle Window::ImplGetMousePointer() const
99 PointerStyle ePointerStyle;
100 bool bWait = false;
102 if ( IsEnabled() && IsInputEnabled() && ! IsInModalMode() )
103 ePointerStyle = GetPointer().GetStyle();
104 else
105 ePointerStyle = PointerStyle::Arrow;
107 const vcl::Window* pWindow = this;
110 // when the pointer is not visible stop the search, as
111 // this status should not be overwritten
112 if ( pWindow->mpWindowImpl->mbNoPtrVisible )
113 return PointerStyle::Null;
115 if ( !bWait )
117 if ( pWindow->mpWindowImpl->mnWaitCount )
119 ePointerStyle = PointerStyle::Wait;
120 bWait = true;
122 else
124 if ( pWindow->mpWindowImpl->mbChildPtrOverwrite )
125 ePointerStyle = pWindow->GetPointer().GetStyle();
129 if ( pWindow->ImplIsOverlapWindow() )
130 break;
132 pWindow = pWindow->ImplGetParent();
134 while ( pWindow );
136 return ePointerStyle;
139 void Window::ImplCallMouseMove( sal_uInt16 nMouseCode, bool bModChanged )
141 if ( mpWindowImpl->mpFrameData->mbMouseIn && mpWindowImpl->mpFrameWindow->mpWindowImpl->mbReallyVisible )
143 sal_uInt64 nTime = tools::Time::GetSystemTicks();
144 long nX = mpWindowImpl->mpFrameData->mnLastMouseX;
145 long nY = mpWindowImpl->mpFrameData->mnLastMouseY;
146 sal_uInt16 nCode = nMouseCode;
147 MouseEventModifiers nMode = mpWindowImpl->mpFrameData->mnMouseMode;
148 bool bLeave;
149 // check for MouseLeave
150 if ( ((nX < 0) || (nY < 0) ||
151 (nX >= mpWindowImpl->mpFrameWindow->mnOutWidth) ||
152 (nY >= mpWindowImpl->mpFrameWindow->mnOutHeight)) &&
153 !ImplGetSVData()->maWinData.mpCaptureWin )
154 bLeave = true;
155 else
156 bLeave = false;
157 nMode |= MouseEventModifiers::SYNTHETIC;
158 if ( bModChanged )
159 nMode |= MouseEventModifiers::MODIFIERCHANGED;
160 ImplHandleMouseEvent( mpWindowImpl->mpFrameWindow, MouseNotifyEvent::MOUSEMOVE, bLeave, nX, nY, nTime, nCode, nMode );
164 void Window::ImplGenerateMouseMove()
166 if ( mpWindowImpl && mpWindowImpl->mpFrameData &&
167 !mpWindowImpl->mpFrameData->mnMouseMoveId )
168 mpWindowImpl->mpFrameData->mnMouseMoveId = Application::PostUserEvent( LINK( mpWindowImpl->mpFrameWindow, Window, ImplGenerateMouseMoveHdl ), nullptr, true );
171 IMPL_LINK_NOARG(Window, ImplGenerateMouseMoveHdl, void*, void)
173 mpWindowImpl->mpFrameData->mnMouseMoveId = nullptr;
174 vcl::Window* pCaptureWin = ImplGetSVData()->maWinData.mpCaptureWin;
175 if( ! pCaptureWin ||
176 (pCaptureWin->mpWindowImpl && pCaptureWin->mpWindowImpl->mpFrame == mpWindowImpl->mpFrame)
179 ImplCallMouseMove( mpWindowImpl->mpFrameData->mnMouseCode );
183 void Window::ImplInvertFocus( const Rectangle& rRect )
185 InvertTracking( rRect, ShowTrackFlags::Small | ShowTrackFlags::TrackWindow );
188 static bool IsWindowFocused(const WindowImpl& rWinImpl)
190 if (rWinImpl.mpSysObj)
191 return true;
193 if (rWinImpl.mpFrameData->mbHasFocus)
194 return true;
196 if (rWinImpl.mbFakeFocusSet)
197 return true;
199 return false;
202 void Window::ImplGrabFocus( GetFocusFlags nFlags )
204 // #143570# no focus for destructing windows
205 if( !mpWindowImpl || mpWindowImpl->mbInDispose )
206 return;
208 // some event listeners do really bad stuff
209 // => prepare for the worst
210 VclPtr<vcl::Window> xWindow( this );
212 // Currently the client window should always get the focus
213 // Should the border window at some point be focusable
214 // we need to change all GrabFocus() instances in VCL,
215 // e.g. in ToTop()
217 if ( mpWindowImpl->mpClientWindow )
219 // For a lack of design we need a little hack here to
220 // ensure that dialogs on close pass the focus back to
221 // the correct window
222 if ( mpWindowImpl->mpLastFocusWindow && (mpWindowImpl->mpLastFocusWindow.get() != this) &&
223 !(mpWindowImpl->mnDlgCtrlFlags & DialogControlFlags::WantFocus) &&
224 mpWindowImpl->mpLastFocusWindow->IsEnabled() &&
225 mpWindowImpl->mpLastFocusWindow->IsInputEnabled() &&
226 ! mpWindowImpl->mpLastFocusWindow->IsInModalMode()
228 mpWindowImpl->mpLastFocusWindow->GrabFocus();
229 else
230 mpWindowImpl->mpClientWindow->GrabFocus();
231 return;
233 else if ( mpWindowImpl->mbFrame )
235 // For a lack of design we need a little hack here to
236 // ensure that dialogs on close pass the focus back to
237 // the correct window
238 if ( mpWindowImpl->mpLastFocusWindow && (mpWindowImpl->mpLastFocusWindow.get() != this) &&
239 !(mpWindowImpl->mnDlgCtrlFlags & DialogControlFlags::WantFocus) &&
240 mpWindowImpl->mpLastFocusWindow->IsEnabled() &&
241 mpWindowImpl->mpLastFocusWindow->IsInputEnabled() &&
242 ! mpWindowImpl->mpLastFocusWindow->IsInModalMode()
245 mpWindowImpl->mpLastFocusWindow->GrabFocus();
246 return;
250 // If the Window is disabled, then we don't change the focus
251 if ( !IsEnabled() || !IsInputEnabled() || IsInModalMode() )
252 return;
254 // we only need to set the focus if it is not already set
255 // note: if some other frame is waiting for an asynchronous focus event
256 // we also have to post an asynchronous focus event for this frame
257 // which is done using ToTop
258 ImplSVData* pSVData = ImplGetSVData();
260 bool bAsyncFocusWaiting = false;
261 vcl::Window *pFrame = pSVData->maWinData.mpFirstFrame;
262 while( pFrame )
264 if( pFrame != mpWindowImpl->mpFrameWindow.get() && pFrame->mpWindowImpl->mpFrameData->mnFocusId )
266 bAsyncFocusWaiting = true;
267 break;
269 pFrame = pFrame->mpWindowImpl->mpFrameData->mpNextFrame;
272 bool bHasFocus = IsWindowFocused(*mpWindowImpl);
274 bool bMustNotGrabFocus = false;
275 // #100242#, check parent hierarchy if some floater prohibits grab focus
277 vcl::Window *pParent = this;
278 while( pParent )
280 if ((pParent->GetStyle() & WB_SYSTEMFLOATWIN) && !(pParent->GetStyle() & WB_MOVEABLE))
282 bMustNotGrabFocus = true;
283 break;
285 pParent = pParent->mpWindowImpl->mpParent;
288 if ( ( pSVData->maWinData.mpFocusWin.get() != this &&
289 !mpWindowImpl->mbInDispose ) ||
290 ( bAsyncFocusWaiting && !bHasFocus && !bMustNotGrabFocus ) )
292 // EndExtTextInput if it is not the same window
293 if ( pSVData->maWinData.mpExtTextInputWin &&
294 (pSVData->maWinData.mpExtTextInputWin.get() != this) )
295 pSVData->maWinData.mpExtTextInputWin->EndExtTextInput();
297 // mark this windows as the last FocusWindow
298 vcl::Window* pOverlapWindow = ImplGetFirstOverlapWindow();
299 pOverlapWindow->mpWindowImpl->mpLastFocusWindow = this;
300 mpWindowImpl->mpFrameData->mpFocusWin = this;
302 if( !bHasFocus )
304 // menu windows never get the system focus
305 // the application will keep the focus
306 if( bMustNotGrabFocus )
307 return;
308 else
310 // here we already switch focus as ToTop()
311 // should not give focus to another window
312 mpWindowImpl->mpFrame->ToTop( SalFrameToTop::GrabFocus | SalFrameToTop::GrabFocusOnly );
313 return;
317 VclPtr<vcl::Window> pOldFocusWindow = pSVData->maWinData.mpFocusWin;
319 pSVData->maWinData.mpFocusWin = this;
321 if ( pOldFocusWindow )
323 // Cursor hidden
324 if ( pOldFocusWindow->mpWindowImpl->mpCursor )
325 pOldFocusWindow->mpWindowImpl->mpCursor->ImplHide();
328 // !!!!! due to old SV-Office Activate/Deactivate handling
329 // !!!!! first as before
330 if ( pOldFocusWindow )
332 // remember Focus
333 vcl::Window* pOldOverlapWindow = pOldFocusWindow->ImplGetFirstOverlapWindow();
334 vcl::Window* pNewOverlapWindow = ImplGetFirstOverlapWindow();
335 if ( pOldOverlapWindow != pNewOverlapWindow )
336 ImplCallFocusChangeActivate( pNewOverlapWindow, pOldOverlapWindow );
338 else
340 vcl::Window* pNewOverlapWindow = ImplGetFirstOverlapWindow();
341 vcl::Window* pNewRealWindow = pNewOverlapWindow->ImplGetWindow();
342 pNewOverlapWindow->mpWindowImpl->mbActive = true;
343 pNewOverlapWindow->Activate();
344 if ( pNewRealWindow != pNewOverlapWindow )
346 pNewRealWindow->mpWindowImpl->mbActive = true;
347 pNewRealWindow->Activate();
351 // call Get- and LoseFocus
352 if ( pOldFocusWindow && ! pOldFocusWindow->IsDisposed() )
354 if ( pOldFocusWindow->IsTracking() &&
355 (pSVData->maWinData.mnTrackFlags & StartTrackingFlags::FocusCancel) )
356 pOldFocusWindow->EndTracking( TrackingEventFlags::Cancel | TrackingEventFlags::Focus );
357 NotifyEvent aNEvt( MouseNotifyEvent::LOSEFOCUS, pOldFocusWindow );
358 if ( !ImplCallPreNotify( aNEvt ) )
359 pOldFocusWindow->CompatLoseFocus();
360 pOldFocusWindow->ImplCallDeactivateListeners( this );
363 if ( pSVData->maWinData.mpFocusWin.get() == this )
365 if ( mpWindowImpl->mpSysObj )
367 mpWindowImpl->mpFrameData->mpFocusWin = this;
368 if ( !mpWindowImpl->mpFrameData->mbInSysObjFocusHdl )
369 mpWindowImpl->mpSysObj->GrabFocus();
372 if ( pSVData->maWinData.mpFocusWin.get() == this )
374 if ( mpWindowImpl->mpCursor )
375 mpWindowImpl->mpCursor->ImplShow();
376 mpWindowImpl->mbInFocusHdl = true;
377 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 if( pOldFocusWindow &&
382 ! pOldFocusWindow->IsDisposed() &&
383 ( pOldFocusWindow->GetDialogControlFlags() & DialogControlFlags::FloatWinPopupModeEndCancel ) )
384 mpWindowImpl->mnGetFocusFlags |= GetFocusFlags::FloatWinPopupModeEndCancel;
385 NotifyEvent aNEvt( MouseNotifyEvent::GETFOCUS, this );
386 if ( !ImplCallPreNotify( aNEvt ) && !xWindow->IsDisposed() )
387 CompatGetFocus();
388 if( !xWindow->IsDisposed() )
389 ImplCallActivateListeners( (pOldFocusWindow && ! pOldFocusWindow->IsDisposed()) ? pOldFocusWindow : nullptr );
390 if( !xWindow->IsDisposed() )
392 mpWindowImpl->mnGetFocusFlags = GetFocusFlags::NONE;
393 mpWindowImpl->mbInFocusHdl = false;
398 ImplNewInputContext();
402 void Window::ImplGrabFocusToDocument( GetFocusFlags nFlags )
404 vcl::Window *pWin = this;
405 while( pWin )
407 if( !pWin->GetParent() )
409 pWin->ImplGetFrameWindow()->GetWindow( GetWindowType::Client )->ImplGrabFocus(nFlags);
410 return;
412 pWin = pWin->GetParent();
416 void Window::MouseMove( const MouseEvent& rMEvt )
418 NotifyEvent aNEvt( MouseNotifyEvent::MOUSEMOVE, this, &rMEvt );
419 if (!EventNotify(aNEvt))
420 mpWindowImpl->mbMouseMove = true;
423 void Window::MouseButtonDown( const MouseEvent& rMEvt )
425 NotifyEvent aNEvt( MouseNotifyEvent::MOUSEBUTTONDOWN, this, &rMEvt );
426 if (!EventNotify(aNEvt))
427 mpWindowImpl->mbMouseButtonDown = true;
430 void Window::MouseButtonUp( const MouseEvent& rMEvt )
432 NotifyEvent aNEvt( MouseNotifyEvent::MOUSEBUTTONUP, this, &rMEvt );
433 if (!EventNotify(aNEvt))
434 mpWindowImpl->mbMouseButtonUp = true;
437 void Window::SetMouseTransparent( bool bTransparent )
440 if ( mpWindowImpl->mpBorderWindow )
441 mpWindowImpl->mpBorderWindow->SetMouseTransparent( bTransparent );
443 if( mpWindowImpl->mpSysObj )
444 mpWindowImpl->mpSysObj->SetMouseTransparent( bTransparent );
446 mpWindowImpl->mbMouseTransparent = bTransparent;
449 void Window::CaptureMouse()
452 ImplSVData* pSVData = ImplGetSVData();
454 // possibly stop tracking
455 if ( pSVData->maWinData.mpTrackWin.get() != this )
457 if ( pSVData->maWinData.mpTrackWin )
458 pSVData->maWinData.mpTrackWin->EndTracking( TrackingEventFlags::Cancel );
461 if ( pSVData->maWinData.mpCaptureWin.get() != this )
463 pSVData->maWinData.mpCaptureWin = this;
464 mpWindowImpl->mpFrame->CaptureMouse( true );
468 void Window::ReleaseMouse()
471 ImplSVData* pSVData = ImplGetSVData();
473 SAL_WARN_IF(!IsMouseCaptured(), "vcl",
474 "Window::ReleaseMouse(): window doesn't have the mouse capture" );
476 if (IsMouseCaptured())
478 pSVData->maWinData.mpCaptureWin = nullptr;
479 mpWindowImpl->mpFrame->CaptureMouse( false );
480 ImplGenerateMouseMove();
484 bool Window::IsMouseCaptured() const
487 return (this == ImplGetSVData()->maWinData.mpCaptureWin);
490 void Window::SetPointer( const Pointer& rPointer )
493 if ( mpWindowImpl->maPointer == rPointer )
494 return;
496 mpWindowImpl->maPointer = rPointer;
498 // possibly immediately move pointer
499 if ( !mpWindowImpl->mpFrameData->mbInMouseMove && ImplTestMousePointerSet() )
500 mpWindowImpl->mpFrame->SetPointer( ImplGetMousePointer() );
502 if (VclPtr<vcl::Window> pWin = GetParentWithLOKNotifier())
504 Pointer aPointer = GetPointer();
505 // We don't map all possible pointers hence we need a default
506 OString aPointerString = "default";
507 auto aIt = vcl::gaLOKPointerMap.find(aPointer.GetStyle());
508 if (aIt != vcl::gaLOKPointerMap.end())
510 aPointerString = aIt->second;
513 // issue mouse pointer events only for document windows
514 // Doc windows' immediate parent SfxFrameViewWindow_Impl is the one with
515 // parent notifier set during initialization
516 if (GetParent()->ImplGetWindowImpl()->mbLOKParentNotifier &&
517 GetParent()->ImplGetWindowImpl()->mnLOKWindowId == 0)
519 pWin->GetLOKNotifier()->libreOfficeKitViewCallback(LOK_CALLBACK_MOUSE_POINTER, aPointerString.getStr());
524 void Window::EnableChildPointerOverwrite( bool bOverwrite )
527 if ( mpWindowImpl->mbChildPtrOverwrite == bOverwrite )
528 return;
530 mpWindowImpl->mbChildPtrOverwrite = bOverwrite;
532 // possibly immediately move pointer
533 if ( !mpWindowImpl->mpFrameData->mbInMouseMove && ImplTestMousePointerSet() )
534 mpWindowImpl->mpFrame->SetPointer( ImplGetMousePointer() );
537 void Window::SetPointerPosPixel( const Point& rPos )
539 Point aPos = ImplOutputToFrame( rPos );
540 const OutputDevice *pOutDev = GetOutDev();
541 if( pOutDev->HasMirroredGraphics() )
543 if( !IsRTLEnabled() )
545 // --- RTL --- (re-mirror mouse pos at this window)
546 pOutDev->ReMirror( aPos );
548 // mirroring is required here, SetPointerPos bypasses SalGraphics
549 mpGraphics->mirror( aPos.X(), this );
551 else if( ImplIsAntiparallel() )
553 pOutDev->ReMirror( aPos );
555 mpWindowImpl->mpFrame->SetPointerPos( aPos.X(), aPos.Y() );
558 void Window::SetLastMousePos(const Point& rPos)
560 // Do this conversion, so when GetPointerPosPixel() calls
561 // ImplFrameToOutput(), we get back the original position.
562 Point aPos = ImplOutputToFrame(rPos);
563 mpWindowImpl->mpFrameData->mnLastMouseX = aPos.X();
564 mpWindowImpl->mpFrameData->mnLastMouseY = aPos.Y();
567 Point Window::GetPointerPosPixel()
570 Point aPos( mpWindowImpl->mpFrameData->mnLastMouseX, mpWindowImpl->mpFrameData->mnLastMouseY );
571 if( ImplIsAntiparallel() )
573 // --- RTL --- (re-mirror mouse pos at this window)
574 const OutputDevice *pOutDev = GetOutDev();
575 pOutDev->ReMirror( aPos );
577 return ImplFrameToOutput( aPos );
580 Point Window::GetLastPointerPosPixel()
583 Point aPos( mpWindowImpl->mpFrameData->mnBeforeLastMouseX, mpWindowImpl->mpFrameData->mnBeforeLastMouseY );
584 if( ImplIsAntiparallel() )
586 // --- RTL --- (re-mirror mouse pos at this window)
587 const OutputDevice *pOutDev = GetOutDev();
588 pOutDev->ReMirror( aPos );
590 return ImplFrameToOutput( aPos );
593 void Window::ShowPointer( bool bVisible )
596 if ( mpWindowImpl->mbNoPtrVisible != !bVisible )
598 mpWindowImpl->mbNoPtrVisible = !bVisible;
600 // possibly immediately move pointer
601 if ( !mpWindowImpl->mpFrameData->mbInMouseMove && ImplTestMousePointerSet() )
602 mpWindowImpl->mpFrame->SetPointer( ImplGetMousePointer() );
606 Window::PointerState Window::GetPointerState()
608 PointerState aState;
609 aState.mnState = 0;
611 if (mpWindowImpl->mpFrame)
613 SalFrame::SalPointerState aSalPointerState;
615 aSalPointerState = mpWindowImpl->mpFrame->GetPointerState();
616 if( ImplIsAntiparallel() )
618 // --- RTL --- (re-mirror mouse pos at this window)
619 const OutputDevice *pOutDev = GetOutDev();
620 pOutDev->ReMirror( aSalPointerState.maPos );
622 aState.maPos = ImplFrameToOutput( aSalPointerState.maPos );
623 aState.mnState = aSalPointerState.mnState;
625 return aState;
628 bool Window::IsMouseOver()
630 return ImplGetWinData()->mbMouseOver;
633 void Window::EnterWait()
636 mpWindowImpl->mnWaitCount++;
638 if ( mpWindowImpl->mnWaitCount == 1 )
640 // possibly immediately move pointer
641 if ( !mpWindowImpl->mpFrameData->mbInMouseMove && ImplTestMousePointerSet() )
642 mpWindowImpl->mpFrame->SetPointer( ImplGetMousePointer() );
646 void Window::LeaveWait()
649 if ( mpWindowImpl->mnWaitCount )
651 mpWindowImpl->mnWaitCount--;
653 if ( !mpWindowImpl->mnWaitCount )
655 // possibly immediately move pointer
656 if ( !mpWindowImpl->mpFrameData->mbInMouseMove && ImplTestMousePointerSet() )
657 mpWindowImpl->mpFrame->SetPointer( ImplGetMousePointer() );
662 bool Window::ImplStopDnd()
664 bool bRet = false;
665 if( mpWindowImpl->mpFrameData && mpWindowImpl->mpFrameData->mxDropTargetListener.is() )
667 bRet = true;
668 mpWindowImpl->mpFrameData->mxDropTarget.clear();
669 mpWindowImpl->mpFrameData->mxDragSource.clear();
670 mpWindowImpl->mpFrameData->mxDropTargetListener.clear();
673 return bRet;
676 void Window::ImplStartDnd()
678 GetDropTarget();
681 Reference< css::datatransfer::dnd::XDropTarget > Window::GetDropTarget()
683 if( !mpWindowImpl )
684 return Reference< css::datatransfer::dnd::XDropTarget >();
686 if( ! mpWindowImpl->mxDNDListenerContainer.is() )
688 sal_Int8 nDefaultActions = 0;
690 if( mpWindowImpl->mpFrameData )
692 if( ! mpWindowImpl->mpFrameData->mxDropTarget.is() )
694 // initialization is done in GetDragSource
695 Reference< css::datatransfer::dnd::XDragSource > xDragSource = GetDragSource();
698 if( mpWindowImpl->mpFrameData->mxDropTarget.is() )
700 nDefaultActions = mpWindowImpl->mpFrameData->mxDropTarget->getDefaultActions();
702 if( ! mpWindowImpl->mpFrameData->mxDropTargetListener.is() )
704 mpWindowImpl->mpFrameData->mxDropTargetListener = new DNDEventDispatcher( mpWindowImpl->mpFrameWindow );
708 mpWindowImpl->mpFrameData->mxDropTarget->addDropTargetListener( mpWindowImpl->mpFrameData->mxDropTargetListener );
710 // register also as drag gesture listener if directly supported by drag source
711 Reference< css::datatransfer::dnd::XDragGestureRecognizer > xDragGestureRecognizer =
712 Reference< css::datatransfer::dnd::XDragGestureRecognizer > (mpWindowImpl->mpFrameData->mxDragSource, UNO_QUERY);
714 if( xDragGestureRecognizer.is() )
716 xDragGestureRecognizer->addDragGestureListener(
717 Reference< css::datatransfer::dnd::XDragGestureListener > (mpWindowImpl->mpFrameData->mxDropTargetListener, UNO_QUERY));
719 else
720 mpWindowImpl->mpFrameData->mbInternalDragGestureRecognizer = true;
723 catch (const RuntimeException&)
725 // release all instances
726 mpWindowImpl->mpFrameData->mxDropTarget.clear();
727 mpWindowImpl->mpFrameData->mxDragSource.clear();
734 mpWindowImpl->mxDNDListenerContainer = static_cast < css::datatransfer::dnd::XDropTarget * > ( new DNDListenerContainer( nDefaultActions ) );
737 // this object is located in the same process, so there will be no runtime exception
738 return Reference< css::datatransfer::dnd::XDropTarget > ( mpWindowImpl->mxDNDListenerContainer, UNO_QUERY );
741 Reference< css::datatransfer::dnd::XDragSource > Window::GetDragSource()
744 #if HAVE_FEATURE_DESKTOP
746 if( mpWindowImpl->mpFrameData )
748 if( ! mpWindowImpl->mpFrameData->mxDragSource.is() )
752 Reference< XComponentContext > xContext( comphelper::getProcessComponentContext() );
753 const SystemEnvData * pEnvData = GetSystemData();
755 if( pEnvData )
757 Sequence< Any > aDragSourceAL( 2 ), aDropTargetAL( 2 );
758 OUString aDragSourceSN, aDropTargetSN;
759 #if defined(_WIN32)
760 aDragSourceSN = "com.sun.star.datatransfer.dnd.OleDragSource";
761 aDropTargetSN = "com.sun.star.datatransfer.dnd.OleDropTarget";
762 aDragSourceAL[ 1 ] = makeAny( static_cast<sal_uInt64>( reinterpret_cast<sal_IntPtr>(pEnvData->hWnd) ) );
763 aDropTargetAL[ 0 ] = makeAny( static_cast<sal_uInt64>( reinterpret_cast<sal_IntPtr>(pEnvData->hWnd) ) );
764 #elif defined MACOSX
765 /* FIXME: Mac OS X specific dnd interface does not exist! *
766 * Using Windows based dnd as a temporary solution */
767 aDragSourceSN = "com.sun.star.datatransfer.dnd.OleDragSource";
768 aDropTargetSN = "com.sun.star.datatransfer.dnd.OleDropTarget";
769 aDragSourceAL[ 1 ] = makeAny( static_cast<sal_uInt64>( reinterpret_cast<sal_IntPtr>(pEnvData->mpNSView) ) );
770 aDropTargetAL[ 0 ] = makeAny( static_cast<sal_uInt64>( reinterpret_cast<sal_IntPtr>(pEnvData->mpNSView) ) );
771 #elif HAVE_FEATURE_X11
772 aDragSourceSN = "com.sun.star.datatransfer.dnd.X11DragSource";
773 aDropTargetSN = "com.sun.star.datatransfer.dnd.X11DropTarget";
775 aDragSourceAL[ 0 ] = makeAny( Application::GetDisplayConnection() );
776 aDragSourceAL[ 1 ] = makeAny(static_cast<sal_IntPtr>(pEnvData->aShellWindow));
777 aDropTargetAL[ 0 ] = makeAny( Application::GetDisplayConnection() );
778 aDropTargetAL[ 1 ] = makeAny(static_cast<sal_IntPtr>(pEnvData->aShellWindow));
779 #endif
780 if( !aDragSourceSN.isEmpty() )
781 mpWindowImpl->mpFrameData->mxDragSource.set(
782 xContext->getServiceManager()->createInstanceWithArgumentsAndContext( aDragSourceSN, aDragSourceAL, xContext ),
783 UNO_QUERY );
785 if( !aDropTargetSN.isEmpty() )
786 mpWindowImpl->mpFrameData->mxDropTarget.set(
787 xContext->getServiceManager()->createInstanceWithArgumentsAndContext( aDropTargetSN, aDropTargetAL, xContext ),
788 UNO_QUERY );
792 // createInstance can throw any exception
793 catch (const Exception&)
795 // release all instances
796 mpWindowImpl->mpFrameData->mxDropTarget.clear();
797 mpWindowImpl->mpFrameData->mxDragSource.clear();
801 return mpWindowImpl->mpFrameData->mxDragSource;
803 #endif
804 return Reference< css::datatransfer::dnd::XDragSource > ();
807 Reference< css::datatransfer::dnd::XDragGestureRecognizer > Window::GetDragGestureRecognizer()
809 return Reference< css::datatransfer::dnd::XDragGestureRecognizer > ( GetDropTarget(), UNO_QUERY );
812 } /* namespace vcl */
814 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */