我想在 Linux 下挂钩、拦截和生成键盘(make/break)事件,然后再将它们传递给任何应用程序。更准确地说,我想检测关键事件流中的模式,并能够根据检测到的模式丢弃/插入事件到流中。
我在 SO 上看到了一些相关问题,但是:
- 它们要么只处理如何获取关键事件(按键记录器等),而不是如何操纵它们的传播(它们只监听,但不拦截/生成)。
- 或者他们在 X 中使用被动/主动抓取(请阅读下面的更多内容)。
小型 DSL
我在下面解释这个问题,但为了使其更加紧凑和易于理解,首先是一个小的 DSL 定义。
-
A_
:用于 make(按)键 A
-
A^
:用于中断(释放)键 A
-
A^->[C_,C^,U_,U^]
: on A^
向 C 发送通断组合,然后向 U 进一步发送处理链(最后发送至应用程序)。如果没有->
那么就没有发送任何内容(但内部状态可能会被修改以检测后续事件)。
-
$X
:执行任意动作。这可以发送一些可配置的关键事件序列(可能类似于C-x C-s
对于 emacs),或执行一个函数。如果我只能发送关键事件,那就足够了,因为我可以根据哪个应用程序处于活动状态在窗口管理器中进一步处理这些事件。
问题描述
好的,通过这种表示法,以下是我想要检测的模式以及我想要沿着处理链传递的事件。
-
A_, A^->[A_,A^]
: 解释。参见上文,请注意发送发生在A^
.
-
A_, B_, A^->[A_,A^], B^->[B_,B^]
:与1基本相同,但重叠事件不会改变处理流程。
-
A_, B_, B^->[$X], A^
:如果在按住另一个键(A)时有一个键(B)的完整接通/断开,则执行X(见上文),并且丢弃A的断开。
(原则上它是一个通过按键事件实现的简单状态机,它可以生成(多个)按键事件作为输出)。
补充笔记
- 该解决方案必须以打字速度运行。
- 修改后的关键事件流的使用者在 Linux 上的 X 下运行(控制台、浏览器、编辑器等)。
- 只有键盘事件影响处理(没有鼠标等)
- 匹配可以发生在键符号(更容易一点)或键码(更难一点)上。对于后者,我只需要读取映射即可从代码转换为键符号。
- 如果可能的话,我更喜欢一个既可以与 USB 键盘一起使用也可以在虚拟机内部使用的解决方案(如果在驱动程序层工作可能会出现问题,其他层应该没问题)。
- 我对实现语言持开放态度。
可能的解决方案和问题
所以基本问题是如何实现这一点。
我已经在窗口管理器中使用被动抓取实现了一个解决方案(XGrabKey
) and XSendEvent
。不幸的是,被动抓取在这种情况下不起作用,因为它们无法正确捕获B^
在上面的第二个模式中。原因是转换后的抓取结束于A^
并且不会继续B^
。如果仍然按住,但仅在大约 1 秒后,新的抓取就会转换为捕获 B。否则就是普通的B^
被发送到应用程序。这可以通过以下方式验证xev
.
我可以将我的实现转换为使用主动抓取(XGrabKeyboard
),但我不确定如果窗口管理器始终有效地抓住键盘,对其他应用程序的影响。 X 文档将主动抓取称为侵入性的并且是为短期使用而设计的。如果有人有这方面的经验,并且长期主动抓取没有重大缺点,那么我会认为这是一个解决方案。
除了窗口管理器(作为 X 客户端运行)之外,我愿意查看关键事件处理的其他层。键盘驱动程序或映射是可能的,只要我能用它们解决上述问题。这也意味着解决方案不必是单独的应用程序。我完全可以让驱动程序或内核模块为我做这件事。请注意,虽然我从未做过任何内核或驱动程序编程,所以我会欣赏一些好的资源。
感谢您的指点!
使用XInput2使设备(键盘)浮动,然后监视设备上的KeyPress和KeyRelease事件,使用XTest重新生成KeyPress和KeyRelease事件。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)