2012-02-08 76 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库中使用代码有任何问题,我试图尽可能使它简单/健壮,但是在将它们放在一起时可能会漏掉一些东西。这是一段时间以前。