在Linux下删除/重写/生成键盘事件 [英] drop/rewrite/generate keyboard events under Linux

查看:80
本文介绍了在Linux下删除/重写/生成键盘事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在Linux下将它们传递给任何应用程序之前,将其挂接到,拦截并生成键盘(接通/断开)事件.更准确地说,我想检测关键事件流中的模式,并能够根据检测到的模式将事件丢弃/插入事件流中.

I would like to hook into, intercept, and generate keyboard (make/break) events under Linux before they get delivered to any application. More precisely, I want to detect patterns in the key event stream and be able to discard/insert events into the stream depending on the detected patterns.

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

I've seen some related questions on SO, but:

  • 他们要么只处理如何获取关键事件(关键记录器等),要么不处理如何传播事件(它们仅侦听,但不拦截/生成).
  • 或者他们在X中使用被动/主动抓斗(请参阅下文中的更多内容).

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

I explain the problem below, but to make it a bit more compact and understandable, first a small DSL definition.

  • A_:用于制作(按)键A
  • A^:用于中断(释放)键A
  • A^->[C_,C^,U_,U^]:在A^上,发送C的通行/断开组合,然后将U进一步发送到处理链(最后到应用程序).如果没有->,则什么也没有发送(但可以修改内部状态以检测后续事件).
  • $X:执行任意操作.这可以发送一些可配置的键事件序列(对于emacs可能类似于C-x C-s)或执行一个函数.如果我只能发送键事件,那就足够了,因为然后我可以根据活动的应用程序在窗口管理器中进一步处理这些事件.
  • A_: for make (press) key A
  • A^: for break (release) key A
  • A^->[C_,C^,U_,U^]: on A^ send a make/break combo for C and then U further down the processing chain (and finally to the application). If there is no -> then there's nothing sent (but internal state might be modified to detect subsequent events).
  • $X: execute an arbitrary action. This can be sending some configurable key event sequence (maybe something like C-x C-s for emacs), or execute a function. If I can only send key events, that would be enough, as I can then further process these in a window manager depending on which application is active.

好的,因此使用此符号,这是我要检测的模式以及要在处理链中传递的事件.

Ok, so with this notation, here are the patterns I want to detect and what events I want to pass on down the processing chain.

  1. A_, A^->[A_,A^]:爆炸参见上文,请注意发送发生在A^上.
  2. A_, B_, A^->[A_,A^], B^->[B_,B^]:与1基本相同.但是重叠的事件不会改变处理流程.
  3. A_, B_, B^->[$X], A^:如果在按住另一个键(A)的同时完成了一个键(B)的完全接通/断开,则执行X(请参见上文),并丢弃A的断开.
  1. A_, A^->[A_,A^]: expl. see above, note that the send happens on A^.
  2. A_, B_, A^->[A_,A^], B^->[B_,B^]: basically the same as 1. but overlapping events don't change the processing flow.
  3. A_, B_, B^->[$X], A^: if there was a complete make/break of a key (B) while another key was held (A), X is executed (see above), and the break of A is discarded.

(从原理上讲,这是一个在键事件上实现的简单状态机,可以生成(多个)键事件作为输出).

(it's in principle a simple statemachine implemented over key events, which can generate (multiple) key events as output).

  • 该解决方案必须以打字速度工作.
  • 修改后的键事件流的消费者在Linux上的X下运行(控制台,浏览器,编辑器等).
  • 只有键盘事件会影响处理(没有鼠标等)
  • 匹配可以发生在keyyms(容易一些)或keycodes(更困难一些)上.对于后者,我只需要阅读映射即可将代码转换为键符.
  • 如果可能的话,我希望能同时使用USB键盘和虚拟机的解决方案(如果在驱动程序层工作可能会出现问题,其他层应该没问题).
  • 我对实现语言很开放.

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

So the basic question is how to implement this.

我已经在窗口管理器中使用被动抓取(XGrabKey)和XSendEvent实现了一个解决方案.不幸的是,被动抓取在这种情况下不起作用,因为它们无法在上述第二种模式中正确捕获B^.原因是转换后的抓取在A^上结束,并且没有继续到B^.如果仍保持但仅在约1秒后,新的抓斗将转换为捕获B.否则,将普通B^发送到应用程序.可以使用xev进行验证.

I have implemented a solution in a window manager using passive grabs (XGrabKey) and XSendEvent. Unfortunately passive grabs don't work in this case as they don't capture correctly B^ in the second pattern above. The reason is that the converted grab ends on A^ and is not continued to B^. A new grab is converted to capture B if still held but only after ~1 sec. Otherwise a plain B^ is sent to the application. This can be verified with xev.

我可以将实现转换为使用主动抓取(XGrabKeyboard),但是如果窗口管理器始终一直在键盘上进行主动抓取,则我不确定对其他应用程序的影响. X文档将主动抓取称为侵入性的,并且设计用于短期使用.如果有人对此有经验,并且长期积极争取并没有重大弊端,那么我会认为这是一种解决方案.

I could convert my implementation to use an active grab (XGrabKeyboard), but I'm not sure about the effect on other applications if the window manager has an active grab on the keyboard all the time. X documentation refers to active grabs as being intrusive and designed for short term use. If someone has experience with this and there are no major drawbacks with longterm active grabs, then I'd consider this a solution.

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

I'm willing to look at other layers of key event processing besides window managers (which operate as X clients). Keyboard drivers or mappings are a possibility as long as I can solve the above problem with them. This also implies that the solution doesn't have to be a separate application. I'm perfectly fine to have a driver or kernel module do this for me. Be aware though that I have never done any kernel or driver programming, so I would appreciate some good resources.

感谢任何指针!

推荐答案

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

Use XInput2 to make device(keyboard) floating, then monitor KeyPress and KeyRelease event on the device, using XTest to regenerate KeyPress & KeyRelease event.

这篇关于在Linux下删除/重写/生成键盘事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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