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.
This commit is contained in:
Camilla Löwy 2020-06-29 20:43:28 +02:00
parent e47832ffcf
commit 6ce2070392
3 changed files with 34 additions and 8 deletions

View File

@ -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)

View File

@ -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;

View File

@ -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;
}