4

我正在用 python 为 Ubuntu Linux 编写一个反 RSI/打字中断程序。我希望能够“锁定键盘”,以便在我“解锁”它之前忽略所有按键。我希望能够强制用户休息一下。

我想要一些编程方式来“关闭”键盘(几乎是瞬间),直到我的程序稍后释放它(可能是 0.1 秒→ 10 秒后)。虽然我已经“关闭了键盘”,但不应将按键发送到任何窗口、窗口管理器等。最好,屏幕仍应显示相同的内容。即使该程序不在最前面且没有焦点,也应锁定键盘。

一些程序已经能够做到这一点(例如 Work Rave)

如何在 Linux/X11 上执行此操作?(最好在 Python 中)

4

3 回答 3

4

基于,这是我想出的代码:

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 上测试。不确定这些是否重要:)

更新添加了更改路径的选项,例如“serio0”或“serio1”。并打印描述,对我来说 serio0 给了我:i8042 KBD port,很可能如果你有“KBD”,这是正确的,继续,否则我不给你保证:)

于 2012-05-24T15:41:53.143 回答
2

执行此操作的规范方法是获取输入。为此,任何窗口都必须是实际可见的。仅输入的窗口通常可以解决问题。但是,您应该给用户一些反馈,为什么他的输入不再有效。这样做作为焦点抓取具有程序崩溃不会使系统无响应的优点。

BTW:我认为强行打断用户,也许在关键操作中间是一个巨大的禁止!我从来不明白这些程序的目的。用户会坐在屏幕前闲置,可能会失去思绪。只是我的2美分。

于 2012-05-26T20:55:43.877 回答
1

这可以通过使用 xinput 的 shell 脚本轻松完成:

 #!/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-xlib 之类的库在 Python 中重新实现它。

于 2012-05-24T20:43:07.673 回答