diff --git a/crates/gpui/src/platform/windows/events.rs b/crates/gpui/src/platform/windows/events.rs index ee2bdf9abf175eb6f3fec58878aef0fbc5896a00..9c10dcec4bb629bfbc78b76e74db099ed605d8be 100644 --- a/crates/gpui/src/platform/windows/events.rs +++ b/crates/gpui/src/platform/windows/events.rs @@ -1307,10 +1307,10 @@ where F: FnOnce(Keystroke) -> PlatformInput, { let virtual_key = VIRTUAL_KEY(wparam.loword()); - let mut modifiers = current_modifiers(); + let modifiers = current_modifiers(); match virtual_key { - VK_SHIFT | VK_CONTROL | VK_MENU | VK_LWIN | VK_RWIN => { + VK_SHIFT | VK_CONTROL | VK_MENU | VK_LMENU | VK_RMENU | VK_LWIN | VK_RWIN => { if state .last_reported_modifiers .is_some_and(|prev_modifiers| prev_modifiers == modifiers) @@ -1460,13 +1460,25 @@ fn is_virtual_key_pressed(vkey: VIRTUAL_KEY) -> bool { unsafe { GetKeyState(vkey.0 as i32) < 0 } } +fn keyboard_uses_altgr() -> bool { + use crate::platform::windows::keyboard::WindowsKeyboardLayout; + WindowsKeyboardLayout::new() + .map(|layout| layout.uses_altgr()) + .unwrap_or(false) +} + #[inline] pub(crate) fn current_modifiers() -> Modifiers { - let altgr = is_virtual_key_pressed(VK_RMENU) && is_virtual_key_pressed(VK_LCONTROL); + let lmenu_pressed = is_virtual_key_pressed(VK_LMENU); + let rmenu_pressed = is_virtual_key_pressed(VK_RMENU); + let lcontrol_pressed = is_virtual_key_pressed(VK_LCONTROL); + + // Only treat right Alt + left Ctrl as AltGr on keyboards that actually use it + let altgr = keyboard_uses_altgr() && rmenu_pressed && lcontrol_pressed; Modifiers { control: is_virtual_key_pressed(VK_CONTROL) && !altgr, - alt: is_virtual_key_pressed(VK_MENU) && !altgr, + alt: (lmenu_pressed || rmenu_pressed) && !altgr, shift: is_virtual_key_pressed(VK_SHIFT), platform: is_virtual_key_pressed(VK_LWIN) || is_virtual_key_pressed(VK_RWIN), function: false, diff --git a/crates/gpui/src/platform/windows/keyboard.rs b/crates/gpui/src/platform/windows/keyboard.rs index 259ebaebff794d4ed7203420c8c66188998c5fa4..7a8478d5910d35fb98a913ed799f2fa1447e9a65 100644 --- a/crates/gpui/src/platform/windows/keyboard.rs +++ b/crates/gpui/src/platform/windows/keyboard.rs @@ -110,6 +110,38 @@ impl WindowsKeyboardLayout { name: "unknown".to_string(), } } + + pub(crate) fn uses_altgr(&self) -> bool { + // Check if this is a known AltGr layout by examining the layout ID + // The layout ID is a hex string like "00000409" (US) or "00000407" (German) + // Extract the language ID (last 4 bytes) + let id_bytes = self.id.as_bytes(); + if id_bytes.len() >= 4 { + let lang_id = &id_bytes[id_bytes.len() - 4..]; + // List of keyboard layouts that use AltGr (non-exhaustive) + matches!( + lang_id, + b"0407" | // German + b"040C" | // French + b"040A" | // Spanish + b"0415" | // Polish + b"0413" | // Dutch + b"0816" | // Portuguese + b"041D" | // Swedish + b"0414" | // Norwegian + b"040B" | // Finnish + b"041F" | // Turkish + b"0419" | // Russian + b"0405" | // Czech + b"040E" | // Hungarian + b"0424" | // Slovenian + b"041B" | // Slovak + b"0418" // Romanian + ) + } else { + false + } + } } impl WindowsKeyboardMapper {