@@ -228,6 +228,26 @@ void MainBackend::m_MainLoop() {
228228
229229 glfwPollEvents ();
230230
231+ // Win11 + AZERTY workaround: AltGr is synthesized as LCtrl-down + RAlt-down on Windows.
232+ // When an overlay (Steam, NVIDIA), an IME, or a focus race intercepts between the two
233+ // synthetic messages, GLFW's PeekMessage-based AltGr hack (win32_window.c) fails to
234+ // discard the LCtrl, AND the matching Ctrl-up is sometimes dropped at release. GLFW
235+ // never recovers — glfwGetKey(GLFW_KEY_*_CONTROL) stays at GLFW_PRESS, so the backend's
236+ // ImGui_ImplGlfw_UpdateKeyModifiers re-emits Ctrl-down on every event. Result: arrows
237+ // jump word-wise / Up = top-of-file / Down = end-of-file until the user changes focus.
238+ // GetAsyncKeyState reads the hardware state via the desktop input thread, bypassing the
239+ // lost WM_KEYUP, and this AddKeyEvent runs AFTER glfwPollEvents so it wins ImGui's queue
240+ // at NewFrame. AddKeyEvent dedupes when the state is unchanged → ~3 Win32 reads/frame.
241+ // No-op on Linux/Mac. See GLFW issues #1622 / #1630 / #1903.
242+ #ifdef WIN32
243+ {
244+ auto & io = ImGui::GetIO ();
245+ io.AddKeyEvent (ImGuiMod_Ctrl, (GetAsyncKeyState (VK_CONTROL ) & 0x8000 ) != 0 );
246+ io.AddKeyEvent (ImGuiMod_Shift, (GetAsyncKeyState (VK_SHIFT ) & 0x8000 ) != 0 );
247+ io.AddKeyEvent (ImGuiMod_Alt, (GetAsyncKeyState (VK_MENU ) & 0x8000 ) != 0 );
248+ }
249+ #endif
250+
231251 glfwGetFramebufferSize (m_MainWindowPtr, &display_w, &display_h);
232252
233253 m_Update (); // to do absolutly before imgui rendering
0 commit comments