1use ferroui_base::input::{IKeyboardDevice, Key, KeyboardDevice};
9use ferroui_base::{FerroLocator, LocatorExtensions};
10use std::rc::Rc;
11
12pub(crate) mod keycode {
14 pub const BACK: i32 = 4;
15 pub const NUM_0: i32 = 7;
16 pub const NUM_1: i32 = 8;
17 pub const NUM_2: i32 = 9;
18 pub const NUM_3: i32 = 10;
19 pub const NUM_4: i32 = 11;
20 pub const NUM_5: i32 = 12;
21 pub const NUM_6: i32 = 13;
22 pub const NUM_7: i32 = 14;
23 pub const NUM_8: i32 = 15;
24 pub const NUM_9: i32 = 16;
25 pub const DPAD_UP: i32 = 19;
26 pub const DPAD_DOWN: i32 = 20;
27 pub const DPAD_LEFT: i32 = 21;
28 pub const DPAD_RIGHT: i32 = 22;
29 pub const DPAD_CENTER: i32 = 23;
30 pub const VOLUME_UP: i32 = 24;
31 pub const VOLUME_DOWN: i32 = 25;
32 pub const CLEAR: i32 = 28;
33 pub const A: i32 = 29;
34 pub const B: i32 = 30;
35 pub const C: i32 = 31;
36 pub const D: i32 = 32;
37 pub const E: i32 = 33;
38 pub const F: i32 = 34;
39 pub const G: i32 = 35;
40 pub const H: i32 = 36;
41 pub const I: i32 = 37;
42 pub const J: i32 = 38;
43 pub const K: i32 = 39;
44 pub const L: i32 = 40;
45 pub const M: i32 = 41;
46 pub const N: i32 = 42;
47 pub const O: i32 = 43;
48 pub const P: i32 = 44;
49 pub const Q: i32 = 45;
50 pub const R: i32 = 46;
51 pub const S: i32 = 47;
52 pub const T: i32 = 48;
53 pub const U: i32 = 49;
54 pub const V: i32 = 50;
55 pub const W: i32 = 51;
56 pub const X: i32 = 52;
57 pub const Y: i32 = 53;
58 pub const Z: i32 = 54;
59 pub const COMMA: i32 = 55;
60 pub const PERIOD: i32 = 56;
61 pub const ALT_LEFT: i32 = 57;
62 pub const ALT_RIGHT: i32 = 58;
63 pub const SHIFT_LEFT: i32 = 59;
64 pub const SHIFT_RIGHT: i32 = 60;
65 pub const TAB: i32 = 61;
66 pub const SPACE: i32 = 62;
67 pub const ENTER: i32 = 66;
68 pub const DEL: i32 = 67;
69 pub const GRAVE: i32 = 68;
70 pub const MINUS: i32 = 69;
71 pub const LEFT_BRACKET: i32 = 71;
72 pub const RIGHT_BRACKET: i32 = 72;
73 pub const BACKSLASH: i32 = 73;
74 pub const SEMICOLON: i32 = 74;
75 pub const APOSTROPHE: i32 = 75;
76 pub const SLASH: i32 = 76;
77 pub const PLUS: i32 = 81;
78 pub const MEDIA_PLAY_PAUSE: i32 = 85;
79 pub const MEDIA_STOP: i32 = 86;
80 pub const MEDIA_NEXT: i32 = 87;
81 pub const MEDIA_PREVIOUS: i32 = 88;
82 pub const PAGE_UP: i32 = 92;
83 pub const PAGE_DOWN: i32 = 93;
84 pub const ESCAPE: i32 = 111;
85 pub const FORWARD_DEL: i32 = 112;
86 pub const CTRL_LEFT: i32 = 113;
87 pub const CTRL_RIGHT: i32 = 114;
88 pub const CAPS_LOCK: i32 = 115;
89 pub const SCROLL_LOCK: i32 = 116;
90 pub const MOVE_HOME: i32 = 122;
91 pub const MOVE_END: i32 = 123;
92 pub const INSERT: i32 = 124;
93 pub const MEDIA_PLAY: i32 = 126;
94 pub const MEDIA_PAUSE: i32 = 127;
95 pub const F1: i32 = 131;
96 pub const F2: i32 = 132;
97 pub const F3: i32 = 133;
98 pub const F4: i32 = 134;
99 pub const F5: i32 = 135;
100 pub const F6: i32 = 136;
101 pub const F7: i32 = 137;
102 pub const F8: i32 = 138;
103 pub const F9: i32 = 139;
104 pub const F10: i32 = 140;
105 pub const F11: i32 = 141;
106 pub const F12: i32 = 142;
107 pub const NUM_LOCK: i32 = 143;
108 pub const NUMPAD_0: i32 = 144;
109 pub const NUMPAD_1: i32 = 145;
110 pub const NUMPAD_2: i32 = 146;
111 pub const NUMPAD_3: i32 = 147;
112 pub const NUMPAD_4: i32 = 148;
113 pub const NUMPAD_5: i32 = 149;
114 pub const NUMPAD_6: i32 = 150;
115 pub const NUMPAD_7: i32 = 151;
116 pub const NUMPAD_8: i32 = 152;
117 pub const NUMPAD_9: i32 = 153;
118 pub const NUMPAD_DIVIDE: i32 = 154;
119 pub const NUMPAD_MULTIPLY: i32 = 155;
120 pub const NUMPAD_SUBTRACT: i32 = 156;
121 pub const NUMPAD_ADD: i32 = 157;
122 pub const NUMPAD_DOT: i32 = 158;
123 pub const NUMPAD_COMMA: i32 = 159;
124 pub const SLEEP: i32 = 223;
125 pub const HELP: i32 = 259;
126}
127
128pub struct AndroidKeyboardDevice;
130
131impl AndroidKeyboardDevice {
132 pub fn instance() -> Option<Rc<dyn IKeyboardDevice>> {
134 FerroLocator::current().get_service::<dyn IKeyboardDevice>()
135 }
136
137 #[allow(clippy::new_ret_no_self)]
139 pub fn new() -> Rc<dyn IKeyboardDevice> {
140 KeyboardDevice::new()
141 }
142
143 pub fn convert_key(key: i32) -> Key {
146 match key {
147 keycode::DEL => Key::Back,
149 keycode::TAB => Key::Tab,
150 keycode::CLEAR => Key::Clear,
152 keycode::ENTER => Key::Return,
153 keycode::MEDIA_PAUSE => Key::Pause,
154 keycode::CAPS_LOCK => Key::CapsLock,
155 keycode::ESCAPE => Key::Escape,
160 keycode::SPACE => Key::Space,
165 keycode::PAGE_UP => Key::Prior,
166 keycode::PAGE_DOWN => Key::PageDown,
167 keycode::MOVE_END => Key::End,
168 keycode::MOVE_HOME => Key::Home,
169 keycode::INSERT => Key::Insert,
174 keycode::FORWARD_DEL => Key::Delete,
175 keycode::HELP => Key::Help,
176 keycode::NUM_0 => Key::D0,
177 keycode::NUM_1 => Key::D1,
178 keycode::NUM_2 => Key::D2,
179 keycode::NUM_3 => Key::D3,
180 keycode::NUM_4 => Key::D4,
181 keycode::NUM_5 => Key::D5,
182 keycode::NUM_6 => Key::D6,
183 keycode::NUM_7 => Key::D7,
184 keycode::NUM_8 => Key::D8,
185 keycode::NUM_9 => Key::D9,
186 keycode::A => Key::A,
187 keycode::B => Key::B,
188 keycode::C => Key::C,
189 keycode::D => Key::D,
190 keycode::E => Key::E,
191 keycode::F => Key::F,
192 keycode::G => Key::G,
193 keycode::H => Key::H,
194 keycode::I => Key::I,
195 keycode::J => Key::J,
196 keycode::K => Key::K,
197 keycode::L => Key::L,
198 keycode::M => Key::M,
199 keycode::N => Key::N,
200 keycode::O => Key::O,
201 keycode::P => Key::P,
202 keycode::Q => Key::Q,
203 keycode::R => Key::R,
204 keycode::S => Key::S,
205 keycode::T => Key::T,
206 keycode::U => Key::U,
207 keycode::V => Key::V,
208 keycode::W => Key::W,
209 keycode::X => Key::X,
210 keycode::Y => Key::Y,
211 keycode::Z => Key::Z,
212 keycode::SLEEP => Key::Sleep,
242 keycode::NUMPAD_0 => Key::NumPad0,
243 keycode::NUMPAD_1 => Key::NumPad1,
244 keycode::NUMPAD_2 => Key::NumPad2,
245 keycode::NUMPAD_3 => Key::NumPad3,
246 keycode::NUMPAD_4 => Key::NumPad4,
247 keycode::NUMPAD_5 => Key::NumPad5,
248 keycode::NUMPAD_6 => Key::NumPad6,
249 keycode::NUMPAD_7 => Key::NumPad7,
250 keycode::NUMPAD_8 => Key::NumPad8,
251 keycode::NUMPAD_9 => Key::NumPad9,
252 keycode::NUMPAD_MULTIPLY => Key::Multiply,
253 keycode::NUMPAD_ADD => Key::Add,
254 keycode::NUMPAD_COMMA => Key::Separator,
255 keycode::NUMPAD_SUBTRACT => Key::Subtract,
256 keycode::NUMPAD_DOT => Key::Decimal,
257 keycode::NUMPAD_DIVIDE => Key::Divide,
258 keycode::F1 => Key::F1,
259 keycode::F2 => Key::F2,
260 keycode::F3 => Key::F3,
261 keycode::F4 => Key::F4,
262 keycode::F5 => Key::F5,
263 keycode::F6 => Key::F6,
264 keycode::F7 => Key::F7,
265 keycode::F8 => Key::F8,
266 keycode::F9 => Key::F9,
267 keycode::F10 => Key::F10,
268 keycode::F11 => Key::F11,
269 keycode::F12 => Key::F12,
270 keycode::NUM_LOCK => Key::NumLock,
283 keycode::SCROLL_LOCK => Key::Scroll,
284 keycode::SHIFT_LEFT => Key::LeftShift,
285 keycode::SHIFT_RIGHT => Key::RightShift,
286 keycode::CTRL_LEFT => Key::LeftCtrl,
287 keycode::CTRL_RIGHT => Key::RightCtrl,
288 keycode::ALT_LEFT => Key::LeftAlt,
289 keycode::ALT_RIGHT => Key::RightAlt,
290 keycode::VOLUME_DOWN => Key::VolumeDown,
299 keycode::VOLUME_UP => Key::VolumeUp,
300 keycode::MEDIA_NEXT => Key::MediaNextTrack,
301 keycode::MEDIA_PREVIOUS => Key::MediaPreviousTrack,
302 keycode::MEDIA_STOP => Key::MediaStop,
303 keycode::MEDIA_PLAY_PAUSE => Key::MediaPlayPause,
304 keycode::SEMICOLON => Key::OemSemicolon,
309 keycode::PLUS => Key::OemPlus,
310 keycode::COMMA => Key::OemComma,
311 keycode::MINUS => Key::OemMinus,
312 keycode::PERIOD => Key::OemPeriod,
313 keycode::GRAVE => Key::OemTilde,
315 keycode::APOSTROPHE => Key::OemQuotes,
319 keycode::SLASH => Key::OemQuestion,
320 keycode::LEFT_BRACKET => Key::OemOpenBrackets,
321 keycode::RIGHT_BRACKET => Key::OemCloseBrackets,
322 keycode::MEDIA_PLAY => Key::Play,
338 keycode::BACKSLASH => Key::OemBackslash,
344
345 keycode::BACK => Key::Escape,
347 keycode::DPAD_CENTER => Key::Space,
348 keycode::DPAD_LEFT => Key::Left,
349 keycode::DPAD_UP => Key::Up,
350 keycode::DPAD_RIGHT => Key::Right,
351 keycode::DPAD_DOWN => Key::Down,
352 _ => Key::None,
353 }
354 }
355}
356
357#[cfg(test)]
358mod tests {
359 use super::*;
360
361 #[test]
362 fn letters_are_the_letter_keys() {
363 let letters = [
364 Key::A, Key::B, Key::C, Key::D, Key::E, Key::F, Key::G, Key::H, Key::I, Key::J, Key::K, Key::L, Key::M,
365 Key::N, Key::O, Key::P, Key::Q, Key::R, Key::S, Key::T, Key::U, Key::V, Key::W, Key::X, Key::Y, Key::Z,
366 ];
367 for (index, letter) in letters.iter().enumerate() {
369 assert_eq!(AndroidKeyboardDevice::convert_key(29 + index as i32), *letter);
370 }
371 }
372
373 #[test]
374 fn digits_are_the_digit_keys() {
375 let digits = [Key::D0, Key::D1, Key::D2, Key::D3, Key::D4, Key::D5, Key::D6, Key::D7, Key::D8, Key::D9];
376 for (index, digit) in digits.iter().enumerate() {
378 assert_eq!(AndroidKeyboardDevice::convert_key(7 + index as i32), *digit);
379 }
380 assert_eq!(AndroidKeyboardDevice::convert_key(144), Key::NumPad0);
381 assert_eq!(AndroidKeyboardDevice::convert_key(153), Key::NumPad9);
382 }
383
384 #[test]
385 fn named_keys() {
386 assert_eq!(AndroidKeyboardDevice::convert_key(66), Key::Return);
387 assert_eq!(AndroidKeyboardDevice::convert_key(66), Key::Enter);
388 assert_eq!(AndroidKeyboardDevice::convert_key(67), Key::Back);
389 assert_eq!(AndroidKeyboardDevice::convert_key(112), Key::Delete);
390 assert_eq!(AndroidKeyboardDevice::convert_key(111), Key::Escape);
391 assert_eq!(AndroidKeyboardDevice::convert_key(61), Key::Tab);
392 assert_eq!(AndroidKeyboardDevice::convert_key(62), Key::Space);
393 assert_eq!(AndroidKeyboardDevice::convert_key(92), Key::PageUp);
394 assert_eq!(AndroidKeyboardDevice::convert_key(93), Key::PageDown);
395 assert_eq!(AndroidKeyboardDevice::convert_key(122), Key::Home);
396 assert_eq!(AndroidKeyboardDevice::convert_key(123), Key::End);
397 assert_eq!(AndroidKeyboardDevice::convert_key(131), Key::F1);
398 assert_eq!(AndroidKeyboardDevice::convert_key(142), Key::F12);
399 assert_eq!(AndroidKeyboardDevice::convert_key(59), Key::LeftShift);
400 assert_eq!(AndroidKeyboardDevice::convert_key(114), Key::RightCtrl);
401 }
402
403 #[test]
404 fn the_back_key_and_the_directional_pad() {
405 assert_eq!(AndroidKeyboardDevice::convert_key(4), Key::Escape);
406 assert_eq!(AndroidKeyboardDevice::convert_key(23), Key::Space);
407 assert_eq!(AndroidKeyboardDevice::convert_key(21), Key::Left);
408 assert_eq!(AndroidKeyboardDevice::convert_key(19), Key::Up);
409 assert_eq!(AndroidKeyboardDevice::convert_key(22), Key::Right);
410 assert_eq!(AndroidKeyboardDevice::convert_key(20), Key::Down);
411 }
412
413 #[test]
414 fn an_unknown_key_code_is_no_key() {
415 assert_eq!(AndroidKeyboardDevice::convert_key(0), Key::None);
417 assert_eq!(AndroidKeyboardDevice::convert_key(3), Key::None);
418 assert_eq!(AndroidKeyboardDevice::convert_key(-1), Key::None);
419 assert_eq!(AndroidKeyboardDevice::convert_key(100_000), Key::None);
420 }
421}