2013-08-04 12 views
5

私は通常のキーボードでキーコードを実装したいと思っています。 これがプログラムを動作させるには、すべてのキーイベントをグローバルに呑み込んで、後でそれらを通過させなければなりません。python xlibでkeyeventsをグローバルにキャプチャ、無視、送信し、偽の入力を認識

私の現在のテストは "1"キーをつかんでいます。このキーを押すと、xtest.fake_inputを介してフォーカスされたウィンドウに「x」を送信するハンドラが呼び出されます。私は "1"キーをつかむだけなので、問題はないはずですよね? "x"が押されたため、何とかハンドラが再び呼び出されます。実際には、私が入力する "1"の瞬間に、プログラムはすべての鍵を聴いています。 がこのイベントを処理した後

display.allow_events(X.ReplayKeyboard, X.CurrentTime) 

を呼び出すこととは何かを持っている可能性がありますが、私はこれをしない場合、すべてがフリーズします。

最後のプログラムでは、リスニング動作の変更は実際には関係ありませんが、私はユーザーイベントから偽のイベントを区別することができなければなりません。これを行うには、私はdisplay.next_event()を素早く転送していますが、ユーザが正確な時刻に入力している可能性があり、それらのキーストロークが失われる可能性があるため、これは理想的ではありません。

私は

display.flush() 
display.sync() 

経由のEventQueueを送信し、空の間にkeygrabを解放しようとしたが、それは何もしません。

だから、どのように偽の入力イベントを認識したり無視したりするのか、なぜ私は突然すべてのキー押し(そしてリリース)を聞いているのですか?

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() 

答えて

4

問題が見つかりました。 xtest.fake_input iがキー入力を送信するときので、奇妙な何かをして、(いくつかのコードI foundで)手動-releasesことはほぼ確実イムは、それがここに

は、キー入力にのみ「1」-keyツバメたとえば、ある作品

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() 
+0

これは、しばらくしてから、またはキーの繰り返しで他のキーをマッシュした後、黙ってクラッシュするように見えます。別のユーザーもこれを報告しましたが、彼のコメントは回答として投稿されたため削除されました。 – ninjagecko

+0

@ ninjagecko私は同じ問題があります。私もどのキーの組み合わせを把握していない。しかし、20分後、1分半後には失敗しました。ランダム/キーボード/マウスの使用に依存しているようです。 – Munchhausen

関連する問題