我正在编写一个纯 Xlib 应用程序,并希望使用 XInput2 扩展来处理 RawMotion 事件。当我使用高于
XISelectEvents
的任何 XI2 事件设置掩码时,如果我使用 XI_PropertyEvent
,就会出现问题。因此,例如,如果我使用 XISetMask(mask, XI_Motion);
,它会正常工作,与 XISetMask(mask, XI_RawMotion);
不同。此外,无论传递的 deviceid 以及设置为掩码的其他事件类型如何,都会出现错误。为什么会发生这种事?
代码示例:
#include <X11/Xlib.h>
#include <X11/extensions/XInput2.h>
int main() {
Display* display = XOpenDisplay(nullptr);
int screen_num = DefaultScreen(display);
Window window = XCreateSimpleWindow(
display,
RootWindow(display, screen_num),
0, 0,
640, 480,
4,
16711680,
WhitePixel(display, screen_num)
);
XSelectInput(display, window, KeyPressMask);
int major_opcode, first_event, first_error;
XQueryExtension(display, "XInputExtension", &major_opcode, &first_event, &first_error);
unsigned char mask[XIMaskLen(XI_LASTEVENT)] = {0, };
XISetMask(mask, XI_RawMotion);
XIEventMask event_mask;
event_mask.deviceid = XIAllDevices;
event_mask.mask_len = sizeof(mask);
event_mask.mask = mask;
XISelectEvents(display, window, &event_mask, 1);
XMapWindow(display, window);
XFlush(display);
while (true) {
XEvent ev;
XNextEvent(display, &ev);
if (ev.type == KeyPress && ev.xkey.keycode == 9) {
break;
}
}
XUnmapWindow(display, window);
XFlush(display);
XDestroyWindow(display, window);
XCloseDisplay(display);
return 0;
}
错误:
X Error of failed request: BadValue (integer parameter out of range for operation)
Major opcode of failed request: 131 (XInputExtension)
Minor opcode of failed request: 46 ()
Value in failed request: 0xd
Serial number of failed request: 16
Current serial number in output stream: 17
问题是 XInput2 使用原始事件调用
XISelectEvents
仅当根窗口通过时才有效。所以解决方案是使用 XISelectEvents(display, DefaultRootWindow(display), &event_mask, 1);