Safely end drag if the source data device gets destroyed

We cannot end a drag after the destroyed() signal for the source data
device is emitted because DataDeviceInterface and its d pointer are gone
by that time.
This commit is contained in:
Vlad Zahorodnii 2020-11-11 15:59:49 +02:00
parent 34982850e2
commit 0613e8f4c9
4 changed files with 17 additions and 16 deletions

View file

@ -175,6 +175,7 @@ DataOfferInterface *DataDeviceInterfacePrivate::createDataOffer(AbstractDataSour
void DataDeviceInterfacePrivate::data_device_destroy_resource(QtWaylandServer::wl_data_device::Resource *resource)
{
Q_UNUSED(resource)
emit q->aboutToBeDestroyed();
delete q;
}

View file

@ -118,6 +118,7 @@ public:
wl_client *client();
Q_SIGNALS:
void aboutToBeDestroyed();
void dragStarted();
void selectionChanged(KWaylandServer::DataSourceInterface*);
void selectionCleared();

View file

@ -293,20 +293,15 @@ void SeatInterface::Private::registerDataDevice(DataDeviceInterface *dataDevice)
}
drag.source = dataDevice;
drag.sourcePointer = interfaceForSurface(originSurface, pointers);
drag.destroyConnection = QObject::connect(dataDevice, &QObject::destroyed, q,
drag.destroyConnection = QObject::connect(dataDevice, &DataDeviceInterface::aboutToBeDestroyed, q,
[this] {
endDrag(display->nextSerial());
cancelDrag(display->nextSerial());
}
);
if (dataDevice->dragSource()) {
drag.dragSourceDestroyConnection = QObject::connect(dataDevice->dragSource(), &AbstractDataSource::aboutToBeDestroyed, q,
[this] {
const auto serial = display->nextSerial();
if (drag.target) {
drag.target->updateDragTarget(nullptr, serial);
drag.target = nullptr;
}
endDrag(serial);
cancelDrag(display->nextSerial());
}
);
} else {
@ -395,6 +390,15 @@ void SeatInterface::Private::registerPrimarySelectionDevice(PrimarySelectionDevi
}
}
void SeatInterface::Private::cancelDrag(quint32 serial)
{
if (drag.target) {
drag.target->updateDragTarget(nullptr, serial);
drag.target = nullptr;
}
endDrag(serial);
}
void SeatInterface::Private::endDrag(quint32 serial)
{
QObject::disconnect(drag.destroyConnection);
@ -1215,14 +1219,8 @@ void SeatInterface::cancelTouchSequence()
(*it)->cancel();
}
if (d->drag.mode == Private::Drag::Mode::Touch) {
// cancel the drag, don't drop.
if (d->drag.target) {
// remove the current target
d->drag.target->updateDragTarget(nullptr, 0);
d->drag.target = nullptr;
}
// and end the drag for the source, serial does not matter
d->endDrag(0);
// cancel the drag, don't drop. serial does not matter
d->cancelDrag(0);
}
d->globalTouch.ids.clear();
}

View file

@ -42,6 +42,7 @@ public:
void registerDataDevice(DataDeviceInterface *dataDevice);
void registerDataControlDevice(DataControlDeviceV1Interface *dataDevice);
void endDrag(quint32 serial);
void cancelDrag(quint32 serial);
quint32 nextSerial() const;
QString name;