From 7f954cbbb8a52e92fe5325848d6e7f5eda0c555d Mon Sep 17 00:00:00 2001 From: Rom Grk Date: Wed, 28 Feb 2024 18:13:02 -0500 Subject: [PATCH] linux: improve key translation (#8560) This PR brings linux XKB key translation more in line with the macOS logic, which fixes quite a few key bindings. --- crates/gpui/src/platform/linux/util.rs | 62 +++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/crates/gpui/src/platform/linux/util.rs b/crates/gpui/src/platform/linux/util.rs index d0ee6287c9f92e4867a16ef078cd3a01a6105699..f5b90541f08504200f04d823860923a484fe9e16 100644 --- a/crates/gpui/src/platform/linux/util.rs +++ b/crates/gpui/src/platform/linux/util.rs @@ -4,15 +4,66 @@ use crate::{Keystroke, Modifiers}; impl Keystroke { pub(super) fn from_xkb(state: &State, modifiers: Modifiers, keycode: Keycode) -> Self { + let mut modifiers = modifiers; + let key_utf32 = state.key_get_utf32(keycode); let key_utf8 = state.key_get_utf8(keycode); let key_sym = state.key_get_one_sym(keycode); + // The logic here tries to replicate the logic in `../mac/events.rs` + // "Consumed" modifiers are modifiers that have been used to translate a key, for example + // pressing "shift" and "1" on US layout produces the key `!` but "consumes" the shift. + // Notes: + // - macOS gets the key character directly ("."), xkb gives us the key name ("period") + // - macOS logic removes consumed shift modifier for symbols: "{", not "shift-{" + // - macOS logic keeps consumed shift modifiers for letters: "shift-a", not "a" or "A" + + let mut handle_consumed_modifiers = true; let key = match key_sym { Keysym::Return => "enter".to_owned(), Keysym::Prior => "pageup".to_owned(), Keysym::Next => "pagedown".to_owned(), - _ => xkb::keysym_get_name(key_sym).to_lowercase(), + + Keysym::comma => ",".to_owned(), + Keysym::period => ".".to_owned(), + Keysym::less => "<".to_owned(), + Keysym::greater => ">".to_owned(), + Keysym::slash => "/".to_owned(), + Keysym::question => "?".to_owned(), + + Keysym::semicolon => ";".to_owned(), + Keysym::colon => ":".to_owned(), + Keysym::apostrophe => "'".to_owned(), + Keysym::quotedbl => "\"".to_owned(), + + Keysym::bracketleft => "[".to_owned(), + Keysym::braceleft => "{".to_owned(), + Keysym::bracketright => "]".to_owned(), + Keysym::braceright => "}".to_owned(), + Keysym::backslash => "\\".to_owned(), + Keysym::bar => "|".to_owned(), + + Keysym::grave => "`".to_owned(), + Keysym::asciitilde => "~".to_owned(), + Keysym::exclam => "!".to_owned(), + Keysym::at => "@".to_owned(), + Keysym::numbersign => "#".to_owned(), + Keysym::dollar => "$".to_owned(), + Keysym::percent => "%".to_owned(), + Keysym::asciicircum => "^".to_owned(), + Keysym::ampersand => "&".to_owned(), + Keysym::asterisk => "*".to_owned(), + Keysym::parenleft => "(".to_owned(), + Keysym::parenright => ")".to_owned(), + Keysym::minus => "-".to_owned(), + Keysym::underscore => "_".to_owned(), + Keysym::equal => "=".to_owned(), + Keysym::plus => "+".to_owned(), + + _ => { + handle_consumed_modifiers = false; + xkb::keysym_get_name(key_sym).to_lowercase() + } }; // Ignore control characters (and DEL) for the purposes of ime_key, @@ -21,6 +72,15 @@ impl Keystroke { && !key_utf8.is_empty()) .then_some(key_utf8); + if handle_consumed_modifiers { + let mod_shift_index = state.get_keymap().mod_get_index(xkb::MOD_NAME_SHIFT); + let is_shift_consumed = state.mod_index_is_consumed(keycode, mod_shift_index); + + if modifiers.shift && is_shift_consumed { + modifiers.shift = false; + } + } + Keystroke { modifiers, key,