From f8668c5a9fcec29adbfc6c2e096c88f1c985ce09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Tue, 7 Feb 2017 03:29:57 +0100 Subject: [PATCH] Win32: Fix key names not matching other platforms This brings printable key names more in line with the results provided on other platforms. Fixes #943. --- README.md | 1 + src/win32_init.c | 55 ++++++++++++++++++++++++++++++++++++++++++++ src/win32_platform.h | 3 ++- src/win32_window.c | 21 ++++++----------- 4 files changed, 65 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index f7d5d67f..52349e48 100644 --- a/README.md +++ b/README.md @@ -193,6 +193,7 @@ information on what to include when reporting a bug. - [Win32] Bugfix: `glfw3native.h` would undefine a foreign `APIENTRY` (#1062) - [Win32] Bugfix: Disabled cursor mode prevented use of caption buttons (#650,#1071) +- [Win32] Bugfix: Returned key names did not match other platforms (#943) - [X11] Moved to XI2 `XI_RawMotion` for disable cursor mode motion input (#125) - [X11] Replaced `_GLFW_HAS_XF86VM` compile-time option with dynamic loading - [X11] Bugfix: `glfwGetVideoMode` would segfault on Cygwin/X diff --git a/src/win32_init.c b/src/win32_init.c index 732ee867..392114d0 100644 --- a/src/win32_init.c +++ b/src/win32_init.c @@ -429,6 +429,60 @@ void _glfwInputErrorWin32(int error, const char* description) _glfwInputError(error, "%s: %s", description, message); } +// Updates key names according to the current keyboard layout +// +void _glfwUpdateKeyNamesWin32(void) +{ + int key; + BYTE state[256] = {0}; + + memset(_glfw.win32.keynames, 0, sizeof(_glfw.win32.keynames)); + + for (key = GLFW_KEY_SPACE; key <= GLFW_KEY_LAST; key++) + { + UINT vk; + int scancode, length; + WCHAR chars[16]; + + scancode = _glfw.win32.scancodes[key]; + if (scancode == -1) + continue; + + if (key >= GLFW_KEY_KP_0 && key <= GLFW_KEY_KP_ADD) + { + const UINT vks[] = { + VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, + VK_NUMPAD4, VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7, + VK_NUMPAD8, VK_NUMPAD9, VK_DECIMAL, VK_DIVIDE, + VK_MULTIPLY, VK_SUBTRACT, VK_ADD + }; + + vk = vks[key - GLFW_KEY_KP_0]; + } + else + vk = MapVirtualKey(scancode, MAPVK_VSC_TO_VK); + + length = ToUnicode(vk, scancode, state, + chars, sizeof(chars) / sizeof(WCHAR), + 0); + + if (length == -1) + { + length = ToUnicode(vk, scancode, state, + chars, sizeof(chars) / sizeof(WCHAR), + 0); + } + + if (length < 1) + continue; + + WideCharToMultiByte(CP_UTF8, 0, chars, 1, + _glfw.win32.keynames[key], + sizeof(_glfw.win32.keynames[key]), + NULL, NULL); + } +} + ////////////////////////////////////////////////////////////////////////// ////// GLFW platform API ////// @@ -448,6 +502,7 @@ int _glfwPlatformInit(void) return GLFW_FALSE; createKeyTables(); + _glfwUpdateKeyNamesWin32(); if (_glfw_SetProcessDpiAwareness) _glfw_SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE); diff --git a/src/win32_platform.h b/src/win32_platform.h index 233510ef..d0572226 100644 --- a/src/win32_platform.h +++ b/src/win32_platform.h @@ -250,9 +250,9 @@ typedef struct _GLFWlibraryWin32 DWORD foregroundLockTimeout; int acquiredMonitorCount; char* clipboardString; - char keyName[64]; short int keycodes[512]; short int scancodes[GLFW_KEY_LAST + 1]; + char keynames[GLFW_KEY_LAST + 1][5]; // Where to place the cursor when re-enabled double restoreCursorPosX, restoreCursorPosY; // The window whose disabled cursor mode is active @@ -353,6 +353,7 @@ void _glfwUnregisterWindowClassWin32(void); WCHAR* _glfwCreateWideStringFromUTF8Win32(const char* source); char* _glfwCreateUTF8FromWideStringWin32(const WCHAR* source); void _glfwInputErrorWin32(int error, const char* description); +void _glfwUpdateKeyNamesWin32(void); void _glfwInitTimerWin32(void); diff --git a/src/win32_window.c b/src/win32_window.c index 2b4ddede..aa7efc84 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -584,6 +584,12 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, return 0; } + case WM_INPUTLANGCHANGE: + { + _glfwUpdateKeyNamesWin32(); + break; + } + case WM_CHAR: case WM_SYSCHAR: case WM_UNICHAR: @@ -1652,20 +1658,7 @@ void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode) const char* _glfwPlatformGetScancodeName(int scancode) { - WCHAR name[16]; - - if (!GetKeyNameTextW(scancode << 16, name, sizeof(name) / sizeof(WCHAR))) - return NULL; - - if (!WideCharToMultiByte(CP_UTF8, 0, name, -1, - _glfw.win32.keyName, - sizeof(_glfw.win32.keyName), - NULL, NULL)) - { - return NULL; - } - - return _glfw.win32.keyName; + return _glfw.win32.keynames[_glfw.win32.keycodes[scancode]]; } int _glfwPlatformGetKeyScancode(int key)