如何在 X11 中捕获另一个按键事件后发送按键
How to send a key press after capturing another key event in X11
我正在尝试在 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()
今天我在谷歌上搜索了很多,找到了 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()
我正在尝试在 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()
今天我在谷歌上搜索了很多,找到了 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()