From 100ede57643f39306760440487c527c9032266c8 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 5 Jan 2022 16:54:03 +0100 Subject: [PATCH] Backends: GLFW: Fix CTRL+A, CTRL+Y, CTRL+Z to match keyboard layout. Converting GLFW untranslated keycodes back to translated keycodes. (#456, #2625) --- backends/imgui_impl_glfw.cpp | 21 +++++++++++++++++++++ docs/CHANGELOG.txt | 3 +++ 2 files changed, 24 insertions(+) diff --git a/backends/imgui_impl_glfw.cpp b/backends/imgui_impl_glfw.cpp index 2504ca877..d11efb625 100644 --- a/backends/imgui_impl_glfw.cpp +++ b/backends/imgui_impl_glfw.cpp @@ -16,6 +16,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2022-01-05: Inputs: Converting GLFW untranslated keycodes back to translated keycodes (in the ImGui_ImplGlfw_KeyCallback() function) in order to match the behavior of every other backend, and facilitate the use of GLFW with lettered-shortcuts API. // 2021-08-17: *BREAKING CHANGE*: Now using glfwSetWindowFocusCallback() to calling io.AddFocusEvent(). If you called ImGui_ImplGlfw_InitXXX() with install_callbacks = false, you MUST install glfwSetWindowFocusCallback() and forward it to the backend via ImGui_ImplGlfw_WindowFocusCallback(). // 2021-07-29: *BREAKING CHANGE*: Now using glfwSetCursorEnterCallback(). MousePos is correctly reported when the host platform window is hovered but not focused. If you called ImGui_ImplGlfw_InitXXX() with install_callbacks = false, you MUST install glfwSetWindowFocusCallback() callback and forward it to the backend via ImGui_ImplGlfw_CursorEnterCallback(). // 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX). @@ -66,6 +67,7 @@ #else #define GLFW_HAS_NEW_CURSORS (0) #endif +#define GLFW_HAS_GET_KEY_NAME (GLFW_VERSION_MAJOR * 1000 + GLFW_VERSION_MINOR * 100 >= 3200) // 3.2+ glfwGetKeyName() // GLFW data enum GlfwClientApi @@ -147,6 +149,25 @@ void ImGui_ImplGlfw_KeyCallback(GLFWwindow* window, int key, int scancode, int a if (bd->PrevUserCallbackKey != NULL && window == bd->Window) bd->PrevUserCallbackKey(window, key, scancode, action, mods); +#if GLFW_HAS_GET_KEY_NAME + // GLFW 3.1+ attempts to "untranslate" keys, which goes the opposite of what every other framework does, making using lettered shortcuts difficult. + // (It had reasons to do so: namely GLFW is/was more likely to be used for WASD-type game controls rather than lettered shortcuts, but IHMO the 3.1 change could have been done differently) + // See https://github.com/glfw/glfw/issues/1502 for details. + // Adding a workaround to undo this (so our keys are translated->untranslated->translated, likely a lossy process). + // This won't cover edge cases but this is at least going to cover common cases. + const char* key_name = glfwGetKeyName(key, scancode); + if (key_name && key_name[0] != 0 && key_name[1] == 0) + { + const char char_names[] = "'-=[]\\,;\'./"; + const int char_keys[] = { GLFW_KEY_GRAVE_ACCENT, GLFW_KEY_MINUS, GLFW_KEY_EQUAL, GLFW_KEY_LEFT_BRACKET, GLFW_KEY_RIGHT_BRACKET, GLFW_KEY_BACKSLASH, GLFW_KEY_COMMA, GLFW_KEY_SEMICOLON, GLFW_KEY_APOSTROPHE, GLFW_KEY_PERIOD, GLFW_KEY_SLASH, 0 }; + IM_ASSERT(IM_ARRAYSIZE(char_names) == IM_ARRAYSIZE(char_keys)); + if (key_name[0] >= '0' && key_name[0] <= '9') { key = GLFW_KEY_0 + (key_name[0] - '0'); } + else if (key_name[0] >= 'A' && key_name[0] <= 'Z') { key = GLFW_KEY_A + (key_name[0] - 'A'); } + else if (const char* p = strchr(char_names, key_name[0])) { key = char_keys[p - char_names]; } + } + // if (action == GLFW_PRESS) printf("key %d scancode %d name '%s'\n", key, scancode, key_name); +#endif + ImGuiIO& io = ImGui::GetIO(); if (key >= 0 && key < IM_ARRAYSIZE(io.KeysDown)) { diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index ebb169e8d..9eae1552c 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -64,6 +64,9 @@ Other Changes: - Platform IME: add ImGuiPlatformImeData::WantVisible, hide IME composition window when not used. (#2589) [@actboy168] - Platform IME: add ImGuiPlatformImeData::InputLineHeight. (#3113) [@liuliu] - Platform IME: [windows] call ImmSetCandidateWindow() to position candidate window. +- Backends: GLFW: fix CTRL+A, CTRL+Z, CTRL+Y shortcuts to match user keyboard layout. We are now converting GLFW + untranslated keycodes back to translated keycodes in order to match the behavior of every other backend, and + facilitate the use of GLFW with lettered-shortcuts API. (#456, #2625) - Backends: OpenGL3: Fixed a buffer overflow in imgui_impl_opengl3_loader.h init (added in 1.86). (#4468, #4830) [@dymk] It would generally not have noticeable side-effect at runtime but would be detected by runtime checkers. - Backends: Metal: Added Apple Metal C++ API support. (#4824, #4746) [@luigifcruz]