From 59bfac50ba20460de5ea2146b8bc9c55fe33899c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Tue, 21 Jun 2016 11:14:46 +0200 Subject: [PATCH] [server] Add support for setting the clipboard selection DataDeviceInterface manually Summary: So far SeatInterface handled automatically which DataDeviceInterface holds the current clipboard selection. While this works fine and is correct it doesn't support use cases like a clipboard manager where the clipboard is hold by a different ClientConnection than the one from the focused keyboard. This change allows to manually set the selected DataDeviceInterface to override the automatic selection, though the automatic selection is still in place. Thus the next update of a selection will override the manually set selection again. Reviewers: #plasma_on_wayland Subscribers: plasma-devel Tags: #plasma_on_wayland Differential Revision: https://phabricator.kde.org/D1972 --- .../autotests/client/test_datadevice.cpp | 5 +++++ .../autotests/client/test_wayland_seat.cpp | 19 ++++++++++++++++ src/wayland/seat_interface.cpp | 22 +++++++++++++++++++ src/wayland/seat_interface.h | 20 +++++++++++++++++ 4 files changed, 66 insertions(+) diff --git a/src/wayland/autotests/client/test_datadevice.cpp b/src/wayland/autotests/client/test_datadevice.cpp index 0fef6f96f9..12767ce8bc 100644 --- a/src/wayland/autotests/client/test_datadevice.cpp +++ b/src/wayland/autotests/client/test_datadevice.cpp @@ -194,11 +194,16 @@ void TestDataDevice::testCreate() QVERIFY(!deviceInterface->selection()); QVERIFY(deviceInterface->parentResource()); + QVERIFY(!m_seatInterface->selection()); + m_seatInterface->setSelection(deviceInterface); + QCOMPARE(m_seatInterface->selection(), deviceInterface); + // and destroy QSignalSpy destroyedSpy(deviceInterface, &QObject::destroyed); QVERIFY(destroyedSpy.isValid()); dataDevice.reset(); QVERIFY(destroyedSpy.wait()); + QVERIFY(!m_seatInterface->selection()); } void TestDataDevice::testDrag() diff --git a/src/wayland/autotests/client/test_wayland_seat.cpp b/src/wayland/autotests/client/test_wayland_seat.cpp index c8d50fed5d..e510be9e5d 100644 --- a/src/wayland/autotests/client/test_wayland_seat.cpp +++ b/src/wayland/autotests/client/test_wayland_seat.cpp @@ -1306,6 +1306,7 @@ void TestWaylandSeat::testSelection() QVERIFY(surface->isValid()); QVERIFY(surfaceCreatedSpy.wait()); auto serverSurface = surfaceCreatedSpy.first().first().value(); + QVERIFY(!m_seatInterface->selection()); m_seatInterface->setFocusedKeyboardSurface(serverSurface); QCOMPARE(m_seatInterface->focusedKeyboardSurface(), serverSurface); QVERIFY(!m_seatInterface->focusedKeyboard()); @@ -1314,6 +1315,7 @@ void TestWaylandSeat::testSelection() QCoreApplication::processEvents(); QVERIFY(selectionSpy.isEmpty()); QVERIFY(selectionClearedSpy.isEmpty()); + QVERIFY(!m_seatInterface->selection()); // now let's try to set a selection - we have keyboard focus, so it should be sent to us QScopedPointer ds(ddm->createDataSource()); @@ -1322,6 +1324,8 @@ void TestWaylandSeat::testSelection() dd1->setSelection(0, ds.data()); QVERIFY(selectionSpy.wait()); QCOMPARE(selectionSpy.count(), 1); + auto ddi = m_seatInterface->selection(); + QVERIFY(ddi); QVERIFY(selectionClearedSpy.isEmpty()); auto df = selectionSpy.first().first().value(); QCOMPARE(df->offeredMimeTypes().count(), 1); @@ -1347,6 +1351,21 @@ void TestWaylandSeat::testSelection() QCoreApplication::processEvents(); QCoreApplication::processEvents(); QCOMPARE(selectionSpy.count(), 1); + + // let's unset the selection on the seat + m_seatInterface->setSelection(nullptr); + // and pass focus back on our surface + m_seatInterface->setFocusedKeyboardSurface(serverSurface); + // we don't have a selection, so it should not send a selection + QVERIFY(!selectionSpy.wait(100)); + // now let's set it manually + m_seatInterface->setSelection(ddi); + QCOMPARE(m_seatInterface->selection(), ddi); + QVERIFY(selectionSpy.wait()); + QCOMPARE(selectionSpy.count(), 2); + // now clear it manully + m_seatInterface->setSelection(nullptr); + QVERIFY(selectionClearedSpy.wait()); } void TestWaylandSeat::testTouch() diff --git a/src/wayland/seat_interface.cpp b/src/wayland/seat_interface.cpp index 30cf8841fc..ca0c53ea53 100644 --- a/src/wayland/seat_interface.cpp +++ b/src/wayland/seat_interface.cpp @@ -1239,5 +1239,27 @@ TextInputInterface *SeatInterface::focusedTextInput() const return d->textInput.focus.textInput; } +DataDeviceInterface *SeatInterface::selection() const +{ + Q_D(); + return d->currentSelection; +} + +void SeatInterface::setSelection(DataDeviceInterface *dataDevice) +{ + Q_D(); + if (d->currentSelection == dataDevice) { + return; + } + d->currentSelection = dataDevice; + if (d->keys.focus.selection) { + if (dataDevice) { + d->keys.focus.selection->sendSelection(dataDevice); + } else { + d->keys.focus.selection->sendClearSelection(); + } + } +} + } } diff --git a/src/wayland/seat_interface.h b/src/wayland/seat_interface.h index 09d4e2b2b8..b5808f4d69 100644 --- a/src/wayland/seat_interface.h +++ b/src/wayland/seat_interface.h @@ -490,6 +490,26 @@ public: TextInputInterface *focusedTextInput() const; ///@} + /** + * @returns The DataDeviceInterface holding the current clipboard selection. + * @since 5.24 + * @see setSelection + **/ + DataDeviceInterface *selection() const; + /** + * This method allows to manually set the @p dataDevice for the current clipboard selection. + * The clipboard selection is handled automatically in SeatInterface. + * If a DataDeviceInterface belonging to the current focused KeyboardInterface + * sets a selection, the current clipboard selection will be updated automatically. + * With this method it's possible to override the automatic clipboard update for + * e.g. the case of a clipboard manager. + * + * @param dataDevice Sets the current clipboard selection. + * @see selection + * @since 5.24 + **/ + void setSelection(DataDeviceInterface *dataDevice); + static SeatInterface *get(wl_resource *native); Q_SIGNALS: