Commit aa42b540 authored by Vlad Zahorodnii's avatar Vlad Zahorodnii

Send a cancelled() event if the dnd data source is not accepted

Currently, Firefox will stuck in "dnd" mode if you try to drag any of
its tabs. The main reason for that is that kwin doesn't send the
wl_data_source.cancelled event if the pointer button has been released
and there is no target surface or if the data source hasn't been
accepted by anyone.

CCBUG: 427528
parent e9016929
......@@ -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()) {
......
......@@ -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;
}
}
......@@ -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);
......
......@@ -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();
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment