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