简体   繁体   English

X11 发送错误的按键

[英]X11 sending wrong key presses

I am making a simple xlib wrapper for recreation, but I am having a problem with X11 since I activated WSL: At the start of some programs, it starts sending a specific key press event and when I press something it stops.我正在为娱乐制作一个简单的 xlib 包装器,但自从我激活 WSL 后,我在使用 X11 时遇到问题:在某些程序开始时,它开始发送特定的按键事件,当我按下某些东西时它停止。

I tried looking at some documentation and even debug input files on /dev/, but seems that WSL don't have them, at least I didn't found.我试着查看一些文档,甚至在 /dev/ 上调试输入文件,但似乎 WSL 没有它们,至少我没有找到。

My window_init():我的 window_init():

    Display* display = XOpenDisplay(NULL);
    Window root = DefaultRootWindow(display);
    XSetWindowAttributes swa;
    swa.event_mask = ExposureMask | PointerMotionMask | KeyPressMask | KeyReleaseMask;
    Window window = XCreateWindow(display, root, 0, 0, w, h, 0, CopyFromParent, InputOutput, CopyFromParent, CWEv>
    XStoreName(display, window, name);
    XMapWindow(display, window);
    XFlush(display);

My window_update():我的窗口更新():

    XEvent event;
    while (XPending(display->display)) {
        char k;
        XNextEvent(display->display, &event);
        switch (event.type) {
            case KeyPress:
               k = XLookupKeysym(&event.xkey, 0)-XK_a;
               if(k >= 0 && k<= 26){
                  keys_down[k] = 1;
                  pressed[k] = 1;
               }
               break;
         }
    }

I still didn't handle the release events property, but at the start of the execution the program dispatches lots of keypresses events.我仍然没有处理释放事件属性,但在执行开始时程序会分派大量按键事件。

Here is a fully verified working example of the same:这是一个完全经过验证的工作示例:

// SPDX-License-Identifier: CC0-1.0
#include <stdlib.h>
#include <stdio.h>
#include <X11/Xlib.h>

int main(void)
{
    Display             *display;
    Window               root, window;
    XSetWindowAttributes attrs;
    XEvent               event;
    Atom                 close_window;

    display = XOpenDisplay(NULL);
    if (!display) {
        fprintf(stderr, "No display.\n");
        return EXIT_FAILURE;
    }

    root = DefaultRootWindow(display);

    attrs.event_mask = ExposureMask | PointerMotionMask | KeyPressMask | KeyReleaseMask;
    window = XCreateWindow(display, root,
                           100, 100, 320, 240,
                           0, CopyFromParent, InputOutput, CopyFromParent,
                           CWEventMask, &attrs);
    XStoreName(display, window, "Example Program");

    close_window = XInternAtom(display, "WM_DELETE_WINDOW", False);
    XSetWMProtocols(display, window, &close_window, 1);

    XMapWindow(display, window);
    XFlush(display);

    while (1) {
        XNextEvent(display, &event);
        if (event.type == ClientMessage && (Atom)(event.xclient.data.l[0]) == close_window)
            break;

        switch (event.type) {

        case MotionNotify:
            // It's just mouse motion events, so we won't mention those.
            break;

        case KeyPress:
            printf("KeyPress event: state = %u (", event.xkey.state);
            if (event.xkey.state & ShiftMask) printf(" Shift");
            if (event.xkey.state & LockMask) printf(" CapsLock");
            if (event.xkey.state & ControlMask) printf(" Control");
            if (event.xkey.state & Mod1Mask) printf(" Mod1");
            if (event.xkey.state & Mod2Mask) printf(" Mod2");
            if (event.xkey.state & Mod3Mask) printf(" Mod3");
            if (event.xkey.state & Mod4Mask) printf(" Mod4");
            if (event.xkey.state & Mod5Mask) printf(" Mod5");
            printf(" ), keycode = %u\n", event.xkey.keycode);
            break;

        case KeyRelease:
            printf("KeyRelease event: state = %u (", event.xkey.state);
            if (event.xkey.state & ShiftMask) printf(" Shift");
            if (event.xkey.state & LockMask) printf(" CapsLock");
            if (event.xkey.state & ControlMask) printf(" Control");
            if (event.xkey.state & Mod1Mask) printf(" Mod1");
            if (event.xkey.state & Mod2Mask) printf(" Mod2");
            if (event.xkey.state & Mod3Mask) printf(" Mod3");
            if (event.xkey.state & Mod4Mask) printf(" Mod4");
            if (event.xkey.state & Mod5Mask) printf(" Mod5");
            printf(" ), keycode = %u\n", event.xkey.keycode);
            break;

        case Expose:
            printf("Expose event: x=%d, y=%d, width=%d, height=%d, count=%d\n", event.xexpose.x, event.xexpose.y, event.xexpose.width, event.xexpose.height, event.xexpose.count);
            break;

        default:
            printf("Event type %d\n", event.type);
        }
        fflush(stdout);
    }

    XCloseDisplay(display);
    return EXIT_SUCCESS;
}

When compiling, link against the X11 library.编译时,链接到 X11 库。

Since Expose is not implemented, it is normal and expected for the contents of the window to be garbage (solid color, copy of existing window data, or anything else; it varies depending on X server and window manager).由于未实施 Expose,因此 window 的内容是垃圾是正常的和预期的(纯色,现有 window 数据的副本,或其他任何内容;它因 X 服务器和 window 管理器而异)。

If you run the program from the command line in Linux, and you keep Enter pressed, the first KeyPress event you get is the first autorepeat event.如果您从 Linux 中的命令行运行该程序,并按住 Enter,您获得的第一个 KeyPress 事件是第一个 autorepeat 事件。 You do sometimes get the KeyRelease event corresponding to the Enter key being released after the window has been mapped, but before any autorepeat events.在 window 被映射之后,但在任何自动重复事件之前,您有时会得到对应于释放 Enter 键的 KeyRelease 事件。 The first described event is usually the Expose event,第一个描述的事件通常是 Expose 事件,
Expose event: x=0, y=0, width=320, height=240, count=0
occasionally followed by the KeyRelease event corresponding to the Enter key,偶尔会跟回车键对应的KeyRelease事件,
KeyRelease event: state = 8192 ( ), keycode = 36
but one should ignore any KeyRelease events anyway that do not correspond to previous KeyPress event, so that shouldn't be an issue.但是无论如何都应该忽略与先前的 KeyPress 事件不对应的任何 KeyRelease 事件,因此这不应该成为问题。 (Shift is Shift , Lock is CapsLock (when on/enabled), Control is Ctrl , Mod1 is Alt , Mod5 AltGr , Mod4 (Windows key).) (Shift 是Shift ,Lock 是CapsLock (打开/启用时),Control 是Ctrl ,Mod1 是Alt ,Mod5 AltGr ,Mod4 (Windows 键)。)

The close_window atom is used to handle the window close button. close_window原子用于处理 window 关闭按钮。 When the button is pressed, the window manager will send a ClientMessage event containing the same atom.按下按钮时,window 管理器将发送包含相同原子的 ClientMessage 事件。

If you get any KeyPress events corresponding to keypresses that occurred prior to the start of the program, it is a bug in WSL that you need to report to Microsoft.如果您收到与程序启动前发生的按键相对应的任何 KeyPress 事件,则这是 WSL 中的错误,您需要向 Microsoft 报告。 (Only KeyRelease events corresponding to keys that are released after the program started, and autorepeat KeyPress events corresponding to keys that are being pressed down when the program starts and afterwards, are expected to occur.) (只有与程序启动后释放的键对应的 KeyRelease 事件,以及与程序启动时和之后按下的键对应的 autorepeat KeyPress 事件才会发生。)

(Personally, instead of WSL, I would recommend running a real Linux installation in a virtual machine in Windows, unless you explicitly intend your programs to be run under WSL instead of actual Linux installations. There just seem to be too many bugs in WSL, in my opinion; plus one can snapshot and start and stop the virtual machine as needed. Others disagree, of course.) (就个人而言,我建议在 Windows 中的虚拟机中运行真正的 Linux 安装,而不是 WSL,除非您明确希望程序在 WSL 下运行,而不是实际的 Linux 安装。WSL 中似乎有太多错误,在我看来;加上一个可以根据需要快照并启动和停止虚拟机。当然,其他人不同意。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM