使用 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"。