xprop-sink

lightweight, streaming X11 property updater

git clone https://9o.is/git/xprop-sink.git

xprop-sink.c

(1724B)


      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <string.h>
      4 #include <X11/Xlib.h>
      5 #include <X11/Xatom.h>
      6 
      7 static int running = 1;
      8 
      9 void
     10 usage(const char *prog)
     11 {
     12 	fprintf(stderr, "Usage: %s <window_id> <property_name>\n", prog);
     13 }
     14 
     15 int
     16 handle_x_errors(Display *dpy, XErrorEvent *ev)
     17 {
     18 	(void)dpy;
     19 	if (ev->error_code == BadWindow)
     20 		running = 0;
     21 	return 0;
     22 }
     23 
     24 int
     25 main(int argc, char **argv)
     26 {
     27 	Display *dpy;
     28 	Window win;
     29 	XWindowAttributes wa;
     30 	Atom atom;
     31 	char *endptr, buffer[1024];
     32 	size_t len;
     33 	int c;
     34 
     35 	if (argc != 3) {
     36 		usage(argv[0]);
     37 		return 1;
     38 	}
     39 
     40 	win = (Window) strtol(argv[1], &endptr, 0);
     41 	if (*endptr != '\0' || win == 0) {
     42 		fprintf(stderr, "Error: Invalid Window ID\n");
     43 		usage(argv[0]);
     44 		return 1;
     45 	}
     46 	
     47 	dpy = XOpenDisplay(NULL);
     48 	if (!dpy) {
     49 		fprintf(stderr, "Error: Cannot open X display\n");
     50 		return 1;
     51 	}
     52 
     53 	XSetErrorHandler(handle_x_errors);
     54 
     55 	atom = XInternAtom(dpy, argv[2], False);
     56 	if (atom == None) {
     57 		fprintf(stderr, "Error: Cannot create X atom\n");
     58 		return 1;
     59 	}
     60 
     61 	if (!XGetWindowAttributes(dpy, win, &wa)) {
     62 		fprintf(stderr, "Error: Window not found\n");
     63 		return 1;
     64 	}
     65 
     66 	setvbuf(stdin, NULL, _IONBF, 0);
     67 
     68 	while (running && fgets(buffer, sizeof(buffer), stdin)) {
     69 		len = strlen(buffer);
     70 
     71 		// If line exceeds buffer size, the remainder drained and ignored
     72 		if (len == sizeof(buffer) - 1 && buffer[len-1] != '\n') {
     73 			while ((c = getchar()) != '\n' && c != EOF);
     74 			continue;
     75 		}
     76 
     77 		len = strlen(buffer);
     78 		buffer[strcspn(buffer, "\r\n")] = 0;
     79 
     80 		if (!XGetWindowAttributes(dpy, win, &wa))
     81 			break;
     82 
     83 		if (len > 0) {
     84 			XChangeProperty(dpy, win, atom, XA_STRING, 8,
     85 					PropModeReplace, (unsigned char *)buffer, (int)len);
     86 			XFlush(dpy);
     87 		}
     88 	}
     89 
     90 	XCloseDisplay(dpy);
     91 	return 0;
     92 }