使用 Xinput2 获取双 RawKeyPress 事件
Getting double RawKeyPress events using Xinput2
所以昨天,我检查了 the xinput source code 以模仿那里正在做的事情,这样我就可以为我正在制作的项目制作击键侦听器。
在检查了源代码之后,尤其是 test_xi2.c
,我想到了这个。
#include <iostream>
#include <X11/Xlib.h>
#include <X11/extensions/XInput2.h>
#include <X11/Xutil.h>
#include <stdio.h>
#include <stdlib.h>
int main() {
Display* display = XOpenDisplay(NULL);
Window win;
win = DefaultRootWindow(display);
XIEventMask* m = new XIEventMask;
m->deviceid = XIAllDevices;
m->mask_len = XIMaskLen(XI_LASTEVENT);
m->mask = (unsigned char*)calloc(m->mask_len, sizeof(char));
XISetMask(m->mask, XI_RawKeyPress);
XISetMask(m->mask, XI_RawKeyRelease);
XISelectEvents(display, win, m, 1);
XSync(display, False);
while(true)
{
XEvent ev;
XGenericEventCookie *cookie = (XGenericEventCookie*)&ev.xcookie;
XNextEvent(display, (XEvent*)&ev);
if (XGetEventData(display, cookie) && cookie->type == GenericEvent) {
switch (cookie->evtype) {
case XI_RawKeyPress: std::cout << "keystroke" << std::endl; break;
}
}
XFreeEventData(display, cookie);
}
XDestroyWindow(display, win);
return 0;
}
您可以通过 g++ main.cpp -lX11 -lXi
.
来编译它
因此,如果您将它与原始来源进行比较,您会看到我唯一没有做的事情,除了监听目前对我无用的所有其他事件类型之外,就是检查是否 cookie->extension == xi_opcode
(line 431 of test_xi2.c
). After researching a bit, I came to the conclusion that it isn't really necessary to check whether this condition is met. xi_opcode
turns out to be an extension opcode, that is queried using XQueryExtension
here。我检查了我的机器,扩展名似乎总是 131,所以它不像一半的 RawKeyPress 事件有一个扩展名,另一半有另一个扩展名。
我真的不知道还能发生什么。
似乎 XIAllDevices
也捕获虚拟 "extra" 设备,在这种情况下包括第二个键盘,这意味着您将获得所有键盘事件 2 次。
尝试使用 XIAllMasterDevices
将所有这些合并为一个 "keyboard"。
所以昨天,我检查了 the xinput source code 以模仿那里正在做的事情,这样我就可以为我正在制作的项目制作击键侦听器。
在检查了源代码之后,尤其是 test_xi2.c
,我想到了这个。
#include <iostream>
#include <X11/Xlib.h>
#include <X11/extensions/XInput2.h>
#include <X11/Xutil.h>
#include <stdio.h>
#include <stdlib.h>
int main() {
Display* display = XOpenDisplay(NULL);
Window win;
win = DefaultRootWindow(display);
XIEventMask* m = new XIEventMask;
m->deviceid = XIAllDevices;
m->mask_len = XIMaskLen(XI_LASTEVENT);
m->mask = (unsigned char*)calloc(m->mask_len, sizeof(char));
XISetMask(m->mask, XI_RawKeyPress);
XISetMask(m->mask, XI_RawKeyRelease);
XISelectEvents(display, win, m, 1);
XSync(display, False);
while(true)
{
XEvent ev;
XGenericEventCookie *cookie = (XGenericEventCookie*)&ev.xcookie;
XNextEvent(display, (XEvent*)&ev);
if (XGetEventData(display, cookie) && cookie->type == GenericEvent) {
switch (cookie->evtype) {
case XI_RawKeyPress: std::cout << "keystroke" << std::endl; break;
}
}
XFreeEventData(display, cookie);
}
XDestroyWindow(display, win);
return 0;
}
您可以通过 g++ main.cpp -lX11 -lXi
.
因此,如果您将它与原始来源进行比较,您会看到我唯一没有做的事情,除了监听目前对我无用的所有其他事件类型之外,就是检查是否 cookie->extension == xi_opcode
(line 431 of test_xi2.c
). After researching a bit, I came to the conclusion that it isn't really necessary to check whether this condition is met. xi_opcode
turns out to be an extension opcode, that is queried using XQueryExtension
here。我检查了我的机器,扩展名似乎总是 131,所以它不像一半的 RawKeyPress 事件有一个扩展名,另一半有另一个扩展名。
我真的不知道还能发生什么。
似乎 XIAllDevices
也捕获虚拟 "extra" 设备,在这种情况下包括第二个键盘,这意味着您将获得所有键盘事件 2 次。
尝试使用 XIAllMasterDevices
将所有这些合并为一个 "keyboard"。