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.
This commit is contained in:
Rom Grk 2024-02-28 18:13:02 -05:00 committed by GitHub
parent c07237df33
commit 7f954cbbb8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -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,