diff --git a/README.md b/README.md index fd3126b1..0fe0987b 100644 --- a/README.md +++ b/README.md @@ -99,6 +99,7 @@ GLFW bundles a number of dependencies in the `deps/` directory. - [X11] Bugfix: `glfwWaitEvents` did not handle `EINTR` for `select` - [X11] Bugfix: `glfwWaitEvents` could return when no events were available - [X11] Bugfix: `XkbGetKeyboard` fails on XWayland + - [X11] Bugfix: Character input did not work correctly for non-UTF-8 locales - [WGL] Made all WGL functions dynamically loaded - [WGL] Removed `GLFW_USE_DWM_SWAP_INTERVAL` compile-time option - [WGL] Bugfix: Swap interval was ignored when DWM was enabled diff --git a/src/x11_init.c b/src/x11_init.c index c62a142f..7df3dde6 100644 --- a/src/x11_init.c +++ b/src/x11_init.c @@ -709,10 +709,12 @@ Cursor _glfwCreateCursor(const GLFWimage* image, int xhot, int yhot) int _glfwPlatformInit(void) { +#if !defined(X_HAVE_UTF8_STRING) // HACK: If the current locale is C, apply the environment's locale - // This is done because the C locale breaks character input + // This is done because the C locale breaks wide character input if (strcmp(setlocale(LC_CTYPE, NULL), "C") == 0) setlocale(LC_CTYPE, ""); +#endif XInitThreads(); diff --git a/src/x11_window.c b/src/x11_window.c index f64a3220..735ae17b 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -37,6 +37,7 @@ #include #include #include +#include // Action for EWMH client messages #define _NET_WM_STATE_REMOVE 0 @@ -845,6 +846,31 @@ static void leaveFullscreenMode(_GLFWwindow* window) } } +// Decode a Unicode code point from a UTF-8 stream +// Based on cutef8 by Jeff Bezanson (Public Domain) +// +#if defined(X_HAVE_UTF8_STRING) +static unsigned int decodeUTF8(const char** s) +{ + unsigned int ch = 0, count = 0; + static const unsigned int offsets[] = + { + 0x00000000u, 0x00003080u, 0x000e2080u, + 0x03c82080u, 0xfa082080u, 0x82082080u + }; + + do + { + ch = (ch << 6) + (unsigned char) **s; + (*s)++; + count++; + } while ((**s & 0xc0) == 0x80); + + assert(count <= 6); + return ch - offsets[count - 1]; +} +#endif /*X_HAVE_UTF8_STRING*/ + // Process the specified X event // static void processEvent(XEvent *event) @@ -895,6 +921,19 @@ static void processEvent(XEvent *event) if (!filtered) { +#if defined(X_HAVE_UTF8_STRING) + Status status; + char buffer[96]; + const char* c = buffer; + + const int count = Xutf8LookupString(window->x11.ic, + &event->xkey, + buffer, sizeof(buffer), + NULL, &status); + + while (c - buffer < count) + _glfwInputChar(window, decodeUTF8(&c), mods, plain); +#else int i; Status status; wchar_t buffer[16]; @@ -906,6 +945,7 @@ static void processEvent(XEvent *event) for (i = 0; i < count; i++) _glfwInputChar(window, buffer[i], mods, plain); +#endif } } else