How to get keycodes for xmodmap?

193,222

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:

  1. 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).
  2. 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:

  1. Why do xev and showkey report different keycodes for a key?
  2. Why does xev not show Alt being pressed properly?
  3. 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.

Share:
193,222

Related videos on Youtube

Yaroslav Bulatov
Author by

Yaroslav Bulatov

Google (OCR team) -> Google Brain -> OpenAI -> PyTorch team (Facebook) http://mathematica-bits.blogspot.com/ https://medium.com/@yaroslavvb

Updated on September 18, 2022

Comments

  • Yaroslav Bulatov
    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 Alt

    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   
    

    For Right Super key, xev and showkey give different keycodes -- 134 and 126 respectively.

    What's going on with these keycodes?

    I tried getting keycodes from showkey -k, and using xmodmap 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
      Admin about 2 years
      I 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
    Yaroslav Bulatov over 11 years
    THe 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
    Yaroslav Bulatov over 11 years
    Right 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
    Richard Fortune over 11 years
    Try Mod1 for Alt.
  • derobert
    derobert over 11 years
    @YaroslavBulatov sounds like your desktop environment is eating the key (possibly to bring up its main menu?)
  • Robert Siemer
    Robert Siemer over 9 years
    Do you have a pointer regarding "off by 8 for historical reasons"?
  • Steve Kehlet
    Steve Kehlet almost 7 years
    How do you make the setxkbmap change permanent?
  • Fredrik Wendt
    Fredrik Wendt over 6 years
    You 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
    Raymond Kroeker over 5 years
    I 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
    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
    Matthias Braun over 4 years
    Add the change to ~/.xinitrc.
  • shiva
    shiva over 4 years
    Here is a more terse filter: xev | grep -A 6 KeyPress. This will only print 6 lines after matching for KeyPress event.
  • Nikana Reklawyks
    Nikana Reklawyks about 4 years
    I 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
    xeruf almost 4 years
    I have a key for which xev reports keycode 93, sudo showkey reports 85 and sudo showkey -s reports 0x76 0xf6 - so I tried sudo setkeycodes with 0x76,0xf6,76 or 85 as scancode and 89 as keycode - but nothing changed, xev still reports 93!
  • Timo
    Timo almost 3 years
    xev ... especially when you move your mouse. Moving my mouse does nothing in xev, work with Ubuntu20.04.