The documentation says that keysyms_per_keycode "Specifies the number
of KeySyms per KeyCode." That's not much to go on, but what I gather
it means is that you could map a keycode to a sequence of keysyms.
Specifying a keysyms_per_keycode value of 2 (and giving a keysyms
array that's of length 2) should assign the sequence of keysyms to the
keycode, I would have thought. That's exactly what I want to do, but
I can't get it to work.
The code I'm using is this (extraneous detail omitted, but I've been
hard-coding this into Adrian Nye's 'mapkeys' program in his Xlib
Programming Manual):
KeySym NewSyms[2];
...
KeySym[0] = XStringToKeysym("Up");
KeySym[1] = XStringToKeysym("Left");
XChangeKeyboardMapping(display, XK_F1, 2, NewSyms, 1);
...
What I would expect this to do is to assign the sequence <Up><Left> to
the F1 key. It does not; it only assigns the first keysym, <Up>, to
the F1 key (the second keysym, <Left>, is apparently ignored). I've
tested this in applications, and with xev.
What am I doing wrong? Does anyone have examples of using the
XChangeKeyboardMapping() function with keysyms_per_keycode > 1? I've
googled for examples, but can't find any. (I did run across a 1992
posting to some newsgroup complaining that he couldn't get this to
work either, but there were no responses.)
BTW, the other numeric arg to XChangeKeyboardMapping(), num_codes,
seems to work just fine.
In case it matters, I'm testing this on the current version of Ubuntu,
with Gnome.
Mike Maxwell
You should go read the keyboard section of the X Window System Protocol
specification (look for a file called proto.txt, proto.ps, or proto.pdf),
which explains keycodes and keysyms and how they relate to each other.
The set of keysyms attached to a keycode is not a "sequence" like you want it
to be. It's the set of alternative symbols that can be generated by a key
depending on which modifiers (Shift, ShiftLock, CapsLock, NumLock, etc.) are
in effect.
Run "xmodmap -pke" to see a bunch of examples. Each line will show a single
keycode and a list of keysyms associated with it. You'll probably see that
most keycodes have 2 keysyms (regular and shifted), although some might have
more, especially in a non-US keyboard layout.
This line for example:
keycode 13 = 4 dollar
indicates that keycode 13 on my keyboard is the key which generates the
keysym XK_4 or XK_dollar, depending on whether the Shift modifier is in
effect. That key has 2 keysyms. Its keysyms_per_keycode is 2.
XKB adds more features on top of the minimal X protocol, but I don't think
"generating a series of multiple KeyPress/KeyRelease events in response to a
single physical keypress" is one of them. (Maybe I'm wrong... I tried to read
the XKB specification once, but it's soooo long and boring!)
--
Alan Curry
Rats, I was hoping that XChangeKeyboardMapping() would allow me to do
things that xkb and xmodmap do not. AFAIK, neither of them allows
generating a sequence of keysyms from a single keycode, either. (xkb
does have a 'count' arg, but it's only for "button presses" on other
devices, not for keyboard remapping; presumably this allows mapping a
middle button click on the mouse to a double left click, for example.
If there's a way to use the button press mechanism for the keyboard, I
haven't discovered it.)
So what do I need to do in order to map a keycode like ^D to a
sequence of keysyms (<down><down><down><down><down><down><down>)? Do
I need to intercept things at the keyboard driver level, and convert
<caps>D to the sequence there? (That would presumably require
interecepting the key strokes for press/release 'd' and checking
whether the <capslock> key was down. It's basically what I do in my
Microsoft Windows keystroke remapper.) Or is there some intermediate
level where I can do this--say, by mapping <caps>D to F15 (a key which
I don't use), and then at some later level mapping the F15 key to
<down><down><down><down><down><down><down>?
Mike Maxwell
xmodmap is nothing more or less than a shell-script-level interface to
XChangeKeyboardMapping (and a few other keyboard/pointer functions). There
shouldn't be any features that you can access by writing your own C code that
aren't exposed by xmodmap.
>So what do I need to do in order to map a keycode like ^D to a
>sequence of keysyms (<down><down><down><down><down><down><down>)? Do
Many programs allow you to specify a Translation Table via .Xresources, which
can bind multiple actions to a single input event.
Or... get xbindkeys and xmacro, write a shell script that invokes xmacro to
inject a series of key events, and use xbindkeys to run that script whenever
the key combination is pressed.
Or... study the xbindkeys and xmacro source code, and combine their
functionality into a single client dedicated to this purpose. (You just need
to understand XGrabKey, XSendEvent or XTest, and a basic event loop)
--
Alan Curry