Skip to main content

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

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