Files
libreoffice/vcl/source/window/mouse.cxx
Jan-Marek Glogowski 3d1f28dd1f configure: Refactor platform defaults
The main idea was to move complexity from source (and Makefiles)
into configure.ac, because otherwise these must replicate the
"same" branching, often resulting in diversions. Better to keep
the logic in one place (configure.ac) and set additional variables
to be used directly by source code and Makefiles.

Notably this introduce the "using_*" platform flags, which should
be considered constants. There is USING_X11, which actually tells,
if the build uses the platform's X11 (and I opted for the removal
of HAVE_FEATURE_X11). I also consider variables constant, after
they have been exported by AC_SUBST, which should never be
conditional, or some AC_DEFINE set them for a config header.

A large block of defaults depends on $using_x11, so we set them to
the same value, but just if the platform doesn't set it.

The other important flag is $using_freetype_fontconfig, if the
platform uses freetype and fontconfig. The headless plugin uses
cairo for its drawing operations and freetype+fontconfig for text,
so $test_cairo = $using_freetype_fontconfig. This is independent
from a the cairo canvas!

The OpenGL X11 code now depends on USING_X11, but it doesn't yet
reflect the filter in Library_vcl.mk protecting glx. I don't know
how correct this glx filter is, seeing that the source code just
checked for "UNX - some  non-X11 targets".

Change-Id: Id1ba1a967a5d8d10ee217458be879ed00459f7e6
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/116440
Tested-by: Jenkins
Reviewed-by: Jan-Marek Glogowski <glogow@fbihome.de>
2021-06-01 15:30:59 +02:00

792 lines
26 KiB
C++

/* -*- 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_feature_desktop.h>
#include <config_vclplug.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( GetOutDev()->ImplIsAntiparallel() )
{
const OutputDevice *pOutDev = GetOutDev();
pOutDev->ReMirror( aFramePos );
}
if ( !GetOutputRectPixel().IsInside( aFramePos ) )
return WindowHitTest::NONE;
if ( mpWindowImpl->mbWinRegion )
{
Point aTempPos = aFramePos;
aTempPos.AdjustX( -GetOutDev()->mnOutOffX );
aTempPos.AdjustY( -GetOutDev()->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) )
return;
sal_uInt64 nTime = tools::Time::GetSystemTicks();
tools::Long nX = mpWindowImpl->mpFrameData->mnLastMouseX;
tools::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->GetOutDev()->mnOutWidth) ||
(nY >= mpWindowImpl->mpFrameWindow->GetOutDev()->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() );
VclPtr<vcl::Window> pWin = GetParentWithLOKNotifier();
if (!pWin)
return;
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( GetOutDev()->mpGraphics->mirror2( aPos.X(), *GetOutDev() ) );
}
else if( GetOutDev()->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( GetOutDev()->ImplIsAntiparallel() )
{
const OutputDevice *pOutDev = GetOutDev();
pOutDev->ReMirror( aPos );
}
return ImplFrameToOutput( aPos );
}
Point Window::GetLastPointerPosPixel()
{
Point aPos( mpWindowImpl->mpFrameData->mnBeforeLastMouseX, mpWindowImpl->mpFrameData->mnBeforeLastMouseY );
if( GetOutDev()->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( GetOutDev()->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 USING_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: */