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

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