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>
792 lines
26 KiB
C++
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: */
|