从XGrabKeyboard中排除一些键

时间:2010-09-25 21:29:42

标签: keyboard x11 xlib

考虑一个应用程序,在聚焦时需要抓住键盘以捕获所有窗口管理器命令(Alt + F4和诸如此类)以进行处理。现在,这具有以下缺点:当抓取键盘时,用户无法通过键盘切换到另一个应用程序或虚拟桌面。我想要一个用户定义的密钥组合白名单(例如,用于切换虚拟桌面的组合键)从抓取中排除。

我可以想到两种可能的方法。当列入白名单的密钥事件时,

  1. 以某种方式告诉X继续像往常一样处理它。这听起来像是一种更自然的方式,但我找不到办法,或者
  2. 取消键盘并手动将事件重新发送到窗口管理器进行处理,但我不知道将它发送到哪里(根窗口?)或者是否可以正常工作。
  3. 任何人都可以填补空白吗?还有其他建议吗?

    如果没有办法从抓斗中排除钥匙,我想我必须满足于有一个“退出键”,在按下时不会敲击键盘。用户必须同时按下那个,然后按下窗口管理器命令,这不是很好。

1 个答案:

答案 0 :(得分:4)

我认为没有办法做到这一点。没有一种机制能够满足您的需求。

方法1是窗口管理器在决定不拦截点击或键时所做的事情。但是,WM在特定键上使用“被动”抓取(XGrabKey =被动XGrabKeyboard =活动),然后是XAllowEvents()。 XAllowEvents()不适用于XGrabKeyboard()。此外,当您使用其中一种重播模式XAllowEvents时,重放事件会绕过具有原始抓取的窗口上及其所有父窗口上的所有被动抓取。 WM的抓取将位于根窗口,它将始终是父窗口,因此无法重播到根窗口,我能说清楚。无论如何,对每一个可能的密钥执行XGrabKey都会有点心理。

方法2会有不良的竞争条件问题,因为在重新发送之前可以处理其他键和鼠标事件,因此您需要重新排序键并将事件发送到已销毁的窗口以及其他混淆。此外,没有好的方法来发送关键事件。许多客户端忽略XSendEvent()(它在允许此事件的事件中设置send_event标志)。可以使用XTest扩展,但可以在生产X服务器上禁用,但仍然存在竞争条件问题。

您可能需要的是一个协议扩展,它允许您在GrabKeyboard之后执行AllowEvents(mode = ReplayKeyboard)并且不绕过父窗口上的被动抓取。

有一点需要注意的是,我不知道可以使用XKB和XInput2完成的所有繁琐工作,所以也许这些扩展中有一些东西。

无论如何,据我所知你必须满足于“转义键”,尽管最终X服务器和/或窗口管理器规范具有“VMWare / VNC-type-thing意识,这可能是好的, “这在短期内对你没有帮助。例如,EWMH规范扩展可以像用于vnc / vmware / stuff-like的新的_NET_WM_WINDOW_TYPE一样简单,并且窗口管理器可以减少其键绑定或者在该窗口被聚焦时为它们添加额外的修饰符。