summaryrefslogtreecommitdiffstats
path: root/vcl/source/window/mouse.cxx
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 16:51:28 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 16:51:28 +0000
commit940b4d1848e8c70ab7642901a68594e8016caffc (patch)
treeeb72f344ee6c3d9b80a7ecc079ea79e9fba8676d /vcl/source/window/mouse.cxx
parentInitial commit. (diff)
downloadlibreoffice-940b4d1848e8c70ab7642901a68594e8016caffc.tar.xz
libreoffice-940b4d1848e8c70ab7642901a68594e8016caffc.zip
Adding upstream version 1:7.0.4.upstream/1%7.0.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vcl/source/window/mouse.cxx')
-rw-r--r--vcl/source/window/mouse.cxx792
1 files changed, 792 insertions, 0 deletions
diff --git a/vcl/source/window/mouse.cxx b/vcl/source/window/mouse.cxx
new file mode 100644
index 000000000..5894d88bd
--- /dev/null
+++ b/vcl/source/window/mouse.cxx
@@ -0,0 +1,792 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include <config_features.h>
+#include <config_feature_desktop.h>
+
+#include <tools/time.hxx>
+
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
+
+#include <vcl/ITiledRenderable.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/window.hxx>
+#include <vcl/cursor.hxx>
+#include <vcl/sysdata.hxx>
+#include <vcl/event.hxx>
+
+#include <sal/types.h>
+
+#include <window.h>
+#include <svdata.hxx>
+#include <salobj.hxx>
+#include <salgdi.hxx>
+#include <salframe.hxx>
+
+#include <dndlistenercontainer.hxx>
+#include <dndeventdispatcher.hxx>
+
+#include <com/sun/star/datatransfer/dnd/XDragSource.hpp>
+#include <com/sun/star/datatransfer/dnd/XDropTarget.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+#include <comphelper/processfactory.hxx>
+
+using namespace ::com::sun::star::uno;
+
+namespace vcl {
+
+WindowHitTest Window::ImplHitTest( const Point& rFramePos )
+{
+ Point aFramePos( rFramePos );
+ if( ImplIsAntiparallel() )
+ {
+ const OutputDevice *pOutDev = GetOutDev();
+ pOutDev->ReMirror( aFramePos );
+ }
+ tools::Rectangle aRect( Point( mnOutOffX, mnOutOffY ), Size( mnOutWidth, mnOutHeight ) );
+ if ( !aRect.IsInside( aFramePos ) )
+ return WindowHitTest::NONE;
+ if ( mpWindowImpl->mbWinRegion )
+ {
+ Point aTempPos = aFramePos;
+ aTempPos.AdjustX( -mnOutOffX );
+ aTempPos.AdjustY( -mnOutOffY );
+ if ( !mpWindowImpl->maWinRegion.IsInside( aTempPos ) )
+ return WindowHitTest::NONE;
+ }
+
+ WindowHitTest nHitTest = WindowHitTest::Inside;
+ if ( mpWindowImpl->mbMouseTransparent )
+ nHitTest |= WindowHitTest::Transparent;
+ return nHitTest;
+}
+
+bool Window::ImplTestMousePointerSet()
+{
+ // as soon as mouse is captured, switch mouse-pointer
+ if ( IsMouseCaptured() )
+ return true;
+
+ // if the mouse is over the window, switch it
+ tools::Rectangle aClientRect( Point( 0, 0 ), GetOutputSizePixel() );
+ return aClientRect.IsInside( GetPointerPosPixel() );
+}
+
+PointerStyle Window::ImplGetMousePointer() const
+{
+ PointerStyle ePointerStyle;
+ bool bWait = false;
+
+ if ( IsEnabled() && IsInputEnabled() && ! IsInModalMode() )
+ ePointerStyle = GetPointer();
+ else
+ ePointerStyle = PointerStyle::Arrow;
+
+ const vcl::Window* pWindow = this;
+ do
+ {
+ // when the pointer is not visible stop the search, as
+ // this status should not be overwritten
+ if ( pWindow->mpWindowImpl->mbNoPtrVisible )
+ return PointerStyle::Null;
+
+ if ( !bWait )
+ {
+ if ( pWindow->mpWindowImpl->mnWaitCount )
+ {
+ ePointerStyle = PointerStyle::Wait;
+ bWait = true;
+ }
+ else
+ {
+ if ( pWindow->mpWindowImpl->mbChildPtrOverwrite )
+ ePointerStyle = pWindow->GetPointer();
+ }
+ }
+
+ if ( pWindow->ImplIsOverlapWindow() )
+ break;
+
+ pWindow = pWindow->ImplGetParent();
+ }
+ while ( pWindow );
+
+ return ePointerStyle;
+}
+
+void Window::ImplCallMouseMove( sal_uInt16 nMouseCode, bool bModChanged )
+{
+ if ( mpWindowImpl->mpFrameData->mbMouseIn && mpWindowImpl->mpFrameWindow->mpWindowImpl->mbReallyVisible )
+ {
+ sal_uInt64 nTime = tools::Time::GetSystemTicks();
+ long nX = mpWindowImpl->mpFrameData->mnLastMouseX;
+ long nY = mpWindowImpl->mpFrameData->mnLastMouseY;
+ sal_uInt16 nCode = nMouseCode;
+ MouseEventModifiers nMode = mpWindowImpl->mpFrameData->mnMouseMode;
+ bool bLeave;
+ // check for MouseLeave
+ bLeave = ((nX < 0) || (nY < 0) ||
+ (nX >= mpWindowImpl->mpFrameWindow->mnOutWidth) ||
+ (nY >= mpWindowImpl->mpFrameWindow->mnOutHeight)) &&
+ !ImplGetSVData()->mpWinData->mpCaptureWin;
+ nMode |= MouseEventModifiers::SYNTHETIC;
+ if ( bModChanged )
+ nMode |= MouseEventModifiers::MODIFIERCHANGED;
+ ImplHandleMouseEvent( mpWindowImpl->mpFrameWindow, MouseNotifyEvent::MOUSEMOVE, bLeave, nX, nY, nTime, nCode, nMode );
+ }
+}
+
+void Window::ImplGenerateMouseMove()
+{
+ if ( mpWindowImpl && mpWindowImpl->mpFrameData &&
+ !mpWindowImpl->mpFrameData->mnMouseMoveId )
+ mpWindowImpl->mpFrameData->mnMouseMoveId = Application::PostUserEvent( LINK( mpWindowImpl->mpFrameWindow, Window, ImplGenerateMouseMoveHdl ), nullptr, true );
+}
+
+IMPL_LINK_NOARG(Window, ImplGenerateMouseMoveHdl, void*, void)
+{
+ mpWindowImpl->mpFrameData->mnMouseMoveId = nullptr;
+ vcl::Window* pCaptureWin = ImplGetSVData()->mpWinData->mpCaptureWin;
+ if( ! pCaptureWin ||
+ (pCaptureWin->mpWindowImpl && pCaptureWin->mpWindowImpl->mpFrame == mpWindowImpl->mpFrame)
+ )
+ {
+ ImplCallMouseMove( mpWindowImpl->mpFrameData->mnMouseCode );
+ }
+}
+
+void Window::ImplInvertFocus( const tools::Rectangle& rRect )
+{
+ InvertTracking( rRect, ShowTrackFlags::Small | ShowTrackFlags::TrackWindow );
+}
+
+static bool IsWindowFocused(const WindowImpl& rWinImpl)
+{
+ if (rWinImpl.mpSysObj)
+ return true;
+
+ if (rWinImpl.mpFrameData->mbHasFocus)
+ return true;
+
+ if (rWinImpl.mbFakeFocusSet)
+ return true;
+
+ return false;
+}
+
+void Window::ImplGrabFocus( GetFocusFlags nFlags )
+{
+ // #143570# no focus for destructing windows
+ if( !mpWindowImpl || mpWindowImpl->mbInDispose )
+ return;
+
+ // some event listeners do really bad stuff
+ // => prepare for the worst
+ VclPtr<vcl::Window> xWindow( this );
+
+ // Currently the client window should always get the focus
+ // Should the border window at some point be focusable
+ // we need to change all GrabFocus() instances in VCL,
+ // e.g. in ToTop()
+
+ if ( mpWindowImpl->mpClientWindow )
+ {
+ // For a lack of design we need a little hack here to
+ // ensure that dialogs on close pass the focus back to
+ // the correct window
+ if ( mpWindowImpl->mpLastFocusWindow && (mpWindowImpl->mpLastFocusWindow.get() != this) &&
+ !(mpWindowImpl->mnDlgCtrlFlags & DialogControlFlags::WantFocus) &&
+ mpWindowImpl->mpLastFocusWindow->IsEnabled() &&
+ mpWindowImpl->mpLastFocusWindow->IsInputEnabled() &&
+ ! mpWindowImpl->mpLastFocusWindow->IsInModalMode()
+ )
+ mpWindowImpl->mpLastFocusWindow->GrabFocus();
+ else
+ mpWindowImpl->mpClientWindow->GrabFocus();
+ return;
+ }
+ else if ( mpWindowImpl->mbFrame )
+ {
+ // For a lack of design we need a little hack here to
+ // ensure that dialogs on close pass the focus back to
+ // the correct window
+ if ( mpWindowImpl->mpLastFocusWindow && (mpWindowImpl->mpLastFocusWindow.get() != this) &&
+ !(mpWindowImpl->mnDlgCtrlFlags & DialogControlFlags::WantFocus) &&
+ mpWindowImpl->mpLastFocusWindow->IsEnabled() &&
+ mpWindowImpl->mpLastFocusWindow->IsInputEnabled() &&
+ ! mpWindowImpl->mpLastFocusWindow->IsInModalMode()
+ )
+ {
+ mpWindowImpl->mpLastFocusWindow->GrabFocus();
+ return;
+ }
+ }
+
+ // If the Window is disabled, then we don't change the focus
+ if ( !IsEnabled() || !IsInputEnabled() || IsInModalMode() )
+ return;
+
+ // we only need to set the focus if it is not already set
+ // note: if some other frame is waiting for an asynchronous focus event
+ // we also have to post an asynchronous focus event for this frame
+ // which is done using ToTop
+ ImplSVData* pSVData = ImplGetSVData();
+
+ bool bAsyncFocusWaiting = false;
+ vcl::Window *pFrame = pSVData->maFrameData.mpFirstFrame;
+ while( pFrame )
+ {
+ if( pFrame != mpWindowImpl->mpFrameWindow.get() && pFrame->mpWindowImpl->mpFrameData->mnFocusId )
+ {
+ bAsyncFocusWaiting = true;
+ break;
+ }
+ pFrame = pFrame->mpWindowImpl->mpFrameData->mpNextFrame;
+ }
+
+ bool bHasFocus = IsWindowFocused(*mpWindowImpl);
+
+ bool bMustNotGrabFocus = false;
+ // #100242#, check parent hierarchy if some floater prohibits grab focus
+
+ vcl::Window *pParent = this;
+ while( pParent )
+ {
+ if ((pParent->GetStyle() & WB_SYSTEMFLOATWIN) && !(pParent->GetStyle() & WB_MOVEABLE))
+ {
+ bMustNotGrabFocus = true;
+ break;
+ }
+ pParent = pParent->mpWindowImpl->mpParent;
+ }
+
+ if ( !(( pSVData->mpWinData->mpFocusWin.get() != this &&
+ !mpWindowImpl->mbInDispose ) ||
+ ( bAsyncFocusWaiting && !bHasFocus && !bMustNotGrabFocus )) )
+ return;
+
+ // EndExtTextInput if it is not the same window
+ if (pSVData->mpWinData->mpExtTextInputWin
+ && (pSVData->mpWinData->mpExtTextInputWin.get() != this))
+ pSVData->mpWinData->mpExtTextInputWin->EndExtTextInput();
+
+ // mark this windows as the last FocusWindow
+ vcl::Window* pOverlapWindow = ImplGetFirstOverlapWindow();
+ pOverlapWindow->mpWindowImpl->mpLastFocusWindow = this;
+ mpWindowImpl->mpFrameData->mpFocusWin = this;
+
+ if( !bHasFocus )
+ {
+ // menu windows never get the system focus
+ // the application will keep the focus
+ if( bMustNotGrabFocus )
+ return;
+ else
+ {
+ // here we already switch focus as ToTop()
+ // should not give focus to another window
+ mpWindowImpl->mpFrame->ToTop( SalFrameToTop::GrabFocus | SalFrameToTop::GrabFocusOnly );
+ return;
+ }
+ }
+
+ VclPtr<vcl::Window> pOldFocusWindow = pSVData->mpWinData->mpFocusWin;
+
+ pSVData->mpWinData->mpFocusWin = this;
+
+ if ( pOldFocusWindow && pOldFocusWindow->mpWindowImpl )
+ {
+ // Cursor hidden
+ if ( pOldFocusWindow->mpWindowImpl->mpCursor )
+ pOldFocusWindow->mpWindowImpl->mpCursor->ImplHide();
+ }
+
+ // !!!!! due to old SV-Office Activate/Deactivate handling
+ // !!!!! first as before
+ if ( pOldFocusWindow )
+ {
+ // remember Focus
+ vcl::Window* pOldOverlapWindow = pOldFocusWindow->ImplGetFirstOverlapWindow();
+ vcl::Window* pNewOverlapWindow = ImplGetFirstOverlapWindow();
+ if ( pOldOverlapWindow != pNewOverlapWindow )
+ ImplCallFocusChangeActivate( pNewOverlapWindow, pOldOverlapWindow );
+ }
+ else
+ {
+ vcl::Window* pNewOverlapWindow = ImplGetFirstOverlapWindow();
+ vcl::Window* pNewRealWindow = pNewOverlapWindow->ImplGetWindow();
+ pNewOverlapWindow->mpWindowImpl->mbActive = true;
+ pNewOverlapWindow->Activate();
+ if ( pNewRealWindow != pNewOverlapWindow )
+ {
+ pNewRealWindow->mpWindowImpl->mbActive = true;
+ pNewRealWindow->Activate();
+ }
+ }
+
+ // call Get- and LoseFocus
+ if ( pOldFocusWindow && ! pOldFocusWindow->IsDisposed() )
+ {
+ NotifyEvent aNEvt( MouseNotifyEvent::LOSEFOCUS, pOldFocusWindow );
+ if ( !ImplCallPreNotify( aNEvt ) )
+ pOldFocusWindow->CompatLoseFocus();
+ pOldFocusWindow->ImplCallDeactivateListeners( this );
+ }
+
+ if (pSVData->mpWinData->mpFocusWin.get() == this)
+ {
+ if ( mpWindowImpl->mpSysObj )
+ {
+ mpWindowImpl->mpFrameData->mpFocusWin = this;
+ if ( !mpWindowImpl->mpFrameData->mbInSysObjFocusHdl )
+ mpWindowImpl->mpSysObj->GrabFocus();
+ }
+
+ if (pSVData->mpWinData->mpFocusWin.get() == this)
+ {
+ if ( mpWindowImpl->mpCursor )
+ mpWindowImpl->mpCursor->ImplShow();
+ mpWindowImpl->mbInFocusHdl = true;
+ mpWindowImpl->mnGetFocusFlags = nFlags;
+ // if we're changing focus due to closing a popup floating window
+ // notify the new focus window so it can restore the inner focus
+ // eg, toolboxes can select their recent active item
+ if( pOldFocusWindow &&
+ ! pOldFocusWindow->IsDisposed() &&
+ ( pOldFocusWindow->GetDialogControlFlags() & DialogControlFlags::FloatWinPopupModeEndCancel ) )
+ mpWindowImpl->mnGetFocusFlags |= GetFocusFlags::FloatWinPopupModeEndCancel;
+ NotifyEvent aNEvt( MouseNotifyEvent::GETFOCUS, this );
+ if ( !ImplCallPreNotify( aNEvt ) && !xWindow->IsDisposed() )
+ CompatGetFocus();
+ if( !xWindow->IsDisposed() )
+ ImplCallActivateListeners( (pOldFocusWindow && ! pOldFocusWindow->IsDisposed()) ? pOldFocusWindow : nullptr );
+ if( !xWindow->IsDisposed() )
+ {
+ mpWindowImpl->mnGetFocusFlags = GetFocusFlags::NONE;
+ mpWindowImpl->mbInFocusHdl = false;
+ }
+ }
+ }
+
+ ImplNewInputContext();
+
+}
+
+void Window::ImplGrabFocusToDocument( GetFocusFlags nFlags )
+{
+ vcl::Window *pWin = this;
+ while( pWin )
+ {
+ if( !pWin->GetParent() )
+ {
+ pWin->mpWindowImpl->mpFrame->GrabFocus();
+ pWin->ImplGetFrameWindow()->GetWindow( GetWindowType::Client )->ImplGrabFocus(nFlags);
+ return;
+ }
+ pWin = pWin->GetParent();
+ }
+}
+
+void Window::MouseMove( const MouseEvent& rMEvt )
+{
+ NotifyEvent aNEvt( MouseNotifyEvent::MOUSEMOVE, this, &rMEvt );
+ EventNotify(aNEvt);
+}
+
+void Window::MouseButtonDown( const MouseEvent& rMEvt )
+{
+ NotifyEvent aNEvt( MouseNotifyEvent::MOUSEBUTTONDOWN, this, &rMEvt );
+ if (!EventNotify(aNEvt))
+ mpWindowImpl->mbMouseButtonDown = true;
+}
+
+void Window::MouseButtonUp( const MouseEvent& rMEvt )
+{
+ NotifyEvent aNEvt( MouseNotifyEvent::MOUSEBUTTONUP, this, &rMEvt );
+ if (!EventNotify(aNEvt))
+ mpWindowImpl->mbMouseButtonUp = true;
+}
+
+void Window::SetMouseTransparent( bool bTransparent )
+{
+
+ if ( mpWindowImpl->mpBorderWindow )
+ mpWindowImpl->mpBorderWindow->SetMouseTransparent( bTransparent );
+
+ if( mpWindowImpl->mpSysObj )
+ mpWindowImpl->mpSysObj->SetMouseTransparent( bTransparent );
+
+ mpWindowImpl->mbMouseTransparent = bTransparent;
+}
+
+void Window::CaptureMouse()
+{
+
+ ImplSVData* pSVData = ImplGetSVData();
+
+ // possibly stop tracking
+ if (pSVData->mpWinData->mpTrackWin.get() != this)
+ {
+ if (pSVData->mpWinData->mpTrackWin)
+ pSVData->mpWinData->mpTrackWin->EndTracking(TrackingEventFlags::Cancel);
+ }
+
+ if (pSVData->mpWinData->mpCaptureWin.get() != this)
+ {
+ pSVData->mpWinData->mpCaptureWin = this;
+ mpWindowImpl->mpFrame->CaptureMouse( true );
+ }
+}
+
+void Window::ReleaseMouse()
+{
+ if (IsMouseCaptured())
+ {
+ ImplSVData* pSVData = ImplGetSVData();
+ pSVData->mpWinData->mpCaptureWin = nullptr;
+ mpWindowImpl->mpFrame->CaptureMouse( false );
+ ImplGenerateMouseMove();
+ }
+}
+
+bool Window::IsMouseCaptured() const
+{
+ return (this == ImplGetSVData()->mpWinData->mpCaptureWin);
+}
+
+void Window::SetPointer( PointerStyle nPointer )
+{
+ if ( mpWindowImpl->maPointer == nPointer )
+ return;
+
+ mpWindowImpl->maPointer = nPointer;
+
+ // possibly immediately move pointer
+ if ( !mpWindowImpl->mpFrameData->mbInMouseMove && ImplTestMousePointerSet() )
+ mpWindowImpl->mpFrame->SetPointer( ImplGetMousePointer() );
+
+ if (VclPtr<vcl::Window> pWin = GetParentWithLOKNotifier())
+ {
+ PointerStyle aPointer = GetPointer();
+ // We don't map all possible pointers hence we need a default
+ OString aPointerString = "default";
+ auto aIt = vcl::gaLOKPointerMap.find(aPointer);
+ if (aIt != vcl::gaLOKPointerMap.end())
+ {
+ aPointerString = aIt->second;
+ }
+
+ // issue mouse pointer events only for document windows
+ // Doc windows' immediate parent SfxFrameViewWindow_Impl is the one with
+ // parent notifier set during initialization
+ if (GetParent()->ImplGetWindowImpl()->mbLOKParentNotifier &&
+ GetParent()->ImplGetWindowImpl()->mnLOKWindowId == 0)
+ {
+ pWin->GetLOKNotifier()->libreOfficeKitViewCallback(LOK_CALLBACK_MOUSE_POINTER, aPointerString.getStr());
+ }
+ }
+}
+
+void Window::EnableChildPointerOverwrite( bool bOverwrite )
+{
+
+ if ( mpWindowImpl->mbChildPtrOverwrite == bOverwrite )
+ return;
+
+ mpWindowImpl->mbChildPtrOverwrite = bOverwrite;
+
+ // possibly immediately move pointer
+ if ( !mpWindowImpl->mpFrameData->mbInMouseMove && ImplTestMousePointerSet() )
+ mpWindowImpl->mpFrame->SetPointer( ImplGetMousePointer() );
+}
+
+void Window::SetPointerPosPixel( const Point& rPos )
+{
+ Point aPos = ImplOutputToFrame( rPos );
+ const OutputDevice *pOutDev = GetOutDev();
+ if( pOutDev->HasMirroredGraphics() )
+ {
+ if( !IsRTLEnabled() )
+ {
+ pOutDev->ReMirror( aPos );
+ }
+ // mirroring is required here, SetPointerPos bypasses SalGraphics
+ aPos.setX( mpGraphics->mirror2( aPos.X(), this ) );
+ }
+ else if( ImplIsAntiparallel() )
+ {
+ pOutDev->ReMirror( aPos );
+ }
+ mpWindowImpl->mpFrame->SetPointerPos( aPos.X(), aPos.Y() );
+}
+
+void Window::SetLastMousePos(const Point& rPos)
+{
+ // Do this conversion, so when GetPointerPosPixel() calls
+ // ImplFrameToOutput(), we get back the original position.
+ Point aPos = ImplOutputToFrame(rPos);
+ mpWindowImpl->mpFrameData->mnLastMouseX = aPos.X();
+ mpWindowImpl->mpFrameData->mnLastMouseY = aPos.Y();
+}
+
+Point Window::GetPointerPosPixel()
+{
+
+ Point aPos( mpWindowImpl->mpFrameData->mnLastMouseX, mpWindowImpl->mpFrameData->mnLastMouseY );
+ if( ImplIsAntiparallel() )
+ {
+ const OutputDevice *pOutDev = GetOutDev();
+ pOutDev->ReMirror( aPos );
+ }
+ return ImplFrameToOutput( aPos );
+}
+
+Point Window::GetLastPointerPosPixel()
+{
+
+ Point aPos( mpWindowImpl->mpFrameData->mnBeforeLastMouseX, mpWindowImpl->mpFrameData->mnBeforeLastMouseY );
+ if( ImplIsAntiparallel() )
+ {
+ const OutputDevice *pOutDev = GetOutDev();
+ pOutDev->ReMirror( aPos );
+ }
+ return ImplFrameToOutput( aPos );
+}
+
+void Window::ShowPointer( bool bVisible )
+{
+
+ if ( mpWindowImpl->mbNoPtrVisible != !bVisible )
+ {
+ mpWindowImpl->mbNoPtrVisible = !bVisible;
+
+ // possibly immediately move pointer
+ if ( !mpWindowImpl->mpFrameData->mbInMouseMove && ImplTestMousePointerSet() )
+ mpWindowImpl->mpFrame->SetPointer( ImplGetMousePointer() );
+ }
+}
+
+Window::PointerState Window::GetPointerState()
+{
+ PointerState aState;
+ aState.mnState = 0;
+
+ if (mpWindowImpl->mpFrame)
+ {
+ SalFrame::SalPointerState aSalPointerState = mpWindowImpl->mpFrame->GetPointerState();
+ if( ImplIsAntiparallel() )
+ {
+ const OutputDevice *pOutDev = GetOutDev();
+ pOutDev->ReMirror( aSalPointerState.maPos );
+ }
+ aState.maPos = ImplFrameToOutput( aSalPointerState.maPos );
+ aState.mnState = aSalPointerState.mnState;
+ }
+ return aState;
+}
+
+bool Window::IsMouseOver() const
+{
+ return ImplGetWinData()->mbMouseOver;
+}
+
+void Window::EnterWait()
+{
+
+ mpWindowImpl->mnWaitCount++;
+
+ if ( mpWindowImpl->mnWaitCount == 1 )
+ {
+ // possibly immediately move pointer
+ if ( !mpWindowImpl->mpFrameData->mbInMouseMove && ImplTestMousePointerSet() )
+ mpWindowImpl->mpFrame->SetPointer( ImplGetMousePointer() );
+ }
+}
+
+void Window::LeaveWait()
+{
+
+ if ( mpWindowImpl->mnWaitCount )
+ {
+ mpWindowImpl->mnWaitCount--;
+
+ if ( !mpWindowImpl->mnWaitCount )
+ {
+ // possibly immediately move pointer
+ if ( !mpWindowImpl->mpFrameData->mbInMouseMove && ImplTestMousePointerSet() )
+ mpWindowImpl->mpFrame->SetPointer( ImplGetMousePointer() );
+ }
+ }
+}
+
+bool Window::ImplStopDnd()
+{
+ bool bRet = false;
+ if( mpWindowImpl->mpFrameData && mpWindowImpl->mpFrameData->mxDropTargetListener.is() )
+ {
+ bRet = true;
+ mpWindowImpl->mpFrameData->mxDropTarget.clear();
+ mpWindowImpl->mpFrameData->mxDragSource.clear();
+ mpWindowImpl->mpFrameData->mxDropTargetListener.clear();
+ }
+
+ return bRet;
+}
+
+void Window::ImplStartDnd()
+{
+ GetDropTarget();
+}
+
+Reference< css::datatransfer::dnd::XDropTarget > Window::GetDropTarget()
+{
+ if( !mpWindowImpl )
+ return Reference< css::datatransfer::dnd::XDropTarget >();
+
+ if( ! mpWindowImpl->mxDNDListenerContainer.is() )
+ {
+ sal_Int8 nDefaultActions = 0;
+
+ if( mpWindowImpl->mpFrameData )
+ {
+ if( ! mpWindowImpl->mpFrameData->mxDropTarget.is() )
+ {
+ // initialization is done in GetDragSource
+ GetDragSource();
+ }
+
+ if( mpWindowImpl->mpFrameData->mxDropTarget.is() )
+ {
+ nDefaultActions = mpWindowImpl->mpFrameData->mxDropTarget->getDefaultActions();
+
+ if( ! mpWindowImpl->mpFrameData->mxDropTargetListener.is() )
+ {
+ mpWindowImpl->mpFrameData->mxDropTargetListener = new DNDEventDispatcher( mpWindowImpl->mpFrameWindow );
+
+ try
+ {
+ mpWindowImpl->mpFrameData->mxDropTarget->addDropTargetListener( mpWindowImpl->mpFrameData->mxDropTargetListener );
+
+ // register also as drag gesture listener if directly supported by drag source
+ Reference< css::datatransfer::dnd::XDragGestureRecognizer > xDragGestureRecognizer(
+ mpWindowImpl->mpFrameData->mxDragSource, UNO_QUERY);
+
+ if( xDragGestureRecognizer.is() )
+ {
+ xDragGestureRecognizer->addDragGestureListener(
+ Reference< css::datatransfer::dnd::XDragGestureListener > (mpWindowImpl->mpFrameData->mxDropTargetListener, UNO_QUERY));
+ }
+ else
+ mpWindowImpl->mpFrameData->mbInternalDragGestureRecognizer = true;
+
+ }
+ catch (const RuntimeException&)
+ {
+ // release all instances
+ mpWindowImpl->mpFrameData->mxDropTarget.clear();
+ mpWindowImpl->mpFrameData->mxDragSource.clear();
+ }
+ }
+ }
+
+ }
+
+ mpWindowImpl->mxDNDListenerContainer = static_cast < css::datatransfer::dnd::XDropTarget * > ( new DNDListenerContainer( nDefaultActions ) );
+ }
+
+ // this object is located in the same process, so there will be no runtime exception
+ return Reference< css::datatransfer::dnd::XDropTarget > ( mpWindowImpl->mxDNDListenerContainer, UNO_QUERY );
+}
+
+Reference< css::datatransfer::dnd::XDragSource > Window::GetDragSource()
+{
+
+#if HAVE_FEATURE_DESKTOP
+
+ if( mpWindowImpl->mpFrameData )
+ {
+ if( ! mpWindowImpl->mpFrameData->mxDragSource.is() )
+ {
+ try
+ {
+ Reference< XComponentContext > xContext( comphelper::getProcessComponentContext() );
+ const SystemEnvData * pEnvData = GetSystemData();
+
+ if( pEnvData )
+ {
+ Sequence< Any > aDragSourceAL( 2 ), aDropTargetAL( 2 );
+ OUString aDragSourceSN, aDropTargetSN;
+#if defined(_WIN32)
+ aDragSourceSN = "com.sun.star.datatransfer.dnd.OleDragSource";
+ aDropTargetSN = "com.sun.star.datatransfer.dnd.OleDropTarget";
+ aDragSourceAL[ 1 ] <<= static_cast<sal_uInt64>( reinterpret_cast<sal_IntPtr>(pEnvData->hWnd) );
+ aDropTargetAL[ 0 ] <<= static_cast<sal_uInt64>( reinterpret_cast<sal_IntPtr>(pEnvData->hWnd) );
+#elif defined MACOSX
+ /* FIXME: macOS specific dnd interface does not exist! *
+ * Using Windows based dnd as a temporary solution */
+ aDragSourceSN = "com.sun.star.datatransfer.dnd.OleDragSource";
+ aDropTargetSN = "com.sun.star.datatransfer.dnd.OleDropTarget";
+ aDragSourceAL[ 1 ] <<= static_cast<sal_uInt64>( reinterpret_cast<sal_IntPtr>(pEnvData->mpNSView) );
+ aDropTargetAL[ 0 ] <<= static_cast<sal_uInt64>( reinterpret_cast<sal_IntPtr>(pEnvData->mpNSView) );
+#elif HAVE_FEATURE_X11
+ aDragSourceSN = "com.sun.star.datatransfer.dnd.X11DragSource";
+ aDropTargetSN = "com.sun.star.datatransfer.dnd.X11DropTarget";
+
+ aDragSourceAL[ 0 ] <<= Application::GetDisplayConnection();
+ aDragSourceAL[ 1 ] <<= pEnvData->aShellWindow;
+ aDropTargetAL[ 0 ] <<= Application::GetDisplayConnection();
+ aDropTargetAL[ 1 ] <<= pEnvData->aShellWindow;
+#endif
+ if( !aDragSourceSN.isEmpty() )
+ mpWindowImpl->mpFrameData->mxDragSource.set(
+ xContext->getServiceManager()->createInstanceWithArgumentsAndContext( aDragSourceSN, aDragSourceAL, xContext ),
+ UNO_QUERY );
+
+ if( !aDropTargetSN.isEmpty() )
+ mpWindowImpl->mpFrameData->mxDropTarget.set(
+ xContext->getServiceManager()->createInstanceWithArgumentsAndContext( aDropTargetSN, aDropTargetAL, xContext ),
+ UNO_QUERY );
+ }
+ }
+
+ // createInstance can throw any exception
+ catch (const Exception&)
+ {
+ // release all instances
+ mpWindowImpl->mpFrameData->mxDropTarget.clear();
+ mpWindowImpl->mpFrameData->mxDragSource.clear();
+ }
+ }
+
+ return mpWindowImpl->mpFrameData->mxDragSource;
+ }
+#endif
+ return Reference< css::datatransfer::dnd::XDragSource > ();
+}
+
+Reference< css::datatransfer::dnd::XDragGestureRecognizer > Window::GetDragGestureRecognizer()
+{
+ return Reference< css::datatransfer::dnd::XDragGestureRecognizer > ( GetDropTarget(), UNO_QUERY );
+}
+
+} /* namespace vcl */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */