summaryrefslogtreecommitdiffstats
path: root/vcl/source/treelist/transfer2.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'vcl/source/treelist/transfer2.cxx')
-rw-r--r--vcl/source/treelist/transfer2.cxx516
1 files changed, 516 insertions, 0 deletions
diff --git a/vcl/source/treelist/transfer2.cxx b/vcl/source/treelist/transfer2.cxx
new file mode 100644
index 000000000..c63770d8a
--- /dev/null
+++ b/vcl/source/treelist/transfer2.cxx
@@ -0,0 +1,516 @@
+/* -*- 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_vclplug.h>
+
+#include <osl/mutex.hxx>
+#include <sot/exchange.hxx>
+#include <tools/debug.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/window.hxx>
+#include <comphelper/processfactory.hxx>
+#include <com/sun/star/datatransfer/clipboard/SystemClipboard.hpp>
+#include <com/sun/star/datatransfer/dnd/XDropTargetDragContext.hpp>
+#include <com/sun/star/datatransfer/dnd/XDragGestureRecognizer.hpp>
+#include <com/sun/star/datatransfer/dnd/XDropTarget.hpp>
+#include <com/sun/star/uno/DeploymentException.hpp>
+#include <svl/urlbmk.hxx>
+#include <vcl/transfer.hxx>
+
+#include <svdata.hxx>
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::com::sun::star::io;
+using namespace ::com::sun::star::datatransfer;
+using namespace ::com::sun::star::datatransfer::clipboard;
+using namespace ::com::sun::star::datatransfer::dnd;
+
+
+DragSourceHelper::DragGestureListener::DragGestureListener( DragSourceHelper& rDragSourceHelper ) :
+ mrParent( rDragSourceHelper )
+{
+}
+
+
+DragSourceHelper::DragGestureListener::~DragGestureListener()
+{
+}
+
+
+void SAL_CALL DragSourceHelper::DragGestureListener::disposing( const EventObject& )
+{
+}
+
+
+void SAL_CALL DragSourceHelper::DragGestureListener::dragGestureRecognized( const DragGestureEvent& rDGE )
+{
+ const SolarMutexGuard aGuard;
+
+ const Point aPtPixel( rDGE.DragOriginX, rDGE.DragOriginY );
+ mrParent.StartDrag( rDGE.DragAction, aPtPixel );
+}
+
+
+DragSourceHelper::DragSourceHelper( vcl::Window* pWindow ) :
+ mxDragGestureRecognizer( pWindow->GetDragGestureRecognizer() )
+{
+ if( mxDragGestureRecognizer.is() )
+ {
+ mxDragGestureListener = new DragSourceHelper::DragGestureListener( *this );
+ mxDragGestureRecognizer->addDragGestureListener( mxDragGestureListener );
+ }
+}
+
+
+void DragSourceHelper::dispose()
+{
+ Reference<XDragGestureRecognizer> xTmp;
+ {
+ std::scoped_lock aGuard( maMutex );
+ xTmp = std::move(mxDragGestureRecognizer);
+ }
+ if( xTmp.is() )
+ xTmp->removeDragGestureListener( mxDragGestureListener );
+}
+
+DragSourceHelper::~DragSourceHelper()
+{
+ dispose();
+}
+
+
+void DragSourceHelper::StartDrag( sal_Int8, const Point& )
+{
+}
+
+
+DropTargetHelper::DropTargetListener::DropTargetListener( DropTargetHelper& rDropTargetHelper ) :
+ mrParent( rDropTargetHelper )
+{
+}
+
+
+DropTargetHelper::DropTargetListener::~DropTargetListener()
+{
+}
+
+
+void SAL_CALL DropTargetHelper::DropTargetListener::disposing( const EventObject& )
+{
+}
+
+
+void SAL_CALL DropTargetHelper::DropTargetListener::drop( const DropTargetDropEvent& rDTDE )
+{
+ const SolarMutexGuard aGuard;
+
+ try
+ {
+ AcceptDropEvent aAcceptEvent;
+ ExecuteDropEvent aExecuteEvt( rDTDE.DropAction & ~DNDConstants::ACTION_DEFAULT, Point( rDTDE.LocationX, rDTDE.LocationY ), rDTDE );
+
+ aExecuteEvt.mbDefault = ( ( rDTDE.DropAction & DNDConstants::ACTION_DEFAULT ) != 0 );
+
+ // in case of a default action, call ::AcceptDrop first and use the returned
+ // accepted action as the execute action in the call to ::ExecuteDrop
+ aAcceptEvent.mnAction = aExecuteEvt.mnAction;
+ aAcceptEvent.maPosPixel = aExecuteEvt.maPosPixel;
+ static_cast<DropTargetEvent&>(const_cast<DropTargetDragEvent&>( aAcceptEvent.maDragEvent )) = rDTDE;
+ const_cast<DropTargetDragEvent&>( aAcceptEvent.maDragEvent ).DropAction = rDTDE.DropAction;
+ const_cast<DropTargetDragEvent&>( aAcceptEvent.maDragEvent ).LocationX = rDTDE.LocationX;
+ const_cast<DropTargetDragEvent&>( aAcceptEvent.maDragEvent ).LocationY = rDTDE.LocationY;
+ const_cast<DropTargetDragEvent&>( aAcceptEvent.maDragEvent ).SourceActions = rDTDE.SourceActions;
+ aAcceptEvent.mbLeaving = false;
+ aAcceptEvent.mbDefault = aExecuteEvt.mbDefault;
+
+ sal_Int8 nRet = mrParent.AcceptDrop( aAcceptEvent );
+
+ if( DNDConstants::ACTION_NONE != nRet )
+ {
+ rDTDE.Context->acceptDrop( nRet );
+
+ if( aExecuteEvt.mbDefault )
+ aExecuteEvt.mnAction = nRet;
+
+ nRet = mrParent.ExecuteDrop( aExecuteEvt );
+ }
+
+ rDTDE.Context->dropComplete( DNDConstants::ACTION_NONE != nRet );
+
+ mpLastDragOverEvent.reset();
+ }
+ catch( const css::uno::Exception& )
+ {
+ }
+}
+
+
+void SAL_CALL DropTargetHelper::DropTargetListener::dragEnter( const DropTargetDragEnterEvent& rDTDEE )
+{
+ const SolarMutexGuard aGuard;
+
+ try
+ {
+ mrParent.ImplBeginDrag( rDTDEE.SupportedDataFlavors );
+ }
+ catch( const css::uno::Exception& )
+ {
+ }
+
+ dragOver( rDTDEE );
+}
+
+
+void SAL_CALL DropTargetHelper::DropTargetListener::dragOver( const DropTargetDragEvent& rDTDE )
+{
+ const SolarMutexGuard aGuard;
+
+ try
+ {
+ mpLastDragOverEvent.reset( new AcceptDropEvent( rDTDE.DropAction & ~DNDConstants::ACTION_DEFAULT, Point( rDTDE.LocationX, rDTDE.LocationY ), rDTDE ) );
+ mpLastDragOverEvent->mbDefault = ( ( rDTDE.DropAction & DNDConstants::ACTION_DEFAULT ) != 0 );
+
+ const sal_Int8 nRet = mrParent.AcceptDrop( *mpLastDragOverEvent );
+
+ if( DNDConstants::ACTION_NONE == nRet )
+ rDTDE.Context->rejectDrag();
+ else
+ rDTDE.Context->acceptDrag( nRet );
+ }
+ catch( const css::uno::Exception& )
+ {
+ }
+}
+
+
+void SAL_CALL DropTargetHelper::DropTargetListener::dragExit( const DropTargetEvent& )
+{
+ const SolarMutexGuard aGuard;
+
+ try
+ {
+ if( mpLastDragOverEvent )
+ {
+ mpLastDragOverEvent->mbLeaving = true;
+ mrParent.AcceptDrop( *mpLastDragOverEvent );
+ mpLastDragOverEvent.reset();
+ }
+
+ mrParent.ImplEndDrag();
+ }
+ catch( const css::uno::Exception& )
+ {
+ }
+}
+
+
+void SAL_CALL DropTargetHelper::DropTargetListener::dropActionChanged( const DropTargetDragEvent& )
+{
+}
+
+
+DropTargetHelper::DropTargetHelper( vcl::Window* pWindow ) :
+ mxDropTarget( pWindow->GetDropTarget() )
+{
+ ImplConstruct();
+}
+
+
+DropTargetHelper::DropTargetHelper( const Reference< XDropTarget >& rxDropTarget ) :
+ mxDropTarget( rxDropTarget )
+{
+ ImplConstruct();
+}
+
+
+void DropTargetHelper::dispose()
+{
+ Reference< XDropTarget > xTmp;
+ {
+ std::scoped_lock aGuard( maMutex );
+ xTmp = std::move(mxDropTarget);
+ }
+ if( xTmp.is() )
+ xTmp->removeDropTargetListener( mxDropTargetListener );
+}
+
+DropTargetHelper::~DropTargetHelper()
+{
+ dispose();
+}
+
+
+void DropTargetHelper::ImplConstruct()
+{
+ if( mxDropTarget.is() )
+ {
+ mxDropTargetListener = new DropTargetHelper::DropTargetListener( *this );
+ mxDropTarget->addDropTargetListener( mxDropTargetListener );
+ mxDropTarget->setActive( true );
+ }
+}
+
+
+void DropTargetHelper::ImplBeginDrag( const Sequence< DataFlavor >& rSupportedDataFlavors )
+{
+ maFormats.clear();
+ TransferableDataHelper::FillDataFlavorExVector( rSupportedDataFlavors, maFormats );
+}
+
+
+void DropTargetHelper::ImplEndDrag()
+{
+ maFormats.clear();
+}
+
+
+sal_Int8 DropTargetHelper::AcceptDrop( const AcceptDropEvent& )
+{
+ return DNDConstants::ACTION_NONE;
+}
+
+
+sal_Int8 DropTargetHelper::ExecuteDrop( const ExecuteDropEvent& )
+{
+ return DNDConstants::ACTION_NONE;
+}
+
+
+bool DropTargetHelper::IsDropFormatSupported(SotClipboardFormatId nFormat) const
+{
+ return std::any_of(maFormats.begin(), maFormats.end(),
+ [&](const DataFlavorEx& data) { return data.mnSotId == nFormat; });
+}
+
+
+// TransferDataContainer
+
+namespace {
+
+struct TDataCntnrEntry_Impl
+{
+ css::uno::Any aAny;
+ SotClipboardFormatId nId;
+};
+
+}
+
+struct TransferDataContainer_Impl
+{
+ std::vector< TDataCntnrEntry_Impl > aFmtList;
+ Link<sal_Int8,void> aFinishedLnk;
+ std::unique_ptr<INetBookmark> pBookmk;
+
+ TransferDataContainer_Impl()
+ {
+ }
+};
+
+
+TransferDataContainer::TransferDataContainer()
+ : pImpl( new TransferDataContainer_Impl )
+{
+}
+
+
+TransferDataContainer::~TransferDataContainer()
+{
+}
+
+
+void TransferDataContainer::AddSupportedFormats()
+{
+}
+
+
+bool TransferDataContainer::GetData(
+ const css::datatransfer::DataFlavor& rFlavor, const OUString& /*rDestDoc*/ )
+{
+ bool bFnd = false;
+ SotClipboardFormatId nFmtId = SotExchange::GetFormat( rFlavor );
+
+ // test first the list
+ for (auto const& format : pImpl->aFmtList)
+ {
+ if( nFmtId == format.nId )
+ {
+ bFnd = SetAny( format.aAny );
+ break;
+ }
+ }
+
+ // test second the bookmark pointer
+ if( !bFnd )
+ switch( nFmtId )
+ {
+ case SotClipboardFormatId::STRING:
+ case SotClipboardFormatId::SOLK:
+ case SotClipboardFormatId::NETSCAPE_BOOKMARK:
+ case SotClipboardFormatId::FILECONTENT:
+ case SotClipboardFormatId::FILEGRPDESCRIPTOR:
+ case SotClipboardFormatId::UNIFORMRESOURCELOCATOR:
+ if( pImpl->pBookmk )
+ bFnd = SetINetBookmark( *pImpl->pBookmk, rFlavor );
+ break;
+
+ default: break;
+ }
+
+ return bFnd;
+}
+
+
+void TransferDataContainer::CopyINetBookmark( const INetBookmark& rBkmk )
+{
+ if( !pImpl->pBookmk )
+ pImpl->pBookmk.reset( new INetBookmark( rBkmk ) );
+ else
+ *pImpl->pBookmk = rBkmk;
+
+ AddFormat( SotClipboardFormatId::STRING );
+ AddFormat( SotClipboardFormatId::SOLK );
+ AddFormat( SotClipboardFormatId::NETSCAPE_BOOKMARK );
+ AddFormat( SotClipboardFormatId::FILECONTENT );
+ AddFormat( SotClipboardFormatId::FILEGRPDESCRIPTOR );
+ AddFormat( SotClipboardFormatId::UNIFORMRESOURCELOCATOR );
+}
+
+
+void TransferDataContainer::CopyAnyData( SotClipboardFormatId nFormatId,
+ const char* pData, sal_uLong nLen )
+{
+ if( nLen )
+ {
+ TDataCntnrEntry_Impl aEntry;
+ aEntry.nId = nFormatId;
+
+ Sequence< sal_Int8 > aSeq( nLen );
+ memcpy( aSeq.getArray(), pData, nLen );
+ aEntry.aAny <<= aSeq;
+ pImpl->aFmtList.push_back( aEntry );
+ AddFormat( nFormatId );
+ }
+}
+
+
+void TransferDataContainer::CopyByteString( SotClipboardFormatId nFormatId,
+ const OString& rStr )
+{
+ CopyAnyData( nFormatId, rStr.getStr(), rStr.getLength() );
+}
+
+
+void TransferDataContainer::CopyString( SotClipboardFormatId nFmt, const OUString& rStr )
+{
+ if( !rStr.isEmpty() )
+ {
+ TDataCntnrEntry_Impl aEntry;
+ aEntry.nId = nFmt;
+ aEntry.aAny <<= rStr;
+ pImpl->aFmtList.push_back( aEntry );
+ AddFormat( aEntry.nId );
+ }
+}
+
+
+void TransferDataContainer::CopyString( const OUString& rStr )
+{
+ CopyString( SotClipboardFormatId::STRING, rStr );
+}
+
+
+bool TransferDataContainer::HasAnyData() const
+{
+ return !pImpl->aFmtList.empty() ||
+ nullptr != pImpl->pBookmk;
+}
+
+
+void TransferDataContainer::StartDrag(
+ vcl::Window* pWindow, sal_Int8 nDragSourceActions,
+ const Link<sal_Int8,void>& rLnk )
+{
+ pImpl->aFinishedLnk = rLnk;
+ TransferableHelper::StartDrag( pWindow, nDragSourceActions );
+}
+
+
+void TransferDataContainer::DragFinished( sal_Int8 nDropAction )
+{
+ pImpl->aFinishedLnk.Call( nDropAction );
+}
+
+Reference<XClipboard> GetSystemClipboard()
+{
+ // On Windows, the css.datatransfer.clipboard.SystemClipboard UNO service is implemented as a
+ // single-instance service (dtrans_CWinClipboard_get_implementation in
+ // vcl/win/dtrans/WinClipboard.cxx) that needs timely disposing to join a spawned thread
+ // (done in DeInitVCL, vcl/source/app/svmain.cxx), while on other platforms it is implemented as
+ // a multi-instance service (ClipboardFactory, vcl/source/components/dtranscomp.cxx) so we
+ // should not hold on to a single instance here:
+#if defined _WIN32
+ DBG_TESTSOLARMUTEX();
+ auto const data = ImplGetSVData();
+ if (!data->m_xSystemClipboard.is())
+ {
+ try
+ {
+ data->m_xSystemClipboard = css::datatransfer::clipboard::SystemClipboard::create(
+ comphelper::getProcessComponentContext());
+ }
+ catch (DeploymentException const &) {}
+ }
+ return data->m_xSystemClipboard;
+#else
+ Reference<XClipboard> xClipboard;
+ try
+ {
+ xClipboard = css::datatransfer::clipboard::SystemClipboard::create(
+ comphelper::getProcessComponentContext());
+ }
+ catch (DeploymentException const &) {}
+ return xClipboard;
+#endif
+}
+
+Reference<XClipboard> GetSystemPrimarySelection()
+{
+ Reference<XClipboard> xSelection;
+ try
+ {
+ Reference<XComponentContext> xContext(comphelper::getProcessComponentContext());
+#if USING_X11
+ // A hack, making the primary selection available as an instance
+ // of the SystemClipboard service on X11:
+ Sequence< Any > args{ Any(OUString("PRIMARY")) };
+ xSelection.set(xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+ "com.sun.star.datatransfer.clipboard.SystemClipboard", args, xContext), UNO_QUERY_THROW);
+#else
+ static Reference< XClipboard > s_xSelection(
+ xContext->getServiceManager()->createInstanceWithContext(
+ "com.sun.star.datatransfer.clipboard.GenericClipboard", xContext), UNO_QUERY);
+ xSelection = s_xSelection;
+#endif
+ }
+ catch (RuntimeException const &) {}
+ return xSelection;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */