Fixed bug 2096 - Mapping from scancode to keycode doesn't work for remapped modifier keys

Jacob Lee

If a user has a non-standard keyboard mapping -- say, their caps lock key has been mapped to Ctrl -- then SDL_GetModState() is no longer accurate: it only considers the unmapped keys. This is a regression from SDL 1.2.

I think there are two parts to this bug: first, GetModState should use keycodes, rather than scancodes, which is easy enough.

Unfortunately, on my system, SDL considers Caps Lock, even when mapped as Control, to be both SDL_SCANCODE_CAPSLOCK and SDLK_CAPSLOCK. The output from checkkeys for it is:

INFO: Key pressed :  scancode 57 = CapsLock, keycode 0x40000039 = CapsLock  modifiers: CAPS

Whereas the output for xev is:

KeyPress event, serial 41, synthetic NO, window 0x4a00001,
    root 0x9a, subw 0x0, time 40218333, (144,177), root:(1458,222),
    state 0x10, keycode 66 (keysym 0xffe3, Control_L), same_screen YES,
    XKeysymToKeycode returns keycode: 37
    XLookupString gives 0 bytes:
    XmbLookupString gives 0 bytes:
    XFilterEvent returns: False

I think the problem is that X11_UpdateKeymap in SDL_x11keyboard.c only builds a mapping for keycodes associated with a Unicode character (anything where X11_KeyCodeToUcs returns a value). In the case of caps lock, SDL scancode 57 becomes x11 keycode 66, which becomes x11 keysym 65507(Control_L), which does not have a unicode value.

To fix this, I suspect that SDL needs a mapping of the rest of the x11 keysyms to their corresponding SDL key codes.
This commit is contained in:
Sam Lantinga
2015-05-28 12:48:20 -07:00
parent 4d1626d042
commit 32d6dcdb47
2 changed files with 59 additions and 79 deletions

View File

@@ -252,8 +252,7 @@ X11_InitKeyboard(_THIS)
#endif
SDL_memcpy(&data->key_layout[min_keycode], scancode_set[best_index].table,
sizeof(SDL_Scancode) * scancode_set[best_index].table_size);
}
else {
} else {
SDL_Keycode keymap[SDL_NUM_SCANCODES];
printf
@@ -316,6 +315,8 @@ X11_UpdateKeymap(_THIS)
key = X11_KeyCodeToUcs4(data->display, (KeyCode)i);
if (key) {
keymap[scancode] = key;
} else {
keymap[scancode] = SDL_SCANCODE_TO_KEYCODE(X11_KeyCodeToSDLScancode(data->display, (KeyCode)i));
}
}
SDL_SetKeymap(0, keymap, SDL_NUM_SCANCODES);