From 6ce207039240a63120a91ee4ba4d39bd0a3ef8c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Mon, 29 Jun 2020 20:43:28 +0200 Subject: [PATCH] Win32: Fix non-BMP Unicode codepoint input Supplementary Plane codepoints from WM_CHAR and WM_SYSCHAR messages were reported as UTF-16 surrogate pairs. Related to #1635. --- README.md | 1 + src/win32_platform.h | 2 ++ src/win32_window.c | 39 +++++++++++++++++++++++++++++++-------- 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 90a1196f..64416958 100644 --- a/README.md +++ b/README.md @@ -152,6 +152,7 @@ information on what to include when reporting a bug. invalid pointer - [Win32] Bugfix: Some synthetic key events were reported as `GLFW_KEY_UNKNOWN` (#1623) + - [Win32] Bugfix: Non-BMP Unicode codepoint input was reported as UTF-16 - [Cocoa] Added support for `VK_EXT_metal_surface` (#1619) - [Cocoa] Added locating the Vulkan loader at runtime in an application bundle - [Cocoa] Moved main menu creation to GLFW initialization time (#1649) diff --git a/src/win32_platform.h b/src/win32_platform.h index 5b260b82..76ea609a 100644 --- a/src/win32_platform.h +++ b/src/win32_platform.h @@ -311,6 +311,8 @@ typedef struct _GLFWwindowWin32 // The last received cursor position, regardless of source int lastCursorPosX, lastCursorPosY; + // The last recevied high surrogate when decoding pairs of UTF-16 messages + WCHAR highSurrogate; } _GLFWwindowWin32; diff --git a/src/win32_window.c b/src/win32_window.c index d9c30c55..9dc52bab 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -646,11 +646,38 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, case WM_CHAR: case WM_SYSCHAR: + { + if (wParam >= 0xd800 && wParam <= 0xdbff) + window->win32.highSurrogate = (WCHAR) wParam; + else + { + unsigned int codepoint = 0; + + if (wParam >= 0xdc00 && wParam <= 0xdfff) + { + if (window->win32.highSurrogate) + { + codepoint += (window->win32.highSurrogate - 0xd800) << 10; + codepoint += (WCHAR) wParam - 0xdc00; + codepoint += 0x10000; + } + } + else + codepoint = (WCHAR) wParam; + + window->win32.highSurrogate = 0; + _glfwInputChar(window, codepoint, getKeyMods(), uMsg != WM_SYSCHAR); + } + + if (uMsg == WM_SYSCHAR && window->win32.keymenu) + break; + + return 0; + } + case WM_UNICHAR: { - const GLFWbool plain = (uMsg != WM_SYSCHAR); - - if (uMsg == WM_UNICHAR && wParam == UNICODE_NOCHAR) + if (wParam == UNICODE_NOCHAR) { // WM_UNICHAR is not sent by Windows, but is sent by some // third-party input method engine @@ -658,11 +685,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, return TRUE; } - _glfwInputChar(window, (unsigned int) wParam, getKeyMods(), plain); - - if (uMsg == WM_SYSCHAR && window->win32.keymenu) - break; - + _glfwInputChar(window, (unsigned int) wParam, getKeyMods(), GLFW_TRUE); return 0; }