Listening to keyboard events without trapping them?

I'm writing an command-line application which listens for Control key release events in X Windows and alerts another process when it detects them.

Being new to GNU/Linux, I'd prefer avoiding to fumble with GCC and therefore I'm looking for a scripting-based solution. Since I know a bit of Python, it seemed natural to go for a Python-based solution, and after scavenging the Internet for examples and reading Python Xlib docs, I've put together this programs which works, but with a caveat: it traps events instead of just listening for them (I mean such events are not passed anymore to the application which they were directed to in the first place).

I've tracked down Control key codes by running "xev". Since I've remapped my modifier keys, on your system they may be different.

To keep things simple, I've left out the code which deals with the external process.

Thank you for your help.

Software:

  • Python 2.7.2

  • Python Xlib 0.15 RC1

  • Perl v5.10.1

  • Debian GNU/Linux version: 6.0.3

  • Kernel version: Linux debian 2.6.32-5-686

  • EDIT: What I can't figure out is that keyboard events do not get trapped unless they are processed (in my programs, this means the line 'print "KeyRelease"' gets executed). Since in my code I don't call any method either on Xlib or on the event object, I don't understand where the difference in processing lies.

    EDIT2: Suggestions about alternative solutions besides using Xlib are also welcome.

    EDIT3: I know Perl too, and suggestions about Perl libraries which could help are welcome too, as long as they don't require recent versions of system libraries, since Debian notoriously lags behind when it comes to packages available in its repositories, and compiling and installing last versions of libraries can be difficult if they have many dependencies (I've tried installing PyGTK, but gave up after failing to reference an up-to-date GLib I had installed).

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

    Thanks to the pykeylogger library mentioned by Croad Langshan, and to the helpful example code provided by Tim Alexander, the author of such library, I've been able to change my program to:

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

    This program accomplishes my goal without any issue. You can read the fields of the "event" object for further information about the event (see source code of "pyxhook.py").


    You need to use the XRecord extension. It can be used with pyxlib (pykeylogger mentioned in the other answer uses this), or by wrapping libX11 and libXtst via ctypes (as I did in synaptiks).

    Note however, that programming with xrecord (and to some degree also with XLib in general) is somehwat hard, because the API is badly documented, and quite baroque and counter-intuitive.


    Presumably this project must have code that solves that problem:

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

    链接地址: http://www.djcxy.com/p/18430.html

    上一篇: 如何在Python中生成键盘事件?

    下一篇: 倾听键盘事件而不捕获它们?