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)
There are three different keyboard events in JavaScript: keydown : Keydown happens when the key is pressed down, and auto repeats if the key is pressed down for long. keypress : This event is fired when an alphabetic, numeric, or punctuation key is pressed down. keyup : Keyup happens when the key is released.
Explanation: The keydown and keyup are the keyboard events are fired when the user presses or releases a key on the keyboard. They are generated for modifier keys, function keys, and alphanumeric keys. 2.
The keyboard event object has two important properties: key and code properties that allow you to detect which key has been pressed. The key property returns the value of the key pressed while the code represents a physical key on the keyboard.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With