Ξ

Keeping the clipboard alive

Published on 2024-09-04 design wayland

It frequently happens to me that I want to paste something, but nothing happens. This is because on wayland (and many other systems, but I will focus on wayland) the copied data is lost when you close the application that you wanted to copy from. I find this deeply confusing. The official solution seems to be to setup a clipboard manager. However, I found out that clipboard managers are not a solution, they just make different trade offs. I believe we can do better.

The Problem

I first thought that the clipboard contains the actual bits that are being copied. But that is not the case. When you hit Ctrl-C, no data is actually copied. Instead the data can be offered in multiple mime types at the same time, so that the receiving end can pick which mime type it prefers. For example, text copied from the web browser could be offered as both text/html and text/plain.

Of course, this mechanism only works as long as the application that is offering the data does not quit. After that, there is no one left to answer the request.

Clipboard managers

A common workaround for that problem is to use a clipboard manager like this:

wl-paste --watch cliphist store

In this case, wl-paste will call cliphist store whenever something is copied. It passes the copied data in one of the available mime types. cliphist will then replace the original offer with its own (text/plain). This means that the clipboard contents will not be lost when the original source goes away. But it also has some drawbacks:

clipmon is another clipboard manager that makes slightly different trade offs: It also replaces the original offer with its own, but it preserves all mime types. This solves the first drawback, but amplifies the second one: the same image might have to be stored in multiple different formats. The author of clipmon wrote a great blog post about these trade offs.

So in summary, the following goals are in conflict:

Finding balance

Many clipboard managers have features beyond just keeping the clipboard alive. But I only care about find a better default behavior.

It would be nice if we could keep the original offer intact, and only replace it with a fallback if the application actually quits. The fallback could be restricted (e.g. only offer text/plain) to avoid wasting resources. Still, I think this would be a more balanced solution than what is currently available.

I came up with the following script which can be used with wl-paste --watch:

#!/bin/sh -e
path="/tmp/clipboard-$USER-$XDG_SEAT.txt"
input=$(cat)

if [ -n "$input" ]; then
    umask 077
    printf '%s' "$input" > "$path"
elif [ -f "$path" ] && ! wl-paste -l >/dev/null 2>&1; then
    wl-copy < "$path"
fi

Moving it into the compositor

I think the behavior I described above should be implemented in compositors for three reasons:

Much of this post is based on discussions in https://github.com/labwc/labwc/issues/2042.