Two years later, I am finally proud to answer my own question.
I have found the easiest, most reliable and most extendable method is to solely rely on xmodmap
.
1. Get keycodes of special keys
Run xev
to determine the key code of keys you wish to use as mode switchers. Then press the keys you are interested in and note down the keycode
$ xev
KeyRelease event, serial 40, synthetic NO, window 0x2600001,
root 0x2a6, subw 0x0, time 1221887800, (885,743), root:(3447,805),
state 0x2010, keycode 66 (keysym 0xff7e, Mode_switch), same_screen YES,
XLookupString gives 0 bytes:
XFilterEvent returns: False
The keycode is on the third line, keycode 66.
For me, these were the keys I was particularly interested in, and their corresponding key codes for me:
Caps Lock
, keycode 66
Pause|Break
, keycode 128
Left Windows key
, keycode 133
Num Lock
, key code 77
2. Set switcher keys
This is the setup I have opted for, but you can choose your own setup. I have saved this to a file $HOME/.xmodmap
.
~/.xmodmap
keycode 66 = Mode_switch
keycode 127 = Multi_key
keycode 133 = Super_L
...
This way I have bound Caps Lock
to Mode_switch
, Pause Break
to Compose
and the left Win
key to Super_L
. The Compose
key is particularly useful as it allows two keys to be combined to ligature. E.g. Compose
followed by T
and M
results in the trademark sign ™
.
3. Get current keymap bindings of xmodmap
In order to not destroy my keyboard layout, I wanted to keep my keys as close to my original layout as possible. In order to do that I printed the current keymap and looked for the keycodes I wanted to change.
$ xmodmap -pke | ag 'keycode 51'
Off course, you could just as easily use grep
or ack
, depending on the tool you prefer to use.
$ xmodmap -pke | grep 'keycode 41'
$ xmodmap -pke | ack 'keycode 31'
The output of this is in the same format as the one you specify in your ~/.xmodmap
like this:
keycode 31 = i I i I rightarrow idotless rightarrow idotless i I rightarrow idotless i I rightarrow idotless
4. Backup your existing xmodmap
Just in case something goes wrong, it's never a bad Idea to have your current xmodmap
available to fall back to easily.
$ xmodmap -pke > ~/.xmodmap.bak
5. Add characters to 2nd, 3rd, 4th level of your keys
As far as I have understood, the format of the .xmodmap
file is like this:
keycode <keycode> = <1st level> <Shift+1st> <2nd level> <shift+2nd> <3rd level> <shift+3rd level> <4th level> <shift+4th> ...
Now, I don't understand all those levels but Mode_Switch
(Caps Lock
in my case) will give you level 2 and Alt Gr
gives me level 3, and that is pretty much all I am interested in so I left the rest of that line as it was in my ~/.xmodmap.bak
and just changed the 3rd, 4th, 5th and 6th columns (level 2 and 3, plus shift) to valid characters (See here for a list of valid characters).
~/.xmodmap
...
keycode 51 = apostrophe asterisk dollar ampersand acute multiply acute multiply apostrophe asterisk acute multiply apostrophe asterisk acute multiply
keycode 59 = comma semicolon parenleft parenright dead_cedilla dead_ogonek dead_cedilla dead_ogonek comma semicolon dead_cedilla dead_ogonek comma semicolon dead_cedilla dead_ogonek
keycode 60 = period colon bracketleft bracketright periodcentered dead_abovedot periodcentered dead_abovedot period colon periodcentered dead_abovedot period colon periodcentered dead_abovedot
keycode 61 = minus underscore braceleft braceright slash backslash braceleft braceright
keycode 65 = space space space space space underscore space space
...
6. Test your .xmodmap
Now let xmodmap
execute your .xmodmap
and test your brand new keyboard layout.
$ xmodmap /home/user/.xmodmap
7. Make sure your keyboard layout is loaded on x init
I added this to my $HOME/.xinitrc
:
~/.xinitrc
...
[-f $HOME/.xmodmap] && xmodmap $HOME/.xmodmap
...
I hope this was helpful!
You can use preserve
for that: add to you type-definition (e.g. THREE_LEVEL
) the line
preserve[LevelThree+Shift] = Shift;
This tells xkb to preserve the shift modifier when figuring out the appropriate level from your modifier combination in the case of LevelThree + Shift
. The shift modifier is passed on for use by the toolkit or the application (see also here: using preserve with types).
Note that this has impact for example on how the application interprets keystroke combinations: if you had defined the above preserve and
key <AC08> { type="THREE_LEVEL", [ k, K, kappa ] };
and you'd press Ctrl + Shift + LevelThree + <AC08>
the application would read it as a key combo Ctrl + Shift + kappa
(instead of usually Ctrl + kappa
) because the shift modifier gets preserved and is passed on to the application.
Best Answer
After running
setxkbmap -print
I realized thatpc
was included in the symbols list. That symbol file sets up the regular modifiers, which is not desired by me.Before, I had added my own layout to the
/usr/share/X11/xkb/symbols
directory and to the/usr/share/X11/xkb/rules/evdev.xml
file. That made my layout appear in the GUI to select keyboard layout.A solution is to make a keyboard layout from scratch instead. One that does not include the
pc
file. However, there are a lot of standard keyboard stuff inpc
that I need. So I read through that file top to bottom picking out the things I needed.In short, creating a layout from scratch basically means:
setxkbmap -print
to a file.pc
with the name of my own file.xkbcomp -I$HOME/additional-include-folder file-from-step-one
.I learned this (in more detail) from this excellent guide: http://hack.org/mc/writings/xkb.html.