From 9ecacf1d7fb782c326bc3c47c25b44fecd6c6677 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Wed, 25 Mar 2020 18:16:15 +0100 Subject: [PATCH] X11: Check XKB key aliases in addition to names --- src/x11_init.c | 290 ++++++++++++++++++++++++++++--------------------- 1 file changed, 165 insertions(+), 125 deletions(-) diff --git a/src/x11_init.c b/src/x11_init.c index ed11bd5a..1a3ec186 100644 --- a/src/x11_init.c +++ b/src/x11_init.c @@ -196,7 +196,7 @@ static int translateKeyCode(int scancode) // static void createKeyTables(void) { - int scancode, key, scancodeMin, scancodeMax; + int scancode, scancodeMin, scancodeMax; memset(_glfw.x11.keycodes, -1, sizeof(_glfw.x11.keycodes)); memset(_glfw.x11.scancodes, -1, sizeof(_glfw.x11.scancodes)); @@ -206,143 +206,183 @@ static void createKeyTables(void) // Use XKB to determine physical key locations independently of the // current keyboard layout - char name[XkbKeyNameLength + 1]; XkbDescPtr desc = XkbGetMap(_glfw.x11.display, 0, XkbUseCoreKbd); - XkbGetNames(_glfw.x11.display, XkbKeyNamesMask, desc); + XkbGetNames(_glfw.x11.display, XkbKeyNamesMask | XkbKeyAliasesMask, desc); scancodeMin = desc->min_key_code; scancodeMax = desc->max_key_code; + const struct + { + int key; + char* name; + } keymap[] = + { + { GLFW_KEY_GRAVE_ACCENT, "TLDE" }, + { GLFW_KEY_1, "AE01" }, + { GLFW_KEY_2, "AE02" }, + { GLFW_KEY_3, "AE03" }, + { GLFW_KEY_4, "AE04" }, + { GLFW_KEY_5, "AE05" }, + { GLFW_KEY_6, "AE06" }, + { GLFW_KEY_7, "AE07" }, + { GLFW_KEY_8, "AE08" }, + { GLFW_KEY_9, "AE09" }, + { GLFW_KEY_0, "AE10" }, + { GLFW_KEY_MINUS, "AE11" }, + { GLFW_KEY_EQUAL, "AE12" }, + { GLFW_KEY_Q, "AD01" }, + { GLFW_KEY_W, "AD02" }, + { GLFW_KEY_E, "AD03" }, + { GLFW_KEY_R, "AD04" }, + { GLFW_KEY_T, "AD05" }, + { GLFW_KEY_Y, "AD06" }, + { GLFW_KEY_U, "AD07" }, + { GLFW_KEY_I, "AD08" }, + { GLFW_KEY_O, "AD09" }, + { GLFW_KEY_P, "AD10" }, + { GLFW_KEY_LEFT_BRACKET, "AD11" }, + { GLFW_KEY_RIGHT_BRACKET, "AD12" }, + { GLFW_KEY_A, "AC01" }, + { GLFW_KEY_S, "AC02" }, + { GLFW_KEY_D, "AC03" }, + { GLFW_KEY_F, "AC04" }, + { GLFW_KEY_G, "AC05" }, + { GLFW_KEY_H, "AC06" }, + { GLFW_KEY_J, "AC07" }, + { GLFW_KEY_K, "AC08" }, + { GLFW_KEY_L, "AC09" }, + { GLFW_KEY_SEMICOLON, "AC10" }, + { GLFW_KEY_APOSTROPHE, "AC11" }, + { GLFW_KEY_Z, "AB01" }, + { GLFW_KEY_X, "AB02" }, + { GLFW_KEY_C, "AB03" }, + { GLFW_KEY_V, "AB04" }, + { GLFW_KEY_B, "AB05" }, + { GLFW_KEY_N, "AB06" }, + { GLFW_KEY_M, "AB07" }, + { GLFW_KEY_COMMA, "AB08" }, + { GLFW_KEY_PERIOD, "AB09" }, + { GLFW_KEY_SLASH, "AB10" }, + { GLFW_KEY_BACKSLASH, "BKSL" }, + { GLFW_KEY_WORLD_1, "LSGT" }, + { GLFW_KEY_SPACE, "SPCE" }, + { GLFW_KEY_ESCAPE, "ESC" }, + { GLFW_KEY_ENTER, "RTRN" }, + { GLFW_KEY_TAB, "TAB" }, + { GLFW_KEY_BACKSPACE, "BKSP" }, + { GLFW_KEY_INSERT, "INS" }, + { GLFW_KEY_DELETE, "DELE" }, + { GLFW_KEY_RIGHT, "RGHT" }, + { GLFW_KEY_LEFT, "LEFT" }, + { GLFW_KEY_DOWN, "DOWN" }, + { GLFW_KEY_UP, "UP" }, + { GLFW_KEY_PAGE_UP, "PGUP" }, + { GLFW_KEY_PAGE_DOWN, "PGDN" }, + { GLFW_KEY_HOME, "HOME" }, + { GLFW_KEY_END, "END" }, + { GLFW_KEY_CAPS_LOCK, "CAPS" }, + { GLFW_KEY_SCROLL_LOCK, "SCLK" }, + { GLFW_KEY_NUM_LOCK, "NMLK" }, + { GLFW_KEY_PRINT_SCREEN, "PRSC" }, + { GLFW_KEY_PAUSE, "PAUS" }, + { GLFW_KEY_F1, "FK01" }, + { GLFW_KEY_F2, "FK02" }, + { GLFW_KEY_F3, "FK03" }, + { GLFW_KEY_F4, "FK04" }, + { GLFW_KEY_F5, "FK05" }, + { GLFW_KEY_F6, "FK06" }, + { GLFW_KEY_F7, "FK07" }, + { GLFW_KEY_F8, "FK08" }, + { GLFW_KEY_F9, "FK09" }, + { GLFW_KEY_F10, "FK10" }, + { GLFW_KEY_F11, "FK11" }, + { GLFW_KEY_F12, "FK12" }, + { GLFW_KEY_F13, "FK13" }, + { GLFW_KEY_F14, "FK14" }, + { GLFW_KEY_F15, "FK15" }, + { GLFW_KEY_F16, "FK16" }, + { GLFW_KEY_F17, "FK17" }, + { GLFW_KEY_F18, "FK18" }, + { GLFW_KEY_F19, "FK19" }, + { GLFW_KEY_F20, "FK20" }, + { GLFW_KEY_F21, "FK21" }, + { GLFW_KEY_F22, "FK22" }, + { GLFW_KEY_F23, "FK23" }, + { GLFW_KEY_F24, "FK24" }, + { GLFW_KEY_F25, "FK25" }, + { GLFW_KEY_KP_0, "KP0" }, + { GLFW_KEY_KP_1, "KP1" }, + { GLFW_KEY_KP_2, "KP2" }, + { GLFW_KEY_KP_3, "KP3" }, + { GLFW_KEY_KP_4, "KP4" }, + { GLFW_KEY_KP_5, "KP5" }, + { GLFW_KEY_KP_6, "KP6" }, + { GLFW_KEY_KP_7, "KP7" }, + { GLFW_KEY_KP_8, "KP8" }, + { GLFW_KEY_KP_9, "KP9" }, + { GLFW_KEY_KP_DECIMAL, "KPDL" }, + { GLFW_KEY_KP_DIVIDE, "KPDV" }, + { GLFW_KEY_KP_MULTIPLY, "KPMU" }, + { GLFW_KEY_KP_SUBTRACT, "KPSU" }, + { GLFW_KEY_KP_ADD, "KPAD" }, + { GLFW_KEY_KP_ENTER, "KPEN" }, + { GLFW_KEY_KP_EQUAL, "KPEQ" }, + { GLFW_KEY_LEFT_SHIFT, "LFSH" }, + { GLFW_KEY_LEFT_CONTROL, "LCTL" }, + { GLFW_KEY_LEFT_ALT, "LALT" }, + { GLFW_KEY_LEFT_SUPER, "LWIN" }, + { GLFW_KEY_RIGHT_SHIFT, "RTSH" }, + { GLFW_KEY_RIGHT_CONTROL, "RCTL" }, + { GLFW_KEY_RIGHT_ALT, "RALT" }, + { GLFW_KEY_RIGHT_SUPER, "RWIN" }, + { GLFW_KEY_MENU, "COMP" } + }; + // Find the X11 key code -> GLFW key code mapping for (scancode = scancodeMin; scancode <= scancodeMax; scancode++) { - memcpy(name, desc->names->keys[scancode].name, XkbKeyNameLength); - name[XkbKeyNameLength] = '\0'; + int key = GLFW_KEY_UNKNOWN; // Map the key name to a GLFW key code. Note: We use the US // keyboard layout. Because function keys aren't mapped correctly // when using traditional KeySym translations, they are mapped // here instead. - if (strcmp(name, "TLDE") == 0) key = GLFW_KEY_GRAVE_ACCENT; - else if (strcmp(name, "AE01") == 0) key = GLFW_KEY_1; - else if (strcmp(name, "AE02") == 0) key = GLFW_KEY_2; - else if (strcmp(name, "AE03") == 0) key = GLFW_KEY_3; - else if (strcmp(name, "AE04") == 0) key = GLFW_KEY_4; - else if (strcmp(name, "AE05") == 0) key = GLFW_KEY_5; - else if (strcmp(name, "AE06") == 0) key = GLFW_KEY_6; - else if (strcmp(name, "AE07") == 0) key = GLFW_KEY_7; - else if (strcmp(name, "AE08") == 0) key = GLFW_KEY_8; - else if (strcmp(name, "AE09") == 0) key = GLFW_KEY_9; - else if (strcmp(name, "AE10") == 0) key = GLFW_KEY_0; - else if (strcmp(name, "AE11") == 0) key = GLFW_KEY_MINUS; - else if (strcmp(name, "AE12") == 0) key = GLFW_KEY_EQUAL; - else if (strcmp(name, "AD01") == 0) key = GLFW_KEY_Q; - else if (strcmp(name, "AD02") == 0) key = GLFW_KEY_W; - else if (strcmp(name, "AD03") == 0) key = GLFW_KEY_E; - else if (strcmp(name, "AD04") == 0) key = GLFW_KEY_R; - else if (strcmp(name, "AD05") == 0) key = GLFW_KEY_T; - else if (strcmp(name, "AD06") == 0) key = GLFW_KEY_Y; - else if (strcmp(name, "AD07") == 0) key = GLFW_KEY_U; - else if (strcmp(name, "AD08") == 0) key = GLFW_KEY_I; - else if (strcmp(name, "AD09") == 0) key = GLFW_KEY_O; - else if (strcmp(name, "AD10") == 0) key = GLFW_KEY_P; - else if (strcmp(name, "AD11") == 0) key = GLFW_KEY_LEFT_BRACKET; - else if (strcmp(name, "AD12") == 0) key = GLFW_KEY_RIGHT_BRACKET; - else if (strcmp(name, "AC01") == 0) key = GLFW_KEY_A; - else if (strcmp(name, "AC02") == 0) key = GLFW_KEY_S; - else if (strcmp(name, "AC03") == 0) key = GLFW_KEY_D; - else if (strcmp(name, "AC04") == 0) key = GLFW_KEY_F; - else if (strcmp(name, "AC05") == 0) key = GLFW_KEY_G; - else if (strcmp(name, "AC06") == 0) key = GLFW_KEY_H; - else if (strcmp(name, "AC07") == 0) key = GLFW_KEY_J; - else if (strcmp(name, "AC08") == 0) key = GLFW_KEY_K; - else if (strcmp(name, "AC09") == 0) key = GLFW_KEY_L; - else if (strcmp(name, "AC10") == 0) key = GLFW_KEY_SEMICOLON; - else if (strcmp(name, "AC11") == 0) key = GLFW_KEY_APOSTROPHE; - else if (strcmp(name, "AB01") == 0) key = GLFW_KEY_Z; - else if (strcmp(name, "AB02") == 0) key = GLFW_KEY_X; - else if (strcmp(name, "AB03") == 0) key = GLFW_KEY_C; - else if (strcmp(name, "AB04") == 0) key = GLFW_KEY_V; - else if (strcmp(name, "AB05") == 0) key = GLFW_KEY_B; - else if (strcmp(name, "AB06") == 0) key = GLFW_KEY_N; - else if (strcmp(name, "AB07") == 0) key = GLFW_KEY_M; - else if (strcmp(name, "AB08") == 0) key = GLFW_KEY_COMMA; - else if (strcmp(name, "AB09") == 0) key = GLFW_KEY_PERIOD; - else if (strcmp(name, "AB10") == 0) key = GLFW_KEY_SLASH; - else if (strcmp(name, "BKSL") == 0) key = GLFW_KEY_BACKSLASH; - else if (strcmp(name, "LSGT") == 0) key = GLFW_KEY_WORLD_1; - else if (strcmp(name, "SPCE") == 0) key = GLFW_KEY_SPACE; - else if (strcmp(name, "ESC") == 0) key = GLFW_KEY_ESCAPE; - else if (strcmp(name, "RTRN") == 0) key = GLFW_KEY_ENTER; - else if (strcmp(name, "TAB") == 0) key = GLFW_KEY_TAB; - else if (strcmp(name, "BKSP") == 0) key = GLFW_KEY_BACKSPACE; - else if (strcmp(name, "INS") == 0) key = GLFW_KEY_INSERT; - else if (strcmp(name, "DELE") == 0) key = GLFW_KEY_DELETE; - else if (strcmp(name, "RGHT") == 0) key = GLFW_KEY_RIGHT; - else if (strcmp(name, "LEFT") == 0) key = GLFW_KEY_LEFT; - else if (strcmp(name, "DOWN") == 0) key = GLFW_KEY_DOWN; - else if (strcmp(name, "UP") == 0) key = GLFW_KEY_UP; - else if (strcmp(name, "PGUP") == 0) key = GLFW_KEY_PAGE_UP; - else if (strcmp(name, "PGDN") == 0) key = GLFW_KEY_PAGE_DOWN; - else if (strcmp(name, "HOME") == 0) key = GLFW_KEY_HOME; - else if (strcmp(name, "END") == 0) key = GLFW_KEY_END; - else if (strcmp(name, "CAPS") == 0) key = GLFW_KEY_CAPS_LOCK; - else if (strcmp(name, "SCLK") == 0) key = GLFW_KEY_SCROLL_LOCK; - else if (strcmp(name, "NMLK") == 0) key = GLFW_KEY_NUM_LOCK; - else if (strcmp(name, "PRSC") == 0) key = GLFW_KEY_PRINT_SCREEN; - else if (strcmp(name, "PAUS") == 0) key = GLFW_KEY_PAUSE; - else if (strcmp(name, "FK01") == 0) key = GLFW_KEY_F1; - else if (strcmp(name, "FK02") == 0) key = GLFW_KEY_F2; - else if (strcmp(name, "FK03") == 0) key = GLFW_KEY_F3; - else if (strcmp(name, "FK04") == 0) key = GLFW_KEY_F4; - else if (strcmp(name, "FK05") == 0) key = GLFW_KEY_F5; - else if (strcmp(name, "FK06") == 0) key = GLFW_KEY_F6; - else if (strcmp(name, "FK07") == 0) key = GLFW_KEY_F7; - else if (strcmp(name, "FK08") == 0) key = GLFW_KEY_F8; - else if (strcmp(name, "FK09") == 0) key = GLFW_KEY_F9; - else if (strcmp(name, "FK10") == 0) key = GLFW_KEY_F10; - else if (strcmp(name, "FK11") == 0) key = GLFW_KEY_F11; - else if (strcmp(name, "FK12") == 0) key = GLFW_KEY_F12; - else if (strcmp(name, "FK13") == 0) key = GLFW_KEY_F13; - else if (strcmp(name, "FK14") == 0) key = GLFW_KEY_F14; - else if (strcmp(name, "FK15") == 0) key = GLFW_KEY_F15; - else if (strcmp(name, "FK16") == 0) key = GLFW_KEY_F16; - else if (strcmp(name, "FK17") == 0) key = GLFW_KEY_F17; - else if (strcmp(name, "FK18") == 0) key = GLFW_KEY_F18; - else if (strcmp(name, "FK19") == 0) key = GLFW_KEY_F19; - else if (strcmp(name, "FK20") == 0) key = GLFW_KEY_F20; - else if (strcmp(name, "FK21") == 0) key = GLFW_KEY_F21; - else if (strcmp(name, "FK22") == 0) key = GLFW_KEY_F22; - else if (strcmp(name, "FK23") == 0) key = GLFW_KEY_F23; - else if (strcmp(name, "FK24") == 0) key = GLFW_KEY_F24; - else if (strcmp(name, "FK25") == 0) key = GLFW_KEY_F25; - else if (strcmp(name, "KP0") == 0) key = GLFW_KEY_KP_0; - else if (strcmp(name, "KP1") == 0) key = GLFW_KEY_KP_1; - else if (strcmp(name, "KP2") == 0) key = GLFW_KEY_KP_2; - else if (strcmp(name, "KP3") == 0) key = GLFW_KEY_KP_3; - else if (strcmp(name, "KP4") == 0) key = GLFW_KEY_KP_4; - else if (strcmp(name, "KP5") == 0) key = GLFW_KEY_KP_5; - else if (strcmp(name, "KP6") == 0) key = GLFW_KEY_KP_6; - else if (strcmp(name, "KP7") == 0) key = GLFW_KEY_KP_7; - else if (strcmp(name, "KP8") == 0) key = GLFW_KEY_KP_8; - else if (strcmp(name, "KP9") == 0) key = GLFW_KEY_KP_9; - else if (strcmp(name, "KPDL") == 0) key = GLFW_KEY_KP_DECIMAL; - else if (strcmp(name, "KPDV") == 0) key = GLFW_KEY_KP_DIVIDE; - else if (strcmp(name, "KPMU") == 0) key = GLFW_KEY_KP_MULTIPLY; - else if (strcmp(name, "KPSU") == 0) key = GLFW_KEY_KP_SUBTRACT; - else if (strcmp(name, "KPAD") == 0) key = GLFW_KEY_KP_ADD; - else if (strcmp(name, "KPEN") == 0) key = GLFW_KEY_KP_ENTER; - else if (strcmp(name, "KPEQ") == 0) key = GLFW_KEY_KP_EQUAL; - else if (strcmp(name, "LFSH") == 0) key = GLFW_KEY_LEFT_SHIFT; - else if (strcmp(name, "LCTL") == 0) key = GLFW_KEY_LEFT_CONTROL; - else if (strcmp(name, "LALT") == 0) key = GLFW_KEY_LEFT_ALT; - else if (strcmp(name, "LWIN") == 0) key = GLFW_KEY_LEFT_SUPER; - else if (strcmp(name, "RTSH") == 0) key = GLFW_KEY_RIGHT_SHIFT; - else if (strcmp(name, "RCTL") == 0) key = GLFW_KEY_RIGHT_CONTROL; - else if (strcmp(name, "RALT") == 0) key = GLFW_KEY_RIGHT_ALT; - else if (strcmp(name, "RWIN") == 0) key = GLFW_KEY_RIGHT_SUPER; - else if (strcmp(name, "COMP") == 0) key = GLFW_KEY_MENU; - else key = GLFW_KEY_UNKNOWN; + for (int i = 0; i < sizeof(keymap) / sizeof(keymap[0]); i++) + { + if (strncmp(desc->names->keys[scancode].name, + keymap[i].name, + XkbKeyNameLength) == 0) + { + key = keymap[i].key; + break; + } + } + + // Fall back to key aliases in case the key name did not match + for (int i = 0; i < desc->names->num_key_aliases; i++) + { + if (key != GLFW_KEY_UNKNOWN) + break; + + if (strncmp(desc->names->key_aliases[i].real, + desc->names->keys[scancode].name, + XkbKeyNameLength) != 0) + { + continue; + } + + for (int j = 0; j < sizeof(keymap) / sizeof(keymap[0]); j++) + { + if (strncmp(desc->names->key_aliases[i].alias, + keymap[j].name, + XkbKeyNameLength) == 0) + { + key = keymap[j].key; + break; + } + } + } _glfw.x11.keycodes[scancode] = key; }