X11: Fix bug that mapped all function keys to GLFW_KEY_UNKNOWN

This commit is contained in:
Ali Sherief 2019-11-21 16:49:44 +02:00
parent a80788c17f
commit e94412d726

View File

@ -38,196 +38,6 @@
#include <locale.h>
// Translate an X11 key code to a GLFW key code.
//
static int translateKeyCode(int scancode)
{
int keySym;
// Valid key code range is [8,255], according to the Xlib manual
if (scancode < 8 || scancode > 255)
return GLFW_KEY_UNKNOWN;
if (_glfw.x11.xkb.available)
{
// Try secondary keysym, for numeric keypad keys
// Note: This way we always force "NumLock = ON", which is intentional
// since the returned key code should correspond to a physical
// location.
keySym = XkbKeycodeToKeysym(_glfw.x11.display, scancode, _glfw.x11.xkb.group, 1);
switch (keySym)
{
case XK_KP_0: return GLFW_KEY_KP_0;
case XK_KP_1: return GLFW_KEY_KP_1;
case XK_KP_2: return GLFW_KEY_KP_2;
case XK_KP_3: return GLFW_KEY_KP_3;
case XK_KP_4: return GLFW_KEY_KP_4;
case XK_KP_5: return GLFW_KEY_KP_5;
case XK_KP_6: return GLFW_KEY_KP_6;
case XK_KP_7: return GLFW_KEY_KP_7;
case XK_KP_8: return GLFW_KEY_KP_8;
case XK_KP_9: return GLFW_KEY_KP_9;
case XK_KP_Separator:
case XK_KP_Decimal: return GLFW_KEY_KP_DECIMAL;
case XK_KP_Equal: return GLFW_KEY_KP_EQUAL;
case XK_KP_Enter: return GLFW_KEY_KP_ENTER;
default: break;
}
// Now try primary keysym for function keys (non-printable keys)
// These should not depend on the current keyboard layout
keySym = XkbKeycodeToKeysym(_glfw.x11.display, scancode, _glfw.x11.xkb.group, 0);
}
else
{
int dummy;
KeySym* keySyms;
keySyms = XGetKeyboardMapping(_glfw.x11.display, scancode, 1, &dummy);
keySym = keySyms[0];
XFree(keySyms);
}
switch (keySym)
{
case XK_Escape: return GLFW_KEY_ESCAPE;
case XK_Tab: return GLFW_KEY_TAB;
case XK_Shift_L: return GLFW_KEY_LEFT_SHIFT;
case XK_Shift_R: return GLFW_KEY_RIGHT_SHIFT;
case XK_Control_L: return GLFW_KEY_LEFT_CONTROL;
case XK_Control_R: return GLFW_KEY_RIGHT_CONTROL;
case XK_Meta_L:
case XK_Alt_L: return GLFW_KEY_LEFT_ALT;
case XK_Mode_switch: // Mapped to Alt_R on many keyboards
case XK_ISO_Level3_Shift: // AltGr on at least some machines
case XK_Meta_R:
case XK_Alt_R: return GLFW_KEY_RIGHT_ALT;
case XK_Super_L: return GLFW_KEY_LEFT_SUPER;
case XK_Super_R: return GLFW_KEY_RIGHT_SUPER;
case XK_Menu: return GLFW_KEY_MENU;
case XK_Num_Lock: return GLFW_KEY_NUM_LOCK;
case XK_Caps_Lock: return GLFW_KEY_CAPS_LOCK;
case XK_Print: return GLFW_KEY_PRINT_SCREEN;
case XK_Scroll_Lock: return GLFW_KEY_SCROLL_LOCK;
case XK_Pause: return GLFW_KEY_PAUSE;
case XK_Delete: return GLFW_KEY_DELETE;
case XK_BackSpace: return GLFW_KEY_BACKSPACE;
case XK_Return: return GLFW_KEY_ENTER;
case XK_Home: return GLFW_KEY_HOME;
case XK_End: return GLFW_KEY_END;
case XK_Page_Up: return GLFW_KEY_PAGE_UP;
case XK_Page_Down: return GLFW_KEY_PAGE_DOWN;
case XK_Insert: return GLFW_KEY_INSERT;
case XK_Left: return GLFW_KEY_LEFT;
case XK_Right: return GLFW_KEY_RIGHT;
case XK_Down: return GLFW_KEY_DOWN;
case XK_Up: return GLFW_KEY_UP;
case XK_F1: return GLFW_KEY_F1;
case XK_F2: return GLFW_KEY_F2;
case XK_F3: return GLFW_KEY_F3;
case XK_F4: return GLFW_KEY_F4;
case XK_F5: return GLFW_KEY_F5;
case XK_F6: return GLFW_KEY_F6;
case XK_F7: return GLFW_KEY_F7;
case XK_F8: return GLFW_KEY_F8;
case XK_F9: return GLFW_KEY_F9;
case XK_F10: return GLFW_KEY_F10;
case XK_F11: return GLFW_KEY_F11;
case XK_F12: return GLFW_KEY_F12;
case XK_F13: return GLFW_KEY_F13;
case XK_F14: return GLFW_KEY_F14;
case XK_F15: return GLFW_KEY_F15;
case XK_F16: return GLFW_KEY_F16;
case XK_F17: return GLFW_KEY_F17;
case XK_F18: return GLFW_KEY_F18;
case XK_F19: return GLFW_KEY_F19;
case XK_F20: return GLFW_KEY_F20;
case XK_F21: return GLFW_KEY_F21;
case XK_F22: return GLFW_KEY_F22;
case XK_F23: return GLFW_KEY_F23;
case XK_F24: return GLFW_KEY_F24;
case XK_F25: return GLFW_KEY_F25;
// Numeric keypad
case XK_KP_Divide: return GLFW_KEY_KP_DIVIDE;
case XK_KP_Multiply: return GLFW_KEY_KP_MULTIPLY;
case XK_KP_Subtract: return GLFW_KEY_KP_SUBTRACT;
case XK_KP_Add: return GLFW_KEY_KP_ADD;
// These should have been detected in secondary keysym test above!
case XK_KP_Insert: return GLFW_KEY_KP_0;
case XK_KP_End: return GLFW_KEY_KP_1;
case XK_KP_Down: return GLFW_KEY_KP_2;
case XK_KP_Page_Down: return GLFW_KEY_KP_3;
case XK_KP_Left: return GLFW_KEY_KP_4;
case XK_KP_Right: return GLFW_KEY_KP_6;
case XK_KP_Home: return GLFW_KEY_KP_7;
case XK_KP_Up: return GLFW_KEY_KP_8;
case XK_KP_Page_Up: return GLFW_KEY_KP_9;
case XK_KP_Delete: return GLFW_KEY_KP_DECIMAL;
case XK_KP_Equal: return GLFW_KEY_KP_EQUAL;
case XK_KP_Enter: return GLFW_KEY_KP_ENTER;
// Last resort: Check for printable keys (should not happen if the XKB
// extension is available). This will give a layout dependent mapping
// (which is wrong, and we may miss some keys, especially on non-US
// keyboards), but it's better than nothing...
case XK_a: return GLFW_KEY_A;
case XK_b: return GLFW_KEY_B;
case XK_c: return GLFW_KEY_C;
case XK_d: return GLFW_KEY_D;
case XK_e: return GLFW_KEY_E;
case XK_f: return GLFW_KEY_F;
case XK_g: return GLFW_KEY_G;
case XK_h: return GLFW_KEY_H;
case XK_i: return GLFW_KEY_I;
case XK_j: return GLFW_KEY_J;
case XK_k: return GLFW_KEY_K;
case XK_l: return GLFW_KEY_L;
case XK_m: return GLFW_KEY_M;
case XK_n: return GLFW_KEY_N;
case XK_o: return GLFW_KEY_O;
case XK_p: return GLFW_KEY_P;
case XK_q: return GLFW_KEY_Q;
case XK_r: return GLFW_KEY_R;
case XK_s: return GLFW_KEY_S;
case XK_t: return GLFW_KEY_T;
case XK_u: return GLFW_KEY_U;
case XK_v: return GLFW_KEY_V;
case XK_w: return GLFW_KEY_W;
case XK_x: return GLFW_KEY_X;
case XK_y: return GLFW_KEY_Y;
case XK_z: return GLFW_KEY_Z;
case XK_1: return GLFW_KEY_1;
case XK_2: return GLFW_KEY_2;
case XK_3: return GLFW_KEY_3;
case XK_4: return GLFW_KEY_4;
case XK_5: return GLFW_KEY_5;
case XK_6: return GLFW_KEY_6;
case XK_7: return GLFW_KEY_7;
case XK_8: return GLFW_KEY_8;
case XK_9: return GLFW_KEY_9;
case XK_0: return GLFW_KEY_0;
case XK_space: return GLFW_KEY_SPACE;
case XK_minus: return GLFW_KEY_MINUS;
case XK_equal: return GLFW_KEY_EQUAL;
case XK_bracketleft: return GLFW_KEY_LEFT_BRACKET;
case XK_bracketright: return GLFW_KEY_RIGHT_BRACKET;
case XK_backslash: return GLFW_KEY_BACKSLASH;
case XK_semicolon: return GLFW_KEY_SEMICOLON;
case XK_apostrophe: return GLFW_KEY_APOSTROPHE;
case XK_grave: return GLFW_KEY_GRAVE_ACCENT;
case XK_comma: return GLFW_KEY_COMMA;
case XK_period: return GLFW_KEY_PERIOD;
case XK_slash: return GLFW_KEY_SLASH;
case XK_less: return GLFW_KEY_WORLD_1; // At least in some layouts...
default: break;
}
// No matching translation was found
return GLFW_KEY_UNKNOWN;
}
// Create key code translation tables
//
static void createKeyTables(void)
@ -252,10 +62,10 @@ static void createKeyTables(void)
memcpy(name, desc->names->keys[scancode].name, XkbKeyNameLength);
name[XkbKeyNameLength] = '\0';
// Map the key name to a GLFW key code. Note: We only map printable
// keys here, and we use the US keyboard layout. The rest of the
// keys (function keys) are mapped using traditional KeySym
// translations.
// 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;
@ -304,6 +114,77 @@ static void createKeyTables(void)
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;
if ((scancode >= 0) && (scancode < 256))
@ -316,11 +197,6 @@ static void createKeyTables(void)
for (scancode = 0; scancode < 256; scancode++)
{
// Translate the un-translated key codes using traditional X11 KeySym
// lookups
if (_glfw.x11.keycodes[scancode] < 0)
_glfw.x11.keycodes[scancode] = translateKeyCode(scancode);
// Store the reverse translation for faster key name lookup
if (_glfw.x11.keycodes[scancode] > 0)
_glfw.x11.scancodes[_glfw.x11.keycodes[scancode]] = scancode;