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

Я пишу приложение из командной строки, которое прослушивает события релиза Control Key в 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

EDIT: Я не могу понять, что события клавиатуры не попадают в ловушку, если они не обрабатываются (в моих программах это означает, что строка "printRelease" "выполняется" ). Поскольку в моем коде я не вызываю никакого метода ни на Xlib, ни на объекте события, я не понимаю, где лежит разница в обработке.

EDIT2: Предложения по альтернативным решениям, кроме использования 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)

Ответы

Ответ 1

Благодаря библиотеке 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()

Эта программа выполняет мою задачу без каких-либо проблем. Вы можете прочитать поля объекта "событие" для получения дополнительной информации о событии (см. Исходный код "pyxhook.py" ).

Ответ 2

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

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

Ответ 4

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

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