禁用键盘但获取全局热键 XLib

4 投票
1 回答
865 浏览
提问于 2025-04-16 17:48

[已解决 - 提供的例子包含答案!] 我正在尝试实现一个程序,这个程序一启动就全屏,并且不允许任何用户输入(无论是鼠标还是键盘),因为它只会对UDEV信号做出反应,也就是当插入USB闪存或光盘时。 我想防止用户插入键盘或鼠标,然后对工作站做一些奇怪的事情。 唯一需要键盘的情况是,当管理员插入键盘并按下CTRL-T时,我的程序会打开一个终端窗口。

我使用的是Debian(Squeeze)和Gnome桌面环境。

我尝试使用XLib,这个方法可以很好地捕捉所有键盘事件,但当我的程序打开终端时,我无法释放键盘(这个功能也正常),所以用户在键盘捕获开启的情况下无法使用命令行。

以下是一些关键的代码片段:

class ScanWSClient(gtk.Window):

   def __init__(self, url):
         # current display
         disp = Display()
         self.display = disp

         gtk.Window.__init__(self)           

         self.terminal_window = None
         self.kb_handler = KeyboardHandler(self).start()

         #self.fullscreen()

         self._browser= webkit.WebView()
         self.add(self._browser)
         self.connect('destroy', gtk.main_quit)

         self._browser.open(url)
         self.show_all()

class KeyboardHandler(threading.Thread):
   def __init__(self, scanws_client):
         super(KeyboardHandler,self).__init__()
         self.running = True
         self.daemon = True          
         self.terminal_window = None
         self.scanws_client = scanws_client #

   def run(self):
         root = self.scanws_client.display.screen().root


         while self.running:
                event = root.display.next_event()
                self.handle_event(event)
                time.sleep(1)

   def handle_event(self,aEvent):
                keycode = aEvent.detail
                state = aEvent.state
                key_type = aEvent.type

                if keycode == 28 and key_type == X.KeyPress:
                      if self.scanws_client.terminal_window == None:
                            self.scanws_client.terminal_window = TerminalWindow(self.scanws_client, "Administrative Shell started...Type  *exit* to return to the locked workstation")
                      else:
                            self.scanws_client.terminal_window.present()
                            self.scanws_client.display.flush() #THIS FLUSH IS NECESSARY TO UNGRAB THE KEYBOARD LATER ON!!!
                      self.scanws_client.display.ungrab_keyboard(1, X.CurrentTime) 
                      print "Key: %s / Mask: %s / Type: %s" % (keycode, state, key_type)

                print self.scanws_client.terminal_window

在我的线程键盘处理程序中,我获取所有Xlib排队的事件,并用我的函数“handle_event”检查是否按下了CTRL-T。如果按下了,我就打开终端并尝试释放键盘(但不成功):

self.scanws_client.display.ungrab_keyboard(1, X.CurrentTime)

谁能告诉我为什么我无法释放我的键盘呢?(这个问题是有点小提示的;)

1 个回答

2

你有没有把对X服务器的请求清空?Xlib是异步的,它会把所有的请求先放在一个缓冲区里,直到这个缓冲区满了,或者你发出一个需要服务器回应的请求,或者你调用了XFlush(这是C语言的接口,不太确定Python的绑定叫什么)。

撰写回答