Skip to content

Why Klipper is good

Thursday, 2 February 2006  |  lubos lunak

Yes, I'm paraphrasing the title of one of the claims how Klipper is an awful hack working in the most stupid way possible whose only purpose is to make sure clipboard content doesn't get lost when you close an application. What a nonsense. Klipper is a tool for keeping several last items from clipboard history, the fact that the several last items include also the very last one is just a nice side-effect. And, while Klipper and X clipboard in general used to have and still have some problems (what doesn't after all), many Klipper problems are actually caused by broken clipboard implementations in various applications including OpenOffice.org or Mozilla/Firefox or by the way X clipboard works and most Klipper hacks are there in order to work around such problems.

The X clipboard works rather differently from what naive expectations about it might be. There's actually no real clipboard. If you copy something to clipboard in app A, then the only thing that happens is that app A tells X that it's now the owner of the clipboard. The data is still stored in A. And if you later decide to paste the clipboard content in app B, then B has to ask X about who's the clipboard owner and after it's told, it needs to communicate with A and get the contents from it. The most obvious demonstration of this fact is that if you close A, clipboard contents get lost. Another consequence of this fact is that just copying to clipboard is a cheap operation, pasting in the same app is cheap, but pasting in another app is not. If the contents were stored in X, all operations would be expensive. And finally one more interesting fact about X clipboard is that if the owner changes, only the previous owner will be told. If C takes over the clipboard, A will be told, but B won't. There are also other things about X clipboard, like that there are actually two of them, but that's not important here.

Lets now go back to about 1998 when Andrew Stanley-Jones gets this simple yet great idea that it might be useful to have a history of clipboard items. Clipboard content is rather easy to overwrite, especially if you use mouse copy/paste, so being able to get the content you had there a minute ago is very handy sometimes (and I tell you I use it every day, including several times while writing this, I've even recently been pondering the idea of adding support for mcedit history to Klipper, because there I loose clipboard content all the time and hate it). Andrew, I'd assume, actually didn't know anything about the internals of the X clipboard. He didn't really need to, Qt shields from X very well, so with QClipboard it was only a matter of using QClipboard::setText(), QClipboard::text() and a QClipboard signal that the clipboard contents have changed. Very simple - you get a signal, fetch the contents with text(), store it in history and then make the user happy from time to time that it's not lost when the user needs it. Klipper was created.

But wait, I said that there's no notification about clipboard changing, right? Well, TrollTech saw this problem even back then and added a mechanism to Qt that made all Qt apps announce it. Announce it to all other Qt apps, that is, as back then X development already stagnated and making other apps support it too would have been a crazy idea (well, after all, even these days many apps just don't care, we'll see). So, and that might have been already by the time Carsten Pfeiffer took over Klipper development, I don't know (I wasn't involved with KDE back then, so I'm making this up a little to have a better story :) ), it was obvious that a different way of tracking clipboard contents was needed, if it was supposed to work with non-Qt/KDE apps too.

The most obvious solution was done and that was simply polling the clipboard contents every second and checking if it has changed. Back then we all used clipboard only for short texts, many apps didn't support inter-application clipboard anyway, so this wasn't really big deal. Klipper transferred a couple of bytes every second, so what?

Another possible solution was to use the fact that the clipboard owner gets notified when it looses the ownership, so Klipper for quite some time also tried to solve the polling this way. Klipper took ownership of the clipboard and whenever it lost it, Klipper immediately asked the new owner about the new text in clipboard and then took ownership again, with this new text. This is not used anymore, Klipper no longer claims clipboard ownership unless explicitly told so, as it causes some trouble. First there's the problem if the clipboard content set by the app is not text then it gets lost, and secondly, such extensive usage of the QClipboard class was a good stress test for it. So good in fact that it had revealed several bugs there that otherwise had gone unnoticed and QClipboard maintainer at TrollTech is even allergic to bugreports about QClipboard and Klipper even if they contain patches (you can find evidence if you grep qclipboard_x11.cpp for klipper :) ). There were KDE releases that unfortunately had bad problems because of such bugs.

Anyway, let's move a bit closer to present days. To days when it was becoming more common that people put other things than just text to clipboard, to days when more apps actually tried to support the X clipboard, to days when we work with more and more data. The fact that Klipper transferred clipboard contents every second was becoming a problem. Fortunately, there comes a hero to save the day (ok, that's me ;) ). There are two ways to solve the problem.

The first is a very pragmatical one. Transfering very large data is expensive, so let's put a maximum limit on it. Size of clipboard contents cannot be determined in advance, but that can be fixed, right? The only practical result of this is that I'm probably the only person in the world who has his own personal freedesktop.org "standard". Really, just check the page and search for "xclipboard". Yes, I proposed it, I got it there but generally people seemed pretty uninterested. What, what was that supposed to be good for? Take this as a lesson how much "freedesktop.org standard" can mean.

The second one was helping Klipper a bit with some Xlib code. If we have a look at section 2.6.2 in ICCCM, the specification which describes how applications should work with the X clipboard, we can see, near the end, that among the targets (=information that the application is supposed to provide about the clipboard contents) there's one called TIMESTAMP, and it's even required. Moreover, everytime applications change clipboard contents, they're supposed to re-acquire the clipboard ownership even if they already own it, thus altering the timestamp. Wow, cool, problem solved. So, after some work, Klipper no longer polls clipboard contents, it polls only the TIMESTAMP information, which is actually very lightweight, it's only a cheap number. Only if the timestamp changes, it's time to actually get a copy of the contents for keeping history.

So much for theory. It didn't seem to help with much more than Gtk (and Qt, but Klipper had used the internal Qt mechanism there anyway, so there had been no polling with Qt apps). For example, OpenOffice.org's clipboard implementation doesn't support TIMESTAMP at all, in Mozilla/Firefox it does, but always "usefully" returns 0. In such case, if Klipper is supposed to keep history, it simply must poll, otherwise it wouldn't work and then you can as well simply turn it off.

This can especially have bad results now that Klipper got support also for keeping images in history. The developer who did this feature unfortunately wasn't aware of all of this written above (well, that's years of experience), or simply didn't really consider possible impacts. After all, who'd expect that selecting(=activating) a text frame in OOo Impress makes a picture out of it that's put into the selection clipboard? Which, of course, given OOo's broken clipboard implementation, gets transferred every second, and, of course, the good practice is to blame Klipper for every single clipboard problem there is.

Making Klipper keep also images in history would be nice, and it'd help with the problem of losing clipboard contents when an app is closed also for images, but this is simply not worth it. In KDE3.5.2 this feature will be off by default, and since we're in string freeze, I'm afraid there even won't be GUI option for this. If you like it, your only chance will be to manually add IgnoreImages=false to section [General] in klipperrc.

Now, if you go back to the why klipper is bad acticle, at the end you'll see that also other than KDE people eventually realized that there are some problems and there's now a new Free Desktop Clipboard Manager Specification that will solve all Klipper's problems and that's already implemented in Gtk. Yeah right, except that it won't solve Klipper's problems, at least for now. We've never really had problems with clipboard contents being lost after an app is closed (my very first reaction to finding out GNOME developers were going to solve it was even just "huh?"), it has been always sufficiently solved by Klipper as a side-effect. But Klipper is supposed to keep history, not only help with lost clipboard contents, and as such it simply needs to keep track of all contents. By the time this was proposed on freedesktop.org I had already given up on my own "personal" spec, I had even almost forgotten (because, if nothing else, I don't remember ever having problems with large clipboard transfer with Qt/KDE, so what'd be the point of having it only in Qt?). However, I managed to sneak into this new spec a variation of it, under the name TARGET_SIZES. Wanna guess how many hits of this name will grepping all of sources of the upcoming SUSE Linux 10.1 show? So, how is it supposed to help Klipper then?

Anyway, let's get to the present day. The reason that I'm telling you all this is that I just spent some time going over Klipper's bugreports and adding some more hacks for various problems of Klipper (of course, read this mostly as "problems of somebody else that show up when using Klipper"). And I also added XFixes support to it, which should avoid polling completely and fix many of the problems resulting from it, if your X supports this relatively new extension. In fact I've been hearing about XFixes patches for Klipper repeatedly for quite some time, no idea why not a single of them has made it in (probably because the average KDE developer has TODO to keep them busy for at least a decade, so we randomly scrap parts of it to keep it at a reasonable size - sigh well, the rule about never having enough memory, money, time and similar also applies to developers I'm afraid). That's the good news, the bad news is that it was too late for 3.5.1 and will be only in 3.5.2, unless you build it yourself or your packagers adds the patches sooner (funnily enough the fact that SUSE packages for 3.5.1 will be delayed a bit may help here).

So, that's all I guess. Not that I'm trying to bash anyone, and I'm not telling you that Klipper or X clipboard are perfect, but this is simply how it was and how it is. I just thought that for a change you might want to see Klipper from the point of view of somebody who really knows it and who has fixed many Klipper's bugs and "bugs".