Прослушивание событий клавиатуры без их захвата?

Я пишу приложение командной строки, которое прослушивает события выпуска клавиши управления в X Windows и предупреждает другой процесс, когда он их обнаруживает.

Будучи новичком в GNU/Linux, я бы предпочел не возиться с GCC, и поэтому я ищу решение на основе сценариев. Поскольку я немного знаком с Python, мне показалось естественным выбрать решение на основе Python, и после поиска в Интернете примеров и чтения документации Python Xlib я собрал эту программу, которая работает, но с оговоркой: она ловит события вместо того, чтобы просто прослушивать их (я имею в виду, что такие события больше не передаются в приложение, на которое они были направлены в первую очередь).

Я отследил коды клавиш управления, запустив «xev». Поскольку я переназначил свои клавиши-модификаторы, в вашей системе они могут отличаться.

Для простоты я опустил код, связанный с внешним процессом.

Спасибо за помощь.

Программное обеспечение:

  • Питон 2.7.2

  • Python Xlib 0.15 RC1

  • Перл v5.10.1

  • Версия Debian GNU/Linux: 6.0.3

  • Версия ядра: Linux debian 2.6.32-5-686

РЕДАКТИРОВАТЬ: Что я не могу понять, так это то, что события клавиатуры не попадают в ловушку, если они не обрабатываются (в моих программах это означает, что выполняется строка «print «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)

person Raffaele Ricciardi    schedule 08.02.2012    source источник


Ответы (4)


Благодаря библиотеке pykeylogger, упомянутой Кродом Лангшаном, и полезному примеру кода, предоставленному Тимом Александром, автором такой библиотеки, я смог изменить свою программу на:

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

person Raffaele Ricciardi    schedule 09.02.2012

Вам нужно использовать расширение XRecord. Его можно использовать с pyxlib (pykeylogger, упомянутый в другом ответе, использует это) или путем упаковки libX11 и libXtst через ctypes (как я сделал в синаптики).

Однако обратите внимание, что программирование с помощью xrecord (и в некоторой степени также с XLib в целом) довольно сложно, потому что API плохо документирован, довольно причудлив и нелогичен.

person lunaryorn    schedule 08.02.2012
comment
Спасибо. Я посмотрю на XRecord. Тем не менее, я добавил пару замечаний к своему вопросу, потому что мне кажется, что решение не за горами, поскольку мой код не перехватывает все события. - person Raffaele Ricciardi; 09.02.2012

Предположительно, в этом проекте должен быть код, решающий эту проблему:

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

person Croad Langshan    schedule 08.02.2012
comment
Ваш комментарий позволил мне составить ответ на мой вопрос. Спасибо. - person Raffaele Ricciardi; 10.02.2012

Обратите внимание, что расширение XRecord по-прежнему не работает в нескольких дистрибутивах. Причина, по которой я какое-то время не возвращался и не обновлял эту библиотеку, заключалась в том, что она была сломана в Ubuntu для нескольких выпусков. Есть способ сделать это с помощью оверлея XInput (мне сказали), но я никогда не занимался этим, потому что я не хотел иметь дело с оверлеем, а не напрямую перехватывать события X.

Прокомментируйте, если есть какие-либо проблемы с использованием кода в pyxhook lib, я пытался сделать его максимально простым/надежным, но, возможно, я что-то пропустил при его сборке. Это было некоторое время назад.

person Tim Alexander    schedule 10.02.2012