From d6b75907cca668d0c2b226d44dcab4ebe55e3b6b Mon Sep 17 00:00:00 2001 From: David Redondo Date: Fri, 20 Jan 2023 11:25:08 +0100 Subject: [PATCH] Data control: Resend selection when not following through with request Normal event flow is from a client view is -> wlr_data_control_device.set_selection wlr_data_control_device.selection or wlr_data_control_source.cancelled wlr_data_control_device.selection However when the race mentioned in the comment happens the client sees -> wlr_data_control_device.set_selection wlr_data_control_device.selection wlr_data_control_source_cancelled Which can confuse client state thinking the clipboard didn't change as it associates the selection event with its own request. Resend the selection event in this case to tell the client the correct selection. BUG:464509 FIXED-IN:5.27 --- src/wayland/seat_interface.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/wayland/seat_interface.cpp b/src/wayland/seat_interface.cpp index a3d49b1c94..871d38b605 100644 --- a/src/wayland/seat_interface.cpp +++ b/src/wayland/seat_interface.cpp @@ -214,9 +214,11 @@ void SeatInterfacePrivate::registerDataControlDevice(DataControlDeviceV1Interfac QObject::connect(dataDevice, &DataControlDeviceV1Interface::selectionChanged, q, [this, dataDevice] { // Special klipper workaround to avoid a race // If the mimetype x-kde-onlyReplaceEmpty is set, and we've had another update in the meantime, do nothing + // but resend selection to mimic normal event flow upon cancel and not confuse the client // See https://github.com/swaywm/wlr-protocols/issues/92 if (dataDevice->selection() && dataDevice->selection()->mimeTypes().contains(QLatin1String("application/x-kde-onlyReplaceEmpty")) && currentSelection) { dataDevice->selection()->cancel(); + dataDevice->sendSelection(currentSelection); return; } q->setSelection(dataDevice->selection()); @@ -225,10 +227,12 @@ void SeatInterfacePrivate::registerDataControlDevice(DataControlDeviceV1Interfac QObject::connect(dataDevice, &DataControlDeviceV1Interface::primarySelectionChanged, q, [this, dataDevice] { // Special klipper workaround to avoid a race // If the mimetype x-kde-onlyReplaceEmpty is set, and we've had another update in the meantime, do nothing + // but resend selection to mimic normal event flow upon cancel and not confuse the client // See https://github.com/swaywm/wlr-protocols/issues/92 if (dataDevice->primarySelection() && dataDevice->primarySelection()->mimeTypes().contains(QLatin1String("application/x-kde-onlyReplaceEmpty")) && currentPrimarySelection) { dataDevice->primarySelection()->cancel(); + dataDevice->sendPrimarySelection(currentPrimarySelection); return; } q->setPrimarySelection(dataDevice->primarySelection());