From 15580a867b1e9a259973f240c2630cfb5093c264 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antal=20Szab=C3=B3?= Date: Tue, 7 Oct 2025 21:28:50 +0200 Subject: [PATCH] windows: Fix handling of AltGr to avoid conflicts (#38925) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous modifier detection treated `AltGr` presses as `Ctrl+Alt`, which broke entering characters produced by AltGr. For example, on a Hungarian layout `{` is typed with `AltGr+B`; our code saw that as `Ctrl+Alt+B` and the keybind took precedence, so the character couldn’t be entered. On Windows, AltGr isn’t a first-class modifier. It’s emulated as a combination of `Right Alt (VK_RMENU)` plus a synthetic `Left Ctrl (VK_LCONTROL)` press. When users press AltGr, `GetKeyState` reports both Ctrl and Alt as down, which makes AltGr indistinguishable from a real `Ctrl+Alt` chord if we only look at aggregate modifier state. Fix: detect the AltGr pattern by checking `VK_RMENU && VK_LCONTROL`. When that pattern is present, treat it as text-entry intent and suppress `control` and `alt` in `current_modifiers()`. This prevents AltGr-produced characters from colliding with `Ctrl+Alt` keybinds while keeping other modifiers intact. Limitation: there is no Windows API to tell whether the active layout actually has AltGr. As a result, on non-AltGr layouts (e.g. US), pressing `Right Alt + Left Ctrl` will be interpreted as AltGr and will not trigger `Ctrl+Alt` keybinds. This is an acceptable trade-off to ensure AltGr layouts can reliably enter characters; users can still invoke `Ctrl+Alt` keybinds using `Left Alt` or by choosing bindings that avoid common AltGr pairs. I based this on https://github.com/zed-industries/zed/pull/36115 after trying other different approaches, but this one is a bit more specific. Does this approach make sense, or is slightly breaking US input in favor of fixing international input a no-go? I think the benefit - being able to type certain characters _at all_ - outweighs the shortcomings. Otherwise, there's a way to detect if the keyboard layout uses AltGr or not, but it's quite hacky, and involves reading the registry to find the current layout dll's name, opening that dll, manually declaring struct layouts that it uses, then parsing out the AltGr flag from a function call result. I don't think that's worth it, but if needed, I can give that a shot, let me know. Release Notes: - windows: Fixed handling of AltGr to avoid keybinds preventing character input --- crates/gpui/src/platform/windows/events.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/gpui/src/platform/windows/events.rs b/crates/gpui/src/platform/windows/events.rs index 3a51c7ad6d124312790466908bc867c7cf557845..a9873c109c7547547ea13b5e7ed4f71194c778a0 100644 --- a/crates/gpui/src/platform/windows/events.rs +++ b/crates/gpui/src/platform/windows/events.rs @@ -1449,9 +1449,11 @@ fn is_virtual_key_pressed(vkey: VIRTUAL_KEY) -> bool { #[inline] pub(crate) fn current_modifiers() -> Modifiers { + let altgr = is_virtual_key_pressed(VK_RMENU) && is_virtual_key_pressed(VK_LCONTROL); + Modifiers { - control: is_virtual_key_pressed(VK_CONTROL), - alt: is_virtual_key_pressed(VK_MENU), + control: is_virtual_key_pressed(VK_CONTROL) && !altgr, + alt: is_virtual_key_pressed(VK_MENU) && !altgr, shift: is_virtual_key_pressed(VK_SHIFT), platform: is_virtual_key_pressed(VK_LWIN) || is_virtual_key_pressed(VK_RWIN), function: false,