Skip to main content

ferroui_base/input/
physical_key_extensions.rs

1use super::{Key, PhysicalKey};
2
3impl PhysicalKey {
4    /// Maps a physical key to a corresponding key, if possible, on a QWERTY
5    /// keyboard. Returns [`Key::None`] when there is none.
6    pub fn to_qwerty_key(self) -> Key {
7        match self {
8            PhysicalKey::None => Key::None,
9            // Writing System Keys
10            PhysicalKey::Backquote => Key::OemTilde,
11            PhysicalKey::Backslash => Key::OemPipe,
12            PhysicalKey::BracketLeft => Key::OemOpenBrackets,
13            PhysicalKey::BracketRight => Key::OemCloseBrackets,
14            PhysicalKey::Comma => Key::OemComma,
15            PhysicalKey::Digit0 => Key::D0,
16            PhysicalKey::Digit1 => Key::D1,
17            PhysicalKey::Digit2 => Key::D2,
18            PhysicalKey::Digit3 => Key::D3,
19            PhysicalKey::Digit4 => Key::D4,
20            PhysicalKey::Digit5 => Key::D5,
21            PhysicalKey::Digit6 => Key::D6,
22            PhysicalKey::Digit7 => Key::D7,
23            PhysicalKey::Digit8 => Key::D8,
24            PhysicalKey::Digit9 => Key::D9,
25            PhysicalKey::Equal => Key::OemPlus,
26            PhysicalKey::IntlBackslash => Key::OemBackslash,
27            PhysicalKey::IntlRo => Key::OemBackslash,
28            PhysicalKey::IntlYen => Key::OemPipe,
29            PhysicalKey::A => Key::A,
30            PhysicalKey::B => Key::B,
31            PhysicalKey::C => Key::C,
32            PhysicalKey::D => Key::D,
33            PhysicalKey::E => Key::E,
34            PhysicalKey::F => Key::F,
35            PhysicalKey::G => Key::G,
36            PhysicalKey::H => Key::H,
37            PhysicalKey::I => Key::I,
38            PhysicalKey::J => Key::J,
39            PhysicalKey::K => Key::K,
40            PhysicalKey::L => Key::L,
41            PhysicalKey::M => Key::M,
42            PhysicalKey::N => Key::N,
43            PhysicalKey::O => Key::O,
44            PhysicalKey::P => Key::P,
45            PhysicalKey::Q => Key::Q,
46            PhysicalKey::R => Key::R,
47            PhysicalKey::S => Key::S,
48            PhysicalKey::T => Key::T,
49            PhysicalKey::U => Key::U,
50            PhysicalKey::V => Key::V,
51            PhysicalKey::W => Key::W,
52            PhysicalKey::X => Key::X,
53            PhysicalKey::Y => Key::Y,
54            PhysicalKey::Z => Key::Z,
55            PhysicalKey::Minus => Key::OemMinus,
56            PhysicalKey::Period => Key::OemPeriod,
57            PhysicalKey::Quote => Key::OemQuotes,
58            PhysicalKey::Semicolon => Key::OemSemicolon,
59            PhysicalKey::Slash => Key::OemQuestion,
60            // Functional Keys
61            PhysicalKey::AltLeft => Key::LeftAlt,
62            PhysicalKey::AltRight => Key::RightAlt,
63            PhysicalKey::Backspace => Key::Back,
64            PhysicalKey::CapsLock => Key::CapsLock,
65            PhysicalKey::ContextMenu => Key::Apps,
66            PhysicalKey::ControlLeft => Key::LeftCtrl,
67            PhysicalKey::ControlRight => Key::RightCtrl,
68            PhysicalKey::Enter => Key::Return,
69            PhysicalKey::MetaLeft => Key::LWin,
70            PhysicalKey::MetaRight => Key::RWin,
71            PhysicalKey::ShiftLeft => Key::LeftShift,
72            PhysicalKey::ShiftRight => Key::RightShift,
73            PhysicalKey::Space => Key::Space,
74            PhysicalKey::Tab => Key::Tab,
75            PhysicalKey::Convert => Key::ImeConvert,
76            PhysicalKey::KanaMode => Key::HangulMode,
77            PhysicalKey::Lang1 => Key::HangulMode,
78            PhysicalKey::Lang2 => Key::KanjiMode,
79            PhysicalKey::Lang3 => Key::OemFinish,
80            PhysicalKey::Lang4 => Key::DbeHiragana,
81            PhysicalKey::Lang5 => Key::DbeSbcsChar,
82            PhysicalKey::NonConvert => Key::ImeNonConvert,
83            // Control Pad Section
84            PhysicalKey::Delete => Key::Delete,
85            PhysicalKey::End => Key::End,
86            PhysicalKey::Help => Key::Help,
87            PhysicalKey::Home => Key::Home,
88            PhysicalKey::Insert => Key::Insert,
89            PhysicalKey::PageDown => Key::PageDown,
90            PhysicalKey::PageUp => Key::PageUp,
91            // Arrow Pad Section
92            PhysicalKey::ArrowDown => Key::Down,
93            PhysicalKey::ArrowLeft => Key::Left,
94            PhysicalKey::ArrowRight => Key::Right,
95            PhysicalKey::ArrowUp => Key::Up,
96            // Numpad Section
97            PhysicalKey::NumLock => Key::NumLock,
98            PhysicalKey::NumPad0 => Key::NumPad0,
99            PhysicalKey::NumPad1 => Key::NumPad1,
100            PhysicalKey::NumPad2 => Key::NumPad2,
101            PhysicalKey::NumPad3 => Key::NumPad3,
102            PhysicalKey::NumPad4 => Key::NumPad4,
103            PhysicalKey::NumPad5 => Key::NumPad5,
104            PhysicalKey::NumPad6 => Key::NumPad6,
105            PhysicalKey::NumPad7 => Key::NumPad7,
106            PhysicalKey::NumPad8 => Key::NumPad8,
107            PhysicalKey::NumPad9 => Key::NumPad9,
108            PhysicalKey::NumPadAdd => Key::Add,
109            PhysicalKey::NumPadClear => Key::Clear,
110            PhysicalKey::NumPadComma => Key::AbntC2,
111            PhysicalKey::NumPadDecimal => Key::Decimal,
112            PhysicalKey::NumPadDivide => Key::Divide,
113            PhysicalKey::NumPadEnter => Key::Return,
114            PhysicalKey::NumPadEqual => Key::OemPlus,
115            PhysicalKey::NumPadMultiply => Key::Multiply,
116            PhysicalKey::NumPadParenLeft => Key::OemOpenBrackets,
117            PhysicalKey::NumPadParenRight => Key::OemCloseBrackets,
118            PhysicalKey::NumPadSubtract => Key::Subtract,
119            // Function Section
120            PhysicalKey::Escape => Key::Escape,
121            PhysicalKey::F1 => Key::F1,
122            PhysicalKey::F2 => Key::F2,
123            PhysicalKey::F3 => Key::F3,
124            PhysicalKey::F4 => Key::F4,
125            PhysicalKey::F5 => Key::F5,
126            PhysicalKey::F6 => Key::F6,
127            PhysicalKey::F7 => Key::F7,
128            PhysicalKey::F8 => Key::F8,
129            PhysicalKey::F9 => Key::F9,
130            PhysicalKey::F10 => Key::F10,
131            PhysicalKey::F11 => Key::F11,
132            PhysicalKey::F12 => Key::F12,
133            PhysicalKey::F13 => Key::F13,
134            PhysicalKey::F14 => Key::F14,
135            PhysicalKey::F15 => Key::F15,
136            PhysicalKey::F16 => Key::F16,
137            PhysicalKey::F17 => Key::F17,
138            PhysicalKey::F18 => Key::F18,
139            PhysicalKey::F19 => Key::F19,
140            PhysicalKey::F20 => Key::F20,
141            PhysicalKey::F21 => Key::F21,
142            PhysicalKey::F22 => Key::F22,
143            PhysicalKey::F23 => Key::F23,
144            PhysicalKey::F24 => Key::F24,
145            PhysicalKey::PrintScreen => Key::Snapshot,
146            PhysicalKey::ScrollLock => Key::Scroll,
147            PhysicalKey::Pause => Key::Pause,
148            // Media Keys
149            PhysicalKey::BrowserBack => Key::BrowserBack,
150            PhysicalKey::BrowserFavorites => Key::BrowserFavorites,
151            PhysicalKey::BrowserForward => Key::BrowserForward,
152            PhysicalKey::BrowserHome => Key::BrowserHome,
153            PhysicalKey::BrowserRefresh => Key::BrowserRefresh,
154            PhysicalKey::BrowserSearch => Key::BrowserSearch,
155            PhysicalKey::BrowserStop => Key::BrowserStop,
156            PhysicalKey::Eject => Key::None,
157            PhysicalKey::LaunchApp1 => Key::LaunchApplication1,
158            PhysicalKey::LaunchApp2 => Key::LaunchApplication2,
159            PhysicalKey::LaunchMail => Key::LaunchMail,
160            PhysicalKey::MediaPlayPause => Key::MediaPlayPause,
161            PhysicalKey::MediaSelect => Key::SelectMedia,
162            PhysicalKey::MediaStop => Key::MediaStop,
163            PhysicalKey::MediaTrackNext => Key::MediaNextTrack,
164            PhysicalKey::MediaTrackPrevious => Key::MediaPreviousTrack,
165            PhysicalKey::Power => Key::None,
166            PhysicalKey::Sleep => Key::Sleep,
167            PhysicalKey::AudioVolumeDown => Key::VolumeDown,
168            PhysicalKey::AudioVolumeMute => Key::VolumeMute,
169            PhysicalKey::AudioVolumeUp => Key::VolumeUp,
170            PhysicalKey::WakeUp => Key::None,
171            // Legacy Keys
172            PhysicalKey::Again => Key::None,
173            PhysicalKey::Copy => Key::DbeHiragana,
174            PhysicalKey::Cut => Key::None,
175            PhysicalKey::Find => Key::None,
176            PhysicalKey::Open => Key::None,
177            PhysicalKey::Paste => Key::None,
178            PhysicalKey::Props => Key::None,
179            PhysicalKey::Select => Key::Select,
180            PhysicalKey::Undo => Key::None,
181            #[allow(unreachable_patterns)]
182            _ => Key::None,
183        }
184    }
185
186    /// Maps a physical key to a corresponding key symbol, if possible, on a
187    /// QWERTY keyboard. `use_shift_modifier` indicates whether the Shift key
188    /// is considered pressed.
189    pub fn to_qwerty_key_symbol(self, use_shift_modifier: bool) -> Option<&'static str> {
190        match self {
191            PhysicalKey::None => None,
192            // Writing System Keys
193            PhysicalKey::Backquote => Some(if use_shift_modifier { "~" } else { "`" }),
194            PhysicalKey::Backslash => Some(if use_shift_modifier { "|" } else { "\\" }),
195            PhysicalKey::BracketLeft => Some(if use_shift_modifier { "{" } else { "[" }),
196            PhysicalKey::BracketRight => Some(if use_shift_modifier { "}" } else { "]" }),
197            PhysicalKey::Comma => Some(if use_shift_modifier { "<" } else { "," }),
198            PhysicalKey::Digit0 => Some(if use_shift_modifier { ")" } else { "0" }),
199            PhysicalKey::Digit1 => Some(if use_shift_modifier { "!" } else { "1" }),
200            PhysicalKey::Digit2 => Some(if use_shift_modifier { "@" } else { "2" }),
201            PhysicalKey::Digit3 => Some(if use_shift_modifier { "#" } else { "3" }),
202            PhysicalKey::Digit4 => Some(if use_shift_modifier { "$" } else { "4" }),
203            PhysicalKey::Digit5 => Some(if use_shift_modifier { "%" } else { "5" }),
204            PhysicalKey::Digit6 => Some(if use_shift_modifier { "^" } else { "6" }),
205            PhysicalKey::Digit7 => Some(if use_shift_modifier { "&" } else { "7" }),
206            PhysicalKey::Digit8 => Some(if use_shift_modifier { "*" } else { "8" }),
207            PhysicalKey::Digit9 => Some(if use_shift_modifier { "(" } else { "9" }),
208            PhysicalKey::Equal => Some(if use_shift_modifier { "+" } else { "=" }),
209            PhysicalKey::IntlBackslash => Some(if use_shift_modifier { "|" } else { "\\" }),
210            PhysicalKey::IntlRo => None,
211            PhysicalKey::IntlYen => None,
212            PhysicalKey::A => Some(if use_shift_modifier { "A" } else { "a" }),
213            PhysicalKey::B => Some(if use_shift_modifier { "B" } else { "b" }),
214            PhysicalKey::C => Some(if use_shift_modifier { "C" } else { "c" }),
215            PhysicalKey::D => Some(if use_shift_modifier { "D" } else { "d" }),
216            PhysicalKey::E => Some(if use_shift_modifier { "E" } else { "e" }),
217            PhysicalKey::F => Some(if use_shift_modifier { "F" } else { "f" }),
218            PhysicalKey::G => Some(if use_shift_modifier { "G" } else { "g" }),
219            PhysicalKey::H => Some(if use_shift_modifier { "H" } else { "h" }),
220            PhysicalKey::I => Some(if use_shift_modifier { "I" } else { "i" }),
221            PhysicalKey::J => Some(if use_shift_modifier { "J" } else { "j" }),
222            PhysicalKey::K => Some(if use_shift_modifier { "K" } else { "k" }),
223            PhysicalKey::L => Some(if use_shift_modifier { "L" } else { "l" }),
224            PhysicalKey::M => Some(if use_shift_modifier { "M" } else { "m" }),
225            PhysicalKey::N => Some(if use_shift_modifier { "N" } else { "n" }),
226            PhysicalKey::O => Some(if use_shift_modifier { "O" } else { "o" }),
227            PhysicalKey::P => Some(if use_shift_modifier { "P" } else { "p" }),
228            PhysicalKey::Q => Some(if use_shift_modifier { "Q" } else { "q" }),
229            PhysicalKey::R => Some(if use_shift_modifier { "R" } else { "r" }),
230            PhysicalKey::S => Some(if use_shift_modifier { "S" } else { "s" }),
231            PhysicalKey::T => Some(if use_shift_modifier { "T" } else { "t" }),
232            PhysicalKey::U => Some(if use_shift_modifier { "U" } else { "u" }),
233            PhysicalKey::V => Some(if use_shift_modifier { "V" } else { "v" }),
234            PhysicalKey::W => Some(if use_shift_modifier { "W" } else { "w" }),
235            PhysicalKey::X => Some(if use_shift_modifier { "X" } else { "x" }),
236            PhysicalKey::Y => Some(if use_shift_modifier { "Y" } else { "y" }),
237            PhysicalKey::Z => Some(if use_shift_modifier { "Z" } else { "z" }),
238            PhysicalKey::Minus => Some(if use_shift_modifier { "_" } else { "-" }),
239            PhysicalKey::Period => Some(if use_shift_modifier { ">" } else { "." }),
240            PhysicalKey::Quote => Some(if use_shift_modifier { "\"" } else { "'" }),
241            PhysicalKey::Semicolon => Some(if use_shift_modifier { ":" } else { ";" }),
242            PhysicalKey::Slash => Some(if use_shift_modifier { "?" } else { "/" }),
243            // Functional Keys
244            PhysicalKey::AltLeft => None,
245            PhysicalKey::AltRight => None,
246            PhysicalKey::Backspace => Some("\u{8}"),
247            PhysicalKey::CapsLock => None,
248            PhysicalKey::ContextMenu => None,
249            PhysicalKey::ControlLeft => None,
250            PhysicalKey::ControlRight => None,
251            PhysicalKey::Enter => Some("\r"),
252            PhysicalKey::MetaLeft => None,
253            PhysicalKey::MetaRight => None,
254            PhysicalKey::ShiftLeft => None,
255            PhysicalKey::ShiftRight => None,
256            PhysicalKey::Space => Some(" "),
257            PhysicalKey::Tab => Some("\t"),
258            PhysicalKey::Convert => None,
259            PhysicalKey::KanaMode => None,
260            PhysicalKey::Lang1 => None,
261            PhysicalKey::Lang2 => None,
262            PhysicalKey::Lang3 => None,
263            PhysicalKey::Lang4 => None,
264            PhysicalKey::Lang5 => None,
265            PhysicalKey::NonConvert => None,
266            // Control Pad Section
267            PhysicalKey::Delete => None,
268            PhysicalKey::End => None,
269            PhysicalKey::Help => None,
270            PhysicalKey::Home => None,
271            PhysicalKey::Insert => None,
272            PhysicalKey::PageDown => None,
273            PhysicalKey::PageUp => None,
274            // Arrow Pad Section
275            PhysicalKey::ArrowDown => None,
276            PhysicalKey::ArrowLeft => None,
277            PhysicalKey::ArrowRight => None,
278            PhysicalKey::ArrowUp => None,
279            // Numpad Section
280            PhysicalKey::NumLock => None,
281            PhysicalKey::NumPad0 => Some("0"),
282            PhysicalKey::NumPad1 => Some("1"),
283            PhysicalKey::NumPad2 => Some("2"),
284            PhysicalKey::NumPad3 => Some("3"),
285            PhysicalKey::NumPad4 => Some("4"),
286            PhysicalKey::NumPad5 => Some("5"),
287            PhysicalKey::NumPad6 => Some("6"),
288            PhysicalKey::NumPad7 => Some("7"),
289            PhysicalKey::NumPad8 => Some("8"),
290            PhysicalKey::NumPad9 => Some("9"),
291            PhysicalKey::NumPadAdd => Some("+"),
292            PhysicalKey::NumPadClear => None,
293            PhysicalKey::NumPadComma => Some(","),
294            PhysicalKey::NumPadDecimal => Some("."),
295            PhysicalKey::NumPadDivide => Some("/"),
296            PhysicalKey::NumPadEnter => Some("\r"),
297            PhysicalKey::NumPadEqual => Some("="),
298            PhysicalKey::NumPadMultiply => Some("*"),
299            PhysicalKey::NumPadParenLeft => Some("("),
300            PhysicalKey::NumPadParenRight => Some(")"),
301            PhysicalKey::NumPadSubtract => Some("-"),
302            // Function Section
303            PhysicalKey::Escape => Some("\u{1B}"),
304            PhysicalKey::F1 => None,
305            PhysicalKey::F2 => None,
306            PhysicalKey::F3 => None,
307            PhysicalKey::F4 => None,
308            PhysicalKey::F5 => None,
309            PhysicalKey::F6 => None,
310            PhysicalKey::F7 => None,
311            PhysicalKey::F8 => None,
312            PhysicalKey::F9 => None,
313            PhysicalKey::F10 => None,
314            PhysicalKey::F11 => None,
315            PhysicalKey::F12 => None,
316            PhysicalKey::F13 => None,
317            PhysicalKey::F14 => None,
318            PhysicalKey::F15 => None,
319            PhysicalKey::F16 => None,
320            PhysicalKey::F17 => None,
321            PhysicalKey::F18 => None,
322            PhysicalKey::F19 => None,
323            PhysicalKey::F20 => None,
324            PhysicalKey::F21 => None,
325            PhysicalKey::F22 => None,
326            PhysicalKey::F23 => None,
327            PhysicalKey::F24 => None,
328            PhysicalKey::PrintScreen => None,
329            PhysicalKey::ScrollLock => None,
330            PhysicalKey::Pause => None,
331            // Media Keys
332            PhysicalKey::BrowserBack => None,
333            PhysicalKey::BrowserFavorites => None,
334            PhysicalKey::BrowserForward => None,
335            PhysicalKey::BrowserHome => None,
336            PhysicalKey::BrowserRefresh => None,
337            PhysicalKey::BrowserSearch => None,
338            PhysicalKey::BrowserStop => None,
339            PhysicalKey::Eject => None,
340            PhysicalKey::LaunchApp1 => None,
341            PhysicalKey::LaunchApp2 => None,
342            PhysicalKey::LaunchMail => None,
343            PhysicalKey::MediaPlayPause => None,
344            PhysicalKey::MediaSelect => None,
345            PhysicalKey::MediaStop => None,
346            PhysicalKey::MediaTrackNext => None,
347            PhysicalKey::MediaTrackPrevious => None,
348            PhysicalKey::Power => None,
349            PhysicalKey::Sleep => None,
350            PhysicalKey::AudioVolumeDown => None,
351            PhysicalKey::AudioVolumeMute => None,
352            PhysicalKey::AudioVolumeUp => None,
353            PhysicalKey::WakeUp => None,
354            // Legacy Keys
355            PhysicalKey::Again => None,
356            PhysicalKey::Copy => None,
357            PhysicalKey::Cut => None,
358            PhysicalKey::Find => None,
359            PhysicalKey::Open => None,
360            PhysicalKey::Paste => None,
361            PhysicalKey::Props => None,
362            PhysicalKey::Select => None,
363            PhysicalKey::Undo => None,
364            #[allow(unreachable_patterns)]
365            _ => None,
366        }
367    }
368}
369
370#[cfg(test)]
371mod tests {
372    use super::*;
373
374    #[test]
375    fn maps_to_qwerty() {
376        assert_eq!(PhysicalKey::A.to_qwerty_key(), Key::A);
377        assert_eq!(PhysicalKey::Digit1.to_qwerty_key(), Key::D1);
378        assert_eq!(PhysicalKey::None.to_qwerty_key(), Key::None);
379        assert_eq!(PhysicalKey::A.to_qwerty_key_symbol(false), Some("a"));
380        assert_eq!(PhysicalKey::A.to_qwerty_key_symbol(true), Some("A"));
381        assert_eq!(PhysicalKey::Digit1.to_qwerty_key_symbol(true), Some("!"));
382        assert_eq!(PhysicalKey::None.to_qwerty_key_symbol(false), None);
383    }
384}