【问题标题】:How do I 'lock the keyboard' to prevent any more keypresses being sent on X11/Linux/Gnome?如何“锁定键盘”以防止在 X11/Linux/Gnome 上发送更多按键?
【发布时间】:2012-05-31 04:32:30
【问题描述】:

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

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

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

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

【问题讨论】:

  • 我认为 VB.NET 不能在 Linux 上运行……是吗?如果确实如此,那么我也许可以自己弄清楚,所以是的,这会有所帮助。
  • 你能把 VB.NET 转换成 Python 吗?我从来没有用 Python 编程过,很抱歉。
  • 我可能看到你是如何告诉 X 停止键盘的,所以是的,如果它在 Linux/X11 上工作,那么这是一个有用的答案,我可以从中学习,所以请添加它。
  • 在 Ddg 上搜索“关闭键盘 x11”给了我this。看起来很有希望,看看有没有帮助,我也试试看。
  • 我不认为 0.1 秒的锁定可能会迫使用户休息(可能会错过一次击键,这与其说是帮助不如说是烦人)。即使是 10 岁也可能不会做太多。

标签: python linux ubuntu keyboard x11


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

    • 我知道禁用键盘是一个奇怪的 UI 动作,但这是出于健康原因。许多反 RSI 程序都可以做到这一点。我当然会有一个通知来告诉用户,也许还有一个“让我输入”按钮。但是我想在用户在其他地方打字时禁用键盘,即会有窗口可见并集中。
    • @Rory:窗口可见性和焦点独立于设备抓取。您可以使用任何窗口抓取输入设备,即使它是不可见的。
    • 我问了一个关于如何获取输入的问题stackoverflow.com/questions/10796363/… 任何帮助将不胜感激。
    • @Pryftan:我不仅能记住键盘锁:我还积极使用它们。顺便说一句,这些锁定开关是通过将键盘的数据线强行拉到 GND 来工作的。我曾经被一个有问题的键盘锁开关骗了,花了一整个晚上都在换键盘。
    • @Pryftan:这也不是“狭隘”的心态。只是我是计算机术语中的“老屁”,出于经验某些事情如何在你的脸上爆炸(通往地狱的道路是用善意铺成的)我建议好好“思考”一下。在现代计算机上,键盘是一种“任意”输入设备,“键盘”是什么,什么不是。假设用户戴着耳机,正在休息看视频并且出现“大声”警告:用户将如何调低音量?音量键?它们也被注册为键盘。
    【解决方案3】:

    这可以通过使用 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 中重新实现它。

    【讨论】:

    • 这是一种很棒、快速、有效和简单的方法。这似乎也是 The Right Way™
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-24
    • 1970-01-01
    • 1970-01-01
    • 2011-12-22
    • 2020-06-26
    • 1970-01-01
    相关资源
    最近更新 更多