聆听键盘事件而不让它们陷入陷阱



我正在编写一个命令行应用程序,该应用程序在X Windows中侦听控制键释放事件,并在检测到这些事件时向另一个进程发出警报。

作为GNU/Linux的新手,我更喜欢避免在GCC上摸索,因此我正在寻找一个基于脚本的解决方案。由于我对Python有一点了解,所以选择基于Python的解决方案似乎很自然。在浏览了互联网上的示例并阅读了PythonXlib文档后,我整理了这些程序,这些程序很有效,但需要注意的是:它会捕获事件,而不仅仅是侦听它们(我的意思是,这些事件不再传递给最初指向的应用程序)。

我已经通过运行"xev"找到了控制键代码。由于我已经重新映射了修改器键,在您的系统中,它们可能会有所不同。

为了简单起见,我省略了处理外部流程的代码。

谢谢你的帮助。

软件:

  • Python 2.7.2

  • Python Xlib 0.15 RC1

  • Perl v.10.1

  • Debian GNU/Linux版本:6.0.3

  • 内核版本:Linux debian 2.6.32-5-686

编辑:我不明白的是,除非对键盘事件进行处理,否则键盘事件不会被捕获(在我的程序中,这意味着"打印"KeyRelease"一行会被执行)。由于在我的代码中,我既不在Xlib上也不在事件对象上调用任何方法,所以我不明白处理的区别在哪里。

第2版:除了使用Xlib之外,还欢迎提出其他解决方案的建议。

第三版:我也了解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)

感谢Croad Langshan提到的pykeylogger库,以及该库的作者Tim Alexander提供的有用的示例代码,我能够将我的程序更改为:

    #!/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()

这个项目毫无问题地实现了我的目标。您可以读取"event"对象的字段以获取有关该事件的更多信息(请参阅"pyxhook.py"的源代码)。

您需要使用XRecord扩展。它可以与pyxlib一起使用(另一个答案中提到的pykeylogger使用这个),也可以通过ctypes包装libX11和libXtst(就像我在synaptik中所做的那样)。

然而,请注意,使用xrecord(在某种程度上,通常也使用XLib)进行编程有些困难,因为API的文档记录很差,而且非常巴洛克和反直觉。

假设这个项目必须有解决这个问题的代码:

http://sourceforge.net/apps/mediawiki/pykeylogger/index.php?title=Main_Page

请注意,XRecord扩展在一些发行版中仍然被破坏。我有一段时间没有回去更新那个库,是因为它在Ubuntu的多个版本中都坏了。有一种方法也可以通过XInput覆盖来实现,(我被告知)但我从未追求过这一点,因为我不想处理覆盖,而不是直接挂钩X事件。

如果在pyxhook库中使用代码有任何问题,请回复,我试图使其尽可能简单/健壮,但在组合时可能遗漏了一些内容。那是很久以前的事了。

相关内容

  • 没有找到相关文章

最新更新