Since X is a server, I there a way to listen for X events via a socket instead of using XNextEvent
?
I have a program that monitors system events via epoll
with epoll_wait
called in a loop running in the main thread. Since I haven't been able to figure out how to listen for X events via a file descriptor, I had to resort to running a dedicated loop for XNextEvent
in a separate thread and putting mutexes around calls to the functions that are called when events occur.
Here's the function I wrote for polling the X events, if anyone is curious. I'm only listening for events related to keyboard layout switching, at the moment.
void* xevent_loop(void*) {
int xkbEventType;
XkbQueryExtension(dpy, 0, &xkbEventType, 0, 0, 0);
XkbSelectEventDetails(dpy,
XkbUseCoreKbd, XkbStateNotify, XkbAllStateComponentsMask,
XkbGroupStateMask);
XSync(dpy, False);
for (XEvent e;;) {
XNextEvent(dpy, &e);
if (e.type == xkbEventType) {
XkbEvent* xkbe = (XkbEvent*) &e;
if (xkbe->any.xkb_type == XkbStateNotify) {
pthread_mutex_lock(&setroot_mutex);
fmt_kbd_layout(xkbe->state.group);
setroot();
pthread_mutex_unlock(&setroot_mutex);
}
}
}
return NULL;
}
You can get the connection's file descriptor by using the macro ConnectionNumber(dpy)
on the display. See man ConnectionNumber
:
The ConnectionNumber macro returns a connection number for the specified display.
This can be used in select()
and poll()
to check for an event being ready.
The definition is in /usr/include/X11/Xlib.h
.