Skip to content
Create a gist now

Instantly share code, notes, and snippets.

Embed URL


Subversion checkout URL

You can clone with
Download ZIP
Watch-xi2 looks for X Window System events that occur when input device hierarchy changes in any way (e.g. when a keyboard or a mouse is connected or disconnected). It may take a single parameter: a shell command to run on the hierarchy change events.
/* (c) Copyright 2010 Anton Kovalenko <>.
LICENSE:Do what you want with this software, but don't blame me.
Compile it with gcc -lX11 -lXi.
#define WATCH_XI2_TIMESTAMP "Time-stamp: <2010-08-14 19:39:55 anton>"
#include <X11/Xlib.h>
#include <X11/extensions/XInput2.h>
#include <X11/Xutil.h>
#include <stdio.h>
#include <stdlib.h>
#define EPIC_FAILF(format,...) \
do { \
fprintf(stderr,format "\n",__VA_ARGS__); \
exit(1); \
} while (0)
#define EPIC_FAIL(string) EPIC_FAILF("%s",string)
void usage()
EPIC_FAIL("\nwatch-xi2 [" WATCH_XI2_TIMESTAMP "]\n\n"
"Watch-xi2 looks for X Window System events that occur when \n"
"input device hierarchy changes in any way (e.g. when keyboard or\n"
"mouse is connected or disconnected).\n\n"
"It may take a single parameter: a shell command to run on the hierarchy\n"
"change events:\n\n"
" watch-xi2 'xmodmap .my-xmodmap'\n\n"
"If no parameter is given, watch-xi2 just prints a line to stdout\n"
"instead of running anything.");
int main(int argc, char *argv[])
Display *dpy;
int major=2, minor=0, xi_opcode, event, error;
XIEventMask interesting;
Window root;
if (argc != 1 && argc != 2 ||
argc == 2 && argv[1][0]=='-')
dpy = XOpenDisplay(NULL);
if (!dpy)
EPIC_FAIL("Can't open display");
if (!XQueryExtension(dpy, "XInputExtension", &xi_opcode, &event, &error))
EPIC_FAIL("X Input extension not available.");
if (XIQueryVersion(dpy,&major,&minor)!=Success)
EPIC_FAIL("XInput2 not supperted");
root = DefaultRootWindow(dpy);
interesting.deviceid = XIAllDevices;
interesting.mask_len = XIMaskLen(XI_HierarchyChanged);
interesting.mask = calloc(interesting.mask_len, sizeof(char));
if (!interesting.mask)
EPIC_FAIL("Out of memory");
XISetMask(interesting.mask, XI_HierarchyChanged);
while (1) {
XEvent xevent;
XGenericEventCookie *cookie = (XGenericEventCookie*)&xevent.xcookie;
if (XGetEventData(dpy,cookie) &&
(cookie->type == GenericEvent) &&
(cookie->extension == xi_opcode)) {
if (argc<2) {
puts("Something happened: please do something useful."); }
else {
printf("Running shell command %s...\n",argv[1]);
system(argv[1]); }
/* Local Variables: */
/* compile-command: "make LDFLAGS='-lX11 -lXi' CFLAGS='-O2' watch-xi2" */
/* End: */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.