Since you want to remap the keys for all applications the best option is to use xmodmap. It is flexible and very powerful but involves typing in a few commands into a terminal.
Step 0 - The approach
The X-server manages the keyboard and all key events and translates that into keycodes for all applications.
The approach would be to map a modifier key (like Super or Right Alt key) as the "mode switch" key and tell the X-server to generate different codes depending on whether a key is pressed with Mode key being held down or not.
By default there is no mode switch key defined and also all keys are configured to generate the same code when they are pressed with or without mode switch. This is good since this means except for the keys you override explicitly no other keys will behave differently or need additional configuration.
However, I would like you to consider using Right Alt key as mode switch especially if you are also using compiz since some compiz plugins map super key shortcuts (e.g., window picker, shift switcher etc). If you are not keen on controlling compiz via the keyboard then Super is just fine.
To xmodmap, the super keys are identified as Super_L or Super_R. You need to pick one to use as the mode switch key. Alternatively, the right alt key is Alt_R. You can confirm these by running xev and pressing the necessary keys on your keyboard. See this post for the steps.
Step 1 - Setting up the modifier map
Open a terminal (
Applications -> Accesories -> Terminal) and run the following command to create a file with current keybindings. We will use this as starting point.
xmodmap -pke > curkeys.map
xmodmap -pm >> curkeys.map
Open this in your favourite text editor.
gedit curkeys.map & opens it in gedit. Towards the end of the file, you will see some lines like this:
keycode 253 =
keycode 254 =
keycode 255 =
xmodmap: up to 4 keys per modifier, (keycodes in parentheses):
shift Shift_L (0x32), Shift_R (0x3e)
lock Caps_Lock (0x42)
control Control_L (0x25), Control_R (0x69)
mod1 Alt_L (0x40), Alt_R (0x6c), Meta_L (0xcd)
mod2 Num_Lock (0x4d)
mod4 Super_L (0x85), Super_R (0x86), Super_L (0xce), Hyper_L (0xcf)
mod5 ISO_Level3_Shift (0x5c), Mode_switch (0xcb)
Delete the line starting with "xmodmap: up to 4..."
Edit the modifier map so it looks like this. Put the word "add " at the beginning of each line and insert "= " after the modifier name. Then remove the codes in parentheses and commas. Also note that I have moved
Mode_switch from the
mod5 line to
mod3 line since it was empty. The modified table should look like this - actual contents will slightly vary in your case from those below (depends on your keyboard layout).
add shift = Shift_L Shift_R
add lock = Caps_Lock
add control = Control_L Control_R
add mod1 = Alt_L Meta_L Alt_R
add mod2 = Num_Lock
add mod3 = Mode_switch
add mod4 = Super_L Super_R Super_L Hyper_L
add mod5 = ISO_Level3_Shift
Remap physical mode-switch key. Add a line like this at the end (Replace Super_L with Super_R or Alt_R if required).
keysym Super_L = Mode_switch
Remove the keyname (Super_L) from any modifier definition. For Super_L this means removing it from the mod4 line.
add mod4 = Super_R Hyper_L
Now the right "Super" key will still act as a normal super key whereas the left key will have special properties.
Now we need to remap the keys to produce different codes whether they are pressed while holding down Super_L or not.
Each line in our file beginning with
keycode specifies 4 keysyms for each key to be generated based on whether Mod1 (shift keys) and Mode switch keys are pressed.(link)
! Key Base Shift Mode Mode+Shift
keycode 13 = 4 dollar 4 quotedbl
keycode 14 = 5 percent 5 colon
keycode 15 = 6 asciicircum 6 comma
keycode 16 = 7 ampersand 7 period
keycode 45 = k K k K
If we want Super_L+k keypress to generate a "+" key then we need to modify it to read so
keycode 45 = k K plus plus
The final plus also maps Shift+Super_L+k to plus, but this can be mapped to something else. For each key there is exactly 1 line to modify. Edit more lines to remap more keys - leave the first 2 entries intact to retain normal keypress behaviour.
Save the file and exit the editor.
Install the keymap by running the following commands in a terminal. The first one sets it up for this session, the second makes it permanent for future sessions.
cp curkeys.map ~/.xmodmap
You can immediately test this by pressing the modified keys (Super_L + k for example).
Step 3 - Adding / revising the map
Once the modified map is installed it is easy to add new keys.
Use xev to find the keycodes and keysyms
test it by running this command to map the key :
xmodmap -e "keycode <code> = <base> <shift> <new-mapping> <new-shift-mapping>"
Replace items in angle brackets (like
<base> etc) with appropriate values.
- Open the
curkeys.map and edit the line for the corresponding keycode.
Reapply with the below commands (first one is not necessary if you did step 2)
cp curkeys.map ~/.xmodmap
Note:1: Modifications made in Keyboard Shortcuts (via e.g.,
System -> Preferences -> Keyboard Shortcuts) affect the modifier map and will be generally lost on next login. So please avoid that.
Note:2: I sometimes get error messages like this while using this method. I don't know what this means, however, these are generally harmless.
X Error of failed request: BadValue (integer parameter out of range for operation)
Major opcode of failed request: 118 (X_SetModifierMapping)
Value in failed request: 0x17
Serial number of failed request: 263
Current serial number in output stream: 263
Detailed help for xmodmap is available here.