I'm trying to read events from X11, here's my minimal repro:
#include <X11/Xlib.h>
#include <X11/extensions/XInput2.h>
#include <dlfcn.h>
#include <stdlib.h>
#include <iostream>
#include <string.h>
int main() {
if (getenv("DISPLAY") == NULL) return 1;
void *x11 = dlopen("libX11.so.6", RTLD_GLOBAL | RTLD_LAZY);
if (x11 == NULL) return 1;
void *xInput2 = dlopen("libXi.so.6", RTLD_GLOBAL | RTLD_LAZY);
if (xInput2 == NULL) return 1;
// Check XInput2 functions are present, since libXi may contain XInput or XInput2.
void *f = dlsym(xInput2, "XISelectEvents");
if (f == NULL) return 1;
// Load definitions
dlsym(x11, "XOpenDisplay");
dlsym(x11, "XDefaultRootWindow");
dlsym(x11, "XQueryExtension");
dlsym(x11, "XSync");
dlsym(x11, "XNextEvent");
dlsym(x11, "XSendEvent");
dlsym(x11, "XFreeEventData");
dlsym(x11, "XGetEventData");
dlsym(xInput2, "XISelectEvents");
Display *display = XOpenDisplay(NULL);
if (display == NULL) return 1;
int xiOpcode;
int queryEvent;
int queryError;
XQueryExtension(display, "XInputExtension", &xiOpcode, &queryEvent, &queryError);
Window root = XDefaultRootWindow(display);
XIEventMask *xiMask = new XIEventMask;
xiMask->deviceid = XIAllMasterDevices;
xiMask->mask_len = XIMaskLen(XI_LASTEVENT);
xiMask->mask = new unsigned char[xiMask->mask_len];
XISetMask(xiMask->mask, XI_RawKeyPress);
XISetMask(xiMask->mask, XI_RawKeyRelease);
XISelectEvents(display, root, xiMask, 1);
XSync(display, 0);
delete [] xiMask->mask;
}
The code is compiled using g++ test.cpp -lX11 -ldl -lXi
It throws the following error:
X Error of failed request: BadValue (integer parameter out of range for operation)
Major opcode of failed request: 132 (XInputExtension)
Minor opcode of failed request: 46 ()
Value in failed request: 0xb
Serial number of failed request: 14
Current serial number in output stream: 15
I'm unable to understand and react to it, any help will be highly appreciated.
I tried debugging and found that error is exactly occured when XISelectEvent is executed.
I feel dumb now, I forgot that the array allocated in the heap using the
newkeyword has garbage in it.I had to use the
to set all the values in the array to 0, then start setting the value of each element as needed.
Update:
We can just use less-known feature of C++ to directly fill the recently allocated array to 0s using
new T()in the single expression.So does this: