clinuxclipboardx11

Access the clipboard on Linux (X11) from a C source code


In a C program, I would like to write a string to the clipboard (and also read back a string from the clipboard) while running X11 in Linux.

This can be easily done in Python with pyperclip, for example; as regards C, however, despite many searches I did not find any example.

  1. This post simply uses the command line and I would like to avoid it.
  2. This post suggests to read the xsel sourcecode. I tried, but the code is somewhat huge.

The selection I must refer to is probably CLIPBOARD (neither PRIMARY, nor SECONDARY). In the linked xsel source, some relevant parts are

#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Xutil.h>

and then

/* Find the "CLIPBOARD" selection if required */
  if (want_clipboard) {
    selection = XInternAtom (display, "CLIPBOARD", False);
  }

but I didn't find a direct relation between XInternAtom and read/write the clipboard.

If XInternAtom is the correct function, how to proceed? Or is there another API that I can use?


Solution

  • XInternAtom() only converts the string name to an integer ID (the 'atom').

    An "atom" in X11 (similar to what other programming languages call a symbol) is just a unique integer ID used to identify certain kinds of "named" objects. Instead of the X server having to process a string name every time some operation is done, you use XInternAtom() to do it just once and use the ID thereafter. (This e.g. allows X11 packets to be fixed-size structs instead of variable-length, which makes them faster to parse, not to mention much smaller.)

    The X server keeps track of all strings ever given to XInternAtom() so that every call for the same name returns the same ID throughout the lifetime of the X display; see the output of xlsatoms.

    The clipboard in X11 is a type of selection. There can be many "selections" (some of them for internal purposes), but the one that deals with Windows/MacOS-style Ctrl-C/Ctrl-V is called "CLIPBOARD" – together with the SunView-style "PRIMARY" and "SECONDARY". The latter two have predefined atoms such as XA_PRIMARY, but the clipboard does not, so you have to use XInternAtom("CLIPBOARD") to retrieve its ID dynamically.

    Contents of a selection are not stored centrally by X; they're kept by the original program where something was copied (which becomes the "selection owner"). Once you have the atom for a selection, you then request its contents from its owner using XConvertSelection() and the process owning that selection stores it in your window and responds with a SelectionNotify event. "Hey, I broke into your house and left the package in your living room."

    Since the results get stored as a property of your window, you will need to create an invisible window first.

    Just like in Windows API, you will need to request a specific data type such as "UTF8_STRING" or "image/png". Asking for the special type "TARGETS" usually returns a text list of types that the selection owner can offer.

    (Data types are also handled as atoms – there is a constant XA_STRING for the legacy format but you must XInternAtom("UTF8_STRING") for the Unicode-compatible one.)

    More documentation and code examples at:

    Watching a selection for changes can be done using the XFIXES extension (which is universally supported), for example.