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) AA^ : for break (release) key AA^->[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!
linux keyboard keyboard-events linux-device-driver xlib
Heron
source share