問題描述
我想在普通鍵盤上實現(xiàn)鍵和弦,我想我使用 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"鍵.如果按下此鍵,它會調(diào)用一個處理程序,該處理程序通過 xtest.fake_input 將x"發(fā)送到焦點窗口.因為我只抓住1"鍵,所以應該沒有問題,對吧?但不知何故,處理程序再次被調(diào)用,因為x"被按下.事實上,當我輸入1"時,程序正在監(jiān)聽 all 鍵.這可能與調(diào)用有關
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)
在處理一個事件之后,但如果我不這樣做,一切都會凍結(jié).
after handling an event, but if i don't do this, everything freezes.
對于最終程序,收聽行為的變化并不真正相關,但我必須能夠?qū)⒓偈录c用戶事件區(qū)分開來.要做到這一點,我只是快進 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.
我嘗試在通過發(fā)送和清空事件隊列期間釋放 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()
推薦答案
我發(fā)現(xiàn)了問題.我?guī)缀蹩梢钥隙?xtest.fake_input 做了一些奇怪的事情,因為當我手動發(fā)送按鍵和釋放時(使用一些代碼我 找到),它可以工作
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"發(fā)送到焦點窗口:
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 全局捕獲、忽略和發(fā)送 keyevents,識別假輸入的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網(wǎng)!