vcl/inc/qt5/QtDragAndDrop.hxx | 13 ++- vcl/inc/qt5/QtInstanceWidget.hxx | 2 vcl/inc/qt5/QtTools.hxx | 9 -- vcl/qt5/QtDragAndDrop.cxx | 132 +++++++++++++++++++++++++++++++++++++-- vcl/qt5/QtInstanceWidget.cxx | 46 +++++++++++++ vcl/qt5/QtTools.cxx | 120 ----------------------------------- 6 files changed, 182 insertions(+), 140 deletions(-)
New commits: commit 81dcfb488ac2a0bfc41ff5f1ca2be46e315dff62 Author: Michael Weghorn <[email protected]> AuthorDate: Wed Jul 23 14:28:27 2025 +0200 Commit: Michael Weghorn <[email protected]> CommitDate: Wed Jul 23 22:56:07 2025 +0200 qt dnd: Move some logic from QtTools to QtDropTarget These are only used in QtDragAndDrop.cxx and are not very generic, so move them to the latter source file instead. Also change the helper functions to create a VCL drop event from a QEvent to helper methods in QtDropTarget and use `this` directly instead of them being static functions that take a QtDropTarget* param. Most of the logic was previously moved to QtTools in commit cc4dbbf714faef42cd17ccd7fcfc240d3e5aa977 Author: Michael Weghorn <[email protected]> Date: Tue Jul 1 16:49:38 2025 +0200 tdf#130857 qt: Extract helpers to convert Qt drag/drop to LO events with the idea to share it between QtFrame and QtInstanceWidget, but the logic was now eventually moved from QtFrame to QtDropTarget in Change-Id: I2b4df4459028b7c2b1da300306e12f032a7605ff Author: Michael Weghorn <[email protected]> Date: Wed Jul 23 13:36:22 2025 +0200 tdf#130857 qt dnd: Move some logic from QtFrame to QtDropTarget instead and that is reused by QtInstanceWidget, so it is no longer needed elsewhere. Change-Id: I2303d88d74bb1da4d1871396075737c1f0b6866c Reviewed-on: https://gerrit.libreoffice.org/c/core/+/188233 Tested-by: Jenkins Reviewed-by: Michael Weghorn <[email protected]> diff --git a/vcl/inc/qt5/QtDragAndDrop.hxx b/vcl/inc/qt5/QtDragAndDrop.hxx index ed8b32a8f10f..77c246352da7 100644 --- a/vcl/inc/qt5/QtDragAndDrop.hxx +++ b/vcl/inc/qt5/QtDragAndDrop.hxx @@ -92,6 +92,13 @@ public: sal_Int8 proposedDropAction() const { return m_nDropAction; } bool dropSuccessful() const { return m_bDropSuccessful; } + +private: + css::datatransfer::dnd::DropTargetDragEnterEvent + createDropTargetDragEnterEvent(const QDragMoveEvent& rEvent, bool bSetDataFlavors, + qreal fScaleFactor); + css::datatransfer::dnd::DropTargetDropEvent createDropTargetDropEvent(const QDropEvent& rEvent, + qreal fScaleFactor); }; /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/vcl/inc/qt5/QtTools.hxx b/vcl/inc/qt5/QtTools.hxx index c97d87f4c881..a30e3fdf4bd9 100644 --- a/vcl/inc/qt5/QtTools.hxx +++ b/vcl/inc/qt5/QtTools.hxx @@ -21,8 +21,6 @@ #include <config_vclplug.h> -#include "QtDragAndDrop.hxx" - #include <QtCore/QDate> #include <QtCore/QPoint> #include <QtCore/QRect> @@ -42,7 +40,6 @@ #include <vcl/qt/QtUtils.hxx> #include <vcl/vclenum.hxx> -#include <com/sun/star/datatransfer/dnd/DropTargetDragEnterEvent.hpp> #include <com/sun/star/lang/Locale.hpp> #include <com/sun/star/uno/Sequence.hxx> #include <com/sun/star/datatransfer/dnd/DNDConstants.hpp> @@ -103,12 +100,6 @@ TriState toVclTriState(Qt::CheckState eTristate); Qt::DropActions toQtDropActions(sal_Int8 dragOperation); sal_Int8 toVclDropActions(Qt::DropActions dragOperation); sal_Int8 toVclDropAction(Qt::DropAction dragOperation); -css::datatransfer::dnd::DropTargetDragEnterEvent -toVclDropTargetDragEnterEvent(const QDragMoveEvent& rEvent, QtDropTarget* pDropTarget, - bool bSetDataFlavors, qreal fScaleFactor); -css::datatransfer::dnd::DropTargetDropEvent -toVclDropTargetDropEvent(const QDropEvent& rEvent, QtDropTarget* pDropTarget, qreal fScaleFactor); -Qt::DropAction getPreferredDropAction(sal_Int8 dragOperation); inline QList<int> toQList(const css::uno::Sequence<sal_Int32>& aSequence) { diff --git a/vcl/qt5/QtDragAndDrop.cxx b/vcl/qt5/QtDragAndDrop.cxx index 04c1198d0307..a5dae454d4a4 100644 --- a/vcl/qt5/QtDragAndDrop.cxx +++ b/vcl/qt5/QtDragAndDrop.cxx @@ -44,6 +44,71 @@ public: return { "application/x.libreoffice-internal-drag-and-drop" }; } }; + +Qt::DropAction lcl_getPreferredDropAction(sal_Int8 dragOperation) +{ + Qt::DropAction eAct = Qt::IgnoreAction; + if (dragOperation & css::datatransfer::dnd::DNDConstants::ACTION_MOVE) + eAct = Qt::MoveAction; + else if (dragOperation & css::datatransfer::dnd::DNDConstants::ACTION_COPY) + eAct = Qt::CopyAction; + else if (dragOperation & css::datatransfer::dnd::DNDConstants::ACTION_LINK) + eAct = Qt::LinkAction; + return eAct; +} + +css::uno::Reference<css::datatransfer::XTransferable> +lcl_getXTransferable(const QMimeData* pMimeData) +{ + css::uno::Reference<css::datatransfer::XTransferable> xTransferable; + const QtMimeData* pQtMimeData = qobject_cast<const QtMimeData*>(pMimeData); + if (!pQtMimeData) + xTransferable = new QtDnDTransferable(pMimeData); + else + xTransferable = pQtMimeData->xTransferable(); + return xTransferable; +} + +sal_Int8 lcl_getUserDropAction(const QDropEvent& rEvent, const sal_Int8 nSourceActions, + const QMimeData* pMimeData) +{ +// we completely ignore all proposals by the Qt event, as they don't +// match at all with the preferred LO DnD actions. +// check the key modifiers to detect a user-overridden DnD action +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + const Qt::KeyboardModifiers eKeyMod = rEvent.modifiers(); +#else + const Qt::KeyboardModifiers eKeyMod = rEvent.keyboardModifiers(); +#endif + sal_Int8 nUserDropAction = 0; + if ((eKeyMod & Qt::ShiftModifier) && !(eKeyMod & Qt::ControlModifier)) + nUserDropAction = css::datatransfer::dnd::DNDConstants::ACTION_MOVE; + else if ((eKeyMod & Qt::ControlModifier) && !(eKeyMod & Qt::ShiftModifier)) + nUserDropAction = css::datatransfer::dnd::DNDConstants::ACTION_COPY; + else if ((eKeyMod & Qt::ShiftModifier) && (eKeyMod & Qt::ControlModifier)) + nUserDropAction = css::datatransfer::dnd::DNDConstants::ACTION_LINK; + nUserDropAction &= nSourceActions; + + // select the default DnD action, if there isn't a user preference + if (0 == nUserDropAction) + { + // default LO internal action is move, but default external action is copy + nUserDropAction = qobject_cast<const QtMimeData*>(pMimeData) + ? css::datatransfer::dnd::DNDConstants::ACTION_MOVE + : css::datatransfer::dnd::DNDConstants::ACTION_COPY; + nUserDropAction &= nSourceActions; + + // if the default doesn't match any allowed source action, fall back to the + // preferred of all allowed source actions + if (0 == nUserDropAction) + nUserDropAction = toVclDropAction(lcl_getPreferredDropAction(nSourceActions)); + + // this is "our" preference, but actually we would even prefer any default, + // if there is any + nUserDropAction |= css::datatransfer::dnd::DNDConstants::ACTION_DEFAULT; + } + return nUserDropAction; +} } QtDragSource::QtDragSource(QtFrame* pFrame) @@ -74,7 +139,7 @@ void QtDragSource::startDrag( drag->setMimeData(new QtDragMimeData(rTrans)); // just a reminder that exec starts a nested event loop, so everything after // this call is just executed, after D'n'D has finished! - drag->exec(toQtDropActions(sourceActions), getPreferredDropAction(sourceActions)); + drag->exec(toQtDropActions(sourceActions), lcl_getPreferredDropAction(sourceActions)); } // the drop will eventually call fire_dragEnd, which will clear the listener. @@ -138,7 +203,7 @@ QtDropTarget::~QtDropTarget() {} void QtDropTarget::handleDragEnterEvent(QDragEnterEvent& rEvent, qreal fScaleFactor) { css::datatransfer::dnd::DropTargetDragEnterEvent aEvent - = toVclDropTargetDragEnterEvent(rEvent, this, true, fScaleFactor); + = createDropTargetDragEnterEvent(rEvent, true, fScaleFactor); dragEnter(aEvent); if (qobject_cast<const QtMimeData*>(rEvent.mimeData())) @@ -150,13 +215,13 @@ void QtDropTarget::handleDragEnterEvent(QDragEnterEvent& rEvent, qreal fScaleFac void QtDropTarget::handleDragMoveEvent(QDragMoveEvent& rEvent, qreal fScaleFactor) { css::datatransfer::dnd::DropTargetDragEnterEvent aEvent - = toVclDropTargetDragEnterEvent(rEvent, this, false, fScaleFactor); + = createDropTargetDragEnterEvent(rEvent, false, fScaleFactor); dragOver(aEvent); // the drop target accepted our drop action => inform Qt if (proposedDropAction() != 0) { - rEvent.setDropAction(getPreferredDropAction(proposedDropAction())); + rEvent.setDropAction(lcl_getPreferredDropAction(proposedDropAction())); rEvent.accept(); } else // or maybe someone else likes it? @@ -169,7 +234,7 @@ void QtDropTarget::handleDropEvent(QDropEvent& rEvent, qreal fScaleFactor) // ask the drop target to accept our drop action css::datatransfer::dnd::DropTargetDropEvent aEvent - = toVclDropTargetDropEvent(rEvent, this, fScaleFactor); + = createDropTargetDropEvent(rEvent, fScaleFactor); drop(aEvent); const bool bDropSuccessful = dropSuccessful(); @@ -178,7 +243,7 @@ void QtDropTarget::handleDropEvent(QDropEvent& rEvent, qreal fScaleFactor) // the drop target accepted our drop action => inform Qt if (bDropSuccessful) { - rEvent.setDropAction(getPreferredDropAction(nDropAction)); + rEvent.setDropAction(lcl_getPreferredDropAction(nDropAction)); rEvent.accept(); } else // or maybe someone else likes it? @@ -198,4 +263,59 @@ void QtDropTarget::dropComplete(sal_Bool success) m_bDropSuccessful = (m_bDropSuccessful && success); } +css::datatransfer::dnd::DropTargetDragEnterEvent +QtDropTarget::createDropTargetDragEnterEvent(const QDragMoveEvent& rEvent, bool bSetDataFlavors, + qreal fScaleFactor) +{ + // prepare our suggested drop action for the drop target + const sal_Int8 nSourceActions = toVclDropActions(rEvent.possibleActions()); + const QMimeData* pMimeData = rEvent.mimeData(); + const sal_Int8 nUserDropAction = lcl_getUserDropAction(rEvent, nSourceActions, pMimeData); + +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + const QPoint aPos = rEvent.position().toPoint(); +#else + const QPoint aPos = rEvent.pos(); +#endif + + css::datatransfer::dnd::DropTargetDragEnterEvent aEvent; + aEvent.Source = static_cast<css::datatransfer::dnd::XDropTarget*>(this); + aEvent.Context = this; + aEvent.LocationX = aPos.x() * fScaleFactor; + aEvent.LocationY = aPos.y() * fScaleFactor; + aEvent.DropAction = nUserDropAction; + aEvent.SourceActions = nSourceActions; + + if (bSetDataFlavors) + aEvent.SupportedDataFlavors = lcl_getXTransferable(pMimeData)->getTransferDataFlavors(); + + return aEvent; +} + +css::datatransfer::dnd::DropTargetDropEvent +QtDropTarget::createDropTargetDropEvent(const QDropEvent& rEvent, qreal fScaleFactor) +{ + // prepare our suggested drop action for the drop target + const sal_Int8 nSourceActions = toVclDropActions(rEvent.possibleActions()); + const sal_Int8 nUserDropAction + = lcl_getUserDropAction(rEvent, nSourceActions, rEvent.mimeData()); + +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + const QPoint aPos = rEvent.position().toPoint(); +#else + const QPoint aPos = rEvent.pos(); +#endif + + css::datatransfer::dnd::DropTargetDropEvent aEvent; + aEvent.Source = static_cast<css::datatransfer::dnd::XDropTarget*>(this); + aEvent.Context = this; + aEvent.LocationX = aPos.x() * fScaleFactor; + aEvent.LocationY = aPos.y() * fScaleFactor; + aEvent.SourceActions = nSourceActions; + aEvent.DropAction = nUserDropAction; + aEvent.Transferable = lcl_getXTransferable(rEvent.mimeData()); + + return aEvent; +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/vcl/qt5/QtTools.cxx b/vcl/qt5/QtTools.cxx index e17936ebfa9c..bb69d490baa4 100644 --- a/vcl/qt5/QtTools.cxx +++ b/vcl/qt5/QtTools.cxx @@ -263,126 +263,6 @@ sal_Int8 toVclDropAction(Qt::DropAction dragOperation) return nRet; } -static css::uno::Reference<css::datatransfer::XTransferable> -lcl_getXTransferable(const QMimeData* pMimeData) -{ - css::uno::Reference<css::datatransfer::XTransferable> xTransferable; - const QtMimeData* pQtMimeData = qobject_cast<const QtMimeData*>(pMimeData); - if (!pQtMimeData) - xTransferable = new QtDnDTransferable(pMimeData); - else - xTransferable = pQtMimeData->xTransferable(); - return xTransferable; -} - -static sal_Int8 lcl_getUserDropAction(const QDropEvent& rEvent, const sal_Int8 nSourceActions, - const QMimeData* pMimeData) -{ -// we completely ignore all proposals by the Qt event, as they don't -// match at all with the preferred LO DnD actions. -// check the key modifiers to detect a user-overridden DnD action -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - const Qt::KeyboardModifiers eKeyMod = rEvent.modifiers(); -#else - const Qt::KeyboardModifiers eKeyMod = rEvent.keyboardModifiers(); -#endif - sal_Int8 nUserDropAction = 0; - if ((eKeyMod & Qt::ShiftModifier) && !(eKeyMod & Qt::ControlModifier)) - nUserDropAction = css::datatransfer::dnd::DNDConstants::ACTION_MOVE; - else if ((eKeyMod & Qt::ControlModifier) && !(eKeyMod & Qt::ShiftModifier)) - nUserDropAction = css::datatransfer::dnd::DNDConstants::ACTION_COPY; - else if ((eKeyMod & Qt::ShiftModifier) && (eKeyMod & Qt::ControlModifier)) - nUserDropAction = css::datatransfer::dnd::DNDConstants::ACTION_LINK; - nUserDropAction &= nSourceActions; - - // select the default DnD action, if there isn't a user preference - if (0 == nUserDropAction) - { - // default LO internal action is move, but default external action is copy - nUserDropAction = qobject_cast<const QtMimeData*>(pMimeData) - ? css::datatransfer::dnd::DNDConstants::ACTION_MOVE - : css::datatransfer::dnd::DNDConstants::ACTION_COPY; - nUserDropAction &= nSourceActions; - - // if the default doesn't match any allowed source action, fall back to the - // preferred of all allowed source actions - if (0 == nUserDropAction) - nUserDropAction = toVclDropAction(getPreferredDropAction(nSourceActions)); - - // this is "our" preference, but actually we would even prefer any default, - // if there is any - nUserDropAction |= css::datatransfer::dnd::DNDConstants::ACTION_DEFAULT; - } - return nUserDropAction; -} - -css::datatransfer::dnd::DropTargetDragEnterEvent -toVclDropTargetDragEnterEvent(const QDragMoveEvent& rEvent, QtDropTarget* pDropTarget, - bool bSetDataFlavors, qreal fScaleFactor) -{ - // prepare our suggested drop action for the drop target - const sal_Int8 nSourceActions = toVclDropActions(rEvent.possibleActions()); - const QMimeData* pMimeData = rEvent.mimeData(); - const sal_Int8 nUserDropAction = lcl_getUserDropAction(rEvent, nSourceActions, pMimeData); - -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - const QPoint aPos = rEvent.position().toPoint(); -#else - const QPoint aPos = rEvent.pos(); -#endif - - css::datatransfer::dnd::DropTargetDragEnterEvent aEvent; - aEvent.Source = static_cast<css::datatransfer::dnd::XDropTarget*>(pDropTarget); - aEvent.Context = pDropTarget; - aEvent.LocationX = aPos.x() * fScaleFactor; - aEvent.LocationY = aPos.y() * fScaleFactor; - aEvent.DropAction = nUserDropAction; - aEvent.SourceActions = nSourceActions; - - if (bSetDataFlavors) - aEvent.SupportedDataFlavors = lcl_getXTransferable(pMimeData)->getTransferDataFlavors(); - - return aEvent; -} - -css::datatransfer::dnd::DropTargetDropEvent -toVclDropTargetDropEvent(const QDropEvent& rEvent, QtDropTarget* pDropTarget, qreal fScaleFactor) -{ - // prepare our suggested drop action for the drop target - const sal_Int8 nSourceActions = toVclDropActions(rEvent.possibleActions()); - const sal_Int8 nUserDropAction - = lcl_getUserDropAction(rEvent, nSourceActions, rEvent.mimeData()); - -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - const QPoint aPos = rEvent.position().toPoint(); -#else - const QPoint aPos = rEvent.pos(); -#endif - - css::datatransfer::dnd::DropTargetDropEvent aEvent; - aEvent.Source = static_cast<css::datatransfer::dnd::XDropTarget*>(pDropTarget); - aEvent.Context = pDropTarget; - aEvent.LocationX = aPos.x() * fScaleFactor; - aEvent.LocationY = aPos.y() * fScaleFactor; - aEvent.SourceActions = nSourceActions; - aEvent.DropAction = nUserDropAction; - aEvent.Transferable = lcl_getXTransferable(rEvent.mimeData()); - - return aEvent; -} - -Qt::DropAction getPreferredDropAction(sal_Int8 dragOperation) -{ - Qt::DropAction eAct = Qt::IgnoreAction; - if (dragOperation & css::datatransfer::dnd::DNDConstants::ACTION_MOVE) - eAct = Qt::MoveAction; - else if (dragOperation & css::datatransfer::dnd::DNDConstants::ACTION_COPY) - eAct = Qt::CopyAction; - else if (dragOperation & css::datatransfer::dnd::DNDConstants::ACTION_LINK) - eAct = Qt::LinkAction; - return eAct; -} - QImage toQImage(const Image& rImage) { QImage aImage; commit 62b4c5e281200ba06411ac289a0aa769dc4308ef Author: Michael Weghorn <[email protected]> AuthorDate: Wed Jul 23 13:54:57 2025 +0200 Commit: Michael Weghorn <[email protected]> CommitDate: Wed Jul 23 22:56:01 2025 +0200 tdf#130857 qt weld dnd: Implement drop support Implement the "Drop" side of Drag'n'Drop support by implementing QtInstanceWidget::get_drop_target and handling the corresponding events in QtInstanceWidget::eventFilter. The relevant logic was moved to QtDropTarget in previous commits up to Change-Id: I2b4df4459028b7c2b1da300306e12f032a7605ff Author: Michael Weghorn <[email protected]> Date: Wed Jul 23 13:36:22 2025 +0200 tdf#130857 qt dnd: Move some logic from QtFrame to QtDropTarget in order to be able to reuse it from here. In a WIP branch for supporting the "Tools" -> "SQL" dialog in Base, this allows to insert text into the "Command to execute" field by selecting it in Kate or Gedit and using drag'n'drop to get it into the LO dialog. Change-Id: I636fbcf1bc8aba67b8e32f81291efe10bc08ac9c Reviewed-on: https://gerrit.libreoffice.org/c/core/+/188232 Tested-by: Jenkins Reviewed-by: Michael Weghorn <[email protected]> diff --git a/vcl/inc/qt5/QtDragAndDrop.hxx b/vcl/inc/qt5/QtDragAndDrop.hxx index c999718b8f3a..ed8b32a8f10f 100644 --- a/vcl/inc/qt5/QtDragAndDrop.hxx +++ b/vcl/inc/qt5/QtDragAndDrop.hxx @@ -86,9 +86,9 @@ public: sal_Bool SAL_CALL supportsService(OUString const& ServiceName) override; css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override; - void handleDragEnterEvent(QDragEnterEvent& rEvent, qreal fScaleFactor); - void handleDragMoveEvent(QDragMoveEvent& rEvent, qreal fScaleFactor); - void handleDropEvent(QDropEvent& rEvent, qreal fScaleFactor); + void handleDragEnterEvent(QDragEnterEvent& rEvent, qreal fScaleFactor = 1.0); + void handleDragMoveEvent(QDragMoveEvent& rEvent, qreal fScaleFactor = 1.0); + void handleDropEvent(QDropEvent& rEvent, qreal fScaleFactor = 1.0); sal_Int8 proposedDropAction() const { return m_nDropAction; } bool dropSuccessful() const { return m_bDropSuccessful; } diff --git a/vcl/inc/qt5/QtInstanceWidget.hxx b/vcl/inc/qt5/QtInstanceWidget.hxx index 3799f09815e4..38edefd7d1e9 100644 --- a/vcl/inc/qt5/QtInstanceWidget.hxx +++ b/vcl/inc/qt5/QtInstanceWidget.hxx @@ -9,6 +9,7 @@ #pragma once +#include "QtDragAndDrop.hxx" #include "QtInstance.hxx" #include <QtWidgets/QApplication> #include <QtWidgets/QWidget> @@ -25,6 +26,7 @@ class QtInstanceWidget : public QObject, public virtual weld::Widget QWidget* m_pWidget; + rtl::Reference<QtDropTarget> m_pDropTarget; int m_nBusyCount = 0; public: diff --git a/vcl/qt5/QtInstanceWidget.cxx b/vcl/qt5/QtInstanceWidget.cxx index 3cf97d867585..a263c5eadcb6 100644 --- a/vcl/qt5/QtInstanceWidget.cxx +++ b/vcl/qt5/QtInstanceWidget.cxx @@ -278,6 +278,41 @@ bool QtInstanceWidget::eventFilter(QObject* pObject, QEvent* pEvent) switch (pEvent->type()) { + case QEvent::DragEnter: + { + if (!m_pDropTarget) + return false; + + QDragEnterEvent* pDragEnterEvent = static_cast<QDragEnterEvent*>(pEvent); + m_pDropTarget->handleDragEnterEvent(*pDragEnterEvent); + return true; + } + case QEvent::DragLeave: + { + if (!m_pDropTarget) + return false; + + m_pDropTarget->dragExit(); + return true; + } + case QEvent::DragMove: + { + if (!m_pDropTarget) + return false; + + QDragMoveEvent* pDragMoveEvent = static_cast<QDragMoveEvent*>(pEvent); + m_pDropTarget->handleDragMoveEvent(*pDragMoveEvent); + return true; + } + case QEvent::Drop: + { + if (!m_pDropTarget) + return false; + + QDropEvent* pDropEvent = static_cast<QDropEvent*>(pEvent); + m_pDropTarget->handleDropEvent(*pDropEvent); + return true; + } case QEvent::KeyPress: { QKeyEvent* pKeyEvent = static_cast<QKeyEvent*>(pEvent); @@ -697,8 +732,15 @@ VclPtr<VirtualDevice> QtInstanceWidget::create_virtual_device() const css::uno::Reference<css::datatransfer::dnd::XDropTarget> QtInstanceWidget::get_drop_target() { - assert(false && "Not implemented yet"); - return nullptr; + SolarMutexGuard g; + + GetQtInstance().RunInMainThread([this] { + getQWidget()->setAcceptDrops(true); + if (!m_pDropTarget) + m_pDropTarget.set(new QtDropTarget); + }); + + return m_pDropTarget; } css::uno::Reference<css::datatransfer::clipboard::XClipboard>
