有谁知道一个xlib函数可以捕获按键事件而不失去原来的焦点吗?如何摆脱它?
(or“使用XGrabKey()而不生成抓取式焦点”?)
(or“如何在系统级消除NotifyGrab和NotifyUngrab焦点事件?”
XGrabKey将在按下键时失去焦点,并在释放键时恢复焦点。
而且我想在不泄漏到原始窗口的情况下捕获按键(就像XGrabKey可以做到的那样)。
参考文献:
1.... XGrabKey将窃取焦点... https://bugs.launchpad.net/gtkhotkey/+bug/390552/comments/8
1....程序接收控制以响应组合键执行某项操作。同时,程序已暂时聚焦... During XGrabKey(board), discover which window had been focused
- XGrabKeyboard函数主动获取键盘控制权并生成FocusIn和FocusOut事件。http://www.x.org/archive/X11R6.8.0/doc/XGrabKeyboard.3.html#toc3
1....我看不出有什么方法可以提供metacity当前的桌面更改行为(同时更改和显示弹出对话框),而不会导致窗口上出现抓取式焦点... https://mail.gnome.org/archives/wm-spec-list/2007-May/msg00000.html
1.... FocusOut事件发生时,全屏模式不应退出,同时显示NotifyGrab... https://bugzilla.mozilla.org/show_bug.cgi?id=578265
1.抓取键盘不允许更改焦点... grabbing keyboard doesnt allow changing focus
1.抓取生成的焦点事件(XGrabKeyboard的主动抓取和XGrabKey的被动抓取)http://www.x.org/releases/X11R7.6/doc/libX11/specs/libX11/libX11.html#Focus_Events_Generated_by_Grabs - XGrabKey源代码:也许我们可以修改它来消除焦点偏离事件?
1.有“DoFocusEvents(按键、老Win、抓取-〉窗口、通知抓取);“在激活键盘抓取()中:http://cgit.freedesktop.org/xorg/xserver/tree/dix/events.c
我正在写一个一键组合键(和鼠标移动)Map软件:https://code.google.com/p/diyism-myboard/
我在Windows中使用RegisterHotKey()和UnRegisterHotKey()实现了这一点:https://code.google.com/p/diyism-myboard/downloads/detail?name=MyBoard.pas
我想使用XGrabKey()和XUngrabKey()将其迁移到Linux中:https://code.google.com/p/diyism-myboard/downloads/detail?name=myboard.py
我已创建$10奖金来解决此问题。我们需要更多支持者来放置奖金。https://www.bountysource.com/issues/1072081-right-button-menu-flashes-while-jkli-keys-move-the-mouse-pointer
8条答案
按热度按时间hlswsv351#
我的当前代码(来自https://github.com/diyism/MyBoard/blob/master/myboard.py):
当我按下“shift”键时,焦点丢失,当我松开它时,焦点又回来了。
gkl3eglg2#
早在90年代初,我就研究过Irix、ultrix和solaris的全局热键,因为在我的Acorn BBC电脑上很容易做到。最终我们决定在xlib以下的级别上用一些专有代码以不可移植的方式解决这个问题。因为我们的软件安装需要超级用户权限,所以我们能够插入适当的软件钩子作为守护程序。
对于Linux(现在),你可能应该通过在操作系统级别处理键盘事件来寻找软件解决方案。我将从这里开始:http://code.google.com/p/logkeys/
一个更通用的解决方案是使用一个带有USB输入和USB输出的小型PC板,它可以充当鼠标和键盘,并根据需要转换键盘按键,但如果您想经常更改Map,则这种方法不太灵活。
pjngdqdw3#
最后,正如您所知,linux意味着自由,我修改了xserver以摆脱抓取式focusout:
而且我还需要摆脱GTK上下文菜单中的XGrabKeyboard:
现在myboard.py运行良好。
我已经把它从googlecode迁移到github:https://github.com/diyism/MyBoard
ocebsuys4#
看起来XQueryKeymap将对您进行排序。C++ source code I found请参见以下内容:
注意,这不是经过测试的代码,也不是我的--我只是在Internet上找到它。
vnjpjtjt5#
我有一个想法,我很确定它会起作用,但我必须上床睡觉,不能亲自测试它,而且它并不漂亮,因为我不认为有任何方法可以在X中实现你想要的效果。以下是我想到的步骤,简而言之:禁用X中的键盘,从较低级别的API读取事件,并选择性地将它们馈送给X。您必须禁用X中的键盘,因为否则,您可以查看事件,但无法停止它;你会把它和X放在一起读,而不是截取它
所以这里是打破了:
1)运行
xinput -list
以获取X正在使用的键盘2)运行
xinput list-props
id查找“Device Enabled”属性3)运行
xinput set-prop id prop 0
以禁用X中的设备:我不知道xinput在xlib级别上是如何工作的,为了简化实现,我只想在shell中调用它。
4)打开
/dev/input/eventX
,其中X是键盘设备。实际上,我会在/dev/input/by-id下搜索名称(在xinput -list中给出)并以这种方式打开它。这可能需要root用户,因为这些设备的权限通常非常严格。5)从此处读取键盘输入:
输入事件的数据格式为:
int是32位的,uscharges是16位的,因为你只对键盘输入感兴趣,你可以很简单地做到这一点:
6)当你得到一个你想捕获的事件时,你自己处理它。否则,使用XSendEvent把它发送到X,这样它就可以正常处理了。把你从/dev/input得到的硬件代码Map到适当的keysym可能是一个技巧,但是我相当肯定在xlib的某个地方有一个函数可以帮助你做到这一点。
7)后藤5并循环直到你完成
8)确保将所有内容都设置回退出时的状态,否则可能会将用户的键盘输入中断为X!
我建议用第二个usb键盘来测试这个,你可以用/dev/input和xinput来禁用和监听键盘,所以如果你崩溃了,你仍然有第一个键盘,并且正常工作。(实际上,我认为故意用第二个键盘来做这件事会很酷,热键加倍!)
但是,是的,需要根和潜在的离开键盘“分离”从X是不漂亮的,并与SendKey转发可能说起来容易做起来难,但我敢肯定,这 * 将 * 工作,并给予你最大的灵活性。
50few1ms6#
要编写一个键(快捷键)Map软件,还可以查看
[libtermkey](http://leonerds-code.blogspot.de/2011/05/libtermkey-read-keypresses-from.html)
,它是一个终端键输入库(用C编写),可以识别XTerm样式的鼠标位置/按钮报告、特殊键(如箭头键和功能键),包括Ctrl-Left
等“修改”键。例如,
[POE::Wheel::TermKey](http://cpansearch.perl.org/src/PEVANS/POE-Wheel-TermKey-0.02/README)
“是libtermkey
库的异步perl Package 器,它提供了一种抽象的方式来读取基于终端的程序中的按键事件。”hgc7kmma7#
你可以使用XQueryKeymap来读取事件,然后你可以使用XTestKey来发送一个退格键事件,然后发送你想要按下的键。更好的是,你可以使用register hotkeys来读取所有键盘事件,然后使用XTestKey来生成键事件。顺便说一句,KDE的“自定义快捷键”控制模块允许使用快捷键来生成按键。Source code。
3pmvbmvn8#
虽然我知道这个问题已经过时了,但它仍然是相关的,而且我已经找到了一个比修改xorg-server更易移植的解决方法。
基本上,当抓取窗口是主动聚焦窗口时,XGrabKey不发送聚焦事件。
如果您观察活动窗口,并在焦点变为新窗口时重置抓取,则不会生成事件。我发现观察
PropertyNotify
事件和查看_NET_ACTIVE_WINDOW
窗口属性可以很好地获取这些信息。我还没有发现任何有害的影响,或坦率地说,任何影响,设置抓取是当前活动的窗口。