I have for years used a home-made keyboard remapping program under
Windows, which allows me to map control keys (actually, the caps-lock
+ alphabetic keys) to cursor control keys. For instance, ^H is left
one character (= left arrow), ^J down one line (= down arrow), ^W
forward one word (= control right arrow), and so forth. My Windows
remapping program is written in C, compiles to an exe and a dll,
intercepts the keystrokes at the system level using an OS hook, and
outputs the desired cursor keys.
Some of this remapping I've been able to do in Linux (Ubuntu) using
xkb. However, there are a number of things that I haven't been able
to figure out how to do, and which it appears to me are in fact not
possible using xkb. I'm hoping someone will prove me wrong!
One limitation of xkb is that, AFAICT, xkb limits the output to one
keystroke per input keystroke. While the mappings listed above are
one-to-one (and I have them working under xkb), several of my mappings
are one-to-many. For example, ^D outputs seven down arrow keystrokes,
and ^U outputs seven up arrow keystrokes. Now several of the xkb
compatibility map functions have a 'count' parameter, including
DeviceButton. But the RedirectKey() function does not. I have
thought about using DeviceButton() mapped to an imaginary device to
produce seven imaginary button presses, and then mapping each of those
button presses back to a keystroke--but if it's possible for xkb to
use as input its own output, I don't know how to do that. Nor can I
figure out a work-around; it does not appear possible to simply
include more than one key as an arg to RedirectKey(), nor to include
RedirectKey() more than once for any given keystroke combination. (In
the case of my ^D and ^U, the output is seven identical keystrokes. I
have a few keystroke mappings where the output should be a sequence of
distinct keystrokes.)
I also can't figure out how to persuade xkb to output as control
characters those <capslock> keystrokes that I don't want changed,
other than converting the <capslock> to a <control> key. For example,
I want <capslock>s to produce a <control>s. It appears to me that xkb
refuses to do this kind of mapping where the input alphabetic
keystroke is the same as the output alphabetic keystroke: I can map
<capslock>s to <control>f, but not to <control>s. I suspect that if I
*always* wanted to do this, it would be trivial with xkb: I would just
map the <capslock> key to a <control> key. The problem is that I
*don't* always want to do that, in particular I don't want to do it
where I map a <capslock> key to a cursor key.
There are a couple other potentially tricky mappings which I haven't
tried yet, because unless I could fix the above problems, there was no
sense in figuring out how to do these. But maybe I just haven't
interpreted the documentation for xkb correctly, and someone will tell
me the problems sketched above are simple to fix.
Alternatively, maybe I would be better off writing my own keyboard
driver in C. I haven't tried that, because I'm not sure where I would
start, nor do I know how I would use such a driver if I did write it.
(Do you create a shared object library, like my Windows remapper? Or
does the driver get loaded some other way?)
So my question is, are there solutions in xkb to the problems I've
sketched above? Specifically the inability to output > 1 keystroke
per input keystroke, and the problem of mapping some (but not all)
<capslock><alpha> keystrokes to <control><alpha> keystrokes?
I can upload my xkb file if that would help.
BTW, here is some of the more useful documentation I've found for xkb:
http://pascal.tsu.ru/en/xkb/
http://hektor.umcs.lublin.pl/~mikosmul/computing/articles/custom-keyboard-layouts-xkb.html
http://www.charvolant.org/~doug/xkb/
http://www.xfree86.org/current/XKBproto.pdf
Mike Maxwell
Get the source code to the version of xkb that you are using.
Enabling multiple output keystrokes per single input keystroke
should be as "simple" as putting a loop around the call to
XSendEvent which specifies the translated output. Subsetting
the transformation for <modifier><alpha> is likely to be a matter
of how to specify the subset in the first place.
In some respects the X Window System is designed for such translations
to occur separately in each client application, using [among others]
XRebindKeysym and XLookupString. This is the only way to avoid
"fighting" between multiple simultaneous clients with different
conventions and independently-varying keyboard focus, which is
the usual case in X11.
> BTW, here is some of the more useful documentation I've found for xkb:
*Thank you* for including the list of documents!
Sometimes old documentation can help, too, especially for details at a
very low level. Adrian Nye, Xlib Programming Manual (Volume 1),
O'Reilly & Associates Inc, 1990, ISBN 0-937175-11-0.
--
Hmm...is this still valid for the current version of X-win? Looks
like his mapkey.c program could be modified to do what I want... I
think I'll give it a shot. (One of the reviewers at O'Reilly says the
example programs he's tried do work in X11R6.)
(http://www.sbin.org/doc/Xlib/chapt_09.html)
Mike Maxwell
Tried it, and it does indeed work...up to a point. It calls a
function
XChangeKeyboardMapping(), the third arg of which is
keysyms_per_keycode
The man page says this "Specifies the number of KeySyms per KeyCode."
This would, IIUC, allow me to map e.g. ^D to a sequence of seven
<Down>
keysyms. But AFAICT, this arg has no effect whatever: I can pass an
array
of > 1 keysym (in the fourth arg), but only the first one winds up in
the map.
(The array seems to be correct, because if I set keysyms_per_keycode
to 1,
and num_codes to 2, both the keycode I pass and the "next" one get
mapped.)
I suspect I should post this problem on comp.windows.x. Thanks for
the
help here!
Mike Maxwell