diff --git a/src/x11_window.c b/src/x11_window.c index a683a821..bbe21799 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -876,6 +876,36 @@ static void releaseMonitor(_GLFWwindow* window) } } +// Encode a Unicode code point to a UTF-8 stream +// Based on cutef8 by Jeff Bezanson (Public Domain) +// +static size_t encodeUTF8(char *dest, uint32_t ch) +{ + if (ch < 0x80) { + dest[0] = (char)ch; + return 1; + } + if (ch < 0x800) { + dest[0] = (ch>>6) | 0xC0; + dest[1] = (ch & 0x3F) | 0x80; + return 2; + } + if (ch < 0x10000) { + dest[0] = (ch>>12) | 0xE0; + dest[1] = ((ch>>6) & 0x3F) | 0x80; + dest[2] = (ch & 0x3F) | 0x80; + return 3; + } + if (ch < 0x110000) { + dest[0] = (ch>>18) | 0xF0; + dest[1] = ((ch>>12) & 0x3F) | 0x80; + dest[2] = ((ch>>6) & 0x3F) | 0x80; + dest[3] = (ch & 0x3F) | 0x80; + return 4; + } + return 0; +} + // Decode a Unicode code point from a UTF-8 stream // Based on cutef8 by Jeff Bezanson (Public Domain) // @@ -2446,7 +2476,8 @@ void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode) const char* _glfwPlatformGetKeyName(int key, int scancode) { KeySym keysym; - int extra; + long ch; + size_t sz; if (!_glfw.x11.xkb.available) return NULL; @@ -2459,15 +2490,17 @@ const char* _glfwPlatformGetKeyName(int key, int scancode) keysym = XkbKeycodeToKeysym(_glfw.x11.display, scancode, 0, 0); if (keysym == NoSymbol) - return NULL; - - XkbTranslateKeySym(_glfw.x11.display, &keysym, 0, - _glfw.x11.keyName, sizeof(_glfw.x11.keyName), - &extra); - - if (!strlen(_glfw.x11.keyName)) return NULL; + ch = _glfwKeySym2Unicode(keysym); + if (ch == -1) + return NULL; + + sz = encodeUTF8(_glfw.x11.keyName, (uint32_t)ch); + if (sz == 0) + return NULL; + _glfw.x11.keyName[sz] = '\0'; + return _glfw.x11.keyName; } diff --git a/src/xkb_unicode.c b/src/xkb_unicode.c index 4c7f4373..d095405e 100644 --- a/src/xkb_unicode.c +++ b/src/xkb_unicode.c @@ -826,6 +826,59 @@ static const struct codepair { { 0x13bd, 0x0153 }, { 0x13be, 0x0178 }, { 0x20ac, 0x20ac }, + // dead keys + { 0xfe50, '`' }, + { 0xfe51, 0x00b4 }, + { 0xfe52, '^' }, + { 0xfe53, '~' }, + { 0xfe54, 0x00af }, + { 0xfe55, 0x02d8 }, + { 0xfe56, 0x02d9 }, + { 0xfe57, 0x00a8 }, + { 0xfe58, 0x02da }, + { 0xfe59, 0x02dd }, + { 0xfe5a, 0x02c7 }, + { 0xfe5b, 0x00b8 }, + { 0xfe5c, 0x02db }, + { 0xfe5d, 0x037a }, + { 0xfe5e, 0x309b }, + { 0xfe5f, 0x309c }, + // { 0xfe60, 0x0323 }, // XK_dead_belowdot + // { 0xfe61, 0x0309 }, // XK_dead_hook + // { 0xfe62, 0x031b }, // XK_dead_horn + { 0xfe63, '/' }, + { 0xfe64, 0x02bc }, + { 0xfe65, 0x02bd }, + { 0xfe66, 0x02f5 }, + { 0xfe67, 0x02f3 }, + { 0xfe68, 0x02cd }, + { 0xfe69, 0xa788 }, + { 0xfe6a, 0x02f7 }, + // { 0xfe6b, 0x032e }, // XK_dead_belowbreve + // { 0xfe6c, 0x0324 }, // XK_dead_belowdiaeresis + // { 0xfe6d, 0x0311 }, // XK_dead_invertedbreve + { 0xfe6e, ',' }, + { 0xfe6f, 0x00a4 }, + // dead vowels for universal syllable entry + { 0xfe80, 'a' }, // XK_dead_a + { 0xfe81, 'A' }, // XK_dead_A + { 0xfe82, 'e' }, // XK_dead_e + { 0xfe83, 'E' }, // XK_dead_E + { 0xfe84, 'i' }, // XK_dead_i + { 0xfe85, 'I' }, // XK_dead_I + { 0xfe86, 'o' }, // XK_dead_o + { 0xfe87, 'O' }, // XK_dead_O + { 0xfe88, 'u' }, // XK_dead_u + { 0xfe89, 'U' }, // XK_dead_U + { 0xfe8a, 0x0259 }, + { 0xfe8b, 0x018f }, + // other + { 0xfe8c, 0x00b5 }, + // extra dead elements for German T3 layout + { 0xfe90, '_' }, + { 0xfe91, 0x02c8 }, + { 0xfe92, 0x02cc }, + // { 0xfe93, 0x0338 }, // XK_dead_longsolidusoverlay // Numeric keypad with numlock on { 0xff80 /*XKB_KEY_KP_Space*/, ' ' }, { 0xffbd /*XKB_KEY_KP_Equal*/, '=' },