Race using wlr_data_control to create a clipboard manager
Created by: davidedmundson
Our clipboard manager (klipper) works as follows:
- On a new clipboard, we copy any text
- If the clipboard becomes empty (typically because a client died), we paste our previously copied text
- A user can also explicitly select an item from the history
We had this on X, and I've retrofitted wlr_data_control into it.
I've implemented wlr_data_control and all of wl-copy, wl-paste work perfectly, to some extent klipper works, but there's a race I can't fix neatly, which I think would happen for all other clipboard managers trying to do the same thing.
My race is:
first copy:
- firefox creates a wl_data_offer
- kwin sees it forwards it klipper which copies the text... (all good so far)
second copy:
-
firefox deletes its old wl_data_offer before creating a new one (unlike other toolkits, but still a valid thing to do)
-
kwin forwards this update to klipper
-
klipper knows the clipboard is empty and starts its operation to prevent an empty clipboard
-
firefox creates a new wl_data_offer and calls set_selection
-
klipper creates a new wlr_data_offer (with the old clipboard text) and calls set_selection
The compositor gets these in any order, and we end up replacing our new clipboard content with out-of-date previous clipboard contents.
Ultimately to prevent a race I think we need an additional fence like:
<event name="selection">
<arg name="id" type="object" interface="zwlr_data_control_offer_v1" allow_null=true>
An integer value that increases, like the xdg_shell configure events
<arg name="serial" type="int">
</event>
<request name="set_selection">
<arg name="source" type="object" interface="zwlr_data_control_source_v1"
allow-null="true"/>
Optional serial which matches the clipboard event we're responding to. If this is out-of-date this selection will be immediately cancelled and ignored. If negative, we always apply the new selection.
<arg name="serial" type="int">
</request>