A semi-technical semi-introduction to X11 (semi-)clipboard
Sun, 20 Jun 2004 16:02 -0400

A couple days ago I was on the IRC channel for a rather nice open-source game (probably the best open-source game in existence, in fact; the only reason I am not plugging it here is because I am afraid that doing so would cause other KDEers to spend way too much time playing it, at the cost of their hacking productivity, which is what happened to me). At that time, the main developer, who uses Windows, added some rudimentary clipboard support to the game, and the implementation for it on Windows, which took all of about 20 lines of code. I decided to contribute an X11 implementation because I knew roughly how things should work, having debugged a few clipboard-related problems in KDE apps, and felt it would be a nice way to make a contribution to a program I like while improving my knowledge. About 330 lines of C++ code later (no, they didn't take me 2 days, just a few hours), I figure I'll give a bit of the technical overview here, since I think it would be nice if more people knew how those things work, particularly since qclipboard_x11.cpp is not the best place to figure things out on the spot.

Now, the most important thing to know about clipboard in X is, well, that there is no clipboard in the normal sense of the word. There is no place where applications can store things, and other can pick them up. Rather, X provides a set of communication primitives that let one implement something similar, and a document called the ICCCM has a section describing the usual conventions for using those primitives for copy-paste. This is why my code, and even more so Qt clipboard code is so complicated compared to doing similar things on Window or Mac OS --- it can not just call a few functions, but must implement a protocol. Let me introduce some of these primitives:

These are basically ways of referring to strings using integers identifies which are common for all apps. An application/library "interns" an atom to get a numeric identifier, and there are a few that are predefined.
Window properties
Each window can have arbitrary properties associated with it, which let one store data associated with an atom identifier. These are often used for communicating with the window manager --- for example the WM_NAME property specifies the window title.
These are kind of obvious --- keypresses, mouse motion, etc., all produce events. So do some operations that are used to implement copy-paste.
Selections are probably the most "interesting" bit here. Essentially, selections are identified with atoms, such as CLIPBOARD, and for each X keeps track of which application owns it, and provides a way of sending events to the current owner.
Now, what does all this have to with clipboard? Well, the clipboard works roughly like this:
  1. When you "copy" something, the application grabs the CLIPBOARD selection
  2. When some application wants to paste something, it asks X to send the owner of CLIPBOARD a message, requesting it to provide data in a certain format, identified by an atom, such as UTF8_STRING, and to put the data into a provided property of a provided window.
  3. The clipboard owner gets a SelectionRequest message with this information. It fills in the data if it can, and responds with a SelectionNotify message, indicating whether the data was provided or not

Notice that there is no common place where data is stored. An immediate consequence of this is that if the application where data was copied from exits, the clipboard contents are lost (since there is no-one to ask for them), unless some other program (like klipper) requests them and saves a copy. It may also seem that the choice of CLIPBOARD above is kind of arbitrary, and that other values may be used instead. This is indeed the case, and two values are currently used --- modern X application distingush between the "clipboard" and the "selection", and the clipboard uses CLIPBOARD, while the selection uses PRIMARY. A rather annoying consequence of this scheme is that when someone pastes, the application must actually wait for an event --- Qt not doing that carefully enough is what caused the infamous bug 61412

An another obvious question about the above summary is, well, how does the requesting application know what format to request the data in? Does it have to try out a lot of different formats? Well, there is a special format called TARGETS, in response to which clipboard owners can reply with the list of formats they support. Of course, if that feature is not supported by the application, the requestor may have to try out a few things. Which can get kind of messy, since there are at least 4 separate formats available for just plain text.

There are further complications, of course. X11 is network-transparent, or rather, it is really a distributed system, so weird things can happen if one is not careful. Imagine if you have a remote window over a fairly high-latency link, and some local ones. You copy some text from the remote application, but then decide you don't really want it, and copy some text from a local application instead. Now, both applications get your copy request, and both send requests to X saying "I want to control CLIPBOARD". The problem is, since the link to the later window is quite slow, if you're a really fast clicker/typer, it's conceivable that the remote message can arrive after the local one, thus having earlier data effectively overwrite later one. This is solved by having each keypress/mouse click have an associated timestamp. When requesting ownership of selection, the timestamp for the click/key press that caused it is provided to X. This way, if an earlier request arrives later, it can be discarded. Thus, timestamps are used to prevent various race conditions. Further, there are also some size limitations for properties. This means that there are additional sub-protocols used to transfer large amounts of data.

Well, that's about all I know. I hope this is clear enough to explain how things work, and to imply why sometimes they doesn't work quite as well as we wish they would.

Sun, 20 Jun 2004 16:02 -0400
A semi-technical semi-introduction to X11 (semi-)clipboard