Как мне «заблокировать клавиатуру», чтобы предотвратить отправку нажатий клавиш в X11/Linux/Gnome?

Я пишу программу защиты от RSI/перерыва для Ubuntu Linux на python. Я хотел бы иметь возможность «заблокировать клавиатуру», чтобы все нажатия клавиш игнорировались, пока я не «разблокирую» ее. Я хочу иметь возможность заставить пользователя сделать перерыв при наборе текста.

Я хотел бы какой-нибудь программный способ «выключить» клавиатуру (почти мгновенно), пока моя программа не выпустит ее позже (что может быть через 0,1 секунды → 10 секунд). Пока я «выключил клавиатуру», никакие нажатия клавиш не должны отправляться ни в какие окна, оконные менеджеры и т. д. Предпочтительно, чтобы на экране по-прежнему отображалось то же содержимое. Клавиатура должна быть заблокирована, даже если эта программа не на переднем плане и не имеет фокуса.

Некоторые программы уже умеют это делать (например, Work Rave).

Как мне это сделать в Linux/X11? (желательно на питоне)


person Rory    schedule 24.05.2012    source источник
comment
Я не думаю, что VB.NET работает в Linux… Правда? Если это так, то я мог бы понять это сам, так что да, это было бы полезно.   -  person Rory    schedule 24.05.2012
comment
Можете ли вы преобразовать VB.NET в Python? Я никогда не программировал на Python, извините за это.   -  person user959631    schedule 24.05.2012
comment
Я, вероятно, мог видеть, как вы говорите X остановить клавиатуру, так что да, если это работает в Linux / X11, то это полезный ответ, из которого я мог бы извлечь уроки, поэтому, пожалуйста, добавьте его.   -  person Rory    schedule 24.05.2012
comment
Поиск отключить клавиатуру x11 на Ddg дал мне это. Выглядит многообещающе, посмотрим, поможет ли, попробую тоже разобраться.   -  person jadkik94    schedule 24.05.2012
comment
Я не думаю, что блокировка в 0,1 секунды, вероятно, заставит пользователя сделать перерыв (возможно, пропустить одно нажатие клавиши, что будет скорее раздражать, чем помогать). Даже 10-ки, вероятно, мало что сделают для этого.   -  person Kevin    schedule 24.05.2012
comment
Я не могу говорить за VB.NET, но C# будет работать в Linux с Mono (но я ожидаю, что что-то в Python с использованием интерфейсов Linux и/или X11 будет иметь гораздо больше шансов сделать то, что вы хотите)   -  person Foon    schedule 25.05.2012


Ответы (3)


Это можно легко сделать с помощью сценария оболочки с помощью xinput :

 #!/bin/sh

 do_it() {
     # need error checking there. We should also restrict which device gets
     # deactivated, by checking other properties.
     keyboard_ids="$(xinput list | sed -rn 's/.*id=([0-9]+).*slave\s+keyboard.*/\1/p')"

     for keyboard_id in $keyboard_ids; do
         # 121 is "Device Active".
         # use xinput watch-props $device_id to see some properties.
         xinput set-int-prop $keyboard_id 121 8 $1;
     done;
 }
 # you maybe don't want to exit in case of failure there.
 do_it 0 ; sleep 5; do_it 1

Эта логика легко переписывается на Python. Если установка xinput проблематична, может быть хорошей идеей получить исходный код xinput и попытаться повторно реализовать его в Python с помощью библиотеки, такой как python-xlib.

person BatchyX    schedule 24.05.2012
comment
Это отличный, быстрый, эффективный и простой способ сделать это. Это также похоже на The Right Way™ - person Rory; 25.05.2012

Основываясь на этом, вот код, который я придумал:

class KeyboardLocker:

    def __init__(self, serio=0):
        self._on = False
        self.serio = serio

    def on(self):
        return self._on

    def write_value(self,path, value):
        with open(path, "a") as f:
            f.write(value)

    def toggle(self):
        if self.on():
            self.turn_off()
        else:
            self.turn_on()

    def description(self):
        path = '/sys/devices/platform/i8042/serio%d/description' % (self.serio,)
        with open(path, "r") as f:
            description = f.read()
        return description

    def turn_on(self):
        try:
            self.write_value('/sys/devices/platform/i8042/serio%d/bind_mode' % (self.serio,),
                            'auto')
        except IOError, e:
            self._on = False
            raise
        else:
            self._on = True
        return self.on()

    def turn_off(self):
        try:
            self.write_value('/sys/devices/platform/i8042/serio%d/bind_mode' % (self.serio,),
                            'manual')
            self.write_value('/sys/devices/platform/i8042/serio%d/drvctl' % (self.serio,),
                            'psmouse')
        except IOError, e:
            self._on = True
            raise
        else:
            self._on = False
        return self.on()

if __name__ == "__main__":
    kl = KeyboardLocker(serio=0)

    device = kl.description()
    print "We got a lock on", device

    proceed = raw_input("Do you want to proceed? (y/n)").lower().startswith("y")
    import sys
    if not proceed: sys.exit(1)

    kl.turn_off()

    import time
    wait = 5
    print "Sleeping few seconds...", wait
    time.sleep(wait)
    print "Voila!"

    kl.turn_on()

    raw_input("Does it work now?")

Протестировано на Linux Mint 12, X11, ноутбуке HP, Gnome. Хотя не уверен, что это имеет значение :)

ОБНОВЛЕНИЕ Добавлена ​​возможность изменить путь, например. «серио0» или «серио1». И печатает описание, для меня serio0 дал: i8042 KBD port, скорее всего если у вас в нем "KBD", то правильно, продолжайте, иначе гарантии не даю :)

person jadkik94    schedule 24.05.2012

Канонический способ сделать это — получить ввод. Для этого ни одно окно не должно быть действительно видно. Окно только для ввода обычно помогает. Однако вы должны дать пользователю какую-то обратную связь, почему его ввод больше не работает. Выполнение этого в качестве захвата фокуса имеет то преимущество, что сбой программы не приведет к тому, что система перестанет отвечать на запросы.

Кстати: я думаю, что принудительное прерывание работы пользователя, возможно, в середине критических операций, является огромным No-Go! Я никогда не понимал цели этих программ. Пользователь будет сидеть перед экраном без дела, возможно, потеряв свои мысли. Просто мои 2 цента.

person datenwolf    schedule 26.05.2012
comment
Я знаю, что отключение клавиатуры — странный шаг в пользовательском интерфейсе, но это по соображениям здоровья. Это делают многие анти-RSI программы. Конечно, у меня было бы уведомление, которое сообщало бы пользователю, и, возможно, была бы кнопка «Позвольте мне ввести». Однако я хочу отключить клавиатуру, пока пользователь печатает где-то еще, т.е. окна будут видны и сфокусированы. - person Rory; 28.05.2012
comment
@Rory: видимость окна и фокус не зависят от захвата устройства. Вы можете захватить устройство ввода любым окном, даже если оно невидимо. - person datenwolf; 28.05.2012
comment
Я задал вопрос о том, как получить ввод stackoverflow.com/questions/10796363/ Будем признательны за любую помощь. - person Rory; 29.05.2012
comment
@Pryftan: я не только достаточно взрослый, чтобы помнить блокировки клавиатуры: я активно их использовал. Эти переключатели блокировки, BTW, работали, принудительно подтягивая линию данных клавиатуры к GND. И однажды меня затроллил неисправный переключатель блокировки клавиатуры, и я провел целый вечер, переключая клавиатуры. - person datenwolf; 13.12.2019
comment
@Pryftan: Кроме того, это не узкое мышление. Просто я старый пердун в компьютерных терминах, и по опыту как некоторые вещи могут взорваться в лицо (благими намерениями дорога в ад вымощена) советую взять хорошо и трудно подумать об этом. Клавиатура на современных компьютерах является произвольным устройством ввода и не так однозначно, что такое клавиатура, а что нет. Скажем, пользователь надел наушники, делает перерыв в просмотре видео и появляется ГРОМКОЕ предупреждение: как пользователь собирается уменьшить громкость? Клавиши громкости? Они также зарегистрированы как клавиатура. - person datenwolf; 13.12.2019
comment
@datenwolf Да, и я достаточно взрослый, чтобы понять, о чем вы говорите. Но под ограниченным или узким я подразумеваю, что на самом деле есть причины блокировать клавиатуру. Теперь, если вы хотите возразить, что это злоупотребление - это и многое другое - я полностью с вами согласен. Я просто говорю, что бывают случаи, когда это имеет значение. Другими словами, это не бинарная вещь. - person Pryftan; 14.12.2019