从XGrabKeyboard排除一些键 [英] Excluding some keys from XGrabKeyboard

查看:327
本文介绍了从XGrabKeyboard排除一些键的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑一个应用程序,该应用程序需要在聚焦时抓住键盘,以便捕获所有窗口管理器命令(Alt + F4和诸如此类)以进行处理.现在,这具有一个缺点,即用户在握住键盘时无法通过键盘切换到另一个应用程序或虚拟桌面.我想要一个用户定义的按键组合(例如,用于切换虚拟桌面的按键组合)的白名单,该列表不包含在抓取中.

我可以想到两种可能的方法.当列入白名单的关键事件到达时,

  1. 以某种方式告诉X继续照常处理它.听起来这是一种更自然的方法,但是我找不到解决方法,或者
  2. 解开键盘,然后手动将事件重新发送到窗口管理器进行处理,但是我不知道将事件发送到哪里(根窗口?),或者甚至不能奏效.

任何人都可以填写这些空白吗?还有其他建议吗?

如果没有办法从抓斗中排除按键,我想我必须满足于拥有一个退出键",当按下该键时可以取消键盘的作用.但是,用户必须同时按一下,然后再按窗口管理器命令,这不是很好.

解决方案

我认为没有办法.没有一种机制可以完全满足您的需要.

方法1类似于窗口管理器在决定不拦截例如单击或按键时的操作.但是,WM在特定键(XGrabKey =被动XGrabKeyboard = active)上使用被动"抓取,然后在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一样简单,例如,窗口管理器可以减少其键绑定或向其添加额外的修饰符,或者例如在该窗口被聚焦时添加一些修饰符.

Consider an application where it's desirable to grab the keyboard when focused in order to capture all window manager commands (Alt+F4 and whatnot) for processing. Now, this has the downside that the user has no way of switching to another application or virtual desktop via the keyboard when the keyboard is grabbed. I'd like to have a user-defined whitelist of key combination (say, the key combinations for switching virtual desktops) that are excluded from the grab.

I can think of two possible approaches. When a whitelisted key event arrives, either

  1. Somehow tell X to continue processing it as usual. This sounds like a more natural way of doing it but I can't find a way to do this, or
  2. Ungrab the keyboard and re-send the event by hand to the window manager for processing, however I don't know where to send it (the root window?) or whether that would even work.

Can anyone fill in the blanks on those? Any other suggestions?

If there's no way to exclude keys from a grab, I guess I'll have to settle for having an "escape key" that ungrabs the keyboard when pressed. The user'll have to press both that and then the window manager command, though, which isn't as nice.

解决方案

I don't think there's a way to do it. None of the mechanisms work quite how you would need them to.

Approach 1 is sort of what the window manager does if it decides not to intercept a click or key for example. However, the WM is using "passive" grabs on particular keys (XGrabKey=passive XGrabKeyboard=active) and then XAllowEvents(). XAllowEvents() does not work with XGrabKeyboard(). also, when you XAllowEvents with one of the Replay modes, the replayed event bypasses all passive grabs on the window that had the original grab and on all its parent windows. The WM's grabs will be on the root window which will always be a parent so there is no way to replay to the root window, best I can tell. Doing XGrabKey on every possible key would be sort of psycho anyhow.

Approach 2 would have bad race condition problems, because other key and mouse events could be processed before you could resend, so you'd reorder keys and send events to destroyed windows and other confusion. Also, there is no good way to send a key event. XSendEvent() is ignored by many clients (it sets a send_event flag in the event allowing this). XTest extension can be used but may be disabled on production X servers and still has race condition issues.

What you probably would need is a protocol extension that let you do an AllowEvents(mode=ReplayKeyboard) after a GrabKeyboard and without bypassing passive grabs on parent windows.

One caveat is that I don't know all the wild stuff that can be done with XKB and XInput2, so maybe there's something in those extensions.

Anyway, as far as I know you have to settle for the "escape key," though it might be nice eventually for the X server and/or the window manager specs to have "VMWare/VNC-type-thing awareness," that won't help you in the short term. An EWMH spec extension could be as simple as a new _NET_WM_WINDOW_TYPE for vnc/vmware/stuff-like-that and the window manager could reduce its keybindings or add an extra modifier to them or something when that window was focused, for example.

这篇关于从XGrabKeyboard排除一些键的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆