我不认为有办法做到这一点。没有一种机制能完全按照您的需要工作。
方法 1 是窗口管理器在决定不拦截点击或按键时所做的事情。但是,WM 在特定键上使用“被动”抓取(XGrabKey=passive XGrabKeyboard=active),然后是 XAllowEvents()。XAllowEvents() 不适用于 XGrabKeyboard()。此外,当您使用其中一种重播模式进行 XAllowEvents 时,重播事件会绕过具有原始抓取的窗口及其所有父窗口上的所有被动抓取。WM 的抓取将在根窗口上,该窗口始终是父窗口,因此无法重播到根窗口,我能说得最好。无论如何,对每一个可能的键都执行 XGrabKey 会有点心理。
方法 2 会出现糟糕的竞争条件问题,因为在重新发送之前可以处理其他键和鼠标事件,因此您需要重新排序键并将事件发送到被破坏的窗口和其他混乱。此外,没有发送关键事件的好方法。XSendEvent() 被许多客户端忽略(它在允许这样做的事件中设置了 send_event 标志)。可以使用 XTest 扩展,但可能在生产 X 服务器上被禁用,并且仍然存在竞争条件问题。
您可能需要的是一个协议扩展,它允许您在 GrabKeyboard 之后执行 AllowEvents(mode=ReplayKeyboard) 而无需绕过父窗口上的被动抓取。
需要注意的是,我不知道所有可以用 XKB 和 XInput2 完成的疯狂的东西,所以也许这些扩展中有一些东西。
无论如何,据我所知,您必须满足于“退出键”,尽管最终 X 服务器和/或窗口管理器规范具有“VMWare/VNC 类型的事物意识”可能会很好,这赢得了短期内帮不了你。例如,EWMH 规范扩展可以像 vnc/vmware/stuff-like 的新 _NET_WM_WINDOW_TYPE 一样简单,并且窗口管理器可以减少其键绑定或为它们添加额外的修饰符或其他东西。