diff --git a/src/x11_init.c b/src/x11_init.c index 98a47f27..f040c06a 100644 --- a/src/x11_init.c +++ b/src/x11_init.c @@ -673,6 +673,7 @@ void _glfwPlatformTerminate(void) } free(_glfw.x11.selection.string); + free(_glfw.x11.keyName); _glfwTerminateJoysticks(); _glfwTerminateContextAPI(); diff --git a/src/x11_platform.h b/src/x11_platform.h index 868429fa..cd1dc054 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -190,6 +190,8 @@ typedef struct _GLFWlibraryX11 char* string; } selection; + char* keyName; + struct { int present; int fd; diff --git a/src/x11_window.c b/src/x11_window.c index b15304bd..cf0bb449 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -33,6 +33,8 @@ #include #include #include +#include +#include // Action for EWMH client messages #define _NET_WM_STATE_REMOVE 0 @@ -1165,8 +1167,271 @@ void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode) const char*_glfwPlatformGetKeyName(int key) { - // TODO: Implement. - return NULL; + int KeyCodeFound = -1; + int printable = 0; + int keySym, ucsChar, keyCode, length; + char* locale; + + switch(key) + { + case GLFW_KEY_A: printable=1; break; + case GLFW_KEY_B: printable=1; break; + case GLFW_KEY_C: printable=1; break; + case GLFW_KEY_D: printable=1; break; + case GLFW_KEY_E: printable=1; break; + case GLFW_KEY_F: printable=1; break; + case GLFW_KEY_G: printable=1; break; + case GLFW_KEY_H: printable=1; break; + case GLFW_KEY_I: printable=1; break; + case GLFW_KEY_J: printable=1; break; + case GLFW_KEY_K: printable=1; break; + case GLFW_KEY_L: printable=1; break; + case GLFW_KEY_M: printable=1; break; + case GLFW_KEY_N: printable=1; break; + case GLFW_KEY_O: printable=1; break; + case GLFW_KEY_P: printable=1; break; + case GLFW_KEY_Q: printable=1; break; + case GLFW_KEY_R: printable=1; break; + case GLFW_KEY_S: printable=1; break; + case GLFW_KEY_T: printable=1; break; + case GLFW_KEY_U: printable=1; break; + case GLFW_KEY_V: printable=1; break; + case GLFW_KEY_W: printable=1; break; + case GLFW_KEY_X: printable=1; break; + case GLFW_KEY_Y: printable=1; break; + case GLFW_KEY_Z: printable=1; break; + case GLFW_KEY_1: printable=1; break; + case GLFW_KEY_2: printable=1; break; + case GLFW_KEY_3: printable=1; break; + case GLFW_KEY_4: printable=1; break; + case GLFW_KEY_5: printable=1; break; + case GLFW_KEY_6: printable=1; break; + case GLFW_KEY_7: printable=1; break; + case GLFW_KEY_8: printable=1; break; + case GLFW_KEY_9: printable=1; break; + case GLFW_KEY_0: printable=1; break; + case GLFW_KEY_SPACE: printable=1; break; + case GLFW_KEY_MINUS: printable=1; break; + case GLFW_KEY_EQUAL: printable=1; break; + case GLFW_KEY_LEFT_BRACKET: printable=1; break; + case GLFW_KEY_RIGHT_BRACKET: printable=1; break; + case GLFW_KEY_BACKSLASH: printable=1; break; + case GLFW_KEY_SEMICOLON: printable=1; break; + case GLFW_KEY_APOSTROPHE: printable=1; break; + case GLFW_KEY_GRAVE_ACCENT: printable=1; break; + case GLFW_KEY_COMMA: printable=1; break; + case GLFW_KEY_PERIOD: printable=1; break; + case GLFW_KEY_SLASH: printable=1; break; + case GLFW_KEY_WORLD_1: printable=1; break; + default: break; + } + + if (printable) + { + // We now need to search for the keyCode. + // This could be sped up through a table, but this function should not be called that frequently + // Valid key code range is [8,255], according to the XLib manual + for(keyCode = 8; keyCode<=255; ++keyCode) + { + if( translateKey(keyCode) == key ) + { + KeyCodeFound = keyCode; + break; + } + } + + if(KeyCodeFound>=0) + { + // get keyboard group in use via state + XkbStateRec state; + XkbGetState(_glfw.x11.display, XkbUseCoreKbd, &state); + + keySym = XkbKeycodeToKeysym(_glfw.x11.display, KeyCodeFound, state.group, 0); + ucsChar = _glfwKeySym2Unicode( keySym ); + if( ucsChar > 0 ) + { + // get current locale and set to for wctomb + locale = setlocale(LC_CTYPE,NULL); + setlocale(LC_CTYPE,""); + if(!_glfw.x11.keyName) + { + // only need to allocate once + _glfw.x11.keyName = calloc(MB_CUR_MAX+1,sizeof(char)); + } + length = wctomb(_glfw.x11.keyName, ucsChar); + + // reset locale + setlocale(LC_CTYPE,locale); + + _glfw.x11.keyName[length]='\0'; + if(length>0) + { + // need to ensure common chars are interpreted similarily: + if(length=1) + { + if(_glfw.x11.keyName[0]>='a' && _glfw.x11.keyName[0]<='z') + { + // Capitalize + _glfw.x11.keyName[0] += 'A'-'a'; + } + + switch(_glfw.x11.keyName[0]) + { + case ' ': return "SPACE"; + case '-': return "MINUS"; + case '=': return "EQUAL"; + case '[': return "LEFT BRACKET"; + case ']': return "RIGHT BRACKET"; + case '\\': return "BACKSLASH"; + case ';': return "SEMICOLON"; + case '\'': return "APOSTROPHE"; + case '`': return "GRAVE ACCENT"; + case ',': return "COMMA"; + case '.': return "PERIOD"; + case '/': return "SLASH"; + default: break; + } + } + return _glfw.x11.keyName; + } + } + + } + } + + + // Fallback to hard coded + switch (key) + { + // Printable keys + case GLFW_KEY_A: return "A"; + case GLFW_KEY_B: return "B"; + case GLFW_KEY_C: return "C"; + case GLFW_KEY_D: return "D"; + case GLFW_KEY_E: return "E"; + case GLFW_KEY_F: return "F"; + case GLFW_KEY_G: return "G"; + case GLFW_KEY_H: return "H"; + case GLFW_KEY_I: return "I"; + case GLFW_KEY_J: return "J"; + case GLFW_KEY_K: return "K"; + case GLFW_KEY_L: return "L"; + case GLFW_KEY_M: return "M"; + case GLFW_KEY_N: return "N"; + case GLFW_KEY_O: return "O"; + case GLFW_KEY_P: return "P"; + case GLFW_KEY_Q: return "Q"; + case GLFW_KEY_R: return "R"; + case GLFW_KEY_S: return "S"; + case GLFW_KEY_T: return "T"; + case GLFW_KEY_U: return "U"; + case GLFW_KEY_V: return "V"; + case GLFW_KEY_W: return "W"; + case GLFW_KEY_X: return "X"; + case GLFW_KEY_Y: return "Y"; + case GLFW_KEY_Z: return "Z"; + case GLFW_KEY_1: return "1"; + case GLFW_KEY_2: return "2"; + case GLFW_KEY_3: return "3"; + case GLFW_KEY_4: return "4"; + case GLFW_KEY_5: return "5"; + case GLFW_KEY_6: return "6"; + case GLFW_KEY_7: return "7"; + case GLFW_KEY_8: return "8"; + case GLFW_KEY_9: return "9"; + case GLFW_KEY_0: return "0"; + case GLFW_KEY_SPACE: return "SPACE"; + case GLFW_KEY_MINUS: return "MINUS"; + case GLFW_KEY_EQUAL: return "EQUAL"; + case GLFW_KEY_LEFT_BRACKET: return "LEFT BRACKET"; + case GLFW_KEY_RIGHT_BRACKET: return "RIGHT BRACKET"; + case GLFW_KEY_BACKSLASH: return "BACKSLASH"; + case GLFW_KEY_SEMICOLON: return "SEMICOLON"; + case GLFW_KEY_APOSTROPHE: return "APOSTROPHE"; + case GLFW_KEY_GRAVE_ACCENT: return "GRAVE ACCENT"; + case GLFW_KEY_COMMA: return "COMMA"; + case GLFW_KEY_PERIOD: return "PERIOD"; + case GLFW_KEY_SLASH: return "SLASH"; + case GLFW_KEY_WORLD_1: return "WORLD 1"; + case GLFW_KEY_WORLD_2: return "WORLD 2"; + + // Function keys + case GLFW_KEY_ESCAPE: return "ESCAPE"; + case GLFW_KEY_F1: return "F1"; + case GLFW_KEY_F2: return "F2"; + case GLFW_KEY_F3: return "F3"; + case GLFW_KEY_F4: return "F4"; + case GLFW_KEY_F5: return "F5"; + case GLFW_KEY_F6: return "F6"; + case GLFW_KEY_F7: return "F7"; + case GLFW_KEY_F8: return "F8"; + case GLFW_KEY_F9: return "F9"; + case GLFW_KEY_F10: return "F10"; + case GLFW_KEY_F11: return "F11"; + case GLFW_KEY_F12: return "F12"; + case GLFW_KEY_F13: return "F13"; + case GLFW_KEY_F14: return "F14"; + case GLFW_KEY_F15: return "F15"; + case GLFW_KEY_F16: return "F16"; + case GLFW_KEY_F17: return "F17"; + case GLFW_KEY_F18: return "F18"; + case GLFW_KEY_F19: return "F19"; + case GLFW_KEY_F20: return "F20"; + case GLFW_KEY_F21: return "F21"; + case GLFW_KEY_F22: return "F22"; + case GLFW_KEY_F23: return "F23"; + case GLFW_KEY_F24: return "F24"; + case GLFW_KEY_F25: return "F25"; + case GLFW_KEY_UP: return "UP"; + case GLFW_KEY_DOWN: return "DOWN"; + case GLFW_KEY_LEFT: return "LEFT"; + case GLFW_KEY_RIGHT: return "RIGHT"; + case GLFW_KEY_LEFT_SHIFT: return "LEFT SHIFT"; + case GLFW_KEY_RIGHT_SHIFT: return "RIGHT SHIFT"; + case GLFW_KEY_LEFT_CONTROL: return "LEFT CONTROL"; + case GLFW_KEY_RIGHT_CONTROL: return "RIGHT CONTROL"; + case GLFW_KEY_LEFT_ALT: return "LEFT ALT"; + case GLFW_KEY_RIGHT_ALT: return "RIGHT ALT"; + case GLFW_KEY_TAB: return "TAB"; + case GLFW_KEY_ENTER: return "ENTER"; + case GLFW_KEY_BACKSPACE: return "BACKSPACE"; + case GLFW_KEY_INSERT: return "INSERT"; + case GLFW_KEY_DELETE: return "DELETE"; + case GLFW_KEY_PAGE_UP: return "PAGE UP"; + case GLFW_KEY_PAGE_DOWN: return "PAGE DOWN"; + case GLFW_KEY_HOME: return "HOME"; + case GLFW_KEY_END: return "END"; + case GLFW_KEY_KP_0: return "KEYPAD 0"; + case GLFW_KEY_KP_1: return "KEYPAD 1"; + case GLFW_KEY_KP_2: return "KEYPAD 2"; + case GLFW_KEY_KP_3: return "KEYPAD 3"; + case GLFW_KEY_KP_4: return "KEYPAD 4"; + case GLFW_KEY_KP_5: return "KEYPAD 5"; + case GLFW_KEY_KP_6: return "KEYPAD 6"; + case GLFW_KEY_KP_7: return "KEYPAD 7"; + case GLFW_KEY_KP_8: return "KEYPAD 8"; + case GLFW_KEY_KP_9: return "KEYPAD 9"; + case GLFW_KEY_KP_DIVIDE: return "KEYPAD DIVIDE"; + case GLFW_KEY_KP_MULTIPLY: return "KEYPAD MULTPLY"; + case GLFW_KEY_KP_SUBTRACT: return "KEYPAD SUBTRACT"; + case GLFW_KEY_KP_ADD: return "KEYPAD ADD"; + case GLFW_KEY_KP_DECIMAL: return "KEYPAD DECIMAL"; + case GLFW_KEY_KP_EQUAL: return "KEYPAD EQUAL"; + case GLFW_KEY_KP_ENTER: return "KEYPAD ENTER"; + case GLFW_KEY_PRINT_SCREEN: return "PRINT SCREEN"; + case GLFW_KEY_NUM_LOCK: return "NUM LOCK"; + case GLFW_KEY_CAPS_LOCK: return "CAPS LOCK"; + case GLFW_KEY_SCROLL_LOCK: return "SCROLL LOCK"; + case GLFW_KEY_PAUSE: return "PAUSE"; + case GLFW_KEY_LEFT_SUPER: return "LEFT SUPER"; + case GLFW_KEY_RIGHT_SUPER: return "RIGHT SUPER"; + case GLFW_KEY_MENU: return "MENU"; + case GLFW_KEY_UNKNOWN: return "UNKNOWN"; + + default: break; + } + + return NULL; } //////////////////////////////////////////////////////////////////////////