2012-02-08 69 views
14

我正在編寫一個命令行應用程序,它在X Windows中監聽Control鍵釋放事件,並在檢測到它們時警告另一個進程。聆聽鍵盤事件而不捕獲它們?

作爲GNU/Linux的新手,我寧願避免摸索GCC,因此我正在尋找一種基於腳本的解決方案。因爲我知道一些Python,所以選擇一個基於Python的解決方案似乎很自然,並且在清除Internet上的示例並閱讀Python Xlib文檔後,我將這些程序合併在一起,但有一點需要注意:它會陷入陷阱事件而不是僅僅聽他們(我的意思是這些事件不再通過它們被引導到的應用程序)。

我通過運行「xev」跟蹤了控制鍵代碼。由於我重新映射了我的修改鍵,在您的系統上它們可能會有所不同。

爲了簡單起見,我省略了處理外部進程的代碼。

謝謝你的幫助。

軟件:

  • 的Python 2.7.2

  • 的Python Xlib的0.15 RC1

  • 的Perl v5.10.1

  • 的Debian GNU/Linux的版本:6.0.3

  • 內核v版爲:Linux的Debian的2.6.32-5-686

編輯:我想不通的是,鍵盤事件不會得到被困,除非它們被處理(在我的計劃,這意味着該行「打印「KeyRelease」被執行)。因爲在我的代碼中,我不會在Xlib或事件對象上調用任何方法,但我不明白處理中的差異在哪裏。

EDIT2:除了使用Xlib之外,還有關於替代解決方案的建議也很受歡迎。編輯3:我也瞭解Perl,並且可以提供幫助的Perl庫的建議也是受歡迎的,只要它們不需要最新版本的系統庫,因爲Debian臭名昭着地落後於它的可用包如果它們有很多依賴關係(我已經嘗試安裝PyGTK,但在未能引用我安裝的最新GLib之後放棄了),那麼編譯和安裝最後版本的庫可能會很困難。

#!/usr/bin/env python 

    from Xlib.display import Display 
    from Xlib import X 

    Control_R = 64 # Keycode for right Control. 
    Control_L = 108 # Keycode for left Control. 
    keycodes = [Control_R, Control_L] # Keycodes we are listening for. 

    # Handle X events. 
    def handle_event(event): 
     # Let us know whether this event is about a Key Release of 
     # one of the key we are interest in. 
     if event.type == X.KeyRelease: 
      keycode = event.detail 
      if keycode in keycodes: 
       print "KeyRelease" 

    # Objects needed to call Xlib. 
    display = Display() 
    root = display.screen().root 

    # Tell the X server we want to catch KeyRelease events. 
    root.change_attributes(event_mask = X.KeyReleaseMask) 

    # Grab those keys. 
    for keycode in keycodes: 
     root.grab_key(keycode, X.AnyModifier, 1, X.GrabModeAsync, X.GrabModeAsync) 

    # Event loop. 
    while 1: 
     event = root.display.next_event() 
     handle_event(event) 

回答

2

您需要使用擴展記錄擴展。它可以與pyxlib(在其他答案中提到的pykeylogger使用這個)一起使用,或者通過ctypes包裝libX11和libXtst(就像我在synaptiks中那樣)。

但是請注意,使用xrecord進行編程(在一定程度上也適用於XLib)通常很難實現,因爲API記錄很糟糕,而且相當巴洛克式且反直覺。

+0

謝謝。我會研究XRecord。但是,我在我的問題中添加了一些註釋,因爲在我看來,解決方案即將到來,因爲我的代碼不會捕獲所有事件。 – 2012-02-09 00:55:56

11

多虧了Croad狼山提到pykeylogger庫,以及由Tim亞歷山大,這樣庫的作者提供了有用的示例代碼,我已經能夠到我的計劃更改爲:

#!/usr/bin/env python 

    from pyxhook import HookManager 

    watched_keys = ["Control_R", "Control_L"] 

    def handle_event (event): 
     if event.Key in watched_keys: 
      print "KeyRelease" 


    hm = HookManager() 
    hm.HookKeyboard() 
    hm.KeyUp = handle_event 
    hm.start() 

這程序完成我的目標沒有任何問題。您可以閱讀「事件」對象的字段以獲取有關該事件的更多信息(請參閱「pyxhook.py」的源代碼)。

1

請注意,XRecord擴展在一些發行版中繼續被破壞。我之前沒有回過頭去更新這個庫的原因是因爲Ubuntu在多個版本中被破壞了。有一種方法可以用XInput疊加層來做到這一點(我被告知),但我從來沒有追求過,因爲我不想處理疊加層而不是直接掛鉤X事件。

回覆如果在pyxhook庫中使用代碼有任何問題,我試圖儘可能使它簡單/健壯,但是在將它們放在一起時可能會漏掉一些東西。這是一段時間以前。