C语言 X11发送错误按键

yr9zkbsy  于 2022-12-29  发布在  其他
关注(0)|答案(1)|浏览(155)

我正在制作一个简单的xlib Package 器以供娱乐,但是自从激活WSL以来,我遇到了X11的问题:在一些程序开始时,它开始发送特定的按键事件,当我按下某个东西时它就停止了。
我试着查看一些文档,甚至调试/dev/上的输入文件,但似乎WSL没有,至少我没有找到。
我的窗口初始化():

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);

我的窗口更新()(_U):

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;
         }
    }

我仍然没有处理release events属性,但是在执行开始时,程序会调度大量的按键事件。

pw9qyyiw

pw9qyyiw1#

以下是经过充分验证的相同工作示例:

// 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;
}

编译时,链接到X11库。
因为Expose没有实现,所以窗口的内容是垃圾(纯色、现有窗口数据的副本或任何其他内容;取决于X服务器和窗口管理器)。
如果您在Linux中从命令行运行程序,并且一直按下Enter键,那么您得到的第一个KeyPress事件就是第一个自动重复事件。您有时会得到KeyRelease事件,该事件对应于在Map窗口之后但在任何自动重复事件之前释放的Enter键。第一个描述的事件通常是Expose事件,
第一个月
偶尔跟随对应于Enter键的KeyRelease事件,
KeyRelease event: state = 8192 ( ), keycode = 36
但无论如何,应该忽略任何不对应于之前的KeyPress事件的KeyRelease事件,所以这不应该是一个问题。(Shift是Shift,Lock是CapsLock(当打开/启用时),Control是Ctrl,Mod 1是Alt,Mod 5 AltGr,Mod 4(Windows键)。
close_window原子用于处理窗口关闭按钮,当按钮被按下时,窗口管理器将发送包含相同原子的ClientMessage事件。
如果您收到任何与程序启动前发生的按键相对应的KeyPress事件,则这是WSL中的一个错误,您需要向Microsoft报告。(预计只会发生与程序启动后释放的键相对应的KeyRelease事件,以及与程序启动时和之后按下的键相对应的自动重复KeyPress事件。)
(就个人而言,我建议在Windows的虚拟机中运行真实的的Linux安装,而不是WSL,除非你明确地打算在WSL下运行程序,而不是在实际的Linux安装下运行。加上一个可以根据需要快照和启动和停止虚拟机。当然,其他人不同意。)

相关问题