I love dmenu, and just for the hell of it wanted a similar program, that
didn't display anything.  So I wrote grab (more like copied the code I
needed from dmenu).  It grabs all key presses until the user hits enter
or escape, and then prints out whatever was typed.  It's not foolproof,
it's not very well tested, but it works for me.  I run it from dwm the
same way as dmenu.  Have fun and do what you will with it.

-Evan

P.S. compile with gcc -lX11
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <X11/keysym.h>
#include <X11/Xutil.h>

int
main(int argc, char *argv[]) {
	XEvent ev;
	Window root;
	Display *dpy;
	int screen, len, running;
	char text[512];

	if (!(dpy = XOpenDisplay(0))) {
		fprintf(stderr, "grab: cannot open display\n");
		exit(EXIT_FAILURE);
	}

	screen = DefaultScreen(dpy);
	root = RootWindow(dpy, screen);

	for (len = 1000; len; len--) {
		if(XGrabKeyboard(dpy, root, True, GrabModeAsync, GrabModeAsync, CurrentTime) == GrabSuccess)
			break;
		usleep(1000);
	}

	if (!len) {
	    fprintf(stderr, "grab: cannot grab keyboard\n");
	    exit(EXIT_FAILURE);
	}

	XSync(dpy, False);
	
	text[0] = 0;
	while (running && !XNextEvent(dpy, &ev)) {
		if (ev.type == KeyPress) {
			KeySym ksym;
			char buf[32];

			len = strlen(text);
			XLookupString(&ev.xkey, buf, sizeof(buf), &ksym, 0);
			switch (ksym) {
				case XK_Return:
					printf("%s\n", text);
				case XK_Escape:
					running = 0;
					break;
				case XK_BackSpace:
					if (len)
					    text[--len] = 0;
					break;
				default:
					strncat(text, buf, sizeof(text));
			}
		}
	}

	XUngrabKeyboard(dpy, CurrentTime);
	XCloseDisplay(dpy);
	return 0;
}

Reply via email to