Is there a way to create a /dev/clipboard like in Cygwin?

Solution 1:

Having a FUSE daemon talk X11 would certainly be possible. But there are some other problems:

Nitpick: "Primary clipboard" contradicts itself. X11 has two commonly used 'selections'; the one called "PRIMARY" is used when you select and middle-click, and the one called "CLIPBOARD" is used when you press CtrlC or CtrlV.

Cygwin's /dev/clipboard is implemented in the cygwin1 runtime, so its code runs in the same context as the accessing program itself. If two users try to read it, they both see their own clipboard contents, because they're accessing it themselves, directly.

Linux filesystem mounts, meanwhile, are globalall read requests go through a single FUSE server process (for that FUSE mount); meaning, it doesn't know for sure which X server's clipboard it should read.

(Remember that there can be multiple users logged in, and multiple X servers running at once.)

There are three possible solutions for the multi-user problem:

  • Have a single system-wide FUSE mount at /dev/clipboard. Every time the FUSE daemon receives a open request, it needs to obtain the requesting program's PID, access /proc/<pid>/environ, extract DISPLAY= & XAUTHORITY= from it, use that information to connect to the correct X server, and read the clipboard.

  • Instead of /dev, put the special file in the user's home directory, e.g. ~/clipboard. Each user runs a separate copy of the daemon. GNOME's Gvfs uses this method for /run/user/*/gvfs (earlier ~/.gvfs). It limits each user to one graphical session, but that's fine – there are many other things that only work once per user, too.

  • Set up a new mount namespace when logging in, e.g. using pam_namespace, so that each session would have a separate view of what's mounted where (inheriting from the root namespace, but being able to mount e.g. /dev/clipboard without it being visible from the outside). The FUSE daemon then is launched by the X session manager, same as in the previous method, but not limited to one session per user.