9

我想在 Linux 下挂钩、拦截和生成键盘(make/break)事件,然后再将它们传递给任何应用程序。更准确地说,我想检测关键事件流中的模式,并能够根据检测到的模式将事件丢弃/插入到流中。

我已经看到了一些关于 SO 的相关问题,但是:

  • 要么他们只处理如何获取关键事件(键盘记录器等),而不是如何操纵它们的传播(他们只听,但不拦截/生成)。
  • 或者他们在 X 中使用被动/主动抓取(阅读下面的更多内容)。

小型 DSL

我在下面解释了这个问题,但为了使它更紧凑和易于理解,首先是一个小的 DSL 定义。

  • A_:用于制作(按下)键A
  • A^: 用于中断(释放)键 A
  • A^->[C_,C^,U_,U^]A^发送 C 的通断组合,然后 U 进一步向下处理链(最后到应用程序)。如果没有,->则没有发送任何内容(但可能会修改内部状态以检测后续事件)。
  • $X: 执行任意动作。这可以是发送一些可配置的键事件序列(可能类似于C-x C-semacs),或者执行一个函数。如果我只能发送关键事件,那就足够了,因为我可以根据哪个应用程序处于活动状态,在窗口管理器中进一步处理这些事件。

问题描述

好的,使用这个符号,这里是我想要检测的模式以及我想要在处理链中传递的事件。

  1. A_, A^->[A_,A^]: 解释 见上文,请注意发送发生在A^.
  2. A_, B_, A^->[A_,A^], B^->[B_,B^]:与1基本相同,但重叠事件不会改变处理流程。
  3. A_, B_, B^->[$X], A^:如果一个键 (B) 完全通/断,而另一个键 (A) 被按住,则执行 X(见上文),并且 A 的断点被丢弃。

(原则上它是一个简单的状态机,通过键事件实现,可以生成(多个)键事件作为输出)。

补充说明

  • 该解决方案必须以打字速度工作。
  • 修改后的关键事件流的使用者在 Linux 上的 X 下运行(控制台、浏览器、编辑器等)。
  • 只有键盘事件影响处理(没有鼠标等)
  • 匹配可以发生在键符(更容易)或键码(更难)上。对于后者,我只需要读取映射即可将代码转换为键符。
  • 如果可能的话,我更喜欢一个既适用于 USB 键盘又适用于虚拟机内部的解决方案(如果在驱动程序层工作可能会出现问题,其他层应该没问题)。
  • 我对实现语言非常开放。

可能的解决方案和问题

所以基本问题是如何实现这一点。

我已经在窗口管理器中使用被动抓取 ( XGrabKey) 和XSendEvent. 不幸的是,被动抓取在这种情况下不起作用,因为它们B^在上面的第二种模式中没有正确捕获。原因是转换后的抓取结束A^而不是继续B^。如果仍然持有但仅在约 1 秒后,新的抓取将转换为捕获 B。否则B^将向应用程序发送一个plain。这可以用 来验证xev

我可以将我的实现转换为使用主动抓取XGrabKeyboard(X 文档将主动抓取称为具有侵入性并且专为短期使用而设计。如果有人有这方面的经验并且长期主动抓取没有重大缺点,那么我会认为这是一个解决方案。

我愿意看看除了窗口管理器(作为 X 客户端运行)之外的其他关键事件处理层。只要我能用它们解决上述问题,键盘驱动程序或映射都是可能的。这也意味着解决方案不必是单独的应用程序。让驱动程序或内核模块为我执行此操作非常好。请注意,尽管我从未做过任何内核或驱动程序编程,所以我会很感激一些好的资源。

感谢您的任何指点!

4

1 回答 1

3

使用 XInput2 使设备(键盘)浮动,然后监视设备上的 KeyPress 和 KeyRelease 事件,使用 XTest 重新生成 KeyPress 和 KeyRelease 事件。

于 2010-10-21T15:56:04.557 回答