Прослушивание событий клавиатуры без их захвата?
Я пишу приложение командной строки, которое прослушивает события отпускания клавиши управления в X Windows и предупреждает другой процесс, когда обнаруживает их.
Будучи новичком в GNU/Linux, я предпочел бы избегать возиться с GCC, и поэтому я ищу решение на основе сценариев. Так как я немного знаю Python, то было вполне естественно выбрать решение на основе Python, и после очистки Интернета для примеров и чтения документации по Python Xlib я собрал эти программы, которые работают, но с оговоркой: ловушки события, а не просто их прослушивание (я имею в виду, что такие события больше не передаются приложению, на которое они были направлены в первую очередь).
Я отследил коды клавиш управления, запустив "xev". Поскольку я переназначил свои клавиши-модификаторы, в вашей системе они могут отличаться.
Для простоты я упустил код, который имеет дело с внешним процессом.
Спасибо за помощь.
Программного обеспечения:
Python 2.7.2
Python Xlib 0.15 RC1
Perl v5.10.1
Версия Debian GNU/Linux: 6.0.3
Версия ядра: Linux Debian 2.6.32-5-686
РЕДАКТИРОВАТЬ: Что я не могу понять, так это то, что события клавиатуры не попадают в ловушку, пока они не будут обработаны (в моих программах это означает, что строка 'print "KeyRelease"' выполняется). Поскольку в моем коде я не вызываю какой-либо метод ни в Xlib, ни в объекте события, я не понимаю, в чем заключается разница в обработке.
РЕДАКТИРОВАТЬ 2: Предложения об альтернативных решениях, кроме использования Xlib, также приветствуются.
EDIT3: Я тоже знаю 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)
4 ответа
Благодаря библиотеке pykeylogger, упомянутой Croad Langshan, и полезному примеру кода, предоставленному Тимом Александером, автором такой библиотеки, я смог изменить свою программу на:
#!/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, упомянутый в другом ответе использует это), или оборачивая libX11 и libXtst через ctypes (как я делал в synaptiks).
Тем не менее, обратите внимание, что программирование с использованием xrecord (и в некоторой степени также с использованием XLib в целом) довольно сложно, потому что API плохо документирован, довольно барочный и нелогичный.
Обратите внимание, что расширение XRecord по-прежнему не работает в нескольких дистрибутивах. Причина, по которой я некоторое время не возвращался и не обновлял эту библиотеку, заключалась в том, что она была сломана в Ubuntu для нескольких выпусков. Есть способ сделать это также с оверлеем XInput, (мне сказали), но я никогда не преследовал это, потому что я не хотел иметь дело с оверлеем, а не перехватывать события X напрямую.
Прокомментируйте, если есть какие-либо проблемы с использованием кода в библиотеке pyxhook, я попытался сделать его максимально простым и надежным, но, возможно, я упустил что-то, когда собирал его вместе. Это было некоторое время назад.
Предположительно этот проект должен иметь код, который решает эту проблему:
http://sourceforge.net/apps/mediawiki/pykeylogger/index.php?title=Main_Page