--- /dev/null
+/*
+ * Send data to primary X selection. Inspired by the `xclip' utility by Kim Saunders.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+
+static Display *dpy;
+static Window win;
+
+static void die(char *msg)
+{
+ fprintf(stderr, "xclipcat: %s\n", msg);
+ exit(1);
+}
+
+int main(void)
+{
+ /* Prepare the string */
+ char send[] = "Brum!\n";
+ int len = sizeof(send);
+
+ /* Create display and window */
+ if (!(dpy = XOpenDisplay(NULL)))
+ die("Cannot open display");
+ win = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy), 0, 0, 1, 1, 0, 0, 0);
+
+ /* Select which events we want to listen to */
+ XSelectInput(dpy, win, PropertyChangeMask);
+
+ /* Take hold of the needed atoms */
+ Atom targets = XInternAtom(dpy, "TARGETS", False);
+
+ /* Assert ownership of the selection */
+ XSetSelectionOwner(dpy, XA_PRIMARY, win, CurrentTime);
+
+ /* Wait for the right event */
+ XEvent ev;
+ for (;;)
+ {
+ XNextEvent(dpy, &ev);
+ if (ev.type == SelectionClear)
+ break;
+ if (ev.type != SelectionRequest)
+ continue;
+
+ Window req_win = ev.xselectionrequest.requestor;
+ Atom req_pty = ev.xselectionrequest.property;
+ if (ev.xselectionrequest.target == targets)
+ {
+ /* We were asked to send a list of supported formats */
+ puts("Type list requested");
+ Atom formats[2] = { targets, XA_STRING };
+ XChangeProperty(dpy, req_win, req_pty, targets, 8, PropModeReplace, (unsigned char *) formats, (int) sizeof(formats));
+ }
+ else
+ {
+ /* We were asked to send the contents */
+ puts("Selection contents requested");
+ XChangeProperty(dpy, req_win, req_pty, XA_STRING, 8, PropModeReplace, (unsigned char *) send, len);
+ }
+
+ /* Respond with another event */
+ XEvent re;
+ re.xselection.property = req_pty;
+ re.xselection.type = SelectionNotify;
+ re.xselection.display = ev.xselectionrequest.display;
+ re.xselection.requestor = req_win;
+ re.xselection.selection = ev.xselectionrequest.selection;
+ re.xselection.target = ev.xselectionrequest.target;
+ re.xselection.time = ev.xselectionrequest.time;
+ XSendEvent(dpy, req_win, 0, 0, &re);
+ XFlush(dpy);
+ }
+ puts("Selection replaced, good bye!");
+
+ return 0;
+}