From f3ba955ae485615b51057b1a914942685166eb3e Mon Sep 17 00:00:00 2001 From: Richard Acayan Date: Wed, 4 Sep 2024 21:31:04 -0400 Subject: [PATCH] core: add meta key Some applications have features (like typing Unicode codepoints in foot) that can only be used with key presses. Add a Meta key to allow the user to always send a keypress. --- src/core/button.rs | 8 +++++--- src/core/graphics.rs | 4 +++- src/core/layout.rs | 22 ++++++++++++++++++++-- 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/core/button.rs b/src/core/button.rs index 2f17007..d0171f4 100644 --- a/src/core/button.rs +++ b/src/core/button.rs @@ -11,6 +11,7 @@ use crate::core::Part; use crate::core::layout::Key; use crate::core::layout::MOD_ALT; use crate::core::layout::MOD_CTRL; +use crate::core::layout::MOD_META; use crate::core::layout::MODIFIERS_MAX; use std::collections::VecDeque; use std::convert::TryInto; @@ -239,11 +240,11 @@ impl Button { if self.modifiers[modifier - 1] == old { self.modifiers[modifier - 1] = new; - if new == ModState::Released && !Layout::is_keysym_modifier(modifier) { + if new == ModState::Released && Layout::is_pressable_modifier(modifier) { self.kbd.release(Layout::modifier_keysym(modifier)); } - if old == ModState::Released && !Layout::is_keysym_modifier(modifier) { + if old == ModState::Released && Layout::is_pressable_modifier(modifier) { self.kbd.press(Layout::modifier_keysym(modifier)); } @@ -468,7 +469,8 @@ impl Button { { let ctrl_pressed = modifiers[MOD_CTRL - 1] != ModState::Released; let alt_pressed = modifiers[MOD_ALT - 1] != ModState::Released; - let mods_pressed = ctrl_pressed || alt_pressed; + let meta_pressed = modifiers[MOD_META - 1] != ModState::Released; + let mods_pressed = ctrl_pressed || alt_pressed || meta_pressed; if part.key_available() && mods_pressed { kbd.press(part.sym()); diff --git a/src/core/graphics.rs b/src/core/graphics.rs index 5159921..af3dcdb 100644 --- a/src/core/graphics.rs +++ b/src/core/graphics.rs @@ -97,7 +97,7 @@ struct Label<'a> { small: bool, } -const LABELS: [Label; 21] = [ +const LABELS: [Label; 22] = [ Label { label: "Alt", secondary: true, small: true, }, Label { label: "Ctrl", @@ -112,6 +112,8 @@ const LABELS: [Label; 21] = [ secondary: true, small: true, }, Label { label: "Ins", secondary: true, small: true, }, + Label { label: "Meta", + secondary: true, small: true, }, Label { label: "\u{2190}", // LEFTWARDS ARROW secondary: true, small: false, }, Label { label: "\u{2191}", // UPWARDS ARROW diff --git a/src/core/layout.rs b/src/core/layout.rs index 0a50982..2d551b7 100644 --- a/src/core/layout.rs +++ b/src/core/layout.rs @@ -56,7 +56,8 @@ pub const MOD_SHIFT: usize = 1; pub const MOD_CTRL: usize = 2; pub const MOD_ALT: usize = 3; pub const MOD_FN: usize = 4; -pub const MODIFIERS_MAX: usize = 4; +pub const MOD_META: usize = 5; +pub const MODIFIERS_MAX: usize = 5; #[derive(Clone)] struct KeyValue(Keysym, String); @@ -417,6 +418,7 @@ impl Part { Keysym::Control_L => MOD_CTRL, Keysym::Alt_L => MOD_ALT, Keysym::XF86_Fn => MOD_FN, + Keysym::Meta_L => MOD_META, _ => 0, } } @@ -501,7 +503,7 @@ pub struct Layout { text_supp: bool, } -const KEYSYMS: [(&str, Keysym, &str); 20] = [ +const KEYSYMS: [(&str, Keysym, &str); 21] = [ ("\\#", Keysym::numbersign, "#"), ("\\?", Keysym::question, "?"), ("\\@", Keysym::at, "@"), @@ -517,6 +519,7 @@ const KEYSYMS: [(&str, Keysym, &str); 20] = [ ("fn", Keysym::XF86_Fn, "Fn"), ("left", Keysym::Left, "←"), ("loc alt", Keysym::Alt_L, "Alt"), + ("loc meta", Keysym::Meta_L, "Meta"), ("right", Keysym::Right, "→"), ("shift", Keysym::Shift_L, "⇧"), ("space", Keysym::space, " "), @@ -533,6 +536,20 @@ impl Layout { } } + /* + * Check if the modifier can be emitted as a key event. + * + * Modifiers that modify the key values (e.g. the Fn key and any accents) + * should usually not be emitted as key events to applications, and their + * only purpose is to modify the key values. The Meta modifier should also + * be inhibited from emitting a key event, because its purpose is to make + * every key value emit a key press. + */ + pub fn is_pressable_modifier(modifier: usize) -> bool + { + !Self::is_keysym_modifier(modifier) && modifier != MOD_META + } + pub fn is_label_modifier(modifier: usize) -> bool { // Shift does not change the keysym used for input, but changes the @@ -547,6 +564,7 @@ impl Layout { MOD_CTRL => Keysym::Control_L, MOD_ALT => Keysym::Alt_L, MOD_FN => Keysym::XF86_Fn, + MOD_META => Keysym::Meta_L, _ => Keysym::NoSymbol, } }