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
This commit is contained in:
parent
decfb64ada
commit
f6e98a34b2
4 changed files with 36 additions and 6 deletions
|
@ -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();
|
||||
|
|
Loading…
Reference in a new issue