From 704e48673142a3270bff113c9e6629eefebb4e98 Mon Sep 17 00:00:00 2001 From: jilliss Date: Sun, 5 Apr 2026 19:05:49 +0800 Subject: [PATCH 1/2] New feature to distinguish whether the `Windows`, `Control`, `Alt`, and `Shift` keys are the left or right keys For use by downstream NIRI --- src/input/keyboard/mod.rs | 2 +- src/input/keyboard/modifiers_state.rs | 59 +++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/src/input/keyboard/mod.rs b/src/input/keyboard/mod.rs index 677939dedcad..8ae7ccc936f4 100644 --- a/src/input/keyboard/mod.rs +++ b/src/input/keyboard/mod.rs @@ -295,7 +295,7 @@ impl KbdInternal { let state_components = xkb.state.update_key(keycode, direction); let modifiers_changed = state_components != 0; if modifiers_changed { - self.mods_state.update_with(&xkb.state); + self.mods_state.update_with_by_keycode(keycode, &xkb.state); } let leds_changed = self.led_state.update_with(&xkb.state, &self.led_mapping); (modifiers_changed, leds_changed) diff --git a/src/input/keyboard/modifiers_state.rs b/src/input/keyboard/modifiers_state.rs index 65fcdb69e1ce..74f377e8343f 100644 --- a/src/input/keyboard/modifiers_state.rs +++ b/src/input/keyboard/modifiers_state.rs @@ -34,6 +34,30 @@ pub struct ModifiersState { /// The "ISO level 5 shift" key pub iso_level5_shift: bool, + /// windows left key + pub logo_left: bool, + + /// windows right key + pub logo_right: bool, + + /// control left key + pub ctrl_right: bool, + + /// control right key + pub ctrl_left: bool, + + /// alt left key + pub alt_left: bool, + + /// alt right key + pub alt_right: bool, + + /// shift left key + pub shift_left: bool, + + /// shift right key + pub shift_right: bool, + /// Cached serialized modifier state, e.g. for sending in `wl_keyboard.modifiers`. /// /// Note that this may have outdated information compared to the other fields, and that @@ -48,6 +72,16 @@ impl ModifiersState { /// serialization is lossy and will not survive round trips. This is documented in /// [`xkb::State::update_mask`]. pub fn update_with(&mut self, state: &xkb::State) { + self.init_key_val(state); + self.serialized = serialize_modifiers(state); + } + + /// Synchronizes the internal modifier flags with the current XKB state. + /// + /// This method checks if standard modifier names (e.g., Ctrl, Alt, Shift, Caps Lock) + /// are currently active in the "effective" state and updates the corresponding + /// boolean fields of the struct. + pub fn init_key_val(&mut self, state: &xkb::State) { self.ctrl = state.mod_name_is_active(&xkb::MOD_NAME_CTRL, xkb::STATE_MODS_EFFECTIVE); self.alt = state.mod_name_is_active(&xkb::MOD_NAME_ALT, xkb::STATE_MODS_EFFECTIVE); self.shift = state.mod_name_is_active(&xkb::MOD_NAME_SHIFT, xkb::STATE_MODS_EFFECTIVE); @@ -57,6 +91,31 @@ impl ModifiersState { self.iso_level3_shift = state.mod_name_is_active(&xkb::MOD_NAME_ISO_LEVEL3_SHIFT, xkb::STATE_MODS_EFFECTIVE); self.iso_level5_shift = state.mod_name_is_active(&xkb::MOD_NAME_MOD3, xkb::STATE_MODS_EFFECTIVE); + } + + /// Updates the modifier states based on the provided keycode and XKB state. + /// + /// This method identifies the specific key pressed (using its Keysym) + /// and sets the corresponding internal boolean flags for modifier keys + /// (Super, Control, Alt, Shift). Finally, it updates the serialized state string. + pub fn update_with_by_keycode(&mut self, keycode: xkb::Keycode, state: &xkb::State) { + // 1. Initialize modifier values based on current state + self.init_key_val(state); + // 2. Identify the specific physical key pressed + let keysym = state.key_get_one_sym(keycode); + // 3. Match specific modifier keys and update their respective flags + match keysym.into() { + xkb::keysyms::KEY_Super_L => self.logo_left = true, + xkb::keysyms::KEY_Super_R => self.logo_right = true, + xkb::keysyms::KEY_Control_L => self.ctrl_left = true, + xkb::keysyms::KEY_Control_R => self.ctrl_right = true, + xkb::keysyms::KEY_Alt_L => self.alt_left = true, + xkb::keysyms::KEY_Alt_R => self.alt_right = true, + xkb::keysyms::KEY_Shift_L => self.shift_left = true, + xkb::keysyms::KEY_Shift_R => self.shift_right = true, + _ => {} // Ignore non-modifier keys + } + // 4. Synchronize the serialized string representation of active modifiers self.serialized = serialize_modifiers(state); } From 36c0a133d6c0e056cda5e147a107df5848e627ab Mon Sep 17 00:00:00 2001 From: jilliss Date: Sat, 11 Apr 2026 14:11:31 +0800 Subject: [PATCH 2/2] fix review comments --- src/input/keyboard/modifiers_state.rs | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/input/keyboard/modifiers_state.rs b/src/input/keyboard/modifiers_state.rs index 74f377e8343f..8e092880865c 100644 --- a/src/input/keyboard/modifiers_state.rs +++ b/src/input/keyboard/modifiers_state.rs @@ -81,7 +81,7 @@ impl ModifiersState { /// This method checks if standard modifier names (e.g., Ctrl, Alt, Shift, Caps Lock) /// are currently active in the "effective" state and updates the corresponding /// boolean fields of the struct. - pub fn init_key_val(&mut self, state: &xkb::State) { + fn init_key_val(&mut self, state: &xkb::State) { self.ctrl = state.mod_name_is_active(&xkb::MOD_NAME_CTRL, xkb::STATE_MODS_EFFECTIVE); self.alt = state.mod_name_is_active(&xkb::MOD_NAME_ALT, xkb::STATE_MODS_EFFECTIVE); self.shift = state.mod_name_is_active(&xkb::MOD_NAME_SHIFT, xkb::STATE_MODS_EFFECTIVE); @@ -99,11 +99,21 @@ impl ModifiersState { /// and sets the corresponding internal boolean flags for modifier keys /// (Super, Control, Alt, Shift). Finally, it updates the serialized state string. pub fn update_with_by_keycode(&mut self, keycode: xkb::Keycode, state: &xkb::State) { - // 1. Initialize modifier values based on current state self.init_key_val(state); - // 2. Identify the specific physical key pressed + // reset value false + let default= Self { + logo_left : false, + logo_right : false, + ctrl_left : false, + ctrl_right : false, + alt_left : false, + alt_right : false, + shift_left : false, + shift_right : false, + ..*self + }; + *self = default; let keysym = state.key_get_one_sym(keycode); - // 3. Match specific modifier keys and update their respective flags match keysym.into() { xkb::keysyms::KEY_Super_L => self.logo_left = true, xkb::keysyms::KEY_Super_R => self.logo_right = true, @@ -115,7 +125,6 @@ impl ModifiersState { xkb::keysyms::KEY_Shift_R => self.shift_right = true, _ => {} // Ignore non-modifier keys } - // 4. Synchronize the serialized string representation of active modifiers self.serialized = serialize_modifiers(state); }