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 lazy_static::lazy_static;
14
15lazy_static! {
16    /// Standard [qwerty] keymap.
17    ///
18    /// The value of this array at index `u`, where `u` is the usage, can be:
19    ///
20    ///  * `None` if the key maps to no `char` (Esc key)
21    ///  * `Some((c, None))` if the key maps to `c`, but does not map to any `char` when shift is pressed
22    ///  * `Some((c, Some(cs)))` if the key maps to `c` when shift is not pressed and to `cs` when it is
23    ///    pressed
24    ///
25    /// [qwerty]: https://en.wikipedia.org/wiki/Keyboard_layout#QWERTY-based_Latin-script_keyboard_layouts
26    pub(crate) static ref QWERTY_MAP: Vec<Option<KeyLevels>> = 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    /// Standard [dvorak] keymap.
155    ///
156    /// [dvorak]: https://en.wikipedia.org/wiki/Dvorak_keyboard_layout
157    pub(crate) static ref DVORAK_MAP: Vec<Option<KeyLevels>> = vec![
158        // 0x00
159        None,
160        None,
161        None,
162        None,
163        // HID_USAGE_KEY_A
164        Some(('a', Some('A'), true).into()),
165        Some(('x', Some('X'), true).into()),
166        Some(('j', Some('J'), true).into()),
167        Some(('e', Some('E'), true).into()),
168        // 0x08
169        Some(('.', Some('>')).into()),
170        Some(('u', Some('U'), true).into()),
171        Some(('i', Some('I'), true).into()),
172        Some(('d', Some('D'), true).into()),
173        // 0x0c
174        Some(('c', Some('C'), true).into()),
175        Some(('h', Some('H'), true).into()),
176        Some(('t', Some('T'), true).into()),
177        Some(('n', Some('N'), true).into()),
178        // 0x10
179        Some(('m', Some('M'), true).into()),
180        Some(('b', Some('B'), true).into()),
181        Some(('r', Some('R'), true).into()),
182        Some(('l', Some('L'), true).into()),
183        // 0x14
184        Some(('\'', Some('"')).into()),
185        Some(('p', Some('P'), true).into()),
186        Some(('o', Some('O'), true).into()),
187        Some(('y', Some('Y'), true).into()),
188        // 0x18
189        Some(('g', Some('G'), true).into()),
190        Some(('k', Some('K'), true).into()),
191        Some((',', Some('<')).into()),
192        Some(('q', Some('Q'), true).into()),
193        // 0x1c
194        Some(('f', Some('F'), true).into()),
195        Some((';', Some(':')).into()),
196        Some(('1', Some('!')).into()),
197        Some(('2', Some('@')).into()),
198        // 0x20
199        Some(('3', Some('#')).into()),
200        Some(('4', Some('$')).into()),
201        Some(('5', Some('%')).into()),
202        Some(('6', Some('^')).into()),
203        // 0x24
204        Some(('7', Some('&')).into()),
205        Some(('8', Some('*')).into()),
206        Some(('9', Some('(')).into()),
207        Some(('0', Some(')')).into()),
208        // 0x28
209        None,
210        None,
211        None,
212        None,
213        // 0x2c
214        Some((' ', Some(' ')).into()),
215        Some(('[', Some('{')).into()),
216        Some((']', Some('}')).into()),
217        Some(('/', Some('?')).into()),
218        // 0x30
219        Some(('=', Some('+')).into()),
220        Some(('\\', Some('|')).into()),
221        None,
222        Some(('s', Some('S'), true).into()),
223        // 0x34
224        Some(('-', Some('_')).into()),
225        Some(('`', Some('~')).into()),
226        Some(('w', Some('W'), true).into()),
227        Some(('v', Some('V'), true).into()),
228        // 0x38
229        Some(('z', Some('Z'), true).into()),
230        None,
231        None,
232        None,
233        // 0x3c
234        None,
235        None,
236        None,
237        None,
238        // 0x40
239        None,
240        None,
241        None,
242        None,
243        // 0x44
244        None,
245        None,
246        None,
247        None,
248        // 0x48
249        None,
250        None,
251        None,
252        None,
253        // 0x4c
254        None,
255        None,
256        None,
257        None,
258        // 0x50
259        None,
260        None,
261        None,
262        None,
263        // 0x54
264        Some(('/', None).into()),
265        Some(('*', None).into()),
266        Some(('-', None).into()),
267        Some(('+', None).into()),
268        // 0x58
269        None,
270        Some(('1', None).into()),
271        Some(('2', None).into()),
272        Some(('3', None).into()),
273        // 0x5c
274        Some(('4', None).into()),
275        Some(('5', None).into()),
276        Some(('6', None).into()),
277        Some(('7', None).into()),
278        // 0x60
279        Some(('8', None).into()),
280        Some(('9', None).into()),
281        Some(('0', None).into()),
282        Some(('.', None).into()),
283    ];
284
285    /// TODO(75723): This map is incomplete, and is here only temporarily for
286    /// kicks.
287    pub(crate) static ref FR_AZERTY_MAP: Vec<Option<KeyLevels>> = vec![
288        // 0x00
289        None,
290        None,
291        None,
292        None,
293        // HID_USAGE_KEY_A
294        Some(('q', Some('Q'), true).into()),
295        Some(('b', Some('B'), true).into()),
296        Some(('c', Some('C'), true).into()),
297        Some(('d', Some('D'), true).into()),
298        // 0x08
299        Some(('e', Some('E'), true).into()),
300        Some(('f', Some('F'), true).into()),
301        Some(('g', Some('G'), true).into()),
302        Some(('h', Some('H'), true).into()),
303        // 0x0c
304        Some(('i', Some('I'), true).into()),
305        Some(('j', Some('J'), true).into()),
306        Some(('k', Some('K'), true).into()),
307        Some(('l', Some('L'), true).into()),
308        // 0x10
309        Some((',', Some('?')).into()),
310        Some(('n', Some('N'), true).into()),
311        Some(('o', Some('O'), true).into()),
312        Some(('p', Some('P'), true).into()),
313        // 0x14
314        Some(('a', Some('A'), true).into()),
315        Some(('r', Some('R'), true).into()),
316        Some(('s', Some('S'), true).into()),
317        Some(('t', Some('T'), true).into()),
318        // 0x18
319        Some(('u', Some('U'), true).into()),
320        Some(('v', Some('V'), true).into()),
321        Some(('z', Some('Z'), true).into()),
322        Some(('x', Some('X'), true).into()),
323        // 0x1c
324        Some(('y', Some('Y'), true).into()),
325        Some(('w', Some('W'), true).into()),
326        Some(('&', Some('1')).into()),
327        Some(('é', Some('2')).into()),
328        // 0x20
329        Some(('"', Some('3')).into()),
330        Some(('\'', Some('4')).into()),
331        Some(('(', Some('5')).into()),
332        Some(('-', Some('6')).into()),
333        // 0x24
334        Some(('è', Some('7')).into()),
335        Some(('—', Some('8')).into()),
336        Some(('ç', Some('9')).into()),
337        Some(('à', Some('0')).into()),
338        // 0x28
339        None,
340        None,
341        None,
342        None,
343        // 0x2c
344        Some((' ', Some(' ')).into()),
345        Some((')', Some('°')).into()),
346        Some(('=', Some('+')).into()),
347        Some(('\u{0302}', Some('\u{0308}')).into()),  // Unicode combining characters circumflex and dieresis.
348        // 0x30
349        Some(('$', Some('£')).into()),
350        Some(('\\', Some('|')).into()),  // Not present on French Azerty?
351        None,
352        Some(('m', Some('M'), true).into()),
353        // 0x34
354        Some(('\'', Some('"')).into()),
355        Some(('²', None).into()),
356        Some((';', Some('.')).into()),
357        Some((':', Some('/')).into()),
358        // 0x38
359        Some(('!', Some('§')).into()),
360        None,
361        None,
362        None,
363        // 0x3c
364        None,
365        None,
366        None,
367        None,
368        // 0x40
369        None,
370        None,
371        None,
372        None,
373        // 0x44
374        None,
375        None,
376        None,
377        None,
378        // 0x48
379        None,
380        None,
381        None,
382        None,
383        // 0x4c
384        None,
385        None,
386        None,
387        None,
388        // 0x50
389        None,
390        None,
391        None,
392        None,
393        // 0x54
394        Some(('/', None).into()),
395        Some(('*', None).into()),
396        Some(('-', None).into()),
397        Some(('+', None).into()),
398        // 0x58
399        None,
400        Some(('1', None).into()),
401        Some(('2', None).into()),
402        Some(('3', None).into()),
403        // 0x5c
404        Some(('4', None).into()),
405        Some(('5', None).into()),
406        Some(('6', None).into()),
407        Some(('7', None).into()),
408        // 0x60
409        Some(('8', None).into()),
410        Some(('9', None).into()),
411        Some(('0', None).into()),
412        Some(('.', None).into()),
413    ];
414
415    /// Standard [colemak] keymap.
416    ///
417    /// [colemak]: https://en.wikipedia.org/wiki/Keyboard_layout#Colemak
418    pub(crate) static ref COLEMAK_MAP: Vec<Option<KeyLevels>> = vec![
419        // 0x00
420        None,
421        None,
422        None,
423        None,
424        // HID_USAGE_KEY_A
425        Some(('a', Some('A'), true).into()),
426        Some(('b', Some('B'), true).into()),
427        Some(('c', Some('C'), true).into()),
428        Some(('s', Some('S'), true).into()),
429        // 0x08
430        Some(('f', Some('F'), true).into()),
431        Some(('t', Some('T'), true).into()),
432        Some(('d', Some('D'), true).into()),
433        Some(('h', Some('H'), true).into()),
434        // 0x0c
435        Some(('u', Some('U'), true).into()),
436        Some(('n', Some('N'), true).into()),
437        Some(('e', Some('E'), true).into()),
438        Some(('i', Some('I'), true).into()),
439        // 0x10
440        Some(('m', Some('M'), true).into()),
441        Some(('k', Some('K'), true).into()),
442        Some(('y', Some('Y'), true).into()),
443        Some((';', Some(':')).into()),
444        // 0x14
445        Some(('q', Some('Q'), true).into()),
446        Some(('p', Some('P'), true).into()),
447        Some(('r', Some('R'), true).into()),
448        Some(('g', Some('G'), true).into()),
449        // 0x18
450        Some(('l', Some('L'), true).into()),
451        Some(('v', Some('V'), true).into()),
452        Some(('w', Some('W'), true).into()),
453        Some(('x', Some('X'), true).into()),
454        // 0x1c
455        Some(('j', Some('J'), true).into()),
456        Some(('z', Some('Z'), true).into()),
457        Some(('1', Some('!')).into()),
458        Some(('2', Some('@')).into()),
459        // 0x20
460        Some(('3', Some('#')).into()),
461        Some(('4', Some('$')).into()),
462        Some(('5', Some('%')).into()),
463        Some(('6', Some('^')).into()),
464        // 0x24
465        Some(('7', Some('&')).into()),
466        Some(('8', Some('*')).into()),
467        Some(('9', Some('(')).into()),
468        Some(('0', Some(')')).into()),
469        // 0x28
470        None,
471        None,
472        None,
473        None,
474        // 0x2c
475        Some((' ', Some(' ')).into()),
476        Some(('-', Some('_')).into()),
477        Some(('=', Some('+')).into()),
478        Some(('[', Some('{')).into()),
479        // 0x30
480        Some((']', Some('}')).into()),
481        Some(('\\', Some('|')).into()),
482        None,
483        Some(('o', Some('O'), true).into()),
484        // 0x34
485        Some(('\'', Some('"')).into()),
486        Some(('`', Some('~')).into()),
487        Some((',', Some('<')).into()),
488        Some(('.', Some('>')).into()),
489        // 0x38
490        Some(('/', Some('?')).into()),
491        None,
492        None,
493        None,
494        // 0x3c
495        None,
496        None,
497        None,
498        None,
499        // 0x40
500        None,
501        None,
502        None,
503        None,
504        // 0x44
505        None,
506        None,
507        None,
508        None,
509        // 0x48
510        None,
511        None,
512        None,
513        None,
514        // 0x4c
515        None,
516        None,
517        None,
518        None,
519        // 0x50
520        None,
521        None,
522        None,
523        None,
524        // 0x54
525        Some(('/', None).into()),
526        Some(('*', None).into()),
527        Some(('-', None).into()),
528        Some(('+', None).into()),
529        // 0x58
530        None,
531        Some(('1', None).into()),
532        Some(('2', None).into()),
533        Some(('3', None).into()),
534        // 0x5c
535        Some(('4', None).into()),
536        Some(('5', None).into()),
537        Some(('6', None).into()),
538        Some(('7', None).into()),
539        // 0x60
540        Some(('8', None).into()),
541        Some(('9', None).into()),
542        Some(('0', None).into()),
543        Some(('.', None).into()),
544    ];
545}
546
547/// Levels corresponding to each defined key.
548pub struct KeyLevels {
549    /// The base, unshifted character.
550    pub(crate) ch: char,
551    /// The shifted character, if present
552    pub(crate) shift_ch: Option<char>,
553    /// Is it a letter?  Letters are affected by Caps Lock, while other keys
554    /// are not.
555    is_letter: bool,
556}
557
558impl From<(char, Option<char>)> for KeyLevels {
559    fn from(s: (char, Option<char>)) -> Self {
560        KeyLevels { ch: s.0, shift_ch: s.1, is_letter: false }
561    }
562}
563
564impl From<(char, Option<char>, bool)> for KeyLevels {
565    fn from(s: (char, Option<char>, bool)) -> Self {
566        KeyLevels { ch: s.0, shift_ch: s.1, is_letter: s.2 }
567    }
568}
569
570impl KeyLevels {
571    pub fn get_key(&self, m: &impl ModifierChecker, l: &impl LockStateChecker) -> Option<char> {
572        if (l.test(LockState::CAPS_LOCK) && self.is_letter) || m.test(Modifiers::SHIFT) {
573            return self.shift_ch;
574        }
575        Some(self.ch)
576    }
577}