views:

378

answers:

1

I'm looking for a way to add one more "layout" to my keyboard. I'm already using a layout that uses altgr for local alphabet letters. What I'd like to add is a mirrored righthand-side keyboard that's activated with the caps-lock (one described in http://xkcd.com/mirrorboard.xkb)

Unfortunately ISO_LEVEL3_SHIFT is already taken by local alphabet. (AFAIK) If I use mode_shift to change groups I cannot use more than 2 levels in a group anymore. Is there a way to create different groups for both altgr and mode_shift?

+1  A: 

For each keycode definition you can have up to eight keysyms. These are organized pairwise into four groups. There is a family of keysyms ISO_Next_Group, ISO_Prev_Group, ISO_First_Group, and ISO_Last_Group that, when pressed, cycle the keysym output by striking the key among the keysym groups. These keys are how you attain multiple layouts.

As an example, assuming ISO_Next_Group has been bound to a keycode and assigned to a modifier, then for this definition:

keycode 53 = x X   Greek_xi Greek_XI   multiply U2297   U24E7 U24CD
pressing my keyboard key with the label “X” on types out “x”. After pressing the `ISO_Next_Group` key, I get “ξ”. Pressing it again, I get “×”. Pressing it again, “ⓧ”. Finally, pressing it a fourth time gets things back to normal.
Having spend several days (because Xkb¹ has horrible documentation; finally found an okay guide here), you can create a symbol definition file with entries like this:
    key <SPCE> {
// Level  I      II       III    IV
        [ space, space,   U2395, U2592 ],    // Group 1
        [ U2423, emspace, U2420, hairspace ] // Group 2
    };

    key <RALT> {
        [ Mode_switch, Mode_switch ]
    };

    key <RCTL> {
        [ ISO_Level3_Shift, ISO_Level3_Shift ]
    };

The brackets enclose a single group. Normally, the first group is active. The group can be temporarily incremented by one with ISO_Group_Shift, a.k.a. Mode_switch. Within a group, the symbols emitted are defined in increasing levels. Level I is with a bare keypress. Shift adds one to the current level. ISO_Level3_Shift sets the level to III.

The example above maps seven symbols to the space bar plus various shift keys such that:

space ⟨ ⟩ U+0020 SPACE
Shift+space ⟨ ⟩ U+0020 SPACE
R. Alt+space ⟨␣⟩ U+2423 OPEN BOX
R. Alt+Shift+space ⟨ ⟩ U+2003 EM SPACE
R. Ctl+space ⟨⎕⟩ U+2395 APL FUNCTIONAL SYMBOL QUAD
R. Ctl+Shift+space ⟨▒⟩ U+2592 MEDIUM SHADE
R. Alt+R. Ctl.+space ⟨␠⟩ U+2420 SYMBOL FOR SPACE
R. Alt+R. Ctl.+Shift+space ⟨ ⟩ U+200A HAIR SPACE

There is also a key ISO_Level5_Shift for level V. So you can have at least six symbols for one level. With the mode shift key this implies that you can configure your keyboard to type out approximately 1,200 distinct symbols, but at that point holding down so many modifiers will likely deaden a few keys.

P.S. The names of all the named symbols are stored in /usr/include/X11/keysymdef.h.


¹ Turns out that xmodmap(1) is buggy and deprecated.

Cirno de Bergerac
Just wondering - is there a way to make some key a modifier that way? So that it does ISO_Next_Group on press and ISO_Prev_Group on release?
viraptor