How to get keycodes for xmodmap?
Solution 1
There are a lot of players between your keyboard and the process that finally handles the keyboard event. Among the major pieces of the landscape are the fact that the X system has its own keyboard-handling layer, and X associates different "keycodes" with keys than your Linux base system does. The showkey
command is showing you the keycodes in Linux-base-system lingo. For xmodmap
you need the X keycodes, which are what xev
is displaying. So long as you're planning to work in X and do your key rebinding with xmodmap
, then, ignore showkeys
and just listen to what xev
says.
What you want to look for in your xev
output are blocks like this:
KeyPress event, serial 27, synthetic NO, window 0x1200001, root 0x101, subw 0x0, time 6417361, (340,373), root:(342,393), state 0x0, keycode 64 (keysym 0xffe9, Alt_L), same_screen YES, XLookupString gives 0 bytes: XmbLookupString gives 0 bytes: XFilterEvent returns: False KeyRelease event, serial 27, synthetic NO, window 0x1200001, root 0x101, subw 0x0, time 6417474, (340,373), root:(342,393), state 0x8, keycode 64 (keysym 0xffe9, Alt_L), same_screen YES, XLookupString gives 0 bytes: XFilterEvent returns: False
xev
tends to generate a lot of output, especially when you move your mouse. You may have to scroll back a while to find the output you're looking for. In the previous output, we see that the keysym Alt_L
is associated with the X keycode 64
.
Solution 2
xev should work
Odd, my xev gives a KeyPress and KeyRelease event for alt (and for the Windows key, here called "super"):
KeyPress event, serial 40, synthetic NO, window 0xae00001,
root 0x2ca, subw 0x0, time 595467354, (98,77), root:(102,443),
state 0x10, keycode 64 (keysym 0xffe9, Alt_L), same_screen YES,
XLookupString gives 0 bytes:
XmbLookupString gives 0 bytes:
XFilterEvent returns: False
KeyRelease event, serial 40, synthetic NO, window 0xae00001,
root 0x2ca, subw 0x0, time 595467453, (98,77), root:(102,443),
state 0x18, keycode 64 (keysym 0xffe9, Alt_L), same_screen YES,
XLookupString gives 0 bytes:
XFilterEvent returns: False
And the right-hand one:
KeyPress event, serial 40, synthetic NO, window 0xae00001,
root 0x2ca, subw 0x0, time 595572876, (75,33), root:(79,399),
state 0x10, keycode 108 (keysym 0xffea, Alt_R), same_screen YES,
XLookupString gives 0 bytes:
XmbLookupString gives 0 bytes:
XFilterEvent returns: False
KeyRelease event, serial 40, synthetic NO, window 0xae00001,
root 0x2ca, subw 0x0, time 595572972, (75,33), root:(79,399),
state 0x18, keycode 108 (keysym 0xffea, Alt_R), same_screen YES,
XLookupString gives 0 bytes:
XFilterEvent returns: False
I can see two possibilities:
- Something else is completely eating the keypress, or defocusing the window upon you pressing alt. Try running xev in an otherwise empty X server (e.g., just run
xinit -- :1
, which should get you a X server with only an xterm—there won't even be a window manager running. Exiting the xterm will close the session). - You just missed the two events in the bulk that xev spews out.
An easy way, if you know the key name
Another possibility: just get the keycodes from xmodmap:
anthony@Zia:~$ xmodmap -pk | grep -i alt
64 0xffe9 (Alt_L) 0xffe7 (Meta_L) 0xffe9 (Alt_L) 0xffe7 (Meta_L)
108 0xffea (Alt_R) 0xffe8 (Meta_R) 0xffea (Alt_R) 0xffe8 (Meta_R)
204 0x0000 (NoSymbol) 0xffe9 (Alt_L) 0x0000 (NoSymbol) 0xffe9 (Alt_L)
anthony@Zia:~$ xmodmap -pk | grep -i super
133 0xffeb (Super_L) 0x0000 (NoSymbol) 0xffeb (Super_L)
134 0xffec (Super_R) 0x0000 (NoSymbol) 0xffec (Super_R)
206 0x0000 (NoSymbol) 0xffeb (Super_L) 0x0000 (NoSymbol) 0xffeb (Super_L)
There is the 64 and 108 again. xmodmap -pm
will show you just the modifier map, which also gives you the numbers (though, this time, in hex).
Solution 3
I "detect" three issues in your question:
- Why do
xev
andshowkey
report different keycodes for a key? - Why does
xev
not show Alt being pressed properly? - How to swap Alt and Win?
Regarding the first question: these days, where the keyboard "driver" in X does not really drive the hardware, it could just pass-through the keycodes from the kernel to the X core, but it doesn't. It adds 8 to the keycode before passing it on.
Second: Something in your X session is grabbing the Alt event. The other answers cover this already. (I.e. xev
doesn't get the event you would like to see). The culprit might be related to your window manager. Try a more naked X session.
Third: Don't use xmodmap
. It has been outdated for a decade. The new guys are XKB and its tool setxkbmap
.
$ setxkbmap -query
rules: evdev
model: pc105
layout: us
variant: altgr-intl
options: caps:backspace
For swapping Alt and Win there is already an option prepared in XKB. Just add it:
$ setxkbmap -option altwin:swap_alt_win
$ setxkbmap -query
rules: evdev
model: pc105
layout: us
variant: altgr-intl
options: altwin:swap_alt_win,caps:backspace
Solution 4
As root, run:
showkey -s
...to see what the scancode is for your mystery key. I got something like this:
# showkey -s
kb mode was RAW
[ if you are trying this under X, it might not work
since the X server is also reading /dev/console ]
press any key (program terminates 10s after last keypress)...
0xc6
0x46 0xc6
0xc6
0x46 0xc6
0x46
Not sure why it appears that one key generates two scancodes. It's not a keydown/keyup thing, as near as I could tell from the pattern. Note the warning, so you may want to run this in single user mode.
I guessed that 0x46 was my scancode.
Next, find an unused keycode with:
xmodmap -pke | less
Here you can see keycode 97 is unused on my system:
keycode 94 = less greater less greater bar brokenbar
keycode 95 = F11 XF86Switch_VT_11 F11 XF86Switch_VT_11
keycode 96 = F12 XF86Switch_VT_12 F12 XF86Switch_VT_12
keycode 97 =
keycode 98 = Katakana NoSymbol Katakana
keycode 99 = Hiragana NoSymbol Hiragana
The keycode X uses and the keycode the kernel uses are OFF BY 8 for "historical reasons". So take 97 - 8 = 89 and use 89 with the setkeycodes command (again as root):
# setkeycodes 46 89
And you should be set. Confirm with xev that you're getting a Keypress Event with the keycode of 97. (though once I told the Fluxbox keys file to use that keycode I didn't get KeyPress events anymore - maybe because Fluxbox swallows them when it uses them?)
Note that the 'setkeycodes' won't survive a reboot, so you'll have to add it to your init scripts (eg. in /etc/rc.local)
Solution 5
I was trying to solve this for myself and I just figured it out.
The main problem is that you aren't getting the event for the keypress. Looking at the log you posted the reason is apparent.
FocusOut event, serial 36, synthetic NO, window 0x4a00001,
mode NotifyGrab, detail NotifyAncestor
FocusIn event, serial 36, synthetic NO, window 0x4a00001,
mode NotifyUngrab, detail NotifyAncestor
KeymapNotify event, serial 36, synthetic NO, window 0x0,
keys: 122 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
You can see the the Focus{In,Out}
events have a mode
of Notify{Grab,Ungrab}
. This indicates that a key was handled by another process (probably a shortcut/keybinding application).
In my case it was xbindkeys, but if you are using a desktop environment they probably have a keybinding system. In order to see these events is xev you will need to stop/disable the other program.
If you can't determine what program is stealing the key events the best solution is to start another X session without it running. Run the following command to start another X session on display :1
, if that is already taken just increase the number at the end. You can of course change the terminal to whatever you prefer or have installed on your system.
xinit /usr/bin/xterm -- :1
Then run xev
again. That should give you the result without it being captured by other programs. Note that the window manager that gets started is hover-focus, so you will have to place your cursor above the xev window in order for the keys to be captured.
As was said in this excellent answer by dubiousjim, the keycode is different because there are a lot of layers between xev and the kernel.
Related videos on Youtube
Yaroslav Bulatov
Google (OCR team) -> Google Brain -> OpenAI -> PyTorch team (Facebook) http://mathematica-bits.blogspot.com/ https://medium.com/@yaroslavvb
Updated on September 18, 2022Comments
-
Yaroslav Bulatov over 1 year
I'm trying to use
xmodmap
to remap Alt / Super keys on Dell L100 keyboard, and have trouble getting the keycodes.For instance, using
xev
doesn't give me keycode for AltFocusOut event, serial 36, synthetic NO, window 0x4a00001, mode NotifyGrab, detail NotifyAncestor FocusIn event, serial 36, synthetic NO, window 0x4a00001, mode NotifyUngrab, detail NotifyAncestor KeymapNotify event, serial 36, synthetic NO, window 0x0, keys: 122 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
For Right Super key,
xev
andshowkey
give different keycodes --134
and126
respectively.What's going on with these keycodes?
I tried getting keycodes from
showkey -k
, and usingxmodmap
file below, but that gave a weird map which remapped b key:clear Mod1 clear Control keycode 125 = Meta_L keycode 126 = Meta_R keycode 58 = Control_L keycode 56 = Control_L keycode 100 = Control_R add Control = Control_L Control_R add Mod1 = Meta_L Meta_R
-
Admin about 2 yearsI have a 5 Row Keyboard (60 Percent Style Keyboard) with left and right Alt keys and a Win (super) key. The Alt keys are reversed with Win keys. I imagine this is a common problem for "60 Percent Keyboards" that are popular with those who like to keep their fingers on Home Row all the time (myself, for using Vim) and also famously popular with gamers. There needs to be a generic 5 Row Keyboard layout packaged with linux distributions.
-
-
Yaroslav Bulatov over 11 yearsTHe problem is that I don't get KeyPress event on Windows key. I tried 3 different keyboards and same result. From xev I only get FocusOut, FocusIn and KeymapNotify as seen above. However, I can go and setup shortcuts through Gnome manager, and it sees Windows key as "Mod4"
-
Yaroslav Bulatov over 11 yearsRight Windows key reports as Mod4, left Windows key reports as Alt...which is confusing because I don't even have an "Alt" category in my xmodmap.
-
Richard Fortune over 11 yearsTry Mod1 for Alt.
-
derobert over 11 years@YaroslavBulatov sounds like your desktop environment is eating the key (possibly to bring up its main menu?)
-
Robert Siemer over 9 yearsDo you have a pointer regarding "off by 8 for historical reasons"?
-
Steve Kehlet almost 7 yearsHow do you make the
setxkbmap
change permanent? -
Fredrik Wendt over 6 yearsYou can filter the events that xev gives you. In this case
xev -event keyboard
would be enough to rid most of the noise. -
Raymond Kroeker over 5 yearsI used your answer to map caps-lock onto a function key (F9 specifically). This lets me use F9 as the prefix key in tmux. Thanks.
-
Greg Bell over 5 years@RobertSiemer tldp.org/HOWTO/Keyboard-and-Console-HOWTO-15.html "Often the X number will be 8 more than the Linux number." My wording with "historical" must have been from another manpage.
-
Matthias Braun over 4 yearsAdd the change to
~/.xinitrc
. -
shiva over 4 yearsHere is a more terse filter:
xev | grep -A 6 KeyPress
. This will only print 6 lines after matching for KeyPress event. -
Nikana Reklawyks about 4 yearsI had this exact problem, a window-manager-based keybinding system eating the keypress (a VolumeUp media button), so I couldn't figure out the KeyPress. Disabling the binding let the press through and I could find the keycode. Thanks !
-
xeruf almost 4 yearsI have a key for which
xev
reports keycode 93,sudo showkey
reports 85 andsudo showkey -s
reports 0x76 0xf6 - so I triedsudo setkeycodes
with0x76
,0xf6
,76
or85
as scancode and89
as keycode - but nothing changed, xev still reports 93! -
Timo almost 3 years
xev ... especially when you move your mouse
. Moving my mouse does nothing inxev
, work withUbuntu20.04
.