【问题标题】:How to send a key press after capturing another key event in X11如何在X11中捕获另一个按键事件后发送按键
【发布时间】:2020-06-26 06:21:27
【问题描述】:

我正在尝试在 Linux 中实现一个 Python 脚本来捕获按键 a 再次发送按键 a(因此它发送 a 两次)。

通过https://github.com/PeterHo/Linalfred/blob/master/src/globalhotkey.py 的一些代码,我得到了以下信息。

按键被很好地捕获,但发送按键事件没有任何作用。我在这里错过了什么?

我也看了globally capture, ignore and send keyevents with python xlib, recognize fake input这个问题。发布的解决方案甚至似乎都没有收到事件(在将print 移植到 Python 3 之后)。

import time

from Xlib import X, protocol
from Xlib.display import Display
from Xlib.ext import record

display = None
root = None

def handler(reply):
    data = reply.data
    while len(data):
        event, data = protocol.rq.EventField(None).parse_binary_value(data, display.display, None, None)
        if event.type == X.KeyPress:
            keycode = event.detail
            print(keycode)
            if keycode == 38:
                window = Display().get_input_focus().focus
                event = protocol.event.KeyPress(
                    time=int(time.time()),
                    root=root,
                    window=window,
                    same_screen=0, child=X.NONE,
                    root_x=0, root_y=0, event_x=0, event_y=0,
                    state=0,
                    detail=keycode
                )
                window.send_event(event, propagate=True)
                event = protocol.event.KeyRelease(
                    time=int(time.time()),
                    root=root,
                    window=window,
                    same_screen=0, child=X.NONE,
                    root_x=0, root_y=0, event_x=0, event_y=0,
                    state=0,
                    detail=keycode
                )
                window.send_event(event, propagate=True)


def main():
    global display, root
    display = Display()
    root = display.screen().root

    ctx = display.record_create_context(
        0,
        [record.AllClients],
        [{
            'core_requests': (0, 0),
            'core_replies': (0, 0),
            'ext_requests': (0, 0, 0, 0),
            'ext_replies': (0, 0, 0, 0),
            'delivered_events': (0, 0),
            'device_events': (X.KeyReleaseMask, X.ButtonReleaseMask),
            'errors': (0, 0),
            'client_started': False,
            'client_died': False,
        }]
    )
    display.record_enable_context(ctx, handler)
    display.record_free_context(ctx)

    while True:
        # Infinite wait, doesn't do anything as no events are grabbed.
        event = root.display.next_event()


if __name__ == '__main__':
    main()

【问题讨论】:

    标签: python input keyboard x11 xlib


    【解决方案1】:

    我今天用谷歌搜索了很多,发现Sending key presses to specific windows in X,它对我有用。

    关键思想是使用display 而不是window 发送事件,并使用sync 显示。如果不同步显示,则根本不会注册按键。

    disp.send_event(window, event, propagate=True)
    disp.sync()
    

    将其应用于我们上面的脚本,我们有以下工作版本:

    import time
    
    from Xlib import X, protocol
    from Xlib.display import Display
    from Xlib.ext import record
    
    display = None
    root = None
    
    def handler(reply):
        data = reply.data
        while len(data):
            event, data = protocol.rq.EventField(None).parse_binary_value(data, display.display, None, None)
            if event.type == X.KeyPress:
                keycode = event.detail
                print(keycode)
                if keycode == 38:
                    disp = Display()
                    window = disp.get_input_focus().focus
                    root = disp.screen().root
                    event = protocol.event.KeyPress(
                        time=0,
                        root=root, window=window, same_screen=0, child=X.NONE,
                        root_x=0, root_y=0, event_x=0, event_y=0,
                        state=0, detail=keycode
                    )
                    disp.send_event(window, event, propagate=True)
                    disp.sync()
                    event = protocol.event.KeyRelease(
                        time=0,
                        root=root, window=window, same_screen=0, child=X.NONE,
                        root_x=0, root_y=0, event_x=0, event_y=0,
                        state=0, detail=keycode
                    )
                    disp.send_event(window, event, propagate=True)
                    disp.sync()
    
    
    def main():
        global display, root
        display = Display()
        root = display.screen().root
    
        ctx = display.record_create_context(
            0,
            [record.AllClients],
            [{
                'core_requests': (0, 0),
                'core_replies': (0, 0),
                'ext_requests': (0, 0, 0, 0),
                'ext_replies': (0, 0, 0, 0),
                'delivered_events': (0, 0),
                'device_events': (X.KeyReleaseMask, X.ButtonReleaseMask),
                'errors': (0, 0),
                'client_started': False,
                'client_died': False,
            }]
        )
        display.record_enable_context(ctx, handler)
        display.record_free_context(ctx)
    
        while True:
            # Infinite wait, doesn't do anything as no events are grabbed.
            event = root.display.next_event()
    
    
    if __name__ == '__main__':
        main()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-20
      • 2011-09-19
      • 1970-01-01
      相关资源
      最近更新 更多