globally capture, ignore and send keyevents with python xlib, recognize fake input(使用 python xlib 全局捕获、忽略和发送 keyevents,识别假输入)
问题描述
我想在普通键盘上实现键和弦,我想我使用 python xlib.为此,程序必须全局吞下所有关键事件,然后才允许它们通过.
i want to implement key chording on a normal keyboard and i thought i use python xlib. for this to work the program has to globally swallow all keyevents and only later allow them to go through.
我当前的测试只是抓住了1"键.如果按下此键,它会调用一个处理程序,该处理程序通过 xtest.fake_input 将x"发送到焦点窗口.因为我只抓住1"键,所以应该没有问题,对吧?但不知何故,处理程序再次被调用,因为x"被按下.事实上,当我输入1"时,程序正在监听 all 键.这可能与调用有关
my current test just grabs the "1" key. if this key is pressed it calls a handler which sends "x" to the focused window via xtest.fake_input. because im only grabbing the "1"-key, there shouldn't be a problem, right? but somehow the handler gets called again, because "x" was pressed. in fact, the moment i type "1" the program is listening to all keys. this could have something to do with calling
display.allow_events(X.ReplayKeyboard, X.CurrentTime)
在处理一个事件之后,但如果我不这样做,一切都会冻结.
after handling an event, but if i don't do this, everything freezes.
对于最终程序,收听行为的变化并不真正相关,但我必须能够将假事件与用户事件区分开来.要做到这一点,我只是快进 display.next_event(),但这并不理想,因为用户可能在那个确切的时刻打字,而那些击键会丢失.
for the final program the change in the listening behaviour is not really relevant, but i have to be able to distinguish the fake events from the user events. to do this i'm just fast forwarding display.next_event(), but this isnt ideal, because the user could be typing at that exact moment and than those keystrokes would be lost.
我尝试在通过发送和清空事件队列期间释放 keygrab
i tried releasing the keygrab during sending and emptying the eventqueue via
display.flush()
display.sync()
但这并没有任何作用.
那么,知道如何识别或忽略虚假输入事件以及为什么我会突然听到所有按键(和释放)吗?
so, any idea how to recognize or ignore fake input events and why i'm suddenly listening to all keypresses (and releases)?
xlib 非常令人沮丧.
xlib is very frustrating.
from Xlib.display import Display
import Xlib
from Xlib import X
import Xlib.XK
import sys
import signal
display = None
root = None
def handle_event(aEvent):
print "handle!"
send_key("x")
def send_key(emulated_key):
global display,root
print "send key"
# ungrabbing doesnt help
root.ungrab_key(10,X.AnyModifier)
window = display.get_input_focus()._data["focus"]
# Generate the correct keycode
keysym = Xlib.XK.string_to_keysym(emulated_key)
keycode = display.keysym_to_keycode(keysym)
# Send a fake keypress via xtestaaa
Xlib.ext.xtest.fake_input(window, Xlib.X.KeyPress, keycode)
Xlib.ext.xtest.fake_input(window, Xlib.X.KeyRelease, keycode)
display.flush()
display.sync()
# fast forward those two events,this seems a bit hacky,
# what if theres another keyevent coming in at that exact time?
while display.pending_events():
display.next_event()
#
root.grab_key(10, X.AnyModifier, True,X.GrabModeSync, X.GrabModeSync)
def main():
# current display
global display,root
display = Display()
root = display.screen().root
# we tell the X server we want to catch keyPress event
root.change_attributes(event_mask = X.KeyPressMask)
# just grab the "1"-key for now
root.grab_key(10, X.AnyModifier, True,X.GrabModeSync, X.GrabModeSync)
# while experimenting everything could freeze, so exit after 10 seconds
signal.signal(signal.SIGALRM, lambda a,b:sys.exit(1))
signal.alarm(10)
while 1:
event = display.next_event()
print "event"
#if i dont call this, the whole thing freezes
display.allow_events(X.ReplayKeyboard, X.CurrentTime)
handle_event(event)
if __name__ == '__main__':
main()
推荐答案
我发现了问题.我几乎可以肯定 xtest.fake_input 做了一些奇怪的事情,因为当我手动发送按键和释放时(使用一些代码我 找到),它可以工作
i found the problem. im almost certain that xtest.fake_input does something weird, because when i send keypresses and -releases manually (with some code i found), it works
这是一个例子,它只吞下按键时的1"键,并在按键释放时将x"发送到焦点窗口:
here is an example, that swallows only the "1"-key on keypress and sends "x" on keyrelease to the focused window:
from Xlib.display import Display
import Xlib
from Xlib import X
import Xlib.XK
import sys
import signal
import time
display = None
root = None
def handle_event(event):
print "handle!"
if (event.type == X.KeyRelease):
send_key("x")
# from http://shallowsky.com/software/crikey/pykey-0.1
def send_key(emulated_key):
shift_mask = 0 # or Xlib.X.ShiftMask
window = display.get_input_focus()._data["focus"]
keysym = Xlib.XK.string_to_keysym(emulated_key)
keycode = display.keysym_to_keycode(keysym)
event = Xlib.protocol.event.KeyPress(
time = int(time.time()),
root = root,
window = window,
same_screen = 0, child = Xlib.X.NONE,
root_x = 0, root_y = 0, event_x = 0, event_y = 0,
state = shift_mask,
detail = keycode
)
window.send_event(event, propagate = True)
event = Xlib.protocol.event.KeyRelease(
time = int(time.time()),
root = display.screen().root,
window = window,
same_screen = 0, child = Xlib.X.NONE,
root_x = 0, root_y = 0, event_x = 0, event_y = 0,
state = shift_mask,
detail = keycode
)
window.send_event(event, propagate = True)
def main():
# current display
global display,root
display = Display()
root = display.screen().root
# we tell the X server we want to catch keyPress event
root.change_attributes(event_mask = X.KeyPressMask|X.KeyReleaseMask)
# just grab the "1"-key for now
root.grab_key(10, 0, True,X.GrabModeSync, X.GrabModeSync)
signal.signal(signal.SIGALRM, lambda a,b:sys.exit(1))
signal.alarm(10)
while 1:
event = display.next_event()
print "event"
handle_event(event)
display.allow_events(X.AsyncKeyboard, X.CurrentTime)
if __name__ == '__main__':
main()
这篇关于使用 python xlib 全局捕获、忽略和发送 keyevents,识别假输入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:使用 python xlib 全局捕获、忽略和发送 keyevents,识别假输入
基础教程推荐
- numpy float:比算术运算中内置的慢 10 倍? 2022-01-01
- 尝试制作WhatsApp机器人 2022-01-01
- Discord.py 缺少必需的参数 2022-01-01
- 用 Python 编写 Fortran 无格式文件 2022-01-01
- pyserial - 可以从线程 a 写入串行端口,是否阻塞从线程 b 读取? 2022-01-01
- 与常规 dict 相比,Python manager.dict() 非常慢 2022-01-01
- 使用生成器和迭代器时 Python 多循环失败 2022-01-01
- 由Python将MP3转换为MIDI(类型错误:无法加载插件:mtg-Melodia:Melodia) 2022-01-01
- 将 x 轴刻度更改为自定义字符串 2022-01-01
- 在 Celery 工作人员中捕获 Heroku SIGTERM 以优雅地关 2022-01-01
