2 min read

X Windows, AltGr, and Mode_switch

I have an application that detects and uses the AltGr key by assuming that mod2 is assigned to the AltGr key. This seems to work fine in most cases, as it is easy to make this the case in X Windows by using Xmodmap. However, I have noticed a strange behavior in my version of X (Slackware64 13.1 X.org 1.7.7).

I have my Xmodmap set up like so:

shift       Shift_L (0x32),  Shift_R (0x3e)
lock        Caps_Lock (0x42)
control     Control_L (0x25),  Control_R (0x69)
mod1        Meta_L (0x85),  Meta_R (0x86),  Meta_L (0xcd)
mod2        Mode_switch (0x40),  Alt_R (0x6c),  Mode_switch (0xcb)

I have a custom Xmodmap that has a number of mappings that make use of the Mode_switch key. The application in particular is various forms of APL. When I enter APL characters in normal programs, I use the Mode_switch key which lets me use my own custom modmap for the keyboard layout. When I am in APL environments, they make use of the Mod2 modifier to work like a Mode_switch key.

I had thought that by adding mode_switch to mod2, that I could use the Mode_switch key as my AltGr key detected in APL. This, unfortunately does not seem to be the case. The key event state used to detect whether mod2mask is set or not appears to be different. Here is what it looks like if I use Alt_R:

KeyPress event, serial 28, synthetic NO, window 0x1000002,
    root 0x142, subw 0x0, time 1960891, (116,-214), root:(446,56),
    state 0x10, keycode 38 (keysym 0x61, a), same_screen YES,
    XLookupString gives 1 bytes: (61) "a"
    XmbLookupString gives 1 bytes: (61) "a"
    XFilterEvent returns: False

In particular, the state is what I want; when Alt_R is used, it is set to 0x10. This corresponds directly to the Mod2Mask in my X.h, which is set as (1<<4). But now look at what xev gives if I use the Mode_switch key instead:

KeyPress event, serial 28, synthetic NO, window 0x1200002,
    root 0x142, subw 0x0, time 2067364, (285,206), root:(645,506),
    state 0x2000, keycode 38 (keysym 0x100237a, U237A), same_screen YES,
    XLookupString gives 3 bytes: (e2 8d ba) "⍺"
    XmbLookupString gives 3 bytes: (e2 8d ba) "⍺"
    XFilterEvent returns: False

Now, the state there is set to be 0x2000, whereas I might have expected it to be more like 0x2010 or something. This means that even though I have my Mode_switch key set as my mod2, I can't actually use it as mod2.

Can anyone explain this to me?