pc_keyboard/layouts/
azerty.rs

1//! French keyboard support
2
3use crate::{DecodedKey, HandleControl, KeyCode, KeyboardLayout, Modifiers};
4
5/// A standard French 102-key (or 105-key including Windows keys) keyboard.
6///
7/// The top row spells `AZERTY`.
8///
9/// Has a 2-row high Enter key, with Oem5 next to the left shift (ISO format).
10///
11/// NB: no "dead key" support for now
12pub struct Azerty;
13
14impl KeyboardLayout for Azerty {
15    fn map_keycode(
16        &self,
17        keycode: KeyCode,
18        modifiers: &Modifiers,
19        handle_ctrl: HandleControl,
20    ) -> DecodedKey {
21        let map_to_unicode = handle_ctrl == HandleControl::MapLettersToUnicode;
22        match keycode {
23            KeyCode::Escape => DecodedKey::Unicode(0x1B.into()),
24            KeyCode::Oem8 => DecodedKey::Unicode('²'),
25            KeyCode::Oem5 => {
26                if modifiers.is_shifted() {
27                    DecodedKey::Unicode('>')
28                } else {
29                    DecodedKey::Unicode('<')
30                }
31            }
32            KeyCode::Key1 => {
33                if modifiers.is_shifted() {
34                    DecodedKey::Unicode('1')
35                } else {
36                    DecodedKey::Unicode('&')
37                }
38            }
39            KeyCode::Key2 => {
40                if modifiers.is_shifted() {
41                    DecodedKey::Unicode('2')
42                } else if modifiers.is_altgr() {
43                    DecodedKey::Unicode('~')
44                } else {
45                    DecodedKey::Unicode('é')
46                }
47            }
48            KeyCode::Key3 => {
49                if modifiers.is_shifted() {
50                    DecodedKey::Unicode('3')
51                } else if modifiers.is_altgr() {
52                    DecodedKey::Unicode('#')
53                } else {
54                    DecodedKey::Unicode('"')
55                }
56            }
57            KeyCode::Key4 => {
58                if modifiers.is_shifted() {
59                    DecodedKey::Unicode('4')
60                } else if modifiers.is_altgr() {
61                    DecodedKey::Unicode('{')
62                } else {
63                    DecodedKey::Unicode('\'')
64                }
65            }
66            KeyCode::Key5 => {
67                if modifiers.is_shifted() {
68                    DecodedKey::Unicode('5')
69                } else if modifiers.is_altgr() {
70                    DecodedKey::Unicode('[')
71                } else {
72                    DecodedKey::Unicode('(')
73                }
74            }
75            KeyCode::Key6 => {
76                if modifiers.is_shifted() {
77                    DecodedKey::Unicode('6')
78                } else if modifiers.is_altgr() {
79                    DecodedKey::Unicode('|')
80                } else {
81                    DecodedKey::Unicode('-')
82                }
83            }
84            KeyCode::Key7 => {
85                if modifiers.is_shifted() {
86                    DecodedKey::Unicode('7')
87                } else if modifiers.is_altgr() {
88                    DecodedKey::Unicode('`')
89                } else {
90                    DecodedKey::Unicode('è')
91                }
92            }
93            KeyCode::Key8 => {
94                if modifiers.is_shifted() {
95                    DecodedKey::Unicode('8')
96                } else if modifiers.is_altgr() {
97                    DecodedKey::Unicode('\\')
98                } else {
99                    DecodedKey::Unicode('_')
100                }
101            }
102            KeyCode::Key9 => {
103                if modifiers.is_shifted() {
104                    DecodedKey::Unicode('9')
105                } else if modifiers.is_altgr() {
106                    DecodedKey::Unicode('^')
107                } else {
108                    DecodedKey::Unicode('ç')
109                }
110            }
111            KeyCode::Key0 => {
112                if modifiers.is_shifted() {
113                    DecodedKey::Unicode('0')
114                } else if modifiers.is_altgr() {
115                    DecodedKey::Unicode('@')
116                } else {
117                    DecodedKey::Unicode('à')
118                }
119            }
120            KeyCode::OemMinus => {
121                if modifiers.is_shifted() {
122                    DecodedKey::Unicode('°')
123                } else if modifiers.is_altgr() {
124                    DecodedKey::Unicode(']')
125                } else {
126                    DecodedKey::Unicode(')')
127                }
128            }
129            KeyCode::OemPlus => {
130                if modifiers.is_shifted() {
131                    DecodedKey::Unicode('+')
132                } else if modifiers.is_altgr() {
133                    DecodedKey::Unicode('}')
134                } else {
135                    DecodedKey::Unicode('=')
136                }
137            }
138            KeyCode::Backspace => DecodedKey::Unicode(0x08.into()),
139            KeyCode::Tab => DecodedKey::Unicode(0x09.into()),
140            KeyCode::Q => {
141                if map_to_unicode && modifiers.is_ctrl() {
142                    DecodedKey::Unicode('\u{0001}')
143                } else if modifiers.is_caps() {
144                    DecodedKey::Unicode('A')
145                } else {
146                    DecodedKey::Unicode('a')
147                }
148            }
149            KeyCode::W => {
150                if map_to_unicode && modifiers.is_ctrl() {
151                    DecodedKey::Unicode('\u{001A}')
152                } else if modifiers.is_caps() {
153                    DecodedKey::Unicode('Z')
154                } else {
155                    DecodedKey::Unicode('z')
156                }
157            }
158            KeyCode::E => {
159                if map_to_unicode && modifiers.is_ctrl() {
160                    DecodedKey::Unicode('\u{0005}')
161                } else if modifiers.is_caps() {
162                    DecodedKey::Unicode('E')
163                } else {
164                    DecodedKey::Unicode('e')
165                }
166            }
167            KeyCode::R => {
168                if map_to_unicode && modifiers.is_ctrl() {
169                    DecodedKey::Unicode('\u{0012}')
170                } else if modifiers.is_caps() {
171                    DecodedKey::Unicode('R')
172                } else {
173                    DecodedKey::Unicode('r')
174                }
175            }
176            KeyCode::T => {
177                if map_to_unicode && modifiers.is_ctrl() {
178                    DecodedKey::Unicode('\u{0014}')
179                } else if modifiers.is_caps() {
180                    DecodedKey::Unicode('T')
181                } else {
182                    DecodedKey::Unicode('t')
183                }
184            }
185            KeyCode::Y => {
186                if map_to_unicode && modifiers.is_ctrl() {
187                    DecodedKey::Unicode('\u{0019}')
188                } else if modifiers.is_caps() {
189                    DecodedKey::Unicode('Y')
190                } else {
191                    DecodedKey::Unicode('y')
192                }
193            }
194            KeyCode::U => {
195                if map_to_unicode && modifiers.is_ctrl() {
196                    DecodedKey::Unicode('\u{0015}')
197                } else if modifiers.is_caps() {
198                    DecodedKey::Unicode('U')
199                } else {
200                    DecodedKey::Unicode('u')
201                }
202            }
203            KeyCode::I => {
204                if map_to_unicode && modifiers.is_ctrl() {
205                    DecodedKey::Unicode('\u{0009}')
206                } else if modifiers.is_caps() {
207                    DecodedKey::Unicode('I')
208                } else {
209                    DecodedKey::Unicode('i')
210                }
211            }
212            KeyCode::O => {
213                if map_to_unicode && modifiers.is_ctrl() {
214                    DecodedKey::Unicode('\u{000F}')
215                } else if modifiers.is_caps() {
216                    DecodedKey::Unicode('O')
217                } else {
218                    DecodedKey::Unicode('o')
219                }
220            }
221            KeyCode::P => {
222                if map_to_unicode && modifiers.is_ctrl() {
223                    DecodedKey::Unicode('\u{0010}')
224                } else if modifiers.is_caps() {
225                    DecodedKey::Unicode('P')
226                } else {
227                    DecodedKey::Unicode('p')
228                }
229            }
230            KeyCode::Oem4 => {
231                if modifiers.is_shifted() {
232                    DecodedKey::Unicode('¨')
233                } else if modifiers.is_altgr() {
234                    DecodedKey::Unicode('ˇ')
235                } else {
236                    DecodedKey::Unicode('^')
237                }
238            }
239            KeyCode::Oem6 => {
240                if modifiers.is_shifted() {
241                    DecodedKey::Unicode('£')
242                } else if modifiers.is_altgr() {
243                    DecodedKey::Unicode('¤')
244                } else {
245                    DecodedKey::Unicode('$')
246                }
247            }
248            KeyCode::Oem7 => {
249                if modifiers.is_shifted() {
250                    DecodedKey::Unicode('µ')
251                } else {
252                    DecodedKey::Unicode('*')
253                }
254            }
255            KeyCode::A => {
256                if map_to_unicode && modifiers.is_ctrl() {
257                    DecodedKey::Unicode('\u{0011}')
258                } else if modifiers.is_caps() {
259                    DecodedKey::Unicode('Q')
260                } else {
261                    DecodedKey::Unicode('q')
262                }
263            }
264            KeyCode::S => {
265                if map_to_unicode && modifiers.is_ctrl() {
266                    DecodedKey::Unicode('\u{0013}')
267                } else if modifiers.is_caps() {
268                    DecodedKey::Unicode('S')
269                } else {
270                    DecodedKey::Unicode('s')
271                }
272            }
273            KeyCode::D => {
274                if map_to_unicode && modifiers.is_ctrl() {
275                    DecodedKey::Unicode('\u{0004}')
276                } else if modifiers.is_caps() {
277                    DecodedKey::Unicode('D')
278                } else {
279                    DecodedKey::Unicode('d')
280                }
281            }
282            KeyCode::F => {
283                if map_to_unicode && modifiers.is_ctrl() {
284                    DecodedKey::Unicode('\u{0006}')
285                } else if modifiers.is_caps() {
286                    DecodedKey::Unicode('F')
287                } else {
288                    DecodedKey::Unicode('f')
289                }
290            }
291            KeyCode::G => {
292                if map_to_unicode && modifiers.is_ctrl() {
293                    DecodedKey::Unicode('\u{0007}')
294                } else if modifiers.is_caps() {
295                    DecodedKey::Unicode('G')
296                } else {
297                    DecodedKey::Unicode('g')
298                }
299            }
300            KeyCode::H => {
301                if map_to_unicode && modifiers.is_ctrl() {
302                    DecodedKey::Unicode('\u{0008}')
303                } else if modifiers.is_caps() {
304                    DecodedKey::Unicode('H')
305                } else {
306                    DecodedKey::Unicode('h')
307                }
308            }
309            KeyCode::J => {
310                if map_to_unicode && modifiers.is_ctrl() {
311                    DecodedKey::Unicode('\u{000A}')
312                } else if modifiers.is_caps() {
313                    DecodedKey::Unicode('J')
314                } else {
315                    DecodedKey::Unicode('j')
316                }
317            }
318            KeyCode::K => {
319                if map_to_unicode && modifiers.is_ctrl() {
320                    DecodedKey::Unicode('\u{000B}')
321                } else if modifiers.is_caps() {
322                    DecodedKey::Unicode('K')
323                } else {
324                    DecodedKey::Unicode('k')
325                }
326            }
327            KeyCode::L => {
328                if map_to_unicode && modifiers.is_ctrl() {
329                    DecodedKey::Unicode('\u{000C}')
330                } else if modifiers.is_caps() {
331                    DecodedKey::Unicode('L')
332                } else {
333                    DecodedKey::Unicode('l')
334                }
335            }
336            KeyCode::Oem1 => {
337                if map_to_unicode && modifiers.is_ctrl() {
338                    DecodedKey::Unicode('\u{000D}')
339                } else if modifiers.is_caps() {
340                    DecodedKey::Unicode('M')
341                } else {
342                    DecodedKey::Unicode('m')
343                }
344            }
345            KeyCode::Oem3 => {
346                if modifiers.is_shifted() {
347                    DecodedKey::Unicode('%')
348                } else {
349                    DecodedKey::Unicode('ù')
350                }
351            }
352            // Enter gives LF, not CRLF or CR
353            KeyCode::Return => DecodedKey::Unicode(10.into()),
354            KeyCode::Z => {
355                if map_to_unicode && modifiers.is_ctrl() {
356                    DecodedKey::Unicode('\u{0017}')
357                } else if modifiers.is_caps() {
358                    DecodedKey::Unicode('W')
359                } else {
360                    DecodedKey::Unicode('w')
361                }
362            }
363            KeyCode::X => {
364                if map_to_unicode && modifiers.is_ctrl() {
365                    DecodedKey::Unicode('\u{0018}')
366                } else if modifiers.is_caps() {
367                    DecodedKey::Unicode('X')
368                } else {
369                    DecodedKey::Unicode('x')
370                }
371            }
372            KeyCode::C => {
373                if map_to_unicode && modifiers.is_ctrl() {
374                    DecodedKey::Unicode('\u{0003}')
375                } else if modifiers.is_caps() {
376                    DecodedKey::Unicode('C')
377                } else {
378                    DecodedKey::Unicode('c')
379                }
380            }
381            KeyCode::V => {
382                if map_to_unicode && modifiers.is_ctrl() {
383                    DecodedKey::Unicode('\u{0016}')
384                } else if modifiers.is_caps() {
385                    DecodedKey::Unicode('V')
386                } else {
387                    DecodedKey::Unicode('v')
388                }
389            }
390            KeyCode::B => {
391                if map_to_unicode && modifiers.is_ctrl() {
392                    DecodedKey::Unicode('\u{0002}')
393                } else if modifiers.is_caps() {
394                    DecodedKey::Unicode('B')
395                } else {
396                    DecodedKey::Unicode('b')
397                }
398            }
399            KeyCode::N => {
400                if map_to_unicode && modifiers.is_ctrl() {
401                    DecodedKey::Unicode('\u{000E}')
402                } else if modifiers.is_caps() {
403                    DecodedKey::Unicode('N')
404                } else {
405                    DecodedKey::Unicode('n')
406                }
407            }
408            KeyCode::M => {
409                if modifiers.is_caps() {
410                    DecodedKey::Unicode('?')
411                } else {
412                    DecodedKey::Unicode(',')
413                }
414            }
415            KeyCode::OemComma => {
416                if modifiers.is_shifted() {
417                    DecodedKey::Unicode('.')
418                } else {
419                    DecodedKey::Unicode(';')
420                }
421            }
422            KeyCode::OemPeriod => {
423                if modifiers.is_shifted() {
424                    DecodedKey::Unicode('/')
425                } else {
426                    DecodedKey::Unicode(':')
427                }
428            }
429            KeyCode::Oem2 => {
430                if modifiers.is_shifted() {
431                    DecodedKey::Unicode('§')
432                } else {
433                    DecodedKey::Unicode('!')
434                }
435            }
436            KeyCode::Spacebar => DecodedKey::Unicode(' '),
437            KeyCode::Delete => DecodedKey::Unicode(127.into()),
438            KeyCode::NumpadDivide => DecodedKey::Unicode('/'),
439            KeyCode::NumpadMultiply => DecodedKey::Unicode('*'),
440            KeyCode::NumpadSubtract => DecodedKey::Unicode('-'),
441            KeyCode::Numpad7 => {
442                if modifiers.numlock {
443                    DecodedKey::Unicode('7')
444                } else {
445                    DecodedKey::RawKey(KeyCode::Home)
446                }
447            }
448            KeyCode::Numpad8 => {
449                if modifiers.numlock {
450                    DecodedKey::Unicode('8')
451                } else {
452                    DecodedKey::RawKey(KeyCode::ArrowUp)
453                }
454            }
455            KeyCode::Numpad9 => {
456                if modifiers.numlock {
457                    DecodedKey::Unicode('9')
458                } else {
459                    DecodedKey::RawKey(KeyCode::PageUp)
460                }
461            }
462            KeyCode::NumpadAdd => DecodedKey::Unicode('+'),
463            KeyCode::Numpad4 => {
464                if modifiers.numlock {
465                    DecodedKey::Unicode('4')
466                } else {
467                    DecodedKey::RawKey(KeyCode::ArrowLeft)
468                }
469            }
470            KeyCode::Numpad5 => DecodedKey::Unicode('5'),
471            KeyCode::Numpad6 => {
472                if modifiers.numlock {
473                    DecodedKey::Unicode('6')
474                } else {
475                    DecodedKey::RawKey(KeyCode::ArrowRight)
476                }
477            }
478            KeyCode::Numpad1 => {
479                if modifiers.numlock {
480                    DecodedKey::Unicode('1')
481                } else {
482                    DecodedKey::RawKey(KeyCode::End)
483                }
484            }
485            KeyCode::Numpad2 => {
486                if modifiers.numlock {
487                    DecodedKey::Unicode('2')
488                } else {
489                    DecodedKey::RawKey(KeyCode::ArrowDown)
490                }
491            }
492            KeyCode::Numpad3 => {
493                if modifiers.numlock {
494                    DecodedKey::Unicode('3')
495                } else {
496                    DecodedKey::RawKey(KeyCode::PageDown)
497                }
498            }
499            KeyCode::Numpad0 => {
500                if modifiers.numlock {
501                    DecodedKey::Unicode('0')
502                } else {
503                    DecodedKey::RawKey(KeyCode::Insert)
504                }
505            }
506            KeyCode::NumpadPeriod => {
507                if modifiers.numlock {
508                    DecodedKey::Unicode('.')
509                } else {
510                    DecodedKey::Unicode(127.into())
511                }
512            }
513            KeyCode::NumpadEnter => DecodedKey::Unicode(10.into()),
514            k => DecodedKey::RawKey(k),
515        }
516    }
517}
518
519#[cfg(test)]
520mod test {
521    use super::*;
522    use crate::{KeyCode, KeyEvent, KeyState, Keyboard, ScancodeSet2};
523
524    #[test]
525    fn test_frazert() {
526        let mut k = Keyboard::new(
527            ScancodeSet2::new(),
528            Azerty,
529            HandleControl::MapLettersToUnicode,
530        );
531        assert_eq!(
532            k.process_keyevent(KeyEvent::new(KeyCode::NumpadDivide, KeyState::Down)),
533            Some(DecodedKey::Unicode('/'))
534        );
535        assert_eq!(
536            k.process_keyevent(KeyEvent::new(KeyCode::NumpadMultiply, KeyState::Down)),
537            Some(DecodedKey::Unicode('*'))
538        );
539        assert_eq!(
540            k.process_keyevent(KeyEvent::new(KeyCode::A, KeyState::Down)),
541            Some(DecodedKey::Unicode('q'))
542        );
543        assert_eq!(
544            k.process_keyevent(KeyEvent::new(KeyCode::Key4, KeyState::Down)),
545            Some(DecodedKey::Unicode('\''))
546        );
547        assert_eq!(
548            k.process_keyevent(KeyEvent::new(KeyCode::Oem5, KeyState::Down)),
549            Some(DecodedKey::Unicode('<'))
550        );
551        assert_eq!(
552            k.process_keyevent(KeyEvent::new(KeyCode::Oem7, KeyState::Down)),
553            Some(DecodedKey::Unicode('*'))
554        );
555        assert_eq!(
556            k.process_keyevent(KeyEvent::new(KeyCode::Numpad0, KeyState::Up)),
557            None
558        );
559        assert_eq!(
560            k.process_keyevent(KeyEvent::new(KeyCode::NumpadLock, KeyState::Down)),
561            Some(DecodedKey::RawKey(KeyCode::NumpadLock))
562        );
563        assert_eq!(
564            k.process_keyevent(KeyEvent::new(KeyCode::NumpadLock, KeyState::Up)),
565            None
566        );
567        assert_eq!(
568            k.process_keyevent(KeyEvent::new(KeyCode::Numpad0, KeyState::Down)),
569            Some(DecodedKey::RawKey(KeyCode::Insert))
570        );
571        assert_eq!(
572            k.process_keyevent(KeyEvent::new(KeyCode::Numpad0, KeyState::Up)),
573            None
574        );
575    }
576}