From 38fd3c6a99ff370156196228307df6bc155c89cb Mon Sep 17 00:00:00 2001 From: Evgeny Date: Wed, 21 May 2025 15:40:28 +0700 Subject: [PATCH] winit-core/keyboard: clarify modifier docs Emphasize the difference between logical and physical state, reference sticky mods. --- src/platform_impl/linux/common/xkb/state.rs | 7 ++++--- winit-core/src/event.rs | 20 +++++++++---------- winit-core/src/keyboard.rs | 22 ++++++++++++++------- 3 files changed, 29 insertions(+), 20 deletions(-) diff --git a/src/platform_impl/linux/common/xkb/state.rs b/src/platform_impl/linux/common/xkb/state.rs index bc37f22e..4228ed64 100644 --- a/src/platform_impl/linux/common/xkb/state.rs +++ b/src/platform_impl/linux/common/xkb/state.rs @@ -153,12 +153,13 @@ impl Drop for XkbState { } } -/// Represents the current state of the keyboard modifiers +/// Represents the current logical state of the keyboard modifiers /// /// Each field of this struct represents a modifier and is `true` if this modifier is active. /// -/// For some modifiers, this means that the key is currently pressed, others are toggled -/// (like caps lock). +/// For some modifiers, this means that the key is logically pressed, others are toggled (like Caps +/// Lock). But physically the key can be in any state (for example, released Shift when +/// it's active as a sticky modifier or released Caps Lock when it's toggled on) #[derive(Copy, Clone, Debug, Default, PartialEq, Eq)] pub struct ModifiersState { /// The "control" key diff --git a/winit-core/src/event.rs b/winit-core/src/event.rs index 40e46dff..41672374 100644 --- a/winit-core/src/event.rs +++ b/winit-core/src/event.rs @@ -808,7 +808,7 @@ pub struct KeyEvent { pub struct Modifiers { pub(crate) state: ModifiersState, - // NOTE: Currently pressed modifiers keys. + // NOTE: Currently active modifiers keys (logically, but not necessarily physically, pressed). // // The field providing a metadata, it shouldn't be used as a source of truth. pub(crate) pressed_mods: ModifiersKeys, @@ -820,47 +820,47 @@ impl Modifiers { Self { state, pressed_mods } } - /// The state of the modifiers. + /// The logical state of the modifiers. pub fn state(&self) -> ModifiersState { self.state } - /// The state of the left shift key. + /// The logical state of the left shift key. pub fn lshift_state(&self) -> ModifiersKeyState { self.mod_state(ModifiersKeys::LSHIFT) } - /// The state of the right shift key. + /// The logical state of the right shift key. pub fn rshift_state(&self) -> ModifiersKeyState { self.mod_state(ModifiersKeys::RSHIFT) } - /// The state of the left alt key. + /// The logical state of the left alt key. pub fn lalt_state(&self) -> ModifiersKeyState { self.mod_state(ModifiersKeys::LALT) } - /// The state of the right alt key. + /// The logical state of the right alt key. pub fn ralt_state(&self) -> ModifiersKeyState { self.mod_state(ModifiersKeys::RALT) } - /// The state of the left control key. + /// The logical state of the left control key. pub fn lcontrol_state(&self) -> ModifiersKeyState { self.mod_state(ModifiersKeys::LCONTROL) } - /// The state of the right control key. + /// The logical state of the right control key. pub fn rcontrol_state(&self) -> ModifiersKeyState { self.mod_state(ModifiersKeys::RCONTROL) } - /// The state of the left super key. + /// The logical state of the left super key. pub fn lsuper_state(&self) -> ModifiersKeyState { self.mod_state(ModifiersKeys::LMETA) } - /// The state of the right super key. + /// The logical state of the right super key. pub fn rsuper_state(&self) -> ModifiersKeyState { self.mod_state(ModifiersKeys::RMETA) } diff --git a/winit-core/src/keyboard.rs b/winit-core/src/keyboard.rs index 216eb8fa..15984f68 100644 --- a/winit-core/src/keyboard.rs +++ b/winit-core/src/keyboard.rs @@ -1687,9 +1687,12 @@ pub enum KeyLocation { } bitflags! { - /// Represents the current state of the keyboard modifiers + /// Represents the current logical state of the keyboard modifiers /// /// Each flag represents a modifier and is set if this modifier is active. + /// + /// Note that the modifier key can be physically released with the modifier + /// still being marked as active, as in the case of sticky modifiers. #[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct ModifiersState: u32 { @@ -1707,34 +1710,39 @@ bitflags! { } impl ModifiersState { - /// Returns `true` if the shift key is pressed. + /// Returns whether the shift modifier is active. pub fn shift_key(&self) -> bool { self.intersects(Self::SHIFT) } - /// Returns `true` if the control key is pressed. + /// Returns whether the control modifier is active. pub fn control_key(&self) -> bool { self.intersects(Self::CONTROL) } - /// Returns `true` if the alt key is pressed. + /// Returns whether the alt modifier is active. pub fn alt_key(&self) -> bool { self.intersects(Self::ALT) } - /// Returns `true` if the meta key is pressed. + /// Returns whether the meta modifier is active. pub fn meta_key(&self) -> bool { self.intersects(Self::META) } } -/// The state of the particular modifiers key. +/// The logical state of the particular modifiers key. #[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub enum ModifiersKeyState { - /// The particular key is pressed. + /// The particular modifier is active or logically, but not necessarily physically, pressed. Pressed, /// The state of the key is unknown. + /// + /// Can include cases when the key is active or logically pressed, for example, when a sticky + /// **Shift** is active, the OS might not preserve information that it was activated by + /// RightShift, so the state of [`ModifiersKeys::RSHIFT`] will be unknown while the state + /// of [`ModifiersState::SHIFT`] will be active. #[default] Unknown, }