diff --git a/src/wayland/autotests/client/test_wayland_seat.cpp b/src/wayland/autotests/client/test_wayland_seat.cpp index f1ef664506..b414e667ca 100644 --- a/src/wayland/autotests/client/test_wayland_seat.cpp +++ b/src/wayland/autotests/client/test_wayland_seat.cpp @@ -1487,6 +1487,19 @@ void TestWaylandSeat::testSelection() m_seatInterface->setSelection(nullptr); QVERIFY(selectionClearedSpy.wait()); QCOMPARE(selectionSpy.count(), 2); + + // create a second ddi and a data source + QScopedPointer dd2(ddm->getDataDevice(m_seat)); + QVERIFY(dd2->isValid()); + QScopedPointer ds2(ddm->createDataSource()); + QVERIFY(ds2->isValid()); + ds2->offer(QStringLiteral("text/plain")); + dd2->setSelection(0, ds2.data()); + QVERIFY(selectionSpy.wait()); + QSignalSpy cancelledSpy(ds2.data(), &DataSource::cancelled); + QVERIFY(cancelledSpy.isValid()); + m_seatInterface->setSelection(ddi); + QVERIFY(cancelledSpy.wait()); } void TestWaylandSeat::testTouch() diff --git a/src/wayland/seat_interface.cpp b/src/wayland/seat_interface.cpp index b35f2781c2..976877ae93 100644 --- a/src/wayland/seat_interface.cpp +++ b/src/wayland/seat_interface.cpp @@ -339,19 +339,25 @@ void SeatInterface::Private::endDrag(quint32 serial) emit q->dragEnded(); } +void SeatInterface::Private::cancelPreviousSelection(DataDeviceInterface *dataDevice) +{ + if (!currentSelection) { + return; + } + if (auto s = currentSelection->selection()) { + if (currentSelection != dataDevice) { + // only if current selection is not on the same device + // that would cancel the newly set source + s->cancel(); + } + } +} + void SeatInterface::Private::updateSelection(DataDeviceInterface *dataDevice, bool set) { if (keys.focus.surface && (keys.focus.surface->client() == dataDevice->client())) { - if (currentSelection) { - // cancel the previous selection - if (auto s = currentSelection->selection()) { - if (currentSelection != dataDevice) { - // only if current selection is not on the same device - // that would cancel the newly set source - s->cancel(); - } - } - } + // cancel the previous selection + cancelPreviousSelection(dataDevice); // new selection on a data device belonging to current keyboard focus currentSelection = dataDevice; } @@ -1303,6 +1309,8 @@ void SeatInterface::setSelection(DataDeviceInterface *dataDevice) if (d->currentSelection == dataDevice) { return; } + // cancel the previous selection + d->cancelPreviousSelection(dataDevice); d->currentSelection = dataDevice; if (d->keys.focus.selection) { if (dataDevice) { diff --git a/src/wayland/seat_interface_p.h b/src/wayland/seat_interface_p.h index bb84ccd7ac..9e83ccaad7 100644 --- a/src/wayland/seat_interface_p.h +++ b/src/wayland/seat_interface_p.h @@ -51,6 +51,7 @@ public: void registerDataDevice(DataDeviceInterface *dataDevice); void registerTextInput(TextInputInterface *textInput); void endDrag(quint32 serial); + void cancelPreviousSelection(DataDeviceInterface *newlySelectedDataDevice); QString name; bool pointer = false;