python xlib xgrabkey keyrelease 事件未触发

标签 python input xlib

我想用 python xlib 捕获 keydown 和 keyup 事件,但是当同时按下某些键时,keyup 事件会消失。

如果同时释放 2 个或更多键,则将有 2 个或更多按键事件,但只有 1 个按键释放事件。

为此,甚至不必同时释放键,例如,如果您快速输入此序列:

  • 按 A
  • 按 B
  • 版本 A
  • 版本 B

  • 将只为 A 产生 1 个 key 释放
  • 按 A
  • 按 B
  • 版本 B
  • 版本 A

  • 将产生 2 个 keyreleases

    from Xlib import X,XK
    from Xlib.display import Display
    import signal,sys
    
    root = None
    display = None
    
    def grab_keyname(n):
        global root
        keysym = XK.string_to_keysym(n)
        keycode = display.keysym_to_keycode(keysym)
        root.grab_key(keycode, X.AnyModifier, False,X.GrabModeSync, X.GrabModeAsync)
    
    def main():
        # current display
        global display,root
        display = Display()
        root = display.screen().root
    
    
        root.change_attributes(event_mask = X.KeyPressMask|X.KeyReleaseMask)
    
        grab_keyname("j")
        grab_keyname("k")
        grab_keyname("l")
    
        signal.signal(signal.SIGALRM, lambda a,b:sys.exit(1))
        signal.alarm(4)
    
        while True:
            event = display.next_event()
            print event.type
    
    main()
    

    最佳答案

    尽管这个问题已有 7 年历史,但对于任何遇到此问题的人来说,这是一个解决方案:
    这是 Xorg 中的一个“错误”(显然是故意的),它导致键盘抓取在按键释放时停止,并且仅在再次按下按钮时重新开始。因此,介于(-> 第二个按键释放事件)之间的任何事件都将丢失。见 https://bugs.freedesktop.org/show_bug.cgi?id=99280
    那里提出的解决方案是有一个计数器来指示仍有多少键被按下,如果仍有未决按下,则手动抓取键盘。此外,键盘需要在最后一次释放事件后松开。
    实现可能如下所示:

    keys_pressed = 0
    # ...
    event = display.next_event()
    if event.type == X.KeyPress:
        keys_pressed += 1
    elif event.type == X.KeyRelease:
        if keys_pressed != 0:
            keys_pressed -= 1
            if keys_pressed == 0:
                display.flush()
                display.ungrab_keyboard(X.CurrentTime)
            else:
                root.grab_keyboard(False, X.GrabModeAsync, X.GrabModeAsync, X.CurrentTime)
    
    请注意检查 keys_pressed != 0在发布分支中:这是因为在松开键盘后,捕获了一个额外的发布事件(可能有一种方法可以防止这种情况发生,但对我的用例来说无关紧要......)

    关于python xlib xgrabkey keyrelease 事件未触发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18160792/

    相关文章:

    python - 在 Python 中从剪贴板静默获取密码

    javascript - 如何对输入标签中的两个数字求和?

    c - 按住另一个按钮时,XGrabButton 不会捕获点击

    c - GIMP 中 Header Pixel 的说明创建了 XPM 图像的 C 头文件

    c# - 从用户处获取输入以填充 C# 中的列表

    linux - 如何解释 XImage 的字段 'data'

    获取 t 统计量的 Python 函数

    python - Pandas 构建在 Django AWS Elastic Beanstalk 部署上失败

    python - fft 和数组到图像/图像到数组的转换

    c - 如何将用户输入与数组进行比较,检查它是否小于最后一个输入