Drop / rewrite / generate keyboard events under Linux

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

I saw some related questions about SO, but:

  • or they only deal with how to get to key events (key registrars, etc.), and not how to manipulate their distribution (they only listen, but do not intercept / generate).
  • or they use passive / active capture in X (more on this below).

Little dsl

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

  • A_ : for the make key (press) A
  • A^ : for break (release) key A
  • A^->[C_,C^,U_,U^] : on A^ send the make / break compilation to C, and then U further down the processing chain (and, finally, to the application). If not -> , then nothing is sent (but the internal state can be changed to detect subsequent events).
  • $X : perform an arbitrary action. This could be sending some custom key event sequence (possibly something like Cx Cs for emacs) or executing a function. If I can only send key events, that would be enough, since I can then process them in the window manager depending on which application is active.

Description of the problem

So, with this notation, here are the patterns that I want to define and which events I want to convey in the processing chain.

  • A_, A^->[A_,A^] : expl. see above, please note that the transfer takes place on A^ .
  • A_, B_, A^->[A_,A^], B^->[B_,B^] : basically the same as 1. but overlapping events do not change the flow of processing.
  • A_, B_, B^->[$X], A^ : if a complete make / break of the key (B) was performed, when another key (A) was saved, X is executed (see above), and the gap A is discarded.

(this is, in principle, a simple statistics machine, implemented by key events, which can generate (several) key events as an output).

Additional notes

  • The solution should work at input speed.
  • Consumers of a modified stream of key events are launched under X on Linux (consoles, browsers, editors, etc.).
  • Processing is affected only by keyboard events (without a mouse, etc.).
  • Matching can occur on keys (a little easier) or on a keyboard (a little harder). With the latter, I just need to read in cartography to translate from code to keysym.
  • If possible, I would prefer a solution that works both with a USB keyboard and inside a virtual machine (it can be a problem when working at the driver level, other levels should be in order).
  • I am pretty good at implementation language.

Possible solutions and questions

So, the main question is how to implement this.

I implemented the solution in the window manager using passive captures ( XGrabKey ) and XSendEvent . Unfortunately, passive captures do not work in this case, since they do not fix B^ correctly in the second figure above. The reason is that the converted capture ends at A^ and does not continue until B^ . A new capture is converted to capture B if it is still held, but only after ~ 1 sec. Otherwise, the regular B^ sent to the application. This can be verified with xev .

I could transform my implementation to use active capture ( XGrabKeyboard ), but I'm not sure about the impact on other applications if the window manager constantly activates the capture on the keyboard. X refers to active grips as intrusive and intended for short-term use. If someone has experience with this, and there are no serious flaws with long active grabs, I would consider this a solution.

I want to see other levels of key event processing, except for window managers (which work as X clients). Keyboard drivers or mappings are an option if I can solve the above problem with them. It also means that the solution does not have to be a separate application. I understand very well that a driver or kernel module does this for me. Keep in mind that I never programmed a kernel or driver, so I would appreciate some good resources.

Thanks for any pointers!

+6
linux keyboard keyboard-events linux-device-driver xlib
source share
1 answer

Use XInput2 to float the device (keyboard), then track the KeyPress and KeyRelease event on the device, using XTest to recover KeyPress and KeyRelease events.

+3
source share

All Articles