diff --git a/src/wayland/datadevice_interface.cpp b/src/wayland/datadevice_interface.cpp index c3505bd960..0ca4400875 100644 --- a/src/wayland/datadevice_interface.cpp +++ b/src/wayland/datadevice_interface.cpp @@ -247,6 +247,9 @@ void DataDeviceInterface::updateDragTarget(SurfaceInterface *surface, quint32 se return; } auto *source = d->seat->dragSource()->dragSource(); + if (source) { + source->setAccepted(false); + } DataOfferInterface *offer = d->createDataOffer(source); d->drag.surface = surface; if (d->seat->isDragPointer()) { diff --git a/src/wayland/datasource_interface.cpp b/src/wayland/datasource_interface.cpp index c5b28a1bff..619e950f7d 100644 --- a/src/wayland/datasource_interface.cpp +++ b/src/wayland/datasource_interface.cpp @@ -26,6 +26,7 @@ public: DataSourceInterface *q; QStringList mimeTypes; DataDeviceManagerInterface::DnDActions supportedDnDActions = DataDeviceManagerInterface::DnDAction::None; + bool isAccepted = false; protected: void data_source_destroy_resource(Resource *resource) override; @@ -107,6 +108,7 @@ DataSourceInterface::~DataSourceInterface() = default; void DataSourceInterface::accept(const QString &mimeType) { d->send_target(mimeType); + d->isAccepted = !mimeType.isNull(); } void DataSourceInterface::requestData(const QString &mimeType, qint32 fd) @@ -181,4 +183,14 @@ wl_client *DataSourceInterface::client() const return d->resource()->client(); } +bool DataSourceInterface::isAccepted() const +{ + return d->isAccepted; +} + +void DataSourceInterface::setAccepted(bool accepted) +{ + d->isAccepted = accepted; +} + } diff --git a/src/wayland/datasource_interface.h b/src/wayland/datasource_interface.h index cce883d225..4f4d98ea99 100644 --- a/src/wayland/datasource_interface.h +++ b/src/wayland/datasource_interface.h @@ -49,6 +49,9 @@ public: wl_client *client() const override; + bool isAccepted() const; + void setAccepted(bool accepted); + private: friend class DataDeviceManagerInterfacePrivate; explicit DataSourceInterface(DataDeviceManagerInterface *parent, wl_resource *parentResource); diff --git a/src/wayland/seat_interface.cpp b/src/wayland/seat_interface.cpp index b86afe8b70..0943dcc25e 100644 --- a/src/wayland/seat_interface.cpp +++ b/src/wayland/seat_interface.cpp @@ -396,16 +396,28 @@ void SeatInterface::Private::registerPrimarySelectionDevice(PrimarySelectionDevi void SeatInterface::Private::endDrag(quint32 serial) { - auto target = drag.target; QObject::disconnect(drag.destroyConnection); QObject::disconnect(drag.dragSourceDestroyConnection); - if (drag.source && drag.source->dragSource()) { - drag.source->dragSource()->dropPerformed(); + + DataDeviceInterface *dragTarget = drag.target; + DataSourceInterface *dragSource = drag.source ? drag.source->dragSource() : nullptr; + if (dragSource) { + // TODO: Also check the current drag-and-drop action. + if (dragTarget && dragSource->isAccepted()) { + dragTarget->drop(); + dragSource->dropPerformed(); + } else { + if (wl_resource_get_version(dragSource->resource()) >= + WL_DATA_SOURCE_DND_FINISHED_SINCE_VERSION) { + dragSource->cancel(); + } + } } - if (target) { - target->drop(); - target->updateDragTarget(nullptr, serial); + + if (dragTarget) { + dragTarget->updateDragTarget(nullptr, serial); } + drag = Drag(); emit q->dragSurfaceChanged(); emit q->dragEnded();