如何“locking键盘”以防止在X11 / Linux / Gnome上发送更多按键?

我正在为Python中的Ubuntu Linux编写一个反RSI /打字中断程序。 我希望能够“locking键盘”,以便所有的按键被忽略,直到我“解锁”它。 我希望能够强制用户打字打破。

我想要一些程序化的方法来“closures”键盘(几乎是瞬间),直到我的程序稍后释放(可能是0.1秒→10秒)。 当我“closures键盘”时,不应该将按键发送到任何窗口,窗口pipe理器等等。优选地,屏幕仍然应该显示相同的内容。 即使该程序不在forefont并且没有焦点,键盘也应该被locking。

一些程序已经能够做到这一点(例如工作狂欢)

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

Solutions Collecting From Web of "如何“locking键盘”以防止在X11 / Linux / Gnome上发送更多按键?"

这可以通过使用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中使用像python-xlib这样的库来重新实现它可能是个好主意。

基于此 ,下面是我提出的一个代码:

 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 Laptop,Gnome上测试。 不知道是否有任何问题,但:)

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

执行此操作的规范方法是通过抓取输入。 为此,没有窗口必须实际可见。 一个只有输入的窗口通常会这样做。 但是,你应该给用户一些反馈,为什么他的输入不再有效。 这样做的重点抓住有一个优势,即程序崩溃不会导致系统无响应。

顺便说一句:我想强行打断用户,也许在一个关键的操作中间是一个巨大的没有去! 我从来没有理解这些方案的目的。 用户会坐在屏幕前面闲置,也许会失去他的想法。 只是我2美分。

顺便说一句,这不是我的代码

这可以阻止用户按下Win Key,Shift键或Alt键,但是我相信你也可以应用其他键。

 Public Class KeyboardJammer Private Delegate Function HookCallback(ByVal nCode As Integer, ByVal wParam As Integer, ByVal lParam As IntPtr) As Integer Private Shared HookDelegate As HookCallback Private Shared HookId As Integer Private Const Wh_Keyboard_LL As Integer = 13 Private Const Vk_Tab As Integer = 9 Private Const Vk_Escape As Integer = 27 Private Const Vk_LWinKey As Integer = 91 Private Const Vk_RWinkKey As Integer = 92 Private Shared Function KeyBoardHookProc(ByVal nCode As Integer, ByVal wParam As Integer, ByVal lParam As IntPtr) As Integer 'All keyboard events will be sent here.' 'Dont process just pass along.' If nCode < 0 Then Return CallNextHookEx(HookId, nCode, wParam, lParam) End If 'Extract the keyboard structure from the lparam' 'This will contain the virtual key and any flags.' 'This is using the my.computer.keyboard to get the' 'flags instead' Dim KeyboardSruct As KBDLLHOOKSTRUCT = Marshal.PtrToStructure(lParam, GetType(KBDLLHOOKSTRUCT)) If KeyboardSruct.vkCode = Vk_Tab And My.Computer.Keyboard.AltKeyDown Then 'Alt Tab' Return 1 ElseIf KeyboardSruct.vkCode = Vk_Escape And My.Computer.Keyboard.CtrlKeyDown Then 'Control Escape' Return 1 ElseIf KeyboardSruct.vkCode = Vk_LWinKey Or KeyboardSruct.vkCode = Vk_RWinkKey Then If KeyboardSruct.vkCode = Vk_Tab Then 'Winkey Tab' Return 1 Else 'Winkey' Return 1 End If ElseIf KeyboardSruct.vkCode = Vk_Escape And My.Computer.Keyboard.AltKeyDown Then 'Alt Escape' Return 1 End If 'Send the message along' Return CallNextHookEx(HookId, nCode, wParam, lParam) End Function Public Shared Sub Jam() 'Add the low level keyboard hook' If HookId = 0 Then HookDelegate = AddressOf KeyBoardHookProc HookId = SetWindowsHookEx(Wh_Keyboard_LL, HookDelegate, Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly.Getmodulees()(0)), 0) If HookId = 0 Then 'error' End If End If End Sub Public Shared Sub UnJam() 'Remove the hook' UnhookWindowsHookEx(HookId) End Sub <DllImport("user32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall)> _ Private Shared Function CallNextHookEx( _ ByVal idHook As Integer, _ ByVal nCode As Integer, _ ByVal wParam As IntPtr, _ ByVal lParam As IntPtr) As Integer End Function <DllImport("user32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall, SetLastError:=True)> _ Private Shared Function SetWindowsHookEx( _ ByVal idHook As Integer, _ ByVal HookProc As HookCallback, _ ByVal hInstance As IntPtr, _ ByVal wParam As Integer) As Integer End Function <DllImport("user32.dll", CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall, SetLastError:=True)> _ Private Shared Function UnhookWindowsHookEx(ByVal idHook As Integer) As Integer End Function Private Structure KBDLLHOOKSTRUCT Public vkCode As Integer Public scanCode As Integer Public flags As Integer Public time As Integer Public dwExtraInfo As IntPtr End Structure End Class 

用法:

 KeyboardJammer.Jam()