Blame SOURCES/0025-Client-Implement-DataDeviceV3.patch

869fe3
From 95783492ae8df7f84c3c13351df5dc114288e96e Mon Sep 17 00:00:00 2001
9fb289
From: David Edmundson <davidedmundson@kde.org>
9fb289
Date: Tue, 16 Feb 2021 09:51:47 +0000
869fe3
Subject: [PATCH 25/40] Client: Implement DataDeviceV3
9fb289
9fb289
DataDeviceV2 fixes a leak of DataDevice resources.
9fb289
9fb289
DataDeviceV3 brings multiple improvements:
9fb289
9fb289
Action negotiation. The source announces which actions are supported,
9fb289
the target then announces which subset of those action the target
9fb289
supports and a preferred action. After negotiation both the source and
9fb289
target are notified of which action is to be performed.
9fb289
9fb289
Drag sources are now notified when contents are dropped and when a
9fb289
client has finished with the drag and drop operation.
9fb289
9fb289
A good test is the draggableicons example in QtBase.
9fb289
9fb289
Change-Id: I55e9759ca5a2e4218d02d863144a64ade53ef764
9fb289
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
9fb289
(cherry picked from commit 283a2d61d03315495a52d82f356e7cb5292f4bb4)
9fb289
---
9fb289
 src/client/qwaylanddatadevice.cpp             | 84 ++++++++++++++-----
9fb289
 src/client/qwaylanddatadevice_p.h             |  8 +-
9fb289
 src/client/qwaylanddatadevicemanager.cpp      |  4 +-
9fb289
 src/client/qwaylanddatadevicemanager_p.h      |  2 +-
9fb289
 src/client/qwaylanddataoffer.cpp              | 25 ++++++
9fb289
 src/client/qwaylanddataoffer_p.h              |  4 +
9fb289
 src/client/qwaylanddatasource.cpp             | 27 +++++-
9fb289
 src/client/qwaylanddatasource_p.h             | 10 ++-
9fb289
 src/client/qwaylanddisplay.cpp                |  2 +-
9fb289
 src/client/qwaylanddnd.cpp                    | 24 +++---
9fb289
 src/client/qwaylanddnd_p.h                    |  7 +-
9fb289
 .../client/datadevicev1/tst_datadevicev1.cpp  |  2 +-
9fb289
 12 files changed, 153 insertions(+), 46 deletions(-)
9fb289
9fb289
diff --git a/src/client/qwaylanddatadevice.cpp b/src/client/qwaylanddatadevice.cpp
9fb289
index bbd2d568..fbb5aa91 100644
9fb289
--- a/src/client/qwaylanddatadevice.cpp
9fb289
+++ b/src/client/qwaylanddatadevice.cpp
9fb289
@@ -72,6 +72,8 @@ QWaylandDataDevice::QWaylandDataDevice(QWaylandDataDeviceManager *manager, QWayl
9fb289
 
9fb289
 QWaylandDataDevice::~QWaylandDataDevice()
9fb289
 {
9fb289
+    if (wl_data_device_get_version(object()) >= WL_DATA_DEVICE_RELEASE_SINCE_VERSION)
9fb289
+        release();
9fb289
 }
9fb289
 
9fb289
 QWaylandDataOffer *QWaylandDataDevice::selectionOffer() const
9fb289
@@ -110,7 +112,7 @@ QWaylandDataOffer *QWaylandDataDevice::dragOffer() const
9fb289
     return m_dragOffer.data();
9fb289
 }
9fb289
 
9fb289
-bool QWaylandDataDevice::startDrag(QMimeData *mimeData, QWaylandWindow *icon)
9fb289
+bool QWaylandDataDevice::startDrag(QMimeData *mimeData, Qt::DropActions supportedActions, QWaylandWindow *icon)
9fb289
 {
9fb289
     auto *seat = m_display->currentInputDevice();
9fb289
     auto *origin = seat->pointerFocus();
9fb289
@@ -123,8 +125,28 @@ bool QWaylandDataDevice::startDrag(QMimeData *mimeData, QWaylandWindow *icon)
9fb289
     }
9fb289
 
9fb289
     m_dragSource.reset(new QWaylandDataSource(m_display->dndSelectionHandler(), mimeData));
9fb289
+
9fb289
+    if (wl_data_device_get_version(object()) >= 3)
9fb289
+        m_dragSource->set_actions(dropActionsToWl(supportedActions));
9fb289
+
9fb289
     connect(m_dragSource.data(), &QWaylandDataSource::cancelled, this, &QWaylandDataDevice::dragSourceCancelled);
9fb289
-    connect(m_dragSource.data(), &QWaylandDataSource::targetChanged, this, &QWaylandDataDevice::dragSourceTargetChanged);
9fb289
+    connect(m_dragSource.data(), &QWaylandDataSource::dndResponseUpdated, this, [this](bool accepted, Qt::DropAction action) {
9fb289
+            auto drag = static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag());
9fb289
+            // in old versions drop action is not set, so we guess
9fb289
+            if (wl_data_source_get_version(m_dragSource->object()) < 3) {
9fb289
+                drag->setResponse(accepted);
9fb289
+            } else {
9fb289
+                QPlatformDropQtResponse response(accepted, action);
9fb289
+                drag->setResponse(response);
9fb289
+            }
9fb289
+    });
9fb289
+    connect(m_dragSource.data(), &QWaylandDataSource::dndDropped, this, [](bool accepted, Qt::DropAction action) {
9fb289
+        QPlatformDropQtResponse response(accepted, action);
9fb289
+        static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->setDropResponse(response);
9fb289
+    });
9fb289
+    connect(m_dragSource.data(), &QWaylandDataSource::finished, this, []() {
9fb289
+        static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->finishDrag();
9fb289
+    });
9fb289
 
9fb289
     start_drag(m_dragSource->object(), origin->wlSurface(), icon->wlSurface(), m_display->currentInputDevice()->serial());
9fb289
     return true;
9fb289
@@ -153,7 +175,7 @@ void QWaylandDataDevice::data_device_drop()
9fb289
         supportedActions = drag->supportedActions();
9fb289
     } else if (m_dragOffer) {
9fb289
         dragData = m_dragOffer->mimeData();
9fb289
-        supportedActions = Qt::CopyAction | Qt::MoveAction | Qt::LinkAction;
9fb289
+        supportedActions = m_dragOffer->supportedActions();
9fb289
     } else {
9fb289
         return;
9fb289
     }
9fb289
@@ -163,7 +185,11 @@ void QWaylandDataDevice::data_device_drop()
9fb289
                                                                           QGuiApplication::keyboardModifiers());
9fb289
 
9fb289
     if (drag) {
9fb289
-        static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->finishDrag(response);
9fb289
+        auto drag =  static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag());
9fb289
+        drag->setDropResponse(response);
9fb289
+        drag->finishDrag();
9fb289
+    } else if (m_dragOffer) {
9fb289
+        m_dragOffer->finish();
9fb289
     }
9fb289
 }
9fb289
 
9fb289
@@ -187,7 +213,7 @@ void QWaylandDataDevice::data_device_enter(uint32_t serial, wl_surface *surface,
9fb289
         supportedActions = drag->supportedActions();
9fb289
     } else if (m_dragOffer) {
9fb289
         dragData = m_dragOffer->mimeData();
9fb289
-        supportedActions = Qt::CopyAction | Qt::MoveAction | Qt::LinkAction;
9fb289
+        supportedActions = m_dragOffer->supportedActions();
9fb289
     }
9fb289
 
9fb289
     const QPlatformDragQtResponse &response = QWindowSystemInterface::handleDrag(m_dragWindow, dragData, m_dragPoint, supportedActions,
9fb289
@@ -198,11 +224,7 @@ void QWaylandDataDevice::data_device_enter(uint32_t serial, wl_surface *surface,
9fb289
         static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->setResponse(response);
9fb289
     }
9fb289
 
9fb289
-    if (response.isAccepted()) {
9fb289
-        wl_data_offer_accept(m_dragOffer->object(), m_enterSerial, m_dragOffer->firstFormat().toUtf8().constData());
9fb289
-    } else {
9fb289
-        wl_data_offer_accept(m_dragOffer->object(), m_enterSerial, nullptr);
9fb289
-    }
9fb289
+    sendResponse(supportedActions, response);
9fb289
 }
9fb289
 
9fb289
 void QWaylandDataDevice::data_device_leave()
9fb289
@@ -236,10 +258,10 @@ void QWaylandDataDevice::data_device_motion(uint32_t time, wl_fixed_t x, wl_fixe
9fb289
         supportedActions = drag->supportedActions();
9fb289
     } else {
9fb289
         dragData = m_dragOffer->mimeData();
9fb289
-        supportedActions = Qt::CopyAction | Qt::MoveAction | Qt::LinkAction;
9fb289
+        supportedActions = m_dragOffer->supportedActions();
9fb289
     }
9fb289
 
9fb289
-    QPlatformDragQtResponse response = QWindowSystemInterface::handleDrag(m_dragWindow, dragData, m_dragPoint, supportedActions,
9fb289
+    const QPlatformDragQtResponse response = QWindowSystemInterface::handleDrag(m_dragWindow, dragData, m_dragPoint, supportedActions,
9fb289
                                                                           QGuiApplication::mouseButtons(),
9fb289
                                                                           QGuiApplication::keyboardModifiers());
9fb289
 
9fb289
@@ -247,11 +269,7 @@ void QWaylandDataDevice::data_device_motion(uint32_t time, wl_fixed_t x, wl_fixe
9fb289
         static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->setResponse(response);
9fb289
     }
9fb289
 
9fb289
-    if (response.isAccepted()) {
9fb289
-        wl_data_offer_accept(m_dragOffer->object(), m_enterSerial, m_dragOffer->firstFormat().toUtf8().constData());
9fb289
-    } else {
9fb289
-        wl_data_offer_accept(m_dragOffer->object(), m_enterSerial, nullptr);
9fb289
-    }
9fb289
+    sendResponse(supportedActions, response);
9fb289
 }
9fb289
 #endif // QT_CONFIG(draganddrop)
9fb289
 
9fb289
@@ -281,11 +299,6 @@ void QWaylandDataDevice::dragSourceCancelled()
9fb289
     m_dragSource.reset();
9fb289
 }
9fb289
 
9fb289
-void QWaylandDataDevice::dragSourceTargetChanged(const QString &mimeType)
9fb289
-{
9fb289
-    static_cast<QWaylandDrag *>(QGuiApplicationPrivate::platformIntegration()->drag())->updateTarget(mimeType);
9fb289
-}
9fb289
-
9fb289
 QPoint QWaylandDataDevice::calculateDragPosition(int x, int y, QWindow *wnd) const
9fb289
 {
9fb289
     QPoint pnt(wl_fixed_to_int(x), wl_fixed_to_int(y));
9fb289
@@ -298,6 +311,33 @@ QPoint QWaylandDataDevice::calculateDragPosition(int x, int y, QWindow *wnd) con
9fb289
     }
9fb289
     return pnt;
9fb289
 }
9fb289
+
9fb289
+void QWaylandDataDevice::sendResponse(Qt::DropActions supportedActions, const QPlatformDragQtResponse &response)
9fb289
+{
9fb289
+    if (response.isAccepted()) {
9fb289
+        if (wl_data_device_get_version(object()) >= 3)
9fb289
+            m_dragOffer->set_actions(dropActionsToWl(supportedActions), dropActionsToWl(response.acceptedAction()));
9fb289
+
9fb289
+        m_dragOffer->accept(m_enterSerial, m_dragOffer->firstFormat());
9fb289
+    } else {
9fb289
+        m_dragOffer->accept(m_enterSerial, QString());
9fb289
+    }
9fb289
+}
9fb289
+
9fb289
+int QWaylandDataDevice::dropActionsToWl(Qt::DropActions actions)
9fb289
+{
9fb289
+
9fb289
+    int wlActions = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
9fb289
+    if (actions & Qt::CopyAction)
9fb289
+        wlActions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
9fb289
+    if (actions & (Qt::MoveAction | Qt::TargetMoveAction))
9fb289
+        wlActions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE;
9fb289
+
9fb289
+    // wayland does not support LinkAction at the time of writing
9fb289
+    return wlActions;
9fb289
+}
9fb289
+
9fb289
+
9fb289
 #endif // QT_CONFIG(draganddrop)
9fb289
 
9fb289
 }
9fb289
diff --git a/src/client/qwaylanddatadevice_p.h b/src/client/qwaylanddatadevice_p.h
9fb289
index 16c3ad28..801dcc2c 100644
9fb289
--- a/src/client/qwaylanddatadevice_p.h
9fb289
+++ b/src/client/qwaylanddatadevice_p.h
9fb289
@@ -64,6 +64,7 @@ QT_REQUIRE_CONFIG(wayland_datadevice);
9fb289
 QT_BEGIN_NAMESPACE
9fb289
 
9fb289
 class QMimeData;
9fb289
+class QPlatformDragQtResponse;
9fb289
 class QWindow;
9fb289
 
9fb289
 namespace QtWaylandClient {
9fb289
@@ -89,7 +90,7 @@ public:
9fb289
 
9fb289
 #if QT_CONFIG(draganddrop)
9fb289
     QWaylandDataOffer *dragOffer() const;
9fb289
-    bool startDrag(QMimeData *mimeData, QWaylandWindow *icon);
9fb289
+    bool startDrag(QMimeData *mimeData, Qt::DropActions supportedActions, QWaylandWindow *icon);
9fb289
     void cancelDrag();
9fb289
 #endif
9fb289
 
9fb289
@@ -109,13 +110,16 @@ private Q_SLOTS:
9fb289
 
9fb289
 #if QT_CONFIG(draganddrop)
9fb289
     void dragSourceCancelled();
9fb289
-    void dragSourceTargetChanged(const QString &mimeType);
9fb289
 #endif
9fb289
 
9fb289
 private:
9fb289
 #if QT_CONFIG(draganddrop)
9fb289
     QPoint calculateDragPosition(int x, int y, QWindow *wnd) const;
9fb289
 #endif
9fb289
+    void sendResponse(Qt::DropActions supportedActions, const QPlatformDragQtResponse &response);
9fb289
+
9fb289
+    static int dropActionsToWl(Qt::DropActions dropActions);
9fb289
+
9fb289
 
9fb289
     QWaylandDisplay *m_display = nullptr;
9fb289
     QWaylandInputDevice *m_inputDevice = nullptr;
9fb289
diff --git a/src/client/qwaylanddatadevicemanager.cpp b/src/client/qwaylanddatadevicemanager.cpp
9fb289
index 35d67307..6dc4f77f 100644
9fb289
--- a/src/client/qwaylanddatadevicemanager.cpp
9fb289
+++ b/src/client/qwaylanddatadevicemanager.cpp
9fb289
@@ -50,8 +50,8 @@ QT_BEGIN_NAMESPACE
9fb289
 
9fb289
 namespace QtWaylandClient {
9fb289
 
9fb289
-QWaylandDataDeviceManager::QWaylandDataDeviceManager(QWaylandDisplay *display, uint32_t id)
9fb289
-    : wl_data_device_manager(display->wl_registry(), id, 1)
9fb289
+QWaylandDataDeviceManager::QWaylandDataDeviceManager(QWaylandDisplay *display, int version, uint32_t id)
9fb289
+    : wl_data_device_manager(display->wl_registry(), id, qMin(version, 3))
9fb289
     , m_display(display)
9fb289
 {
9fb289
     // Create transfer devices for all input devices.
9fb289
diff --git a/src/client/qwaylanddatadevicemanager_p.h b/src/client/qwaylanddatadevicemanager_p.h
9fb289
index bd05c0fb..510d9be4 100644
9fb289
--- a/src/client/qwaylanddatadevicemanager_p.h
9fb289
+++ b/src/client/qwaylanddatadevicemanager_p.h
9fb289
@@ -68,7 +68,7 @@ class QWaylandInputDevice;
9fb289
 class Q_WAYLAND_CLIENT_EXPORT QWaylandDataDeviceManager : public QtWayland::wl_data_device_manager
9fb289
 {
9fb289
 public:
9fb289
-    QWaylandDataDeviceManager(QWaylandDisplay *display, uint32_t id);
9fb289
+    QWaylandDataDeviceManager(QWaylandDisplay *display, int version, uint32_t id);
9fb289
     ~QWaylandDataDeviceManager() override;
9fb289
 
9fb289
     QWaylandDataDevice *getDataDevice(QWaylandInputDevice *inputDevice);
9fb289
diff --git a/src/client/qwaylanddataoffer.cpp b/src/client/qwaylanddataoffer.cpp
9fb289
index 2297e8a1..c9e158cc 100644
9fb289
--- a/src/client/qwaylanddataoffer.cpp
9fb289
+++ b/src/client/qwaylanddataoffer.cpp
9fb289
@@ -82,6 +82,15 @@ QMimeData *QWaylandDataOffer::mimeData()
9fb289
     return m_mimeData.data();
9fb289
 }
9fb289
 
9fb289
+Qt::DropActions QWaylandDataOffer::supportedActions() const
9fb289
+{
9fb289
+    if (wl_data_offer_get_version(const_cast<::wl_data_offer*>(object())) < 3) {
9fb289
+        return Qt::MoveAction | Qt::CopyAction;
9fb289
+    }
9fb289
+
9fb289
+    return m_supportedActions;
9fb289
+}
9fb289
+
9fb289
 void QWaylandDataOffer::startReceiving(const QString &mimeType, int fd)
9fb289
 {
9fb289
     receive(mimeType, fd);
9fb289
@@ -93,6 +102,22 @@ void QWaylandDataOffer::data_offer_offer(const QString &mime_type)
9fb289
     m_mimeData->appendFormat(mime_type);
9fb289
 }
9fb289
 
9fb289
+void QWaylandDataOffer::data_offer_action(uint32_t dnd_action)
9fb289
+{
9fb289
+    Q_UNUSED(dnd_action);
9fb289
+    // This is the compositor telling the drag target what action it should perform
9fb289
+    // It does not map nicely into Qt final drop semantics, other than pretending there is only one supported action?
9fb289
+}
9fb289
+
9fb289
+void QWaylandDataOffer::data_offer_source_actions(uint32_t source_actions)
9fb289
+{
9fb289
+    m_supportedActions = Qt::DropActions();
9fb289
+    if (source_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE)
9fb289
+        m_supportedActions |= Qt::MoveAction;
9fb289
+    if (source_actions & WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY)
9fb289
+        m_supportedActions |= Qt::CopyAction;
9fb289
+}
9fb289
+
9fb289
 QWaylandMimeData::QWaylandMimeData(QWaylandAbstractDataOffer *dataOffer)
9fb289
     : m_dataOffer(dataOffer)
9fb289
 {
9fb289
diff --git a/src/client/qwaylanddataoffer_p.h b/src/client/qwaylanddataoffer_p.h
9fb289
index 9cf1483c..6f667398 100644
9fb289
--- a/src/client/qwaylanddataoffer_p.h
9fb289
+++ b/src/client/qwaylanddataoffer_p.h
9fb289
@@ -82,6 +82,7 @@ public:
9fb289
     explicit QWaylandDataOffer(QWaylandDisplay *display, struct ::wl_data_offer *offer);
9fb289
     ~QWaylandDataOffer() override;
9fb289
     QMimeData *mimeData() override;
9fb289
+    Qt::DropActions supportedActions() const;
9fb289
 
9fb289
     QString firstFormat() const;
9fb289
 
9fb289
@@ -89,10 +90,13 @@ public:
9fb289
 
9fb289
 protected:
9fb289
     void data_offer_offer(const QString &mime_type) override;
9fb289
+    void data_offer_source_actions(uint32_t source_actions) override;
9fb289
+    void data_offer_action(uint32_t dnd_action) override;
9fb289
 
9fb289
 private:
9fb289
     QWaylandDisplay *m_display = nullptr;
9fb289
     QScopedPointer<QWaylandMimeData> m_mimeData;
9fb289
+    Qt::DropActions m_supportedActions;
9fb289
 };
9fb289
 
9fb289
 
9fb289
diff --git a/src/client/qwaylanddatasource.cpp b/src/client/qwaylanddatasource.cpp
9fb289
index f45122fb..5599cbd4 100644
9fb289
--- a/src/client/qwaylanddatasource.cpp
9fb289
+++ b/src/client/qwaylanddatasource.cpp
9fb289
@@ -101,7 +101,32 @@ void QWaylandDataSource::data_source_send(const QString &mime_type, int32_t fd)
9fb289
 
9fb289
 void QWaylandDataSource::data_source_target(const QString &mime_type)
9fb289
 {
9fb289
-    Q_EMIT targetChanged(mime_type);
9fb289
+    m_accepted = !mime_type.isEmpty();
9fb289
+    Q_EMIT dndResponseUpdated(m_accepted, m_dropAction);
9fb289
+}
9fb289
+
9fb289
+void QWaylandDataSource::data_source_action(uint32_t action)
9fb289
+{
9fb289
+    Qt::DropAction qtAction = Qt::IgnoreAction;
9fb289
+
9fb289
+    if (action == WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE)
9fb289
+        qtAction = Qt::MoveAction;
9fb289
+    else if (action == WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY)
9fb289
+        qtAction = Qt::CopyAction;
9fb289
+
9fb289
+    m_dropAction = qtAction;
9fb289
+    Q_EMIT dndResponseUpdated(m_accepted, m_dropAction);
9fb289
+}
9fb289
+
9fb289
+void QWaylandDataSource::data_source_dnd_finished()
9fb289
+{
9fb289
+    Q_EMIT finished();
9fb289
+}
9fb289
+
9fb289
+void QWaylandDataSource::data_source_dnd_drop_performed()
9fb289
+{
9fb289
+
9fb289
+    Q_EMIT dndDropped(m_accepted, m_dropAction);
9fb289
 }
9fb289
 
9fb289
 }
9fb289
diff --git a/src/client/qwaylanddatasource_p.h b/src/client/qwaylanddatasource_p.h
9fb289
index 25afff79..96f07bc3 100644
9fb289
--- a/src/client/qwaylanddatasource_p.h
9fb289
+++ b/src/client/qwaylanddatasource_p.h
9fb289
@@ -77,17 +77,25 @@ public:
9fb289
     QMimeData *mimeData() const;
9fb289
 
9fb289
 Q_SIGNALS:
9fb289
-    void targetChanged(const QString &mime_type);
9fb289
     void cancelled();
9fb289
+    void finished();
9fb289
+
9fb289
+    void dndResponseUpdated(bool accepted, Qt::DropAction action);
9fb289
+    void dndDropped(bool accepted, Qt::DropAction action);
9fb289
 
9fb289
 protected:
9fb289
     void data_source_cancelled() override;
9fb289
     void data_source_send(const QString &mime_type, int32_t fd) override;
9fb289
     void data_source_target(const QString &mime_type) override;
9fb289
+    void data_source_dnd_drop_performed() override;
9fb289
+    void data_source_dnd_finished() override;
9fb289
+    void data_source_action(uint32_t action) override;
9fb289
 
9fb289
 private:
9fb289
     QWaylandDisplay *m_display = nullptr;
9fb289
     QMimeData *m_mime_data = nullptr;
9fb289
+    bool m_accepted = false;
9fb289
+    Qt::DropAction m_dropAction = Qt::IgnoreAction;
9fb289
 };
9fb289
 
9fb289
 }
9fb289
diff --git a/src/client/qwaylanddisplay.cpp b/src/client/qwaylanddisplay.cpp
9fb289
index 9f595af3..ea344c61 100644
9fb289
--- a/src/client/qwaylanddisplay.cpp
9fb289
+++ b/src/client/qwaylanddisplay.cpp
9fb289
@@ -354,7 +354,7 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin
9fb289
         mInputDevices.append(inputDevice);
9fb289
 #if QT_CONFIG(wayland_datadevice)
9fb289
     } else if (interface == QStringLiteral("wl_data_device_manager")) {
9fb289
-        mDndSelectionHandler.reset(new QWaylandDataDeviceManager(this, id));
9fb289
+        mDndSelectionHandler.reset(new QWaylandDataDeviceManager(this, version, id));
9fb289
 #endif
9fb289
     } else if (interface == QStringLiteral("qt_surface_extension")) {
9fb289
         mWindowExtension.reset(new QtWayland::qt_surface_extension(registry, id, 1));
9fb289
diff --git a/src/client/qwaylanddnd.cpp b/src/client/qwaylanddnd.cpp
9fb289
index 6535aa16..97ee5b2e 100644
9fb289
--- a/src/client/qwaylanddnd.cpp
9fb289
+++ b/src/client/qwaylanddnd.cpp
9fb289
@@ -66,7 +66,7 @@ void QWaylandDrag::startDrag()
9fb289
 {
9fb289
     QBasicDrag::startDrag();
9fb289
     QWaylandWindow *icon = static_cast<QWaylandWindow *>(shapedPixmapWindow()->handle());
9fb289
-    if (m_display->currentInputDevice()->dataDevice()->startDrag(drag()->mimeData(), icon)) {
9fb289
+    if (m_display->currentInputDevice()->dataDevice()->startDrag(drag()->mimeData(), drag()->supportedActions(), icon)) {
9fb289
         icon->addAttachOffset(-drag()->hotSpot());
9fb289
     } else {
9fb289
         // Cancelling immediately does not work, since the event loop for QDrag::exec is started
9fb289
@@ -103,31 +103,31 @@ void QWaylandDrag::endDrag()
9fb289
     m_display->currentInputDevice()->handleEndDrag();
9fb289
 }
9fb289
 
9fb289
-void QWaylandDrag::updateTarget(const QString &mimeType)
9fb289
+void QWaylandDrag::setResponse(bool accepted)
9fb289
 {
9fb289
-    setCanDrop(!mimeType.isEmpty());
9fb289
-
9fb289
-    if (canDrop()) {
9fb289
-        updateCursor(defaultAction(drag()->supportedActions(), m_display->currentInputDevice()->modifiers()));
9fb289
-    } else {
9fb289
-        updateCursor(Qt::IgnoreAction);
9fb289
-    }
9fb289
+    // This method is used for old DataDevices where the drag action is not communicated
9fb289
+    Qt::DropAction action = defaultAction(drag()->supportedActions(), m_display->currentInputDevice()->modifiers());
9fb289
+    setResponse(QPlatformDropQtResponse(accepted, action));
9fb289
 }
9fb289
 
9fb289
-void QWaylandDrag::setResponse(const QPlatformDragQtResponse &response)
9fb289
+void QWaylandDrag::setResponse(const QPlatformDropQtResponse &response)
9fb289
 {
9fb289
     setCanDrop(response.isAccepted());
9fb289
 
9fb289
     if (canDrop()) {
9fb289
-        updateCursor(defaultAction(drag()->supportedActions(), m_display->currentInputDevice()->modifiers()));
9fb289
+        updateCursor(response.acceptedAction());
9fb289
     } else {
9fb289
         updateCursor(Qt::IgnoreAction);
9fb289
     }
9fb289
 }
9fb289
 
9fb289
-void QWaylandDrag::finishDrag(const QPlatformDropQtResponse &response)
9fb289
+void QWaylandDrag::setDropResponse(const QPlatformDropQtResponse &response)
9fb289
 {
9fb289
     setExecutedDropAction(response.acceptedAction());
9fb289
+}
9fb289
+
9fb289
+void QWaylandDrag::finishDrag()
9fb289
+{
9fb289
     QKeyEvent event(QEvent::KeyPress, Qt::Key_Escape, Qt::NoModifier);
9fb289
     eventFilter(shapedPixmapWindow(), &event);
9fb289
 }
9fb289
diff --git a/src/client/qwaylanddnd_p.h b/src/client/qwaylanddnd_p.h
9fb289
index 474fe2ab..747f0190 100644
9fb289
--- a/src/client/qwaylanddnd_p.h
9fb289
+++ b/src/client/qwaylanddnd_p.h
9fb289
@@ -71,9 +71,10 @@ public:
9fb289
     QWaylandDrag(QWaylandDisplay *display);
9fb289
     ~QWaylandDrag() override;
9fb289
 
9fb289
-    void updateTarget(const QString &mimeType);
9fb289
-    void setResponse(const QPlatformDragQtResponse &response);
9fb289
-    void finishDrag(const QPlatformDropQtResponse &response);
9fb289
+    void setResponse(bool accepted);
9fb289
+    void setResponse(const QPlatformDropQtResponse &response);
9fb289
+    void setDropResponse(const QPlatformDropQtResponse &response);
9fb289
+    void finishDrag();
9fb289
 
9fb289
 protected:
9fb289
     void startDrag() override;
9fb289
diff --git a/tests/auto/client/datadevicev1/tst_datadevicev1.cpp b/tests/auto/client/datadevicev1/tst_datadevicev1.cpp
9fb289
index 1568b3b9..067410d0 100644
9fb289
--- a/tests/auto/client/datadevicev1/tst_datadevicev1.cpp
9fb289
+++ b/tests/auto/client/datadevicev1/tst_datadevicev1.cpp
9fb289
@@ -35,7 +35,7 @@
9fb289
 
9fb289
 using namespace MockCompositor;
9fb289
 
9fb289
-constexpr int dataDeviceVersion = 1;
9fb289
+constexpr int dataDeviceVersion = 3;
9fb289
 
9fb289
 class DataDeviceCompositor : public DefaultCompositor {
9fb289
 public:
9fb289
-- 
9fb289
2.35.1
9fb289