Re: How can I modify a keyboard event before it reaches an app?
Jim Peters <[email protected]>
| Newsgroups | gmane.comp.xfree86.forum |
|---|---|
| Message-ID | <[email protected]> |
Randy Kramer wrote: > Maybe your question should have been over on [email protected]. From the description of that list it looked to me like that was for people working on the X server codebase itself rather than people coding X clients. Maybe I'll ask there if I don't make much progress here. > I probably can't help you much, but I have similar desires, so we > may be able to compare notes. I am particularly interested in > mapping a keypress to a sequence of keypresses. I have vague hopes > of trying to modify the X server to do so, but I'm a newbie to C and > to the X codebase. Yes, I think it should (hopefully) be relatively easy to hack this into the X server -- in a hardcoded form, at least. But that does mean that I can't then release my new window manager out for the rest of the world to use, because it requires modifications to the server, which would be a shame. > Out of curiosity, how did you map common code fragments to shortcut > keys in the Linux console? Can you point me to a HOWTO or the name > of a utility? The equivalent of "xmodmap" on the Linux console is "loadkeys", which is a lot more flexible, allowing you to attach strings to keys and handle multiple modifiers. For example, this is the mapping for the 'I' key I use: keycode 23 = i I F66 F50 ctrlr keycode 23 = Insert control keycode 23 = Tab alt keycode 23 = Meta_i shift alt keycode 23 = Meta_I control alt keycode 23 = Meta_Tab I've changed the modifier key labels around in the keymap to make it easier for me (so ctrlr is actually AltGr), but this definition means that pressing the right-control and 'I' gives 'F66' and shift-right-control 'I' gives 'F50'. These are defined as follows: string F66 = "if (" string F50 = "int " You can include control characters and escape sequences in these strings, so it is easy to do emacs commands, word-forward, word-back and so on. I even have a separate app updating a couple of the keystrings with the current date/time via system calls, so I can type the current time into any console app/shell/etc with a keypress. > After a little bit of investigation, I decided that the right place to > do it is in the X server. My reasoning starts with that the X server > handles the keyboard inputs anyway, I want them to be sent to whichever > X client window has the focus, and I want them to be appear exactly > like regular keystrokes. (I found some X utilities that were a step in > the right direction, but they sent keystrokes that were somehow > recognizable by the X clients as faked, or from a different source > which they could reject. Hence, that utility didn't work for all X > clients, notably Mozilla and KDE apps, IIRC.) Okay, interesting. I know that events sent with XSendEvent do have a flag set on them to warn apps that they have been 'faked'. I found a tool called 'xvkbd' that pops up a virtual keyboard, and that uses either XSendEvent, or preferably the XTEST extension, to fake the key events. The big problem with this kind of approach (without hacking the X server) is that there have to be two streams of keyboard events coming out of the server -- one that is the 'original' stream which goes only to the event-mapping client, and also the modified stream (forced through with XSendEvent or XTEST, perhaps) which goes to the focus window -- but both of these event streams are forced to come down the same channel. I've had a quick look at XTEST, and it looks like the only chance of getting this to work might be to do an active or passive grab on the keyboard to either catch all key events or to catch the chosen modifiers, and when it comes to the time to force some events to the focus window, force the keys the user is actually pressing to be released through XTEST, perhaps manually let go of the grab through Xlib calls if necessary, and then fake the replacement key presses with XTEST, before reinstating the grab, faking the re-pressing of the user's actual keys and then waiting again for some more to arrive. This might just about be a viable solution, if I am lucky. There could be problems, though, if the user presses or releases a key whilst all this XTEST forced pressing and unpressing is going on. > > My initial attempts have not been very successful, and I am > > wondering if what I hope to achieve is in fact impossible. > > Nope. If dos and Windows can do it, Linux has a chance ;-) Not if the basic design of X gets in the way! At least, it is possible that it requires a new (or modified) X extension to support this kind of thing. > I should note that the people who've replied to me on the forum or > XFree86 lists have stated that the X server is not the right place to > do that, and pointed me to some other potential solutions. > > * http://twiki.org/cgi-bin/view/Wikilearn/XServerModificationProject I looked at XIM, but it seems to me that this is of no use because it doesn't seem to generate standard KeyPress events. All your apps would need to be XIM-aware for it to work. > * http://bugs.xfree86.org/cgi-bin/bugzilla/show_bug.cgi?id=43 This is interesting. I've actually already written the code to convert my chosen key mappings to/from keycodes and modifier maps, so that part is not a problem. If a quick personal hack to the X server is all that is required, then this is probably no big deal. However, if you are hoping for a "good solution", i.e. something that might end up in the future codebase as an extension or whatever, then this is a lot more work. I found this page on XKB (an X extension): http://www.pango.org/input-resources.shtml The 'unreliable guide to XKB' linked from there is also interesting (I am also a Happy Hacking Keyboard user): http://www.charvolant.org/~doug/xkb/ So, maybe XKB is a possible candidate, but it does say there that XKB is very poorly documented. I notice that Ivan Pascal, the guy who mentioned using the "Compose" key functionality in that discussion on the 'bugs' page, is also someone who has done some experimentation with XKB. (See the links from the Pango page, and the bibliography on the 'unreliable guide'). I can't figure out what he is talking about a 'compose' file with Xlib, though -- whether this is connected with XKB or not. > My opinion is that it belongs in the X server. That seems to be a > minority opinion, and a patch might never make it into CVS. (And I > might never manage to create a patch.) Still that is my preference. The way I see it at present there are these options: - X client to do the mapping, using passive modifier grabs to get the key events, and XTEST to force the mapped key events through. This needs to be tried, and if we're lucky it will work. - Using the XKB extension and maybe some undocumented features of it (like 'compose' strings or something, if they exist). - Hacking the X server or an extension or whatever. This is cleanest from the point of view of X clients, but not at all easy to release to the rest of the world. My time is limited due to work, but I think I will put some time in to try the first of these options soonish. Jim -- Jim Peters (_)/=\~/_(_) [email protected] (_) /=\ ~/_ (_) Uazú (_) /=\ ~/_ (_) http:// B'ham, UK (_) ____ /=\ ____ ~/_ ____ (_) uazu.net SBaGen: binaural beats for brainwave entrainment: http://uazu.net/SB