Skip to main content

devela/sys/os/browser/web/event/key/
location.rs

1// devela::sys::os::browser::web::event::key::location
2//
3//! Defines [`WebKeyLocation`].
4//
5// TOC
6// enum WebKeyLocation
7// impl KeyMod
8// impl KeyMods
9
10use crate::{KeyMod, KeyMods};
11
12#[doc = crate::_tags!(interaction web)]
13/// Which part of the keyboard the key event originates from.
14#[doc = crate::_doc_meta!{location("sys/os/browser/web")}]
15///
16/// - <https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#keyboard_locations>
17#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
18pub enum WebKeyLocation {
19    /// The key is not identified as being located in a particular area of the keyboard. (Default)
20    #[default]
21    Standard = 0,
22    /// On the left side of the keyboard.
23    Left = 1,
24    /// Ont he right side of the keyboard.
25    Right = 2,
26    /// On the numeric keypad.
27    NumPad = 3,
28}
29impl WebKeyLocation {
30    /// Constructs a keyboard location from the numeric value of its representation.
31    pub const fn from_repr(from: u8) -> Self {
32        use WebKeyLocation as L;
33        match from {
34            0 => L::Standard,
35            1 => L::Left,
36            2 => L::Right,
37            3 => L::NumPad,
38            _ => L::Standard,
39        }
40    }
41}
42
43#[rustfmt::skip]
44impl KeyMod {
45    /// Atempts to construct a `KeyMod` from a JavaScript `KeyboardEvent`
46    /// physical [code] and [location].
47    ///
48    /// [code]: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code
49    /// [location]: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/location
50    // https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_code_values
51    pub const fn from_web_code(code: &str, location: WebKeyLocation) -> Option<Self> {
52        use {KeyMod as K, WebKeyLocation as L};
53        match (code.as_bytes(), location) {
54            (b"ShiftLeft", L::Left) => Some(K::LeftShift),
55            (b"ControlLeft", L::Left) => Some(K::LeftControl),
56            (b"AltLeft", L::Left) => Some(K::LeftAlt),
57            (b"MetaLeft", L::Left) => Some(K::LeftSuper),
58            (b"ShiftRight", L::Right) => Some(K::RightShift),
59            (b"ControlRight", L::Right) => Some(K::RightControl),
60            (b"AltRight", L::Right) => Some(K::RightAlt),
61            (b"MetaRight", L::Right) => Some(K::RightSuper),
62            (b"AltGraph", L::Standard) => Some(K::AltGr),
63            (b"Level5Shift", L::Standard) => Some(K::IsoLevel5Shift),
64            _ => None,
65        }
66    }
67    /// Returns a JavaScript `KeyboardEvent` physical [code] and [location].
68    ///
69    /// [code]: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code
70    /// [location]: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/location
71    // https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_code_values
72    pub const fn to_web_code(self) -> (&'static str, WebKeyLocation) {
73        use {KeyMod as K, WebKeyLocation as L};
74        match self {
75            K::LeftShift => ("ShiftLeft", L::Left),
76            K::LeftControl => ("ControlLeft", L::Left),
77            K::LeftAlt => ("AltLeft", L::Left),
78            K::LeftSuper => ("MetaLeft", L::Left),
79            K::RightShift => ("ShiftRight", L::Right),
80            K::RightControl => ("ControlRight", L::Right),
81            K::RightAlt => ("AltRight", L::Right),
82            K::RightSuper => ("MetaRight", L::Right),
83            K::AltGr => ("AltGraph", L::Standard),
84            K::IsoLevel5Shift => ("Level5Shift", L::Standard),
85        }
86    }
87    /// Atempts to construct a `KeyMod` from a JavaScript `KeyboardEvent`
88    /// semantic [key] and [location].
89    ///
90    /// [key]: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key
91    /// [location]: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/location
92    pub const fn from_web_key(key: &str, location: WebKeyLocation) -> Option<Self> {
93        use {KeyMod as K, WebKeyLocation as L};
94        match (key.as_bytes(), location) {
95            (b"Shift", L::Left) => Some(K::LeftShift),
96            (b"Control", L::Left) => Some(K::LeftControl),
97            (b"Alt", L::Left) => Some(K::LeftAlt),
98            (b"Meta", L::Left) => Some(K::LeftSuper),
99            (b"Shift", L::Right) => Some(K::RightShift),
100            (b"Control", L::Right) => Some(K::RightControl),
101            (b"Alt", L::Right) => Some(K::RightAlt),
102            (b"Meta", L::Right) => Some(K::RightSuper),
103            (b"AltGraph", L::Standard) => Some(K::AltGr),
104            (b"Level5Shift", L::Standard) => Some(K::IsoLevel5Shift),
105            _ => None,
106        }
107    }
108    /// Returns a JavaScript `KeyboardEvent` semantic [key] and [location].
109    ///
110    /// [key]: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key
111    /// [location]: https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/location
112    pub const fn to_web_key(self) -> (&'static str, WebKeyLocation) {
113        use {KeyMod as K, WebKeyLocation as L};
114        match self {
115            K::LeftShift => ("Shift", L::Left),
116            K::LeftControl => ("Control", L::Left),
117            K::LeftAlt => ("Alt", L::Left),
118            K::LeftSuper => ("Meta", L::Left),
119            K::RightShift => ("Shift", L::Right),
120            K::RightControl => ("Control", L::Right),
121            K::RightAlt => ("Alt", L::Right),
122            K::RightSuper => ("Meta", L::Right),
123            K::AltGr => ("AltGraph", L::Standard),
124            K::IsoLevel5Shift => ("Level5Shift", L::Standard),
125        }
126    }
127}
128
129impl KeyMods {
130    /// Constructs `KeyMods` from a compact web modifier bitmask.
131    ///
132    /// Bit layout:
133    /// - 0: Control
134    /// - 1: Shift
135    /// - 2: Alt
136    /// - 3: Super / Meta
137    /// - 4: AltGraph
138    /// - 5: CapsLock
139    /// - 6: NumLock
140    /// - 7: ScrollLock
141    pub const fn from_web(bits: u8) -> Self {
142        Self::from_bits(bits as u16)
143    }
144
145    /// Converts `KeyMods` into a compact web modifier bitmask.
146    ///
147    /// Only the web-representable low byte is preserved.
148    pub const fn to_web(self) -> u8 {
149        (self.bits() & 0x00FF) as u8
150    }
151}