我想在普通键盘上实现按键编码,并考虑使用Python xlib。为了使其正常工作,程序必须全局捕获所有按键事件,并稍后才允许它们通过。
我的当前测试仅抓取“1”键。如果按下此键,则调用处理程序,通过xtest.fake_input将“x”发送到焦点窗口。因为只有“1”键被抓取,所以不应该有问题,对吗? 但是,由于按下了“x”,处理程序再次被调用。实际上,从我键入“1”的那一刻起,程序就侦听所有键。 这可能与调用有关。
我的当前测试仅抓取“1”键。如果按下此键,则调用处理程序,通过xtest.fake_input将“x”发送到焦点窗口。因为只有“1”键被抓取,所以不应该有问题,对吗? 但是,由于按下了“x”,处理程序再次被调用。实际上,从我键入“1”的那一刻起,程序就侦听所有键。 这可能与调用有关。
display.allow_events(X.ReplayKeyboard, X.CurrentTime)
在处理完事件后,如果我不这样做,一切都会冻结。
对于最终程序,监听行为的变化并不是很重要,但我必须能够区分伪造事件和用户事件。为了做到这一点,我只是快进display.next_event(),但这并不理想,因为用户可能正在输入,那么那些按键就会丢失。
我试过在发送期间释放keygrab并通过以下方式清空eventqueue
display.flush()
display.sync()
但那并没有做任何事情。
那么,有什么办法可以识别或忽略虚假的输入事件,为什么我突然听到了所有按键(和释放)?
Xlib非常令人沮丧。
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()
time=int(time.time())
替换为time = X.CurrentTime
,问题得到了解决。 - Gilles Castel