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

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