Xwayland Clipboard

I hate every single line of xwayland code I wrote, it is ugly, long and hard to maintain. Now I know very well why there is wayland in the first place, sadly a complete wayland compositor has to bring a piece of crap of X with it. I just finished the selection handling in xwayland by mimicing weston code. After finally understand that 1000 lines of confusing code, I just found out I can't do any better.

Handling X11 selection revolves around 4 events: XSelectionNotify, XSelectionRequest, XPropertyNotify and XfixesSelectionNotify. Their names are just as confusing as how they work. It gets more complicated when INCR protocol is involved.

Our job in compositor, for xwayland, is a proxy. That means getting wl_data_source to X data_offer, and writing to wl_data_offer from a X data_source when there is no data_offer and data_source in X at all. In wayland, the protocol utilises PIPE for implementing clipboard. In X, it is implemented by writing to a property of a X window. If you have no idea about the properties in X. It is like a key value hash map, every window has a such hash map. Clients communicates by reading/writing properties. Here is catch, the developers ought to adher the specificiation, ICCCM for correctly implementing their clients or XWM. If anything goes wrong...

Back to our topic, how do we work with those 4 events? Let's walk through the story. When a client press "ctrl-c", it declares the owner of CLIPBOARD, which is a special atom in the X. Nothing happens at the moment, until another client, the requestor press "ctrl-v", it then search for the owner of the CLIPBOARD and ask for data, it begins our first event XSelectionRequest, basically it says, "hey, the owner, I would like you to convert what you have in the CLIPBOARD to the target I asked and write to my property that I tell you". Then the owner can use a function XConvertSelection for that purpose. When it finishes, the owner send XSelectionNotify event to the requestor. The requestor indicates the end of the transaction by deletes the property.

We didn't mention the other two events. It has to do with our xwayland usage. I tried to summary the transaction as brief as possible, but we also omitted a lot of details. There are other playes, the wm(part of your wayland compositor), the CLIPBOARD_MANAGER and the role of xserver(xwayland in this case) in the story. Let me start by asking a few questions:

  • How does the XWM know about the onwer of the CLIPBOARD?
  • How does a wl_data_source becomes the owner of the CLIPBOARD?
  • How do we copy the property to wl_data_offer or vice versa?

When a owner of the CLIPBOARD annouces itself in Xwayland, the XWM need to make a wl_data_source out of it. This is done through the XfixesSelectionNotify event. In the event, we, the XWM, would ask for all the targets (or mimes in wayland terms) that owner has(not the data itself). With that, we have enough to create a proxy wl_date_source, if there is no wl_client ask for data, we do nothing more, otherwise, the XWM represents the wl_client asking data from X.

On the other end, if a wl_data_source becomes available, the XWM gets notified and simply declares the owner of CLIPBOARD, if we are to process any XSelectionRequests, a PIPE need to create inside the XWM for reading from wl_data_source and writes the data to some X properties.

In the end, the selection data flows like this.

The ugly part is when INCR protocol comes in. INCR is for the case when you could not read/write X properties in one shot. Basically the XRequestor need to delete the property selection owner wrote to and wait for it to write again. For us xwayland case, we are in the akward situation for waiting on both X client deleting property and PIPE fd becomes available for IO.