Skip to main content

devela/ui/event/key/
event.rs

1// devela/src/ui/event/key/event.rs
2//
3//! Defines [`EventKey`], [`EventKeyFfi`].
4//
5
6use crate::{ConstInit, Key, KeyMods, KeyState};
7
8#[doc = crate::_tags!(event interaction)]
9/// Represents a keyboard event.
10#[doc = crate::_doc_meta!{
11    location("ui/event"),
12    test_size_of(EventKey = 20|160; niche Option),
13}]
14///
15#[doc = "See also [`EventKeyFfi`]."]
16#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
17pub struct EventKey {
18    /// The key representing the human-readable code.
19    ///
20    /// This corresponds to X11's keysym.
21    pub semantic: Key,
22
23    /// The key representing the hardware scan code.
24    ///
25    /// This corresponds to X11's scancode XKB mapped.
26    pub physical: Key,
27
28    /// The active modifiers of the key (e.g., Shift, Ctrl).
29    pub mods: KeyMods,
30
31    /// The state of the key (pressed or released).
32    pub state: KeyState,
33}
34impl ConstInit for EventKey {
35    const INIT: Self = Self {
36        semantic: Key::INIT,
37        physical: Key::INIT,
38        mods: KeyMods::INIT,
39        state: KeyState::INIT,
40    };
41}
42impl EventKey {
43    /// Creates a key event from fully specified fields.
44    pub const fn new(semantic: Key, physical: Key, mods: KeyMods, state: KeyState) -> Self {
45        Self { semantic, physical, mods, state }
46    }
47    /// Creates a key press whose semantic and physical keys are the same.
48    pub const fn press(key: Key) -> Self {
49        Self::new(key, key, KeyMods::new(), KeyState::Press)
50    }
51    /// Creates a modified key press whose semantic and physical keys are the same.
52    pub const fn modified_press(key: Key, mods: KeyMods) -> Self {
53        Self::new(key, key, mods, KeyState::Press)
54    }
55    /// Creates a text-producing key press with unknown physical origin.
56    pub const fn text(c: char) -> Self {
57        Self::new(Key::Char(c), Key::Unknown, KeyMods::new(), KeyState::Press)
58    }
59    /// Creates a modified text-producing key press with unknown physical origin.
60    pub const fn modified_text(c: char, mods: KeyMods) -> Self {
61        Self::new(Key::Char(c), Key::Unknown, mods, KeyState::Press)
62    }
63    /// Returns this key event with a different state.
64    pub const fn with_state(mut self, state: KeyState) -> Self {
65        self.state = state;
66        self
67    }
68    /// Returns this key event with different modifiers.
69    pub const fn with_mods(mut self, mods: KeyMods) -> Self {
70        self.mods = mods;
71        self
72    }
73}
74
75#[cfg(ffi··)]
76pub use ffi::*;
77#[cfg(ffi··)]
78#[rustfmt::skip]
79#[cfg_attr(nightly_doc, doc(cfg(ffi··)))]
80mod ffi {
81    use super::*;
82    use crate::KeyFfi;
83
84    #[doc = crate::_tags!(event interaction ffi)]
85    /// An FFI-safe version of [`EventKey`].
86    #[doc = crate::_doc_meta!{
87        location("ui/event"),
88        test_size_of(EventKeyFfi = 20|160; niche Option),
89    }]
90    #[repr(C)]
91    #[allow(missing_docs)]
92    #[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash)]
93    pub struct EventKeyFfi {
94        #[doc = crate::_tags!(ffi)]
95        /// The key representing the human-readable code.
96        pub semantic: KeyFfi,
97
98        #[doc = crate::_tags!(ffi)]
99        /// The key representing the hardware scan code.
100        pub physical: KeyFfi,
101
102        /// The state of the key (pressed or released).
103        pub state: KeyState,
104
105        /// The active modifiers of the key (e.g., Shift, Ctrl).
106        pub mods: KeyMods,
107    }
108
109    impl EventKey {
110        /// Converts `EventKey` to `EventKeyFfi`.
111        pub const fn to_ffi(&self) -> EventKeyFfi {
112            EventKeyFfi {
113                semantic: self.semantic.to_ffi(),
114                physical: self.physical.to_ffi(),
115                state: self.state,
116                mods: self.mods,
117            }
118        }
119        /// Converts `EventKeyFfi` to `EventKey`.
120        pub const fn from_ffi(from: &EventKeyFfi) -> EventKey {
121            EventKey {
122                semantic: Key::from_ffi(from.semantic),
123                physical: Key::from_ffi(from.physical),
124                state: from.state,
125                mods: from.mods,
126            }
127        }
128    }
129    impl From<&EventKey> for EventKeyFfi { fn from(e: &EventKey) -> Self { EventKey::to_ffi(e) } }
130    impl From<&EventKeyFfi> for EventKey { fn from(e: &EventKeyFfi) -> Self { Self::from_ffi(e) } }
131    impl From<EventKey> for EventKeyFfi { fn from(e: EventKey) -> Self { EventKey::to_ffi(&e) } }
132    impl From<EventKeyFfi> for EventKey { fn from(e: EventKeyFfi) -> Self { Self::from_ffi(&e) } }
133}