#include <stdlib.h> #include <stdio.h> #include <X11/extensions/XInput2.h> #include <X11/extensions/Xfixes.h> static Display *dpy; static int buttons_held = 0; // Tracks number of buttons currently held XIEventMask evmasks; /* Return 1 if XI2 is available, 0 otherwise */ static int has_xi2(Display *dpy){ int major = 2, minor = 2; int rc = XIQueryVersion(dpy, &major, &minor); if (rc == BadRequest) { printf("No XI2 support. Server supports version %d.%d only.\n", major, minor); return 0; } else if (rc != Success) { fprintf(stderr, "Internal Error! This is a bug in Xlib.\n"); } printf("XI2 supported. Server provides version %d.%d.\n", major, minor); return 1; } static void select_events(Display *dpy, Window win){ evmasks.deviceid = XIAllDevices; evmasks.mask_len = XIMaskLen(XI_LASTEVENT); evmasks.mask = (unsigned char*)calloc(evmasks.mask_len, sizeof(char)); XISetMask(evmasks.mask, XI_RawButtonPress); XISetMask(evmasks.mask, XI_RawButtonRelease); XISelectEvents(dpy, win, &evmasks, 1); XFlush(dpy); } int main(int argc, char **argv){ int xi_opcode, event, error; XEvent ev; dpy = XOpenDisplay(NULL); if (!dpy) { fprintf(stderr, "Failed to open display.\n"); return -1; } if (!XQueryExtension(dpy, "XInputExtension", &xi_opcode, &event, &error)) { printf("X Input extension not available.\n"); return -1; } if (!has_xi2(dpy)) return -1; /* Select for XI2 events */ select_events(dpy, DefaultRootWindow(dpy)); while (1) { XGenericEventCookie *cookie = &ev.xcookie; XNextEvent(dpy, &ev); if (cookie->type != GenericEvent || cookie->extension != xi_opcode || !XGetEventData(dpy, cookie)) continue; XIDeviceEvent *xie = (XIDeviceEvent *)cookie->data; switch (cookie->evtype) { case XI_RawButtonPress: if (xie->detail >= 4 && xie->detail <= 7) break; // Ignore scroll if (buttons_held == 0) { XFixesHideCursor(dpy, DefaultRootWindow(dpy)); } buttons_held++; break; case XI_RawButtonRelease: if (xie->detail >= 4 && xie->detail <= 7) break; // Ignore scroll if (buttons_held > 0) { buttons_held--; } if (buttons_held == 0) { XFixesShowCursor(dpy, DefaultRootWindow(dpy)); } break; } XFreeEventData(dpy, cookie); } return 0; }