From 9f3d6c8f841de796c0162c61d8de075647e5d970 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Mon, 10 Oct 2016 10:43:15 +0200 Subject: [PATCH] [server] Cancel previous selection from SeatInterface::setSelection Summary: When changing the selection the previous selection needs to be cancelled. This is already done in the "normal" updating of the selection. If the previous selection doesn't get cancelled QtWayland is not able to accept anything new from the clipboard. The setSelection didn't cancel it yet, due to that copy from Xwayland to QtWayland windows doesn't work in KWin as KWin uses the setSelection call for the Xwayland clipboard. With this change the cancelling of previous selection is moved into a dedicated method and called from the normal way and the setSelection way. Reviewers: #plasma_on_wayland, bshah Subscribers: plasma-devel Tags: #plasma_on_wayland Differential Revision: https://phabricator.kde.org/D2997 --- .../autotests/client/test_wayland_seat.cpp | 13 +++++++++ src/wayland/seat_interface.cpp | 28 ++++++++++++------- src/wayland/seat_interface_p.h | 1 + 3 files changed, 32 insertions(+), 10 deletions(-) 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;