keymaps/
defs.rs

1// Copyright 2021 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! # Old-style keymaps definitions.
6//!
7//! The keymaps defined in this module are statically defined and compiled in.
8//! This is useful during the transition towards a more configurable keymap
9//! support.
10
11use crate::{LockStateChecker, ModifierChecker};
12use fidl_fuchsia_ui_input3::{LockState, Modifiers};
13use std::sync::LazyLock;
14
15/// Standard [qwerty] keymap.
16///
17/// The value of this array at index `u`, where `u` is the usage, can be:
18///
19///  * `None` if the key maps to no `char` (Esc key)
20///  * `Some((c, None))` if the key maps to `c`, but does not map to any `char` when shift is pressed
21///  * `Some((c, Some(cs)))` if the key maps to `c` when shift is not pressed and to `cs` when it is
22///    pressed
23///
24/// [qwerty]: https://en.wikipedia.org/wiki/Keyboard_layout#QWERTY-based_Latin-script_keyboard_layouts
25pub(crate) static QWERTY_MAP: LazyLock<Vec<Option<KeyLevels>>> = LazyLock::new(|| {
26    vec![
27        // 0x00
28        None,
29        None,
30        None,
31        None,
32        // HID_USAGE_KEY_A
33        Some(('a', Some('A'), true).into()),
34        Some(('b', Some('B'), true).into()),
35        Some(('c', Some('C'), true).into()),
36        Some(('d', Some('D'), true).into()),
37        // 0x08
38        Some(('e', Some('E'), true).into()),
39        Some(('f', Some('F'), true).into()),
40        Some(('g', Some('G'), true).into()),
41        Some(('h', Some('H'), true).into()),
42        // 0x0c
43        Some(('i', Some('I'), true).into()),
44        Some(('j', Some('J'), true).into()),
45        Some(('k', Some('K'), true).into()),
46        Some(('l', Some('L'), true).into()),
47        // 0x10
48        Some(('m', Some('M'), true).into()),
49        Some(('n', Some('N'), true).into()),
50        Some(('o', Some('O'), true).into()),
51        Some(('p', Some('P'), true).into()),
52        // 0x14
53        Some(('q', Some('Q'), true).into()),
54        Some(('r', Some('R'), true).into()),
55        Some(('s', Some('S'), true).into()),
56        Some(('t', Some('T'), true).into()),
57        // 0x18
58        Some(('u', Some('U'), true).into()),
59        Some(('v', Some('V'), true).into()),
60        Some(('w', Some('W'), true).into()),
61        Some(('x', Some('X'), true).into()),
62        // 0x1c
63        Some(('y', Some('Y'), true).into()),
64        Some(('z', Some('Z'), true).into()),
65        Some(('1', Some('!')).into()),
66        Some(('2', Some('@')).into()),
67        // 0x20
68        Some(('3', Some('#')).into()),
69        Some(('4', Some('$')).into()),
70        Some(('5', Some('%')).into()),
71        Some(('6', Some('^')).into()),
72        // 0x24
73        Some(('7', Some('&')).into()),
74        Some(('8', Some('*')).into()),
75        Some(('9', Some('(')).into()),
76        Some(('0', Some(')')).into()),
77        // 0x28
78        None,
79        None,
80        None,
81        None,
82        // 0x2c
83        Some((' ', Some(' ')).into()),
84        Some(('-', Some('_')).into()),
85        Some(('=', Some('+')).into()),
86        Some(('[', Some('{')).into()),
87        // 0x30
88        Some((']', Some('}')).into()),
89        Some(('\\', Some('|')).into()),
90        None,
91        Some((';', Some(':')).into()),
92        // 0x34
93        Some(('\'', Some('"')).into()),
94        Some(('`', Some('~')).into()),
95        Some((',', Some('<')).into()),
96        Some(('.', Some('>')).into()),
97        // 0x38
98        Some(('/', Some('?')).into()),
99        None,
100        None,
101        None,
102        // 0x3c
103        None,
104        None,
105        None,
106        None,
107        // 0x40
108        None,
109        None,
110        None,
111        None,
112        // 0x44
113        None,
114        None,
115        None,
116        None,
117        // 0x48
118        None,
119        None,
120        None,
121        None,
122        // 0x4c
123        None,
124        None,
125        None,
126        None,
127        // 0x50
128        None,
129        None,
130        None,
131        None,
132        // 0x54
133        Some(('/', None).into()),
134        Some(('*', None).into()),
135        Some(('-', None).into()),
136        Some(('+', None).into()),
137        // 0x58
138        None,
139        Some(('1', None).into()),
140        Some(('2', None).into()),
141        Some(('3', None).into()),
142        // 0x5c
143        Some(('4', None).into()),
144        Some(('5', None).into()),
145        Some(('6', None).into()),
146        Some(('7', None).into()),
147        // 0x60
148        Some(('8', None).into()),
149        Some(('9', None).into()),
150        Some(('0', None).into()),
151        Some(('.', None).into()),
152    ]
153});
154
155/// Standard [dvorak] keymap.
156///
157/// [dvorak]: https://en.wikipedia.org/wiki/Dvorak_keyboard_layout
158pub(crate) static DVORAK_MAP: LazyLock<Vec<Option<KeyLevels>>> = LazyLock::new(|| {
159    vec![
160        // 0x00
161        None,
162        None,
163        None,
164        None,
165        // HID_USAGE_KEY_A
166        Some(('a', Some('A'), true).into()),
167        Some(('x', Some('X'), true).into()),
168        Some(('j', Some('J'), true).into()),
169        Some(('e', Some('E'), true).into()),
170        // 0x08
171        Some(('.', Some('>')).into()),
172        Some(('u', Some('U'), true).into()),
173        Some(('i', Some('I'), true).into()),
174        Some(('d', Some('D'), true).into()),
175        // 0x0c
176        Some(('c', Some('C'), true).into()),
177        Some(('h', Some('H'), true).into()),
178        Some(('t', Some('T'), true).into()),
179        Some(('n', Some('N'), true).into()),
180        // 0x10
181        Some(('m', Some('M'), true).into()),
182        Some(('b', Some('B'), true).into()),
183        Some(('r', Some('R'), true).into()),
184        Some(('l', Some('L'), true).into()),
185        // 0x14
186        Some(('\'', Some('"')).into()),
187        Some(('p', Some('P'), true).into()),
188        Some(('o', Some('O'), true).into()),
189        Some(('y', Some('Y'), true).into()),
190        // 0x18
191        Some(('g', Some('G'), true).into()),
192        Some(('k', Some('K'), true).into()),
193        Some((',', Some('<')).into()),
194        Some(('q', Some('Q'), true).into()),
195        // 0x1c
196        Some(('f', Some('F'), true).into()),
197        Some((';', Some(':')).into()),
198        Some(('1', Some('!')).into()),
199        Some(('2', Some('@')).into()),
200        // 0x20
201        Some(('3', Some('#')).into()),
202        Some(('4', Some('$')).into()),
203        Some(('5', Some('%')).into()),
204        Some(('6', Some('^')).into()),
205        // 0x24
206        Some(('7', Some('&')).into()),
207        Some(('8', Some('*')).into()),
208        Some(('9', Some('(')).into()),
209        Some(('0', Some(')')).into()),
210        // 0x28
211        None,
212        None,
213        None,
214        None,
215        // 0x2c
216        Some((' ', Some(' ')).into()),
217        Some(('[', Some('{')).into()),
218        Some((']', Some('}')).into()),
219        Some(('/', Some('?')).into()),
220        // 0x30
221        Some(('=', Some('+')).into()),
222        Some(('\\', Some('|')).into()),
223        None,
224        Some(('s', Some('S'), true).into()),
225        // 0x34
226        Some(('-', Some('_')).into()),
227        Some(('`', Some('~')).into()),
228        Some(('w', Some('W'), true).into()),
229        Some(('v', Some('V'), true).into()),
230        // 0x38
231        Some(('z', Some('Z'), true).into()),
232        None,
233        None,
234        None,
235        // 0x3c
236        None,
237        None,
238        None,
239        None,
240        // 0x40
241        None,
242        None,
243        None,
244        None,
245        // 0x44
246        None,
247        None,
248        None,
249        None,
250        // 0x48
251        None,
252        None,
253        None,
254        None,
255        // 0x4c
256        None,
257        None,
258        None,
259        None,
260        // 0x50
261        None,
262        None,
263        None,
264        None,
265        // 0x54
266        Some(('/', None).into()),
267        Some(('*', None).into()),
268        Some(('-', None).into()),
269        Some(('+', None).into()),
270        // 0x58
271        None,
272        Some(('1', None).into()),
273        Some(('2', None).into()),
274        Some(('3', None).into()),
275        // 0x5c
276        Some(('4', None).into()),
277        Some(('5', None).into()),
278        Some(('6', None).into()),
279        Some(('7', None).into()),
280        // 0x60
281        Some(('8', None).into()),
282        Some(('9', None).into()),
283        Some(('0', None).into()),
284        Some(('.', None).into()),
285    ]
286});
287
288/// TODO(75723): This map is incomplete, and is here only temporarily for
289/// kicks.
290pub(crate) static FR_AZERTY_MAP: LazyLock<Vec<Option<KeyLevels>>> = LazyLock::new(|| {
291    vec![
292        // 0x00
293        None,
294        None,
295        None,
296        None,
297        // HID_USAGE_KEY_A
298        Some(('q', Some('Q'), true).into()),
299        Some(('b', Some('B'), true).into()),
300        Some(('c', Some('C'), true).into()),
301        Some(('d', Some('D'), true).into()),
302        // 0x08
303        Some(('e', Some('E'), true).into()),
304        Some(('f', Some('F'), true).into()),
305        Some(('g', Some('G'), true).into()),
306        Some(('h', Some('H'), true).into()),
307        // 0x0c
308        Some(('i', Some('I'), true).into()),
309        Some(('j', Some('J'), true).into()),
310        Some(('k', Some('K'), true).into()),
311        Some(('l', Some('L'), true).into()),
312        // 0x10
313        Some((',', Some('?')).into()),
314        Some(('n', Some('N'), true).into()),
315        Some(('o', Some('O'), true).into()),
316        Some(('p', Some('P'), true).into()),
317        // 0x14
318        Some(('a', Some('A'), true).into()),
319        Some(('r', Some('R'), true).into()),
320        Some(('s', Some('S'), true).into()),
321        Some(('t', Some('T'), true).into()),
322        // 0x18
323        Some(('u', Some('U'), true).into()),
324        Some(('v', Some('V'), true).into()),
325        Some(('z', Some('Z'), true).into()),
326        Some(('x', Some('X'), true).into()),
327        // 0x1c
328        Some(('y', Some('Y'), true).into()),
329        Some(('w', Some('W'), true).into()),
330        Some(('&', Some('1')).into()),
331        Some(('é', Some('2')).into()),
332        // 0x20
333        Some(('"', Some('3')).into()),
334        Some(('\'', Some('4')).into()),
335        Some(('(', Some('5')).into()),
336        Some(('-', Some('6')).into()),
337        // 0x24
338        Some(('è', Some('7')).into()),
339        Some(('—', Some('8')).into()),
340        Some(('ç', Some('9')).into()),
341        Some(('à', Some('0')).into()),
342        // 0x28
343        None,
344        None,
345        None,
346        None,
347        // 0x2c
348        Some((' ', Some(' ')).into()),
349        Some((')', Some('°')).into()),
350        Some(('=', Some('+')).into()),
351        Some(('\u{0302}', Some('\u{0308}')).into()), // Unicode combining characters circumflex and dieresis.
352        // 0x30
353        Some(('$', Some('£')).into()),
354        Some(('\\', Some('|')).into()), // Not present on French Azerty?
355        None,
356        Some(('m', Some('M'), true).into()),
357        // 0x34
358        Some(('\'', Some('"')).into()),
359        Some(('²', None).into()),
360        Some((';', Some('.')).into()),
361        Some((':', Some('/')).into()),
362        // 0x38
363        Some(('!', Some('§')).into()),
364        None,
365        None,
366        None,
367        // 0x3c
368        None,
369        None,
370        None,
371        None,
372        // 0x40
373        None,
374        None,
375        None,
376        None,
377        // 0x44
378        None,
379        None,
380        None,
381        None,
382        // 0x48
383        None,
384        None,
385        None,
386        None,
387        // 0x4c
388        None,
389        None,
390        None,
391        None,
392        // 0x50
393        None,
394        None,
395        None,
396        None,
397        // 0x54
398        Some(('/', None).into()),
399        Some(('*', None).into()),
400        Some(('-', None).into()),
401        Some(('+', None).into()),
402        // 0x58
403        None,
404        Some(('1', None).into()),
405        Some(('2', None).into()),
406        Some(('3', None).into()),
407        // 0x5c
408        Some(('4', None).into()),
409        Some(('5', None).into()),
410        Some(('6', None).into()),
411        Some(('7', None).into()),
412        // 0x60
413        Some(('8', None).into()),
414        Some(('9', None).into()),
415        Some(('0', None).into()),
416        Some(('.', None).into()),
417    ]
418});
419
420/// Standard [colemak] keymap.
421///
422/// [colemak]: https://en.wikipedia.org/wiki/Keyboard_layout#Colemak
423pub(crate) static COLEMAK_MAP: LazyLock<Vec<Option<KeyLevels>>> = LazyLock::new(|| {
424    vec![
425        // 0x00
426        None,
427        None,
428        None,
429        None,
430        // HID_USAGE_KEY_A
431        Some(('a', Some('A'), true).into()),
432        Some(('b', Some('B'), true).into()),
433        Some(('c', Some('C'), true).into()),
434        Some(('s', Some('S'), true).into()),
435        // 0x08
436        Some(('f', Some('F'), true).into()),
437        Some(('t', Some('T'), true).into()),
438        Some(('d', Some('D'), true).into()),
439        Some(('h', Some('H'), true).into()),
440        // 0x0c
441        Some(('u', Some('U'), true).into()),
442        Some(('n', Some('N'), true).into()),
443        Some(('e', Some('E'), true).into()),
444        Some(('i', Some('I'), true).into()),
445        // 0x10
446        Some(('m', Some('M'), true).into()),
447        Some(('k', Some('K'), true).into()),
448        Some(('y', Some('Y'), true).into()),
449        Some((';', Some(':')).into()),
450        // 0x14
451        Some(('q', Some('Q'), true).into()),
452        Some(('p', Some('P'), true).into()),
453        Some(('r', Some('R'), true).into()),
454        Some(('g', Some('G'), true).into()),
455        // 0x18
456        Some(('l', Some('L'), true).into()),
457        Some(('v', Some('V'), true).into()),
458        Some(('w', Some('W'), true).into()),
459        Some(('x', Some('X'), true).into()),
460        // 0x1c
461        Some(('j', Some('J'), true).into()),
462        Some(('z', Some('Z'), true).into()),
463        Some(('1', Some('!')).into()),
464        Some(('2', Some('@')).into()),
465        // 0x20
466        Some(('3', Some('#')).into()),
467        Some(('4', Some('$')).into()),
468        Some(('5', Some('%')).into()),
469        Some(('6', Some('^')).into()),
470        // 0x24
471        Some(('7', Some('&')).into()),
472        Some(('8', Some('*')).into()),
473        Some(('9', Some('(')).into()),
474        Some(('0', Some(')')).into()),
475        // 0x28
476        None,
477        None,
478        None,
479        None,
480        // 0x2c
481        Some((' ', Some(' ')).into()),
482        Some(('-', Some('_')).into()),
483        Some(('=', Some('+')).into()),
484        Some(('[', Some('{')).into()),
485        // 0x30
486        Some((']', Some('}')).into()),
487        Some(('\\', Some('|')).into()),
488        None,
489        Some(('o', Some('O'), true).into()),
490        // 0x34
491        Some(('\'', Some('"')).into()),
492        Some(('`', Some('~')).into()),
493        Some((',', Some('<')).into()),
494        Some(('.', Some('>')).into()),
495        // 0x38
496        Some(('/', Some('?')).into()),
497        None,
498        None,
499        None,
500        // 0x3c
501        None,
502        None,
503        None,
504        None,
505        // 0x40
506        None,
507        None,
508        None,
509        None,
510        // 0x44
511        None,
512        None,
513        None,
514        None,
515        // 0x48
516        None,
517        None,
518        None,
519        None,
520        // 0x4c
521        None,
522        None,
523        None,
524        None,
525        // 0x50
526        None,
527        None,
528        None,
529        None,
530        // 0x54
531        Some(('/', None).into()),
532        Some(('*', None).into()),
533        Some(('-', None).into()),
534        Some(('+', None).into()),
535        // 0x58
536        None,
537        Some(('1', None).into()),
538        Some(('2', None).into()),
539        Some(('3', None).into()),
540        // 0x5c
541        Some(('4', None).into()),
542        Some(('5', None).into()),
543        Some(('6', None).into()),
544        Some(('7', None).into()),
545        // 0x60
546        Some(('8', None).into()),
547        Some(('9', None).into()),
548        Some(('0', None).into()),
549        Some(('.', None).into()),
550    ]
551});
552
553/// Levels corresponding to each defined key.
554pub struct KeyLevels {
555    /// The base, unshifted character.
556    pub(crate) ch: char,
557    /// The shifted character, if present
558    pub(crate) shift_ch: Option<char>,
559    /// Is it a letter?  Letters are affected by Caps Lock, while other keys
560    /// are not.
561    is_letter: bool,
562}
563
564impl From<(char, Option<char>)> for KeyLevels {
565    fn from(s: (char, Option<char>)) -> Self {
566        KeyLevels { ch: s.0, shift_ch: s.1, is_letter: false }
567    }
568}
569
570impl From<(char, Option<char>, bool)> for KeyLevels {
571    fn from(s: (char, Option<char>, bool)) -> Self {
572        KeyLevels { ch: s.0, shift_ch: s.1, is_letter: s.2 }
573    }
574}
575
576impl KeyLevels {
577    pub fn get_key(&self, m: &impl ModifierChecker, l: &impl LockStateChecker) -> Option<char> {
578        if (l.test(LockState::CAPS_LOCK) && self.is_letter) || m.test(Modifiers::SHIFT) {
579            return self.shift_ch;
580        }
581        Some(self.ch)
582    }
583}