2013-08-04 8 views
5

일반 키보드에서 키 코드를 구현하고 싶습니다. 파이썬 xlib를 사용한다고 생각합니다. 이 프로그램을 작동 시키려면 모든 키 이벤트를 전체적으로 삼키고 나중에 만 통과하도록 허용해야합니다.는 파이어 폭스 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 found과 같이) keypresses와 -releases를 보내면 작동합니다.

여기에 keypress의 "1"

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 분 30 초 후에 실패했다. 무작위이거나 키보드/마우스 사용에 의존적 인 것으로 보입니다. – Munchhausen