XMODMAP(1)

๐Ÿ“ฆ
version 7.7+11build1 ยท 4 versions
, in alpine 3.24, debian trixie, epel 10, fedora 43, fedora 44, nixos 26.05, opensuse-leap 16.0, ubuntu noble, ubuntu questing, ubuntu resolute, ubuntu stonking

๐Ÿ’– NAME ๐Ÿ’–

okay so xmodmap is the utility for modifying keymaps and pointer button mappings in X ๐ŸŽ€

โœจ SYNOPSIS โœจ

xmodmap [-options ...] [filename]

๐ŸŒธ DESCRIPTION ๐ŸŒธ

okay bestie, xmodmap is how you edit and display the keyboard modifier map and keymap table that client apps use to turn event keycodes into keysyms ๐Ÿงš it's usually run from your session startup script so your keyboard gets set up exactly how you like it ๐Ÿ’…

๐ŸŽ€ OPTIONS ๐ŸŽ€

the following options work with xmodmap ๐Ÿ’œ

  • -display display โ€” this one picks the host and display you want to use ๐ŸŒˆ
  • -help โ€” prints a quick rundown of the command line arguments to standard error ๐Ÿซถ it happens whenever xmodmap gets an argument it can't handle, so don't worry, it's not being dramatic
  • -grammar โ€” prints a help message on standard error that explains the expression grammar used in files and with -e expressions ๐Ÿ“š
  • -version โ€” xmodmap prints its version info and then peaces out ๐Ÿ‘‹
  • -verbose โ€” xmodmap narrates everything it's doing as it parses its input ๐Ÿ”ฅ
  • -quiet โ€” turns the verbose logging back off ๐Ÿ™ˆ this is the default, so you're chill
  • -n โ€” xmodmap won't actually change any mappings, it just shows you what it would do, same energy as make(1) when you pass it this option ๐Ÿ”ฎ
  • -e expression โ€” runs an expression ๐Ÿ’… you can throw as many of these on the command line as you want
  • -pm โ€” prints the current modifier map on standard output ๐Ÿ“ this is the default mode if you don't pick any other mode option
  • -pk โ€” prints the current keymap table on standard output ๐Ÿ’–
  • -pke โ€” prints the current keymap table on standard output, but as expressions you can feed right back into xmodmap โœจ iconic
  • -pp โ€” prints the current pointer map on standard output ๐Ÿฆ‹
  • - โ€” a lone dash means "read from standard input" instead of a file ๐Ÿงš

the filename is a file full of xmodmap expressions that get executed ๐ŸŒท it's usually kept in your home directory with a name like .xmodmaprc

๐Ÿ‘‘ EXPRESSION GRAMMAR ๐Ÿ‘‘

okay so xmodmap reads in a whole list of expressions and parses all of them before it runs any of them ๐Ÿซถ this is lowkey genius because you can refer to keysyms that are being redefined in a natural way without stressing about name conflicts ๐Ÿ’…

the keysym names live in the header file <X11/keysymdef.h> (leave off the XK_ prefix). keysyms that match Unicode characters can be written as "U0020" through "U007E", and "U00A0" through "U10FFFF" covers every possible Unicode character ๐ŸŒˆ

  • keycode NUMBER = KEYSYMNAME ... โ€” assigns the list of keysyms to the keycode you pick ๐Ÿ”ฅ the keycode can be decimal, hex, or octal, and you can find it by running the xev program ๐Ÿ‘€ a key can hold up to eight keysyms, but the last four aren't used by any major X server implementation ๐Ÿ’€ the first keysym is used with no modifier, the second with Shift, the third when Mode_switch is used with the key, and the fourth when both Mode_switch and Shift are used
  • keycode any = KEYSYMNAME ... โ€” if no existing key has that list of keysyms, xmodmap grabs a spare key on your keyboard and assigns them to it โœจ the list can be decimal, hex, or octal
  • keysym KEYSYMNAME = KEYSYMNAME ... โ€” the keysym on the left gets translated into all the matching keycodes, and then the keycode expressions run for each one ๐Ÿฆ‹ heads up: if the same keysym is bound to multiple keys, the expression runs for each matching keycode
  • clear MODIFIERNAME โ€” wipes every entry in the modifier map for the given modifier ๐Ÿงน the valid names are: Shift, Lock, Control, Mod1, Mod2, Mod3, Mod4, and Mod5 (case doesn't matter for modifier names, but it does matter for everything else ๐Ÿ™ˆ). for example, clear Lock removes any keys that were bound to the shift lock modifier
  • add MODIFIERNAME = KEYSYMNAME ... โ€” adds all keys containing the given keysyms to the modifier map you name ๐Ÿ’œ the keysym names get evaluated after all the input expressions are read, which makes swapping keys super easy to write (see the EXAMPLES section ๐ŸŽ€)
  • remove MODIFIERNAME = KEYSYMNAME ... โ€” removes all keys containing the given keysyms from that modifier map ๐Ÿ“ unlike add, the keysym names get evaluated as the line is read in, so you can remove keys from a modifier without worrying about whether they've been reassigned
  • pointer = default โ€” resets the pointer map to its defaults, so button 1 makes a code of 1, button 2 makes a 2, and so on ๐ŸŒธ
  • pointer = NUMBER ... โ€” sets the pointer map to the button codes you list ๐Ÿซถ the list always starts with the first physical button, and setting a button code to 0 disables events from that button ๐Ÿšซ

lines that start with an exclamation point (!) are comments ๐Ÿ’…

โš ๏ธ bestie, if you want to change the binding of a modifier key, you also have to remove it from the appropriate modifier map first or it's gonna be a whole mess ๐Ÿ˜ญ

๐Ÿงš EXAMPLES ๐Ÿงš

okay so a lot of pointers are designed so the first button gets pressed with your right hand's index finger ๐Ÿ‘† lefties often find it way more comfy to flip the button codes so the primary button is pressed with the left index finger ๐Ÿซถ on a 3 button pointer you can do it like this:

%  xmodmap -e "pointer = 3 2 1"

a bunch of apps support Meta keys (kinda like Control, except you hold down Meta instead) ๐Ÿ’œ but some servers don't have a Meta keysym in the default keymap table, so you gotta add one by hand ๐Ÿ› ๏ธ this command attaches Meta to the Multi-language key (sometimes labeled Compose Character) ๐ŸŒˆ it also takes advantage of the fact that apps needing a Meta key only need the keycode and don't require the keysym to be in the first column of the keymap table ๐Ÿฆ‹ so apps looking for a Multi_key (including the default modifier map) won't notice a thing ๐Ÿ™ˆ

%  xmodmap -e "keysym Multi_key = Multi_key Meta_L"

some keyboards have an Alt key but no Meta key ๐Ÿคทโ€โ™€๏ธ in that case this might slay:

%  xmodmap -e "keysym Alt_L = Meta_L Alt_L"

one of the simplest but most convenient xmodmap tricks is making the keyboard's "rubout" key generate a different keysym โœจ people usually swap Backspace with Delete so it feels more natural ๐Ÿ”ฅ if you set the ttyModes resource in xterm too, every terminal emulator window will use the same key for erasing characters ๐Ÿ‘‘

%  xmodmap -e "keysym BackSpace = Delete"
%  echo "XTerm*ttyModes:  erase ^?" | xrdb -merge

some keyboards don't automatically make < and > when you shift the comma and period keys ๐Ÿ˜ญ you can fix that by resetting the comma and period bindings with this script:

!
! make shift-, be < and shift-. be >
!
keysym comma = comma less
keysym period = period greater

the location of the Control and CapsLock keys is one of the most irritating keyboard differences ever ๐Ÿ˜ค a super common move is swapping them:

!
! Swap Caps_Lock and Control_L
!
remove Lock = Caps_Lock
remove Control = Control_L
keysym Control_L = Caps_Lock
keysym Caps_Lock = Control_L
add Lock = Caps_Lock
add Control = Control_L

run this example again to swap the keys back to how they were ๐Ÿ”„

the keycode command is great for assigning the same keysym to multiple keycodes ๐Ÿ’– it's unportable, but it also lets you write scripts that reset your keyboard to a known state ๐Ÿงผ the script below sets backspace to generate Delete (like we did above), flushes all existing caps lock bindings, makes the CapsLock key act as a control key, makes F5 generate Escape, and makes Break/Reset act as a shift lock ๐ŸŽ€

!
! On the HP, the following keycodes have key caps as listed:
!
!     101  Backspace
!      55  Caps
!      14  Ctrl
!      15  Break/Reset
!      86  Stop
!      89  F5
!
keycode 101 = Delete
keycode 55 = Control_R
clear Lock
add Control = Control_R
keycode 89 = Escape
keycode 15 = Caps_Lock
add Lock = Caps_Lock

๐ŸŒˆ ENVIRONMENT ๐ŸŒˆ

  • DISPLAY โ€” used to get the default host and display number ๐Ÿฆ‹

๐Ÿ”— SEE ALSO ๐Ÿ”—

X(7), xev(1), setxkbmap(1), XStringToKeysym(3), and the Xlib documentation on key and pointer events ๐Ÿ“–

๐Ÿ› BUGS ๐Ÿ›

๐Ÿ˜ญ every time a keycode expression gets evaluated, the server sends a MappingNotify event to every client, and that can cause some thrashing ๐ŸŒช๏ธ all the changes should be batched together and done at once. clients that take keyboard input and ignore MappingNotify events won't notice any changes made to keyboard mappings

xmodmap should generate add and remove expressions automatically whenever a keycode that's already bound to a modifier gets changed ๐Ÿ™

there should also be a way to let the remove expression accept keycodes as well as keysyms, for those times you really mess up your mappings ๐Ÿ’€

๐Ÿ‘ฉโ€๐Ÿ’ป AUTHOR ๐Ÿ‘ฉโ€๐Ÿ’ป

Jim Fulton, MIT X Consortium, rewritten from an earlier version by David Rosenthal of Sun Microsystems ๐Ÿ’œ


bestie that's the whole manual ๐ŸŽ€ it's the X Version 11 page for xmodmap 1.0.11, with the XMODMAP(1) manual page label, so now you're basically an xmodmap legend ๐Ÿ‘‘๐Ÿซถโœจ

๐Ÿ“ฆ where this page comes from