I confirmed all of the following on a ThinkPad P1 running Pop!_OS (a derivative
of Ubuntu 18.10) in GNOME.
Finding Key Codes
Run xev
in a terminal and start typing. There's a lot of data, but what you're
looking for is usually the second 3rd line of a block after the word keycode
:
KeyRelease event, serial 37, synthetic NO, window 0x3c00001,
root 0x1a5, subw 0x0, time 291165043, (404,446), root:(454,634),
state 0x0, **keycode 107** (keysym 0xff67, Menu), same_screen YES,
XLookupString gives 0 bytes:
XFilterEvent returns: False
There are some keys that xev
won't print a key code for, such as Print Screen.
For these, you can grep through the file created in the next section.
Tools Needed
xmodmap
Dumping Your Current Bindings
You can print the current mappings to standard out by running xmodmap -pke
.
You'll save some potential headaches by first backing up your xmodmap
layout
to a file:
xmodmap -pke ~/.Xmodmap.orig
This file also serves as an easy reference for where keys are if they don't show
up in xev
.
cat ~/.Xmodmap | grep Print
keycode 107 = Print Sys_Req Print Sys_Req
Command To Quickly Change A Binding
You already know this, but just to reaffirm:
xmodmap -e "keycode [number] = [keys...]"
This will temporarily rebind a key for your session. Running xmodmap -pke
again will reflect these changes.
Syntax
xmodmap
uses space-delimited columns to denote the different modifiers/modes
for a keycode
. From left to right they are:
- The key by itself
- Shift + the key
- Mode_switch + the key
- Mode_switch + shift + the key
For example:
xmodmap -e "44 = j J Down Next"
This sets the "J" key "j" by itself, "J" when pressed with Shift, Down Arrow
when pressed with Mode_switch, and Page Down when pressed with Mode_switch and
Shift.
Mode_switch
Mode_switch
is a separate generic modifier, similar to Shift. I don't think
many keyboards come with a dedicated Mode_switch
(AltGr) key anymore, but you
can set one up with xmodmap
.
# Set left Alt as Mode_switch
xmodmap -e "keycode 108 = Mode_switch"
Run scripts with GNOME Settings or xbindkeys
I'm not aware of a way to run arbitrary scripts with xmodmap
. There are,
however, a few easy ways.
From i3 config
The i3 docs have examples on
using the bindsym
/bindcode
directives in your ~/.config/i3/config
file.
bindcode 214 exec /home/you/some_script.sh
I don't have i3 set up yet, haven't tested this, but it's straight from the user
manual. I'm guessing the codes match what you find in xmodmap
& friends.
GNOME
Check out Settings > Devices > Keyboard > Keyboard Shortcuts. Click plus and
add a script/key combo. Note that you must put the full path (from the root) to
the script and ensure it's executable.

In my testing, GNOME doesn't let you use some keys, such as Home and End.
xbindkeys
xbindkeys
can intercept any
key press and run a script instead.
Too see some config file examples, run xbindkeys --defaults > $HOME/.xbindkeysrc
and view the file.
Note that it won't open a terminal, just execute the file in a process.
Your Examples
Here's the actual commands to run for what you want. Be sure to confirm your own
key codes, these are just what I happen to have.
Step 1: Remap With xmodmap
# print screen --> use as another super key, print screen with Mode_switch
# Note: On GNOME, it appears Super_R doesn't work the same as Super_L
xmodmap -e "keycode 107 = Super_L NoSymbol Print Sys_Req"
# left alt --> mode_switch key
xmodmap -e "keycode 64 = Mode_switch NoSymbol"
# escape key --> tilde and backtick
# Note: this can have unexpected consequences if you use `xcape` to map
# Control/Caps to send Escape when tapped. It will instead send `/~ when you
# press Caps Lock attempting to get Escape.
# A solution might be to switch the keys around and use a non-op key as a
# placeholder, like in the xcape README
# https://github.com/alols/xcape/blob/master/README.md#examples
xmodmap -e "keycode 9 = grave asciitilde grave asciitilde"
# original tild and back tick --> backspace
xmodmap -e "keycode 49 = BackSpace"
# backspace --> delete, and
# mode_switch + backspace --> home
xmodmap -e "keycode 22 = Delete NoSymbol Home"
# mode_switch + delete --> end
# Note: This won't work when combined with `xbindkeys`, since `xbindkeys`
# hijacks the entire Delete key from X.
xmodmap -e "keycode 119 = Delete NoSymbol End"
# mode_switch + h, j, k, l --> additional arrow keys
# Bonus: capital J/K are Page Down/Up, H/L are Home/End with Mode_switch + Shift
xmodmap -e "keycode 43 = h H Left Home"
xmodmap -e "keycode 44 = j J Down Next"
xmodmap -e "keycode 45 = k K Up Prior"
xmodmap -e "keycode 46 = l L Right End"
Step 2: Save Changes
# Write current config to a file
xmodmap -pke > ~/.Xmodmap
# Load the config into xmodmap
xmodmap ~/.Xmodmap
Adding the last command above to your ~/.profile
or ~/.bash_profile
will
load it whenever you log in, assuming you have a standard set up. For me it was
kinda slow, you may want to just add all of the xmodmap -e
commands manually.
Step 3: Set Bindings For Custom Scripts With xbindkeys
Make sure xbindkeys
is installed, and add this to your ~/.xbindkeysrc
file:
# disable home, end, insert, delete keys and map them to run some script, and
"some-script-in-PATH"
Home
"some-script-in-PATH"
End
"some-script-in-PATH"
Insert
"some-script-in-PATH"
Delete
Then reload with xbindkeys -p
.
Step 4: There Is No Step 4
Further Reading
Emacs Wiki Page on remapping
Emacs Wiki Page on xmodmap
Arch Wiki about Xmodmap
More about Mode_switch on StackExchange
A more comprehensive and effort intensive solution is to just write your own
keyboard
layouts.