XISelectEvent throws X Error: BadValue (integer out of range for operation)
XISelectEvent throws X Error: BadValue (integer out of range for operation)
我正在尝试从 X11 读取事件,这是我的最小重现:
#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;
}
代码使用g++ test.cpp -lX11 -ldl -lXi
编译
它抛出以下错误:
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
我无法理解并对此做出反应,我们将不胜感激任何帮助。
我试过调试,发现错误正是在执行XISelectEvent
时发生的。
我现在傻了,我忘了用new
关键字在堆中分配的数组里面有垃圾
我不得不使用
memset(xiMask->mask, 0, xiMask->mask_len);
将数组中的所有值设置为0,然后根据需要开始设置每个元素的值。
更新:
我们可以使用 C++ 鲜为人知的特性,在单个表达式中使用 new T()
直接将最近分配的数组填充为 0。
这也是:
xiMask->mask = new unsigned char[xiMask->mask_len]();
我正在尝试从 X11 读取事件,这是我的最小重现:
#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;
}
代码使用g++ test.cpp -lX11 -ldl -lXi
它抛出以下错误:
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
我无法理解并对此做出反应,我们将不胜感激任何帮助。
我试过调试,发现错误正是在执行XISelectEvent
时发生的。
我现在傻了,我忘了用new
关键字在堆中分配的数组里面有垃圾
我不得不使用
memset(xiMask->mask, 0, xiMask->mask_len);
将数组中的所有值设置为0,然后根据需要开始设置每个元素的值。
更新:
我们可以使用 C++ 鲜为人知的特性,在单个表达式中使用 new T()
直接将最近分配的数组填充为 0。
这也是:
xiMask->mask = new unsigned char[xiMask->mask_len]();