diff --git a/crates/gpui/src/platform/linux/keyboard.rs b/crates/gpui/src/platform/linux/keyboard.rs index 9d5f44739e1d48b01687705c4111616ff24135a4..5b9874bd0f46c8bdd5cd2dc4d0e1133dd794d6ee 100644 --- a/crates/gpui/src/platform/linux/keyboard.rs +++ b/crates/gpui/src/platform/linux/keyboard.rs @@ -1,3 +1,4 @@ +#[cfg(any(feature = "wayland", feature = "x11"))] use collections::HashMap; #[cfg(any(feature = "wayland", feature = "x11"))] use xkbcommon::xkb::Keycode; @@ -58,15 +59,53 @@ impl LinuxKeyboardMapper { } } - pub(crate) fn get_key(&self, keycode: Keycode, shift: bool) -> Option { - if shift { - self.code_to_shifted_key.get(&keycode).cloned() - } else { + pub(crate) fn get_key( + &self, + keycode: Keycode, + modifiers: &mut crate::Modifiers, + ) -> Option { + if is_alphabetic_key(keycode) || !modifiers.shift { self.code_to_key.get(&keycode).cloned() + } else { + modifiers.shift = false; + self.code_to_shifted_key.get(&keycode).cloned() } } } +#[cfg(any(feature = "wayland", feature = "x11"))] +fn is_alphabetic_key(keycode: Keycode) -> bool { + matches!( + keycode.raw(), + 0x0026 // a + | 0x0038 // b + | 0x0036 // c + | 0x0028 // d + | 0x001a // e + | 0x0029 // f + | 0x002a // g + | 0x002b // h + | 0x001f // i + | 0x002c // j + | 0x002d // k + | 0x002e // l + | 0x003a // m + | 0x0039 // n + | 0x0020 // o + | 0x0021 // p + | 0x0018 // q + | 0x001b // r + | 0x0027 // s + | 0x001c // t + | 0x001e // u + | 0x0037 // v + | 0x0019 // w + | 0x0035 // x + | 0x001d // y + | 0x0034 // z + ) +} + // All typeable scan codes for the standard US keyboard layout, ANSI104 #[cfg(any(feature = "wayland", feature = "x11"))] const TYPEABLE_CODES: &[u32] = &[ diff --git a/crates/gpui/src/platform/linux/platform.rs b/crates/gpui/src/platform/linux/platform.rs index f431cb5f6941174c08f7bb68269aedc5d338643c..a00516e321d15fa0ba41ada9862cd4acc29ce51d 100644 --- a/crates/gpui/src/platform/linux/platform.rs +++ b/crates/gpui/src/platform/linux/platform.rs @@ -759,9 +759,33 @@ impl crate::Keystroke { Keysym::XF86_New => "new".to_owned(), Keysym::XF86_Open => "open".to_owned(), Keysym::XF86_Save => "save".to_owned(), + Keysym::F1 => "f1".to_owned(), + Keysym::F2 => "f2".to_owned(), + Keysym::F3 => "f3".to_owned(), + Keysym::F4 => "f4".to_owned(), + Keysym::F5 => "f5".to_owned(), + Keysym::F6 => "f6".to_owned(), + Keysym::F7 => "f7".to_owned(), + Keysym::F8 => "f8".to_owned(), + Keysym::F9 => "f9".to_owned(), + Keysym::F10 => "f10".to_owned(), + Keysym::F11 => "f11".to_owned(), + Keysym::F12 => "f12".to_owned(), + Keysym::F13 => "f13".to_owned(), + Keysym::F14 => "f14".to_owned(), + Keysym::F15 => "f15".to_owned(), + Keysym::F16 => "f16".to_owned(), + Keysym::F17 => "f17".to_owned(), + Keysym::F18 => "f18".to_owned(), + Keysym::F19 => "f19".to_owned(), + Keysym::F20 => "f20".to_owned(), + Keysym::F21 => "f21".to_owned(), + Keysym::F22 => "f22".to_owned(), + Keysym::F23 => "f23".to_owned(), + Keysym::F24 => "f24".to_owned(), _ => keyboard_state .mapper - .get_key(keycode, modifiers.shift) + .get_key(keycode, &mut modifiers) .unwrap_or_else(|| { let name = xkb::keysym_get_name(key_sym).to_lowercase(); if key_sym.is_keypad_key() { @@ -772,15 +796,6 @@ impl crate::Keystroke { }), }; - if modifiers.shift { - // we only include the shift for upper-case letters by convention, - // so don't include for numbers and symbols, but do include for - // tab/enter, etc. - if key.chars().count() == 1 && key.to_lowercase() == key.to_uppercase() { - modifiers.shift = false; - } - } - // Ignore control characters (and DEL) for the purposes of key_char let key_char = (!key_utf8.is_empty() && !key_utf8.chars().next().unwrap().is_control()) .then_some(key_utf8);