diff --git a/CHANGELOG.md b/CHANGELOG.md index 7659fbd..d5c6520 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ * Fix Ctrl combination handling for Colemak and De105Key layouts * Fix 102/105-key German layout: Add missing Alt-Gr combinations +* Added tool to print keyboard layouts as ASCII-art +* Cleaned up how layouts are implemented ## v0.8.0 (13 Sep 2024) diff --git a/Cargo.toml b/Cargo.toml index fccb2fd..5845a0a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,5 +8,6 @@ categories = ["embedded", "no-std"] license = "MIT OR Apache-2.0" repository = "https://github.com/rust-embedded-community/pc-keyboard.git" edition = "2021" +rust-version = "1.61" [dependencies] diff --git a/README.md b/README.md index 86fec61..e85dee9 100644 --- a/README.md +++ b/README.md @@ -4,295 +4,7 @@ A simple driver for handling PC keyboards, with both Scancode Set 1 (when running on a PC) and Scancode Set 2 support (when reading a PS/2 keyboard output directly). -## Supports: - -- Scancode Set 1 (from the i8042 PC keyboard controller) -- Scancode Set 2 (direct from the AT or PS/2 interface keyboard) -- Several keyboard layouts: - -| Name | No. Keys | Description | Link | -| ---------------------------------------------------- | -------- | ------------------------------------------------------------------------ | ----------------------------------------------------------------------------------- | -| [`Us104Key`](./src/layouts/us104.rs) | 101/104 | North American standard English | [Wikipedia](https://en.wikipedia.org/wiki/QWERTY#United_States) | -| [`Uk105Key`](./src/layouts/uk105.rs) | 102/105 | United Kingdom standard English | [Wikipedia](https://en.wikipedia.org/wiki/QWERTY#United_Kingdom) | -| [`Azerty`](./src/layouts/azerty.rs) | 102/105 | Typically used in French locales | [Wikipedia](https://en.wikipedia.org/wiki/AZERTY) | -| [`De105Key`](./src/layouts/de105.rs) | 102/105 | German layout | [Wikipedia](https://en.wikipedia.org/wiki/QWERTZ) | -| [`FiSe105Key`](./src/layouts/fi_se105.rs) | 102/105 | Finnish/Swedish layout | [Wikipedia](https://en.wikipedia.org/wiki/QWERTY#Finnish%E2%80%93Swedish) | -| [`No105Key`](./src/layouts/no105.rs) | 102/105 | Norwegian layout | [Wikipedia](https://en.wikipedia.org/wiki/QWERTY#Norwegian) | -| [`Jis109Key`](./src/layouts/jis109.rs) | 106/109 | JIS 109-key layout (Latin chars only) | [Wikipedia](https://en.wikipedia.org/wiki/Japanese_input_method#Japanese_keyboards) | -| [`Colemak`](./src/layouts/colemak.rs) | 101/104 | A keyboard layout designed to make typing more efficient and comfortable | [Wikipedia](https://en.wikipedia.org/wiki/Colemak) | -| [`Dvorak104Key`](./src/layouts/dvorak104.rs) | 101/104 | The more 'ergonomic' alternative to QWERTY | [Wikipedia](https://en.wikipedia.org/wiki/Dvorak_keyboard_layout) | -| [`DVP104Key`](./src/layouts/dvorak_programmer104.rs) | 101/104 | Dvorak for Programmers | [Wikipedia](https://en.wikipedia.org/wiki/Dvorak_keyboard_layout#Programmer_Dvorak) | - -101/104 keys is ANSI layout (wide Enter key) and 102/105 keys is ISO layout -(tall Enter key). The difference between 101 and 104 (and between 102 and -105) comes from the two Windows keys and the Menu key that were added when -Windows 95 came out. JIS keyboards have extra keys, added by making the -space-bar and backspace keys shorter. - - -## Usage - -There are three basic steps to handling keyboard input. Your application may bypass some of these. - -* `Ps2Decoder` - converts 11-bit PS/2 words into bytes, removing the start/stop - bits and checking the parity bits. Only needed if you talk to the PS/2 - keyboard over GPIO pins and not required if you talk to the i8042 PC keyboard - controller. -* `ScancodeSet` - converts from Scancode Set 1 (i8042 PC keyboard controller) or - Scancode Set 2 (raw PS/2 keyboard output) into a symbolic `KeyCode` and an - up/down `KeyState`. -* `EventDecoder` - converts symbolic `KeyCode` and `KeyState` into a Unicode - characters (where possible) according to the currently selected `KeyboardLayout`. - -There is also `Keyboard` which combines the above three functions into a single object. - -See the [`examples`](./examples) folder for more details. - -## [Documentation](https://docs.rs/crate/pc-keyboard) - -## Keycodes - -This crate uses symbolic keycodes to abstract over Scancode Set 1 and Scancode -Set 2. They represented by the `KeyCode` enum. The scancodes can come from one of three supported keyboards: 102/105 key ISO, 101/104 key ANSI and 106/109-key JIS. - -### 102/105 key ISO - -This is the mapping of `KeyCode` to a 102/105-key ISO keyboard: - -```text -┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ -│Esc │ │ F1 │ F2 │ F3 │ F4 │ │ F5 │ F6 │ F7 │ F8 │ │ F9 │F10 │F11 │F12 │ │PrSc│Scrl│PBrk│ -└────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ - -┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ -│Oem8│Key1│Key2│Key3│Key4│Key5│Key6│Key7│Key8│Key9│Key0│Oem─│Oem+│Backspace│ │Inse│Home│PgUp│ │NumL│Num/│Num*│Num─│ -├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ -│ Tab │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │Oem4│Oem6│ Enter │ │Dele│End │PgDo│ │Num7│Num8│Num9│ │ -├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐ │ └────┴────┴────┘ ├────┼────┼────┤Num+│ -│CapsLo│ A │ S │ D │ F │ G │ H │ J │ K │ L │Oem1│Oem3│Oem7│ │ │Num4│Num5│Num6│ │ -├────┬─┴───┬┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┴───────┤ ┌────┐ ├────┼────┼────┼────┤ -│LShf│Oem5 │ Z │ X │ C │ V │ B │ N │ M │OemC│OemP│Oem2│ RShift │ │ Up │ │Num1│Num2│Num3│ │ -├────┴┬────┴┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┴────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤Num │ -│LCtrl│LWin │ Alt │ Space │AltGr│RWin │ Menu │RCtrl │ │Left│Down│Righ│ │Num0 │NumP│Ente│ -└─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ -``` - -The 102-key is missing `LWin`, `RWin`, and `Menu`. - -(Reference: ) - -### 101/104 key ANSI - -This is the mapping of `KeyCode` to a 101/104-key ANSI keyboard: - -```text -┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ -│Esc │ │ F1 │ F2 │ F3 │ F4 │ │ F5 │ F6 │ F7 │ F8 │ │ F9 │F10 │F11 │F12 │ │PrSc│Scrl│PBrk│ -└────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ - -┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ -│Oem8│Key1│Key2│Key3│Key4│Key5│Key6│Key7│Key8│Key9│Key0│Oem─│Oem+│Backspace│ │Inse│Home│PgUp│ │NumL│Num/│Num*│Num─│ -├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────+────+────┤ ├────┼────┼────┼────┤ -│ Tab │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │Oem4│Oem6│ Oem7 │ │Dele│End │PgDo│ │Num7│Num8│Num9│ │ -├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴────────┤ └────┴────┴────┘ ├────┼────┼────┤Num+│ -│CapsLo│ A │ S │ D │ F │ G │ H │ J │ K │ L │Oem1│Oem3│ Enter │ │Num4│Num5│Num6│ │ -├──────┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────────────┤ ┌────┐ ├────┼────┼────┼────┤ -│ LShift │ Z │ X │ C │ V │ B │ N │ M │OemC│OemP│Oem2│ RShift │ │ Up │ │Num1│Num2│Num3│ │ -├─────┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┴────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤Num │ -│LCtrl│LWin │ Alt │ Space │AltGr│RWin │ Menu │RCtrl │ │Left│Down│Righ│ │Num0 │NumP│Ente│ -└─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ -``` - -Note that the `Oem5` key is missing on the 104-key ANSI keyboard. - -The 101-key is also missing `LWin`, `RWin`, and `Menu`. - -(Reference: ) - -### 106/109 key JIS - -This is the mapping of `KeyCode` to a 106/109-key JIS keyboard: - -```text -┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ -│Esc │ │ F1 │ F2 │ F3 │ F4 │ │ F5 │ F6 │ F7 │ F8 │ │ F9 │F10 │F11 │F12 │ │PrSc│Scrl│PBrk│ -└────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ - -┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ -│Oem8│Key1│Key2│Key3│Key4│Key5│Key6│Key7│Key8│Key9│Key0│Oem─│Oem+│Om13│BkSp│ │Inse│Home│PgUp│ │NumL│Num/│Num*│Num─│ -├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ -│ Tab │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │Oem4│Oem6│ Enter │ │Dele│End │PgDo│ │Num7│Num8│Num9│ │ -├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐ │ └────┴────┴────┘ ├────┼────┼────┤Num+│ -│CapsLo│ A │ S │ D │ F │ G │ H │ J │ K │ L │Oem1│Oem3│Oem7│ │ │Num4│Num5│Num6│ │ -├──────┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┴───────┤ ┌────┐ ├────┼────┼────┼────┤ -│LShift │ Z │ X │ C │ V │ B │ N │ M │OemC│OemP│Oem2│Oem12 │RShift │ │ Up │ │Num1│Num2│Num3│ │ -├─────┬───┴─┬──┴──┬─┴───┬┴────┴────┴────┴────┴┬───┴─┬──┴──┬─┴──┬───┴┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤Num │ -│LCtrl│LWin │LAlt │Oem9 │ Space Bar │Oem10│Oem11│RWin│Menu│RCtrl │ │Left│Down│Righ│ │Num0 │NumP│Ente│ -└─────┴─────┴─────┴─────┴─────────────────────┴─────┴─────┴────┴────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ -``` - -Note that the `Oem5` is missing on the 109-key JIS layout, but `Oem9` (Muhenkan), `Oem10` (Henkan/Zenkouho), `Oem11` (Hiragana/Katakana), `Oem12` (Backslash) and `Oem13` (¥) are added. - -The 106-key is missing `LWin`, `RWin`, and `Menu`. - -(Reference: ) - -### Conversion Table - -Scancode Set 1 and Scancode Set 2 can be losslessly converted. Indeed, this is -what the i8042 keyboard controller in your PC does - it takes Scancode Set 2 -from the keyboard and provides Scancode Set 1 to the Operating System. This -allowed them to change the keyboard design without breaking compatibility with -any MS-DOS applications that read raw scancodes from the keyboard. - -This table shows the correspondence between our symbolic KeyCode, Scancode Set 1 -and Scancode Set 2. We may extend this in the future to also handle USB HID -Scancodes. Any codes prefixed `0xE0` or `0xE1` are *extended* multi-byte -scancodes. Typically these are keys that were not on the IBM PC and PC/XT -keyboards so they they were added in such a way that if you ignored the 0xE0, -you got a reasonable result anyway. For example `ArrowLeft` is `0xE04B` in -Scancode Set 1 because `Numpad4` is `0x4B` and that was the left-arrow key on an -IBM PC or PC/XT. - -| Symbolic Key | Scancode Set 1 | Scancode Set 2 | -| -------------- | -------------- | -------------- | -| Escape | 0x01 | 0x76 | -| F1 | 0x3B | 0x05 | -| F2 | 0x3C | 0x06 | -| F3 | 0x3D | 0x04 | -| F4 | 0x3E | 0x0C | -| F5 | 0x3F | 0x03 | -| F6 | 0x40 | 0x0B | -| F7 | 0x41 | 0x83 | -| F8 | 0x42 | 0x0A | -| F9 | 0x43 | 0x01 | -| F10 | 0x44 | 0x09 | -| F11 | 0x57 | 0x78 | -| F12 | 0x58 | 0x07 | -| PrintScreen | 0xE037 | 0xE07C | -| SysRq | 0x54 | 0x7F | -| ScrollLock | 0x46 | 0x7E | -| PauseBreak | -- | -- | -| - | -- | -- | -| Oem8 | 0x29 | 0x0E | -| Key1 | 0x02 | 0x16 | -| Key2 | 0x03 | 0x1E | -| Key3 | 0x04 | 0x26 | -| Key4 | 0x05 | 0x25 | -| Key5 | 0x06 | 0x2E | -| Key6 | 0x07 | 0x36 | -| Key7 | 0x08 | 0x3D | -| Key8 | 0x09 | 0x3E | -| Key9 | 0x0A | 0x46 | -| Key0 | 0x0B | 0x45 | -| OemMinus | 0x0C | 0x4E | -| OemPlus | 0x0D | 0x55 | -| Backspace | 0x0E | 0x66 | -| Insert | 0xE052 | 0xE070 | -| Home | 0xE047 | 0xE06C | -| PageUp | 0xE049 | 0xE07D | -| NumpadLock | 0x45 | 0x77 | -| NumpadDivide | 0xE035 | 0xE04A | -| NumpadMultiply | 0x37 | 0x7C | -| NumpadSubtract | 0x4A | 0x7B | -| - | -- | -- | -| Tab | 0x0F | 0x0D | -| Q | 0x10 | 0x15 | -| W | 0x11 | 0x1D | -| E | 0x12 | 0x24 | -| R | 0x13 | 0x2D | -| T | 0x14 | 0x2C | -| Y | 0x15 | 0x35 | -| U | 0x16 | 0x3C | -| I | 0x17 | 0x43 | -| O | 0x18 | 0x44 | -| P | 0x19 | 0x4D | -| Oem4 | 0x1A | 0x54 | -| Oem6 | 0x1B | 0x5B | -| Oem5 | 0x56 | 0x61 | -| Oem7 | 0x2B | 0x5D | -| Delete | 0xE053 | 0xE071 | -| End | 0xE04F | 0xE069 | -| PageDown | 0xE051 | 0xE07A | -| Numpad7 | 0x47 | 0x6C | -| Numpad8 | 0x48 | 0x75 | -| Numpad9 | 0x49 | 0x7D | -| NumpadAdd | 0x4E | 0x79 | -| - | -- | -- | -| CapsLock | 0x3A | 0x58 | -| A | 0x1E | 0x1C | -| S | 0x1F | 0x1B | -| D | 0x20 | 0x23 | -| F | 0x21 | 0x2B | -| G | 0x22 | 0x34 | -| H | 0x23 | 0x33 | -| J | 0x24 | 0x3B | -| K | 0x25 | 0x42 | -| L | 0x26 | 0x4B | -| Oem1 | 0x27 | 0x4C | -| Oem3 | 0x28 | 0x52 | -| Return | 0x1C | 0x5A | -| Numpad4 | 0x4B | 0x6B | -| Numpad5 | 0x4C | 0x73 | -| Numpad6 | 0x4D | 0x74 | -| - | -- | -- | -| LShift | 0x2A | 0x12 | -| Z | 0x2C | 0x1A | -| X | 0x2D | 0x22 | -| C | 0x2E | 0x21 | -| V | 0x2F | 0x2A | -| B | 0x30 | 0x32 | -| N | 0x31 | 0x31 | -| M | 0x32 | 0x3A | -| OemComma | 0x33 | 0x41 | -| OemPeriod | 0x34 | 0x49 | -| Oem2 | 0x35 | 0x4A | -| RShift | 0x36 | 0x59 | -| ArrowUp | 0xE048 | 0xE075 | -| Numpad1 | 0x4F | 0x69 | -| Numpad2 | 0x50 | 0x72 | -| Numpad3 | 0x51 | 0x7A | -| NumpadEnter | 0xE01C | 0xE075 | -| - | -- | -- | -| LControl | 0x1D | 0x14 | -| LWin | 0xE05B | 0xE01F | -| LAlt | 0x38 | 0x11 | -| Spacebar | 0x39 | 0x29 | -| RAltGr | 0xE038 | 0xE011 | -| RWin | 0xE05C | 0xE027 | -| Apps | 0xE05C | 0xE02F | -| RControl | 0xE01D | 0xE014 | -| ArrowLeft | 0xE04B | 0xE06B | -| ArrowDown | 0xE050 | 0xE072 | -| ArrowRight | 0xE04D | 0xE074 | -| Numpad0 | 0x52 | 0x70 | -| NumpadPeriod | 0x53 | 0x71 | -| - | -- | -- | -| Oem9 | 0x7B | 0x67 | -| Oem10 | 0x79 | 0x64 | -| Oem11 | 0x70 | 0x13 | -| Oem12 | 0x73 | 0x51 | -| Oem13 | 0x7D | 0x6A | -| - | -- | -- | -| PrevTrack | 0xE010 | 0xE015 | -| NextTrack | 0xE019 | 0xE04D | -| Mute | 0xE020 | 0xE023 | -| Calculator | 0xE021 | 0xE02B | -| Play | 0xE022 | 0xE034 | -| Stop | 0xE024 | 0xE03B | -| VolumeDown | 0xE02E | 0xE021 | -| VolumeUp | 0xE030 | 0xE032 | -| WWWHome | 0xE032 | 0xE03A | -| TooManyKeys | -- | 0x00 | -| PowerOnTestOk | -- | 0xAA | -| RControl2 | 0xE11D | 0xE114 | -| RAlt2 | 0xE02A | 0xE012 | - -__Note 1:__ `PauseBreak` does not have a scancode because it's something we infer from a -sequence of other keypresses (`NumLock` with `RControl2` held). - -__Note 2:__ `SysReq` doesn't have a key on the diagram, because the scancode is -only generated when you do `Alt` + `PrintScreen`. +See for documentation, or read [`src/lib.rs`](./src/lib.rs). ## Minimum Supported Rust Version (MSRV) diff --git a/examples/print_keyboard.rs b/examples/print_keyboard.rs new file mode 100644 index 0000000..0bda4ac --- /dev/null +++ b/examples/print_keyboard.rs @@ -0,0 +1,506 @@ +//! Prints a keyboard as a Unicode graphic + +use std::collections::HashMap; + +use pc_keyboard::{DecodedKey, KeyCode, KeyboardLayout, Modifiers}; + +fn main() { + println!("Keyboard Layouts"); + println!("================"); + println!(); + println!("/// ****************************************"); + println!("/// # Azerty"); + println!("///"); + show_kb(&pc_keyboard::layouts::Azerty); + println!("/// ****************************************"); + println!("/// # Colemak"); + println!("///"); + show_kb(&pc_keyboard::layouts::Colemak); + println!("/// ****************************************"); + println!("/// # De105Key"); + println!("///"); + show_kb(&pc_keyboard::layouts::De105Key); + println!("/// ****************************************"); + println!("/// # Dvorak104Key"); + println!("///"); + show_kb(&pc_keyboard::layouts::Dvorak104Key); + println!("/// ****************************************"); + println!("/// # DVP104Key"); + println!("///"); + show_kb(&pc_keyboard::layouts::DVP104Key); + println!("/// ****************************************"); + println!("/// # FiSe105Key"); + println!("///"); + show_kb(&pc_keyboard::layouts::FiSe105Key); + println!("/// ****************************************"); + println!("/// # Jis109Key"); + println!("///"); + show_kb(&pc_keyboard::layouts::Jis109Key); + println!("/// ****************************************"); + println!("/// # No105Key"); + println!("///"); + show_kb(&pc_keyboard::layouts::No105Key); + println!("/// ****************************************"); + println!("/// # Uk105Key"); + println!("///"); + show_kb(&pc_keyboard::layouts::Uk105Key); + println!("/// ****************************************"); + println!("/// # Us104Key"); + println!("///"); + show_kb(&pc_keyboard::layouts::Us104Key); +} + +fn show_kb(layout: &dyn KeyboardLayout) { + let mut modifiers = Modifiers { + lshift: false, + rshift: false, + lctrl: false, + rctrl: false, + numlock: true, + capslock: false, + lalt: false, + ralt: false, + rctrl2: false, + }; + println!("/// ## Unmodified"); + show_kb_modifiers(layout, &modifiers); + + modifiers.capslock = true; + println!("/// ## Caps Lock"); + show_kb_modifiers(layout, &modifiers); + modifiers.capslock = false; + + modifiers.lshift = true; + println!("/// ## Shifted"); + show_kb_modifiers(layout, &modifiers); + modifiers.lshift = false; + + modifiers.rctrl = true; + println!("/// ## Control"); + show_kb_modifiers(layout, &modifiers); + modifiers.rctrl = false; + + modifiers.ralt = true; + println!("/// ## AltGr"); + show_kb_modifiers(layout, &modifiers); + modifiers.ralt = false; + + modifiers.ralt = true; + modifiers.lshift = true; + println!("/// ## Shift AltGr"); + show_kb_modifiers(layout, &modifiers); + modifiers.ralt = false; + modifiers.lshift = false; +} + +fn show_kb_modifiers(layout: &dyn KeyboardLayout, modifiers: &Modifiers) { + let mut map = Map::new(modifiers); + map.insert("esc", KeyCode::Escape, layout); + map.insert("key1", KeyCode::Key1, layout); + map.insert("key2", KeyCode::Key2, layout); + map.insert("key3", KeyCode::Key3, layout); + map.insert("key4", KeyCode::Key4, layout); + map.insert("key5", KeyCode::Key5, layout); + map.insert("key6", KeyCode::Key6, layout); + map.insert("key7", KeyCode::Key7, layout); + map.insert("key8", KeyCode::Key8, layout); + map.insert("key9", KeyCode::Key9, layout); + map.insert("key0", KeyCode::Key0, layout); + map.insert("oem_minus", KeyCode::OemMinus, layout); + map.insert("oem_plus", KeyCode::OemPlus, layout); + map.insert("backspace", KeyCode::Backspace, layout); + map.insert("numpad_divide", KeyCode::NumpadDivide, layout); + map.insert("numpad_multiply", KeyCode::NumpadMultiply, layout); + map.insert("numpad_subtract", KeyCode::NumpadSubtract, layout); + map.insert("tab", KeyCode::Tab, layout); + map.insert("oem4", KeyCode::Oem4, layout); + map.insert("oem6", KeyCode::Oem6, layout); + map.insert("oem7", KeyCode::Oem7, layout); + map.insert("delete", KeyCode::Delete, layout); + map.insert("numpad7", KeyCode::Numpad7, layout); + map.insert("numpad8", KeyCode::Numpad8, layout); + map.insert("numpad9", KeyCode::Numpad9, layout); + map.insert("numpadl", KeyCode::NumpadAdd, layout); + map.insert("oem1", KeyCode::Oem1, layout); + map.insert("oem3", KeyCode::Oem3, layout); + map.insert("enter", KeyCode::Return, layout); + map.insert("numpad4", KeyCode::Numpad4, layout); + map.insert("numpad5", KeyCode::Numpad5, layout); + map.insert("numpad6", KeyCode::Numpad6, layout); + map.insert("oem_comma", KeyCode::OemComma, layout); + map.insert("oem_period", KeyCode::OemPeriod, layout); + map.insert("oem2", KeyCode::Oem2, layout); + map.insert("numpad1", KeyCode::Numpad1, layout); + map.insert("numpad2", KeyCode::Numpad2, layout); + map.insert("numpad3", KeyCode::Numpad3, layout); + map.insert("numpade", KeyCode::NumpadEnter, layout); + map.insert("space", KeyCode::Spacebar, layout); + map.insert("numpad0", KeyCode::Numpad0, layout); + map.insert("numpad_period", KeyCode::NumpadPeriod, layout); + map.insert("q", KeyCode::Q, layout); + map.insert("w", KeyCode::W, layout); + map.insert("e", KeyCode::E, layout); + map.insert("r", KeyCode::R, layout); + map.insert("t", KeyCode::T, layout); + map.insert("y", KeyCode::Y, layout); + map.insert("u", KeyCode::U, layout); + map.insert("i", KeyCode::I, layout); + map.insert("o", KeyCode::O, layout); + map.insert("p", KeyCode::P, layout); + map.insert("a", KeyCode::A, layout); + map.insert("s", KeyCode::S, layout); + map.insert("d", KeyCode::D, layout); + map.insert("f", KeyCode::F, layout); + map.insert("g", KeyCode::G, layout); + map.insert("h", KeyCode::H, layout); + map.insert("j", KeyCode::J, layout); + map.insert("k", KeyCode::K, layout); + map.insert("l", KeyCode::L, layout); + map.insert("z", KeyCode::Z, layout); + map.insert("x", KeyCode::X, layout); + map.insert("c", KeyCode::C, layout); + map.insert("v", KeyCode::V, layout); + map.insert("b", KeyCode::B, layout); + map.insert("n", KeyCode::N, layout); + map.insert("m", KeyCode::M, layout); + match layout.get_physical() { + pc_keyboard::PhysicalKeyboard::Iso => { + map.insert("oem8", KeyCode::Oem8, layout); + map.insert("oem5", KeyCode::Oem5, layout); + map.print_iso(); + } + pc_keyboard::PhysicalKeyboard::Ansi => { + map.insert("oem8", KeyCode::Oem8, layout); + map.print_ansi(); + } + pc_keyboard::PhysicalKeyboard::Jis => { + map.insert("oem12", KeyCode::Oem12, layout); + map.insert("oem13", KeyCode::Oem13, layout); + map.print_jis(); + } + } +} + +struct Map { + inner: HashMap<&'static str, char>, + modifiers: Modifiers, +} + +impl Map { + fn new(modifiers: &Modifiers) -> Map { + Map { + inner: HashMap::new(), + modifiers: modifiers.clone(), + } + } + + fn insert(&mut self, label: &'static str, keycode: KeyCode, layout: &dyn KeyboardLayout) { + match layout.map_keycode( + keycode, + &self.modifiers, + pc_keyboard::HandleControl::MapLettersToUnicode, + ) { + DecodedKey::Unicode(c) => self.inner.insert(label, c), + e => { + panic!("Wanted unicode from {:?}, got {:?}!", keycode, e); + } + }; + } + + fn get(&self, label: &'static str) -> String { + let c = self.inner.get(label).unwrap(); + let c_value = *c as u32; + if c_value <= 32 || c_value == 0x7F { + format!("{:04x}", c_value) + } else { + format!("{:^4}", c) + } + } + + fn print_ansi(&self) { + let es = self.get("esc"); + let o8 = self.get("oem8"); + let k1 = self.get("key1"); + let k2 = self.get("key2"); + let k3 = self.get("key3"); + let k4 = self.get("key4"); + let k5 = self.get("key5"); + let k6 = self.get("key6"); + let k7 = self.get("key7"); + let k8 = self.get("key8"); + let k9 = self.get("key9"); + let k0 = self.get("key0"); + let om = self.get("oem_minus"); + let ol = self.get("oem_plus"); + let bs = self.get("backspace"); + let nd = self.get("numpad_divide"); + let nm = self.get("numpad_multiply"); + let ns = self.get("numpad_subtract"); + let tb = self.get("tab"); + let o4 = self.get("oem4"); + let o6 = self.get("oem6"); + let o7 = self.get("oem7"); + let de = self.get("delete"); + let n7 = self.get("numpad7"); + let n8 = self.get("numpad8"); + let n9 = self.get("numpad9"); + let nl = self.get("numpadl"); + let o1 = self.get("oem1"); + let o3 = self.get("oem3"); + let en = self.get("enter"); + let n4 = self.get("numpad4"); + let n5 = self.get("numpad5"); + let n6 = self.get("numpad6"); + let oc = self.get("oem_comma"); + let op = self.get("oem_period"); + let o2 = self.get("oem2"); + let n1 = self.get("numpad1"); + let n2 = self.get("numpad2"); + let n3 = self.get("numpad3"); + let ne = self.get("numpade"); + let sp = self.get("space"); + let n0 = self.get("numpad0"); + let np = self.get("numpad_period"); + + let kq = self.get("q"); + let kw = self.get("w"); + let ke = self.get("e"); + let kr = self.get("r"); + let kt = self.get("t"); + let ky = self.get("y"); + let ku = self.get("u"); + let ki = self.get("i"); + let ko = self.get("o"); + let kp = self.get("p"); + let ka = self.get("a"); + let ks = self.get("s"); + let kd = self.get("d"); + let kf = self.get("f"); + let kg = self.get("g"); + let kh = self.get("h"); + let kj = self.get("j"); + let kk = self.get("k"); + let kl = self.get("l"); + let kz = self.get("z"); + let kx = self.get("x"); + let kc = self.get("c"); + let kv = self.get("v"); + let kb = self.get("b"); + let kn = self.get("n"); + let km = self.get("m"); + + println!( + r#"/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │{es}│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │{o8}│{k1}│{k2}│{k3}│{k4}│{k5}│{k6}│{k7}│{k8}│{k9}│{k0}│{om}│{ol}│ {bs} │ │ │ │ │ │ │{nd}│{nm}│{ns}│ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │{tb} │{kq}│{kw}│{ke}│{kr}│{kt}│{ky}│{ku}│{ki}│{ko}│{kp}│{o4}│{o6}│ {o7} │ │{de}│ │ │ │{n7}│{n8}│{n9}│ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴────────┤ └────┴────┴────┘ ├────┼────┼────┤{nl}│ +/// │ │{ka}│{ks}│{kd}│{kf}│{kg}│{kh}│{kj}│{kk}│{kl}│{o1}│{o3}│ {en} │ │{n4}│{n5}│{n6}│ │ +/// ├──────┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────────────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │{kz}│{kx}│{kc}│{kv}│{kb}│{kn}│{km}│{oc}│{op}│{o2}│ │ │ │ │{n1}│{n2}│{n3}│ │ +/// ├─────┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤{ne}│ +/// │ │ │ │ {sp} │ │ │ │ │ │ │ │ │ │{n0} │{np}│ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +///"# + ); + } + + fn print_iso(&self) { + let es = self.get("esc"); + let o8 = self.get("oem8"); + let k1 = self.get("key1"); + let k2 = self.get("key2"); + let k3 = self.get("key3"); + let k4 = self.get("key4"); + let k5 = self.get("key5"); + let k6 = self.get("key6"); + let k7 = self.get("key7"); + let k8 = self.get("key8"); + let k9 = self.get("key9"); + let k0 = self.get("key0"); + let om = self.get("oem_minus"); + let ol = self.get("oem_plus"); + let bs = self.get("backspace"); + let nd = self.get("numpad_divide"); + let nm = self.get("numpad_multiply"); + let ns = self.get("numpad_subtract"); + let tb = self.get("tab"); + let o4 = self.get("oem4"); + let o6 = self.get("oem6"); + let o7 = self.get("oem7"); + let de = self.get("delete"); + let n7 = self.get("numpad7"); + let n8 = self.get("numpad8"); + let n9 = self.get("numpad9"); + let nl = self.get("numpadl"); + let o1 = self.get("oem1"); + let o3 = self.get("oem3"); + let en = self.get("enter"); + let n4 = self.get("numpad4"); + let n5 = self.get("numpad5"); + let n6 = self.get("numpad6"); + let oc = self.get("oem_comma"); + let op = self.get("oem_period"); + let o2 = self.get("oem2"); + let n1 = self.get("numpad1"); + let n2 = self.get("numpad2"); + let n3 = self.get("numpad3"); + let ne = self.get("numpade"); + let sp = self.get("space"); + let n0 = self.get("numpad0"); + let np = self.get("numpad_period"); + let o5 = self.get("oem5"); + + let kq = self.get("q"); + let kw = self.get("w"); + let ke = self.get("e"); + let kr = self.get("r"); + let kt = self.get("t"); + let ky = self.get("y"); + let ku = self.get("u"); + let ki = self.get("i"); + let ko = self.get("o"); + let kp = self.get("p"); + let ka = self.get("a"); + let ks = self.get("s"); + let kd = self.get("d"); + let kf = self.get("f"); + let kg = self.get("g"); + let kh = self.get("h"); + let kj = self.get("j"); + let kk = self.get("k"); + let kl = self.get("l"); + let kz = self.get("z"); + let kx = self.get("x"); + let kc = self.get("c"); + let kv = self.get("v"); + let kb = self.get("b"); + let kn = self.get("n"); + let km = self.get("m"); + + println!( + r#"/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │{es}│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │{o8}│{k1}│{k2}│{k3}│{k4}│{k5}│{k6}│{k7}│{k8}│{k9}│{k0}│{om}│{ol}│ {bs} │ │ │ │ │ │ │{nd}│{nm}│{ns}│ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │{tb} │{kq}│{kw}│{ke}│{kr}│{kt}│{ky}│{ku}│{ki}│{ko}│{kp}│{o4}│{o6}│ {en} │ │{de}│ │ │ │{n7}│{n8}│{n9}│ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐ │ └────┴────┴────┘ ├────┼────┼────┤{nl}│ +/// │ │{ka}│{ks}│{kd}│{kf}│{kg}│{kh}│{kj}│{kk}│{kl}│{o1}│{o3}│{o7}│ │ │{n4}│{n5}│{n6}│ │ +/// ├────┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┴───────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │{o5}│{kz}│{kx}│{kc}│{kv}│{kb}│{kn}│{km}│{oc}│{op}│{o2}│ │ │ │ │{n1}│{n2}│{n3}│ │ +/// ├────┴┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤{ne}│ +/// │ │ │ │ {sp} │ │ │ │ │ │ │ │ │ │{n0} │{np}│ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +///"# + ); + } + + fn print_jis(&self) { + let es = self.get("esc"); + let k1 = self.get("key1"); + let k2 = self.get("key2"); + let k3 = self.get("key3"); + let k4 = self.get("key4"); + let k5 = self.get("key5"); + let k6 = self.get("key6"); + let k7 = self.get("key7"); + let k8 = self.get("key8"); + let k9 = self.get("key9"); + let k0 = self.get("key0"); + let om = self.get("oem_minus"); + let ol = self.get("oem_plus"); + let bs = self.get("backspace"); + let nd = self.get("numpad_divide"); + let nm = self.get("numpad_multiply"); + let ns = self.get("numpad_subtract"); + let tb = self.get("tab"); + let o4 = self.get("oem4"); + let o6 = self.get("oem6"); + let o7 = self.get("oem7"); + let de = self.get("delete"); + let n7 = self.get("numpad7"); + let n8 = self.get("numpad8"); + let n9 = self.get("numpad9"); + let nl = self.get("numpadl"); + let o1 = self.get("oem1"); + let o3 = self.get("oem3"); + let en = self.get("enter"); + let n4 = self.get("numpad4"); + let n5 = self.get("numpad5"); + let n6 = self.get("numpad6"); + let oc = self.get("oem_comma"); + let op = self.get("oem_period"); + let o2 = self.get("oem2"); + let n1 = self.get("numpad1"); + let n2 = self.get("numpad2"); + let n3 = self.get("numpad3"); + let ne = self.get("numpade"); + let sp = self.get("space"); + let n0 = self.get("numpad0"); + let np = self.get("numpad_period"); + let od = self.get("oem12"); + let oe = self.get("oem13"); + + let kq = self.get("q"); + let kw = self.get("w"); + let ke = self.get("e"); + let kr = self.get("r"); + let kt = self.get("t"); + let ky = self.get("y"); + let ku = self.get("u"); + let ki = self.get("i"); + let ko = self.get("o"); + let kp = self.get("p"); + let ka = self.get("a"); + let ks = self.get("s"); + let kd = self.get("d"); + let kf = self.get("f"); + let kg = self.get("g"); + let kh = self.get("h"); + let kj = self.get("j"); + let kk = self.get("k"); + let kl = self.get("l"); + let kz = self.get("z"); + let kx = self.get("x"); + let kc = self.get("c"); + let kv = self.get("v"); + let kb = self.get("b"); + let kn = self.get("n"); + let km = self.get("m"); + + println!( + r#"/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │{es}│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ │{k1}│{k2}│{k3}│{k4}│{k5}│{k6}│{k7}│{k8}│{k9}│{k0}│{om}│{ol}│{oe}│{bs}│ │ │ │ │ │ │{nd}│{nm}│{ns}│ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │{tb} │{kq}│{kw}│{ke}│{kr}│{kt}│{ky}│{ku}│{ki}│{ko}│{kp}│{o4}│{o6}│ {en} │ │{de}│ │ │ │{n7}│{n8}│{n9}│ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐ │ └────┴────┴────┘ ├────┼────┼────┤{nl}│ +/// │ │{ka}│{ks}│{kd}│{kf}│{kg}│{kh}│{kj}│{kk}│{kl}│{o1}│{o3}│{o7}│ │ │{n4}│{n5}│{n6}│ │ +/// ├──────┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┼───────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │{kz}│{kx}│{kc}│{kv}│{kb}│{kn}│{km}│{oc}│{op}│{o2}│{od} │ │ │ │ │{n1}│{n2}│{n3}│ │ +/// ├─────┬───┴─┬──┴──┬─┴───┬┴────┴────┴────┴────┴┬───┴─┬──┴──┬─┴──┬───┴┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤{ne}│ +/// │ │ │ │ │ {sp} │ │ │ │ │ │ │ │ │ │ │{n0} │{np}│ │ +/// └─────┴─────┴─────┴─────┴─────────────────────┴─────┴─────┴────┴────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +///"# + ); + } +} diff --git a/src/layouts/azerty.rs b/src/layouts/azerty.rs index 9c721c7..35fc007 100644 --- a/src/layouts/azerty.rs +++ b/src/layouts/azerty.rs @@ -1,519 +1,193 @@ //! French keyboard support -use crate::{DecodedKey, HandleControl, KeyCode, KeyboardLayout, Modifiers}; +use crate::{ + DecodedKey, HandleControl, KeyCode, KeyboardLayout, Modifiers, PhysicalKeyboard, QUO, SLS, +}; /// A standard French 102-key (or 105-key including Windows keys) keyboard. /// -/// The top row spells `AZERTY`. -/// -/// Has a 2-row high Enter key, with Oem5 next to the left shift (ISO format). +/// The top row spells `AZERTY`. Has a 2-row high Enter key, with Oem5 next to +/// the left shift (ISO format). /// /// NB: no "dead key" support for now +/// +/// These diagrams illustrate the conversion from [`KeyCode`] to Unicode. We +/// show either a Unicode glyph, or a hex number if the glyph isn't a +/// printable character. Blank spaces are passed through as +/// [`DecodedKey::RawKey`]. +/// +/// Run the `print_keyboard` example to re-generate these images. +/// +/// ## Unmodified +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ ² │ & │ é │ " │ ' │ ( │ - │ è │ _ │ ç │ à │ ) │ = │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ a │ z │ e │ r │ t │ y │ u │ i │ o │ p │ ^ │ $ │ 000a │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐ │ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │ q │ s │ d │ f │ g │ h │ j │ k │ l │ m │ ù │ * │ │ │ 4 │ 5 │ 6 │ │ +/// ├────┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┴───────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ < │ w │ x │ c │ v │ b │ n │ , │ ; │ : │ ! │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├────┴┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ . │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +/// +/// ## Caps Lock +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ ² │ & │ é │ " │ ' │ ( │ - │ è │ _ │ ç │ à │ ) │ = │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ A │ Z │ E │ R │ T │ Y │ U │ I │ O │ P │ ^ │ $ │ 000a │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐ │ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │ Q │ S │ D │ F │ G │ H │ J │ K │ L │ M │ ù │ * │ │ │ 4 │ 5 │ 6 │ │ +/// ├────┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┴───────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ < │ W │ X │ C │ V │ B │ N │ , │ ; │ : │ ! │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├────┴┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ . │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +/// +/// ## Shifted +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ ² │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ ° │ + │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ A │ Z │ E │ R │ T │ Y │ U │ I │ O │ P │ ¨ │ £ │ 000a │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐ │ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │ Q │ S │ D │ F │ G │ H │ J │ K │ L │ M │ % │ µ │ │ │ 4 │ 5 │ 6 │ │ +/// ├────┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┴───────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ > │ W │ X │ C │ V │ B │ N │ ? │ . │ / │ § │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├────┴┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ . │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +/// +/// ## Control +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ ² │ & │ é │ " │ ' │ ( │ - │ è │ _ │ ç │ à │ ) │ = │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │0001│001a│0005│0012│0014│0019│0015│0009│000f│0010│ ^ │ $ │ 000a │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐ │ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │0011│0013│0004│0006│0007│0008│000a│000b│000c│000d│ ù │ * │ │ │ 4 │ 5 │ 6 │ │ +/// ├────┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┴───────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ < │0017│0018│0003│0016│0002│000e│ , │ ; │ : │ ! │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├────┴┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ . │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +/// +/// ## AltGr +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ ² │ & │ ~ │ # │ { │ [ │ | │ ` │ \ │ ^ │ @ │ ] │ } │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ a │ z │ € │ r │ t │ y │ u │ i │ o │ p │ ^ │ ¤ │ 000a │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐ │ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │ q │ s │ d │ f │ g │ h │ j │ k │ l │ m │ ù │ * │ │ │ 4 │ 5 │ 6 │ │ +/// ├────┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┴───────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ < │ w │ x │ c │ v │ b │ n │ , │ ; │ : │ ! │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├────┴┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ . │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +/// +/// ## Shift AltGr +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ ² │ 1 │ ~ │ # │ { │ [ │ | │ ` │ \ │ ^ │ @ │ ] │ } │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ A │ Z │ € │ R │ T │ Y │ U │ I │ O │ P │ ¨ │ ¤ │ 000a │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐ │ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │ Q │ S │ D │ F │ G │ H │ J │ K │ L │ M │ % │ µ │ │ │ 4 │ 5 │ 6 │ │ +/// ├────┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┴───────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ > │ W │ X │ C │ V │ B │ N │ ? │ . │ / │ § │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├────┴┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ . │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` pub struct Azerty; impl KeyboardLayout for Azerty { + #[rustfmt::skip] fn map_keycode( &self, keycode: KeyCode, modifiers: &Modifiers, handle_ctrl: HandleControl, ) -> DecodedKey { - let map_to_unicode = handle_ctrl == HandleControl::MapLettersToUnicode; match keycode { - KeyCode::Escape => DecodedKey::Unicode(0x1B.into()), - KeyCode::Oem8 => DecodedKey::Unicode('²'), - KeyCode::Oem5 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('>') - } else { - DecodedKey::Unicode('<') - } - } - KeyCode::Key1 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('1') - } else { - DecodedKey::Unicode('&') - } - } - KeyCode::Key2 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('2') - } else if modifiers.is_altgr() { - DecodedKey::Unicode('~') - } else { - DecodedKey::Unicode('é') - } - } - KeyCode::Key3 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('3') - } else if modifiers.is_altgr() { - DecodedKey::Unicode('#') - } else { - DecodedKey::Unicode('"') - } - } - KeyCode::Key4 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('4') - } else if modifiers.is_altgr() { - DecodedKey::Unicode('{') - } else { - DecodedKey::Unicode('\'') - } - } - KeyCode::Key5 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('5') - } else if modifiers.is_altgr() { - DecodedKey::Unicode('[') - } else { - DecodedKey::Unicode('(') - } - } - KeyCode::Key6 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('6') - } else if modifiers.is_altgr() { - DecodedKey::Unicode('|') - } else { - DecodedKey::Unicode('-') - } - } - KeyCode::Key7 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('7') - } else if modifiers.is_altgr() { - DecodedKey::Unicode('`') - } else { - DecodedKey::Unicode('è') - } - } - KeyCode::Key8 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('8') - } else if modifiers.is_altgr() { - DecodedKey::Unicode('\\') - } else { - DecodedKey::Unicode('_') - } - } - KeyCode::Key9 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('9') - } else if modifiers.is_altgr() { - DecodedKey::Unicode('^') - } else { - DecodedKey::Unicode('ç') - } - } - KeyCode::Key0 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('0') - } else if modifiers.is_altgr() { - DecodedKey::Unicode('@') - } else { - DecodedKey::Unicode('à') - } - } - KeyCode::OemMinus => { - if modifiers.is_shifted() { - DecodedKey::Unicode('°') - } else if modifiers.is_altgr() { - DecodedKey::Unicode(']') - } else { - DecodedKey::Unicode(')') - } - } - KeyCode::OemPlus => { - if modifiers.is_shifted() { - DecodedKey::Unicode('+') - } else if modifiers.is_altgr() { - DecodedKey::Unicode('}') - } else { - DecodedKey::Unicode('=') - } - } - KeyCode::Backspace => DecodedKey::Unicode(0x08.into()), - KeyCode::Tab => DecodedKey::Unicode(0x09.into()), - KeyCode::Q => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0001}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('A') - } else { - DecodedKey::Unicode('a') - } - } - KeyCode::W => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{001A}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('Z') - } else { - DecodedKey::Unicode('z') - } - } - KeyCode::E => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0005}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('E') - } else { - DecodedKey::Unicode('e') - } - } - KeyCode::R => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0012}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('R') - } else { - DecodedKey::Unicode('r') - } - } - KeyCode::T => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0014}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('T') - } else { - DecodedKey::Unicode('t') - } - } - KeyCode::Y => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0019}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('Y') - } else { - DecodedKey::Unicode('y') - } - } - KeyCode::U => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0015}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('U') - } else { - DecodedKey::Unicode('u') - } - } - KeyCode::I => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0009}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('I') - } else { - DecodedKey::Unicode('i') - } - } - KeyCode::O => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{000F}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('O') - } else { - DecodedKey::Unicode('o') - } - } - KeyCode::P => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0010}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('P') - } else { - DecodedKey::Unicode('p') - } - } - KeyCode::Oem4 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('¨') - } else if modifiers.is_altgr() { - DecodedKey::Unicode('ˇ') - } else { - DecodedKey::Unicode('^') - } - } - KeyCode::Oem6 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('£') - } else if modifiers.is_altgr() { - DecodedKey::Unicode('¤') - } else { - DecodedKey::Unicode('$') - } - } - KeyCode::Oem7 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('µ') - } else { - DecodedKey::Unicode('*') - } - } - KeyCode::A => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0011}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('Q') - } else { - DecodedKey::Unicode('q') - } - } - KeyCode::S => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0013}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('S') - } else { - DecodedKey::Unicode('s') - } - } - KeyCode::D => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0004}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('D') - } else { - DecodedKey::Unicode('d') - } - } - KeyCode::F => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0006}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('F') - } else { - DecodedKey::Unicode('f') - } - } - KeyCode::G => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0007}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('G') - } else { - DecodedKey::Unicode('g') - } - } - KeyCode::H => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0008}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('H') - } else { - DecodedKey::Unicode('h') - } - } - KeyCode::J => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{000A}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('J') - } else { - DecodedKey::Unicode('j') - } - } - KeyCode::K => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{000B}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('K') - } else { - DecodedKey::Unicode('k') - } - } - KeyCode::L => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{000C}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('L') - } else { - DecodedKey::Unicode('l') - } - } - KeyCode::Oem1 => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{000D}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('M') - } else { - DecodedKey::Unicode('m') - } - } - KeyCode::Oem3 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('%') - } else { - DecodedKey::Unicode('ù') - } - } - // Enter gives LF, not CRLF or CR - KeyCode::Return => DecodedKey::Unicode(10.into()), - KeyCode::Z => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0017}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('W') - } else { - DecodedKey::Unicode('w') - } - } - KeyCode::X => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0018}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('X') - } else { - DecodedKey::Unicode('x') - } - } - KeyCode::C => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0003}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('C') - } else { - DecodedKey::Unicode('c') - } - } - KeyCode::V => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0016}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('V') - } else { - DecodedKey::Unicode('v') - } - } - KeyCode::B => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0002}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('B') - } else { - DecodedKey::Unicode('b') - } - } - KeyCode::N => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{000E}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('N') - } else { - DecodedKey::Unicode('n') - } - } - KeyCode::M => { - if modifiers.is_caps() { - DecodedKey::Unicode('?') - } else { - DecodedKey::Unicode(',') - } - } - KeyCode::OemComma => { - if modifiers.is_shifted() { - DecodedKey::Unicode('.') - } else { - DecodedKey::Unicode(';') - } - } - KeyCode::OemPeriod => { - if modifiers.is_shifted() { - DecodedKey::Unicode('/') - } else { - DecodedKey::Unicode(':') - } - } - KeyCode::Oem2 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('§') - } else { - DecodedKey::Unicode('!') - } - } - KeyCode::Spacebar => DecodedKey::Unicode(' '), - KeyCode::Delete => DecodedKey::Unicode(127.into()), - KeyCode::NumpadDivide => DecodedKey::Unicode('/'), - KeyCode::NumpadMultiply => DecodedKey::Unicode('*'), - KeyCode::NumpadSubtract => DecodedKey::Unicode('-'), - KeyCode::Numpad7 => { - if modifiers.numlock { - DecodedKey::Unicode('7') - } else { - DecodedKey::RawKey(KeyCode::Home) - } - } - KeyCode::Numpad8 => { - if modifiers.numlock { - DecodedKey::Unicode('8') - } else { - DecodedKey::RawKey(KeyCode::ArrowUp) - } - } - KeyCode::Numpad9 => { - if modifiers.numlock { - DecodedKey::Unicode('9') - } else { - DecodedKey::RawKey(KeyCode::PageUp) - } - } - KeyCode::NumpadAdd => DecodedKey::Unicode('+'), - KeyCode::Numpad4 => { - if modifiers.numlock { - DecodedKey::Unicode('4') - } else { - DecodedKey::RawKey(KeyCode::ArrowLeft) - } - } - KeyCode::Numpad5 => DecodedKey::Unicode('5'), - KeyCode::Numpad6 => { - if modifiers.numlock { - DecodedKey::Unicode('6') - } else { - DecodedKey::RawKey(KeyCode::ArrowRight) - } - } - KeyCode::Numpad1 => { - if modifiers.numlock { - DecodedKey::Unicode('1') - } else { - DecodedKey::RawKey(KeyCode::End) - } - } - KeyCode::Numpad2 => { - if modifiers.numlock { - DecodedKey::Unicode('2') - } else { - DecodedKey::RawKey(KeyCode::ArrowDown) - } - } - KeyCode::Numpad3 => { - if modifiers.numlock { - DecodedKey::Unicode('3') - } else { - DecodedKey::RawKey(KeyCode::PageDown) - } - } - KeyCode::Numpad0 => { - if modifiers.numlock { - DecodedKey::Unicode('0') - } else { - DecodedKey::RawKey(KeyCode::Insert) - } - } - KeyCode::NumpadPeriod => { - if modifiers.numlock { - DecodedKey::Unicode('.') - } else { - DecodedKey::Unicode(127.into()) - } - } - KeyCode::NumpadEnter => DecodedKey::Unicode(10.into()), - k => DecodedKey::RawKey(k), + // ========= Row 2 (the numbers) ========= + KeyCode::Oem8 => DecodedKey::Unicode('²'), + KeyCode::Key1 => modifiers.handle_symbol2('&', '1'), + KeyCode::Key2 => modifiers.handle_symbol3('é', '2', '~'), + KeyCode::Key3 => modifiers.handle_symbol3('"', '3', '#'), + KeyCode::Key4 => modifiers.handle_symbol3(QUO, '4', '{'), + KeyCode::Key5 => modifiers.handle_symbol3('(', '5', '['), + KeyCode::Key6 => modifiers.handle_symbol3('-', '6', '|'), + KeyCode::Key7 => modifiers.handle_symbol3('è', '7', '`'), + KeyCode::Key8 => modifiers.handle_symbol3('_', '8', SLS), + KeyCode::Key9 => modifiers.handle_symbol3('ç', '9', '^'), + KeyCode::Key0 => modifiers.handle_symbol3('à', '0', '@'), + KeyCode::OemMinus => modifiers.handle_symbol3(')', '°', ']'), + KeyCode::OemPlus => modifiers.handle_symbol3('=', '+', '}'), + // ========= Row 3 (QWERTY) ========= + KeyCode::Q => modifiers.handle_ascii_2('A', handle_ctrl), + KeyCode::W => modifiers.handle_ascii_2('Z', handle_ctrl), + KeyCode::E => modifiers.handle_ascii_3('E', '€', handle_ctrl), + KeyCode::Oem4 => modifiers.handle_symbol2('^', '¨'), + KeyCode::Oem6 => modifiers.handle_symbol3('$', '£', '¤'), + // ========= Row 4 (ASDFG) ========= + KeyCode::A => modifiers.handle_ascii_2('Q', handle_ctrl), + KeyCode::Oem1 => modifiers.handle_ascii_2('M', handle_ctrl), + KeyCode::Oem3 => modifiers.handle_symbol2('ù', '%'), + KeyCode::Oem7 => modifiers.handle_symbol2('*', 'µ'), + // ========= Row 5 (ZXCVB) ========= + KeyCode::Oem5 => modifiers.handle_symbol2('<', '>'), + KeyCode::Z => modifiers.handle_ascii_2('W', handle_ctrl), + KeyCode::M => modifiers.handle_symbol2(',', '?'), + KeyCode::OemComma => modifiers.handle_symbol2(';', '.'), + KeyCode::OemPeriod => modifiers.handle_symbol2(':', '/'), + KeyCode::Oem2 => modifiers.handle_symbol2('!', '§'), + // ========= Fallback ========= + e => super::Us104Key.map_keycode(e, modifiers, handle_ctrl), } } + + fn get_physical(&self) -> PhysicalKeyboard { + PhysicalKeyboard::Iso + } } #[cfg(test)] diff --git a/src/layouts/colemak.rs b/src/layouts/colemak.rs index 1114946..b1b6bc4 100644 --- a/src/layouts/colemak.rs +++ b/src/layouts/colemak.rs @@ -1,486 +1,176 @@ -//! The Colemak keyboard support +//! Colemak keyboard support -use crate::{DecodedKey, HandleControl, KeyCode, KeyboardLayout, Modifiers}; +use crate::{DecodedKey, HandleControl, KeyCode, KeyboardLayout, Modifiers, PhysicalKeyboard}; /// A Colemak 101-key (or 104-key including Windows keys) keyboard. /// /// Has a 1-row high Enter key, with Oem5 above (ANSI layout). +/// +/// Based on US 101/104 key, with the letters re-arranged. +/// +/// These diagrams illustrate the conversion from [`KeyCode`] to Unicode. We +/// show either a Unicode glyph, or a hex number if the glyph isn't a +/// printable character. Blank spaces are passed through as +/// [`DecodedKey::RawKey`]. +/// +/// Run the `print_keyboard` example to re-generate these images. +/// +/// ## Unmodified +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ ` │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ - │ = │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ q │ w │ f │ p │ g │ j │ l │ u │ y │ ; │ [ │ ] │ \ │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴────────┤ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │ a │ r │ s │ t │ d │ h │ n │ e │ i │ o │ ' │ 000a │ │ 4 │ 5 │ 6 │ │ +/// ├──────┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────────────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ z │ x │ c │ v │ b │ k │ m │ , │ . │ / │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├─────┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ . │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +/// +/// ## Caps Lock +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ ` │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ - │ = │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ Q │ W │ F │ P │ G │ J │ L │ U │ Y │ ; │ [ │ ] │ \ │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴────────┤ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │ A │ R │ S │ T │ D │ H │ N │ E │ I │ O │ ' │ 000a │ │ 4 │ 5 │ 6 │ │ +/// ├──────┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────────────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ Z │ X │ C │ V │ B │ K │ M │ , │ . │ / │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├─────┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ . │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +/// +/// ## Shifted +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ ~ │ ! │ @ │ # │ $ │ % │ ^ │ & │ * │ ( │ ) │ _ │ + │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ Q │ W │ F │ P │ G │ J │ L │ U │ Y │ : │ { │ } │ | │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴────────┤ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │ A │ R │ S │ T │ D │ H │ N │ E │ I │ O │ " │ 000a │ │ 4 │ 5 │ 6 │ │ +/// ├──────┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────────────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ Z │ X │ C │ V │ B │ K │ M │ < │ > │ ? │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├─────┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ . │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +/// +/// ## Control +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ ` │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ - │ = │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │0011│0017│0006│0010│0007│000a│000c│0015│0019│ ; │ [ │ ] │ \ │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴────────┤ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │0001│0012│0013│0014│0004│0008│000e│0005│0009│000f│ ' │ 000a │ │ 4 │ 5 │ 6 │ │ +/// ├──────┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────────────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │001a│0018│0003│0016│0002│000b│000d│ , │ . │ / │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├─────┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ . │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +/// +/// ## AltGr +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ ` │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ - │ = │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ q │ w │ f │ p │ g │ j │ l │ u │ y │ ; │ [ │ ] │ \ │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴────────┤ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │ a │ r │ s │ t │ d │ h │ n │ e │ i │ o │ ' │ 000a │ │ 4 │ 5 │ 6 │ │ +/// ├──────┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────────────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ z │ x │ c │ v │ b │ k │ m │ , │ . │ / │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├─────┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ . │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +/// +/// ## Shift AltGr +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ ~ │ ! │ @ │ # │ $ │ % │ ^ │ & │ * │ ( │ ) │ _ │ + │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ Q │ W │ F │ P │ G │ J │ L │ U │ Y │ : │ { │ } │ | │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴────────┤ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │ A │ R │ S │ T │ D │ H │ N │ E │ I │ O │ " │ 000a │ │ 4 │ 5 │ 6 │ │ +/// ├──────┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────────────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ Z │ X │ C │ V │ B │ K │ M │ < │ > │ ? │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├─────┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ . │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` pub struct Colemak; impl KeyboardLayout for Colemak { + #[rustfmt::skip] fn map_keycode( &self, keycode: KeyCode, modifiers: &Modifiers, handle_ctrl: HandleControl, ) -> DecodedKey { - let map_to_unicode = handle_ctrl == HandleControl::MapLettersToUnicode; match keycode { - KeyCode::Oem8 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('~') - } else { - DecodedKey::Unicode('`') - } - } - KeyCode::Escape => DecodedKey::Unicode(0x1B.into()), - KeyCode::Key1 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('!') - } else { - DecodedKey::Unicode('1') - } - } - KeyCode::Key2 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('@') - } else { - DecodedKey::Unicode('2') - } - } - KeyCode::Key3 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('#') - } else { - DecodedKey::Unicode('3') - } - } - KeyCode::Key4 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('$') - } else { - DecodedKey::Unicode('4') - } - } - KeyCode::Key5 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('%') - } else { - DecodedKey::Unicode('5') - } - } - KeyCode::Key6 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('^') - } else { - DecodedKey::Unicode('6') - } - } - KeyCode::Key7 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('&') - } else { - DecodedKey::Unicode('7') - } - } - KeyCode::Key8 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('*') - } else { - DecodedKey::Unicode('8') - } - } - KeyCode::Key9 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('(') - } else { - DecodedKey::Unicode('9') - } - } - KeyCode::Key0 => { - if modifiers.is_shifted() { - DecodedKey::Unicode(')') - } else { - DecodedKey::Unicode('0') - } - } - KeyCode::OemMinus => { - if modifiers.is_shifted() { - DecodedKey::Unicode('_') - } else { - DecodedKey::Unicode('-') - } - } - KeyCode::OemPlus => { - if modifiers.is_shifted() { - DecodedKey::Unicode('+') - } else { - DecodedKey::Unicode('=') - } - } - KeyCode::Backspace => DecodedKey::Unicode(0x08.into()), - KeyCode::Tab => DecodedKey::Unicode(0x09.into()), - KeyCode::Q => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0011}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('Q') - } else { - DecodedKey::Unicode('q') - } - } - KeyCode::W => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0017}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('W') - } else { - DecodedKey::Unicode('w') - } - } - KeyCode::E => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0006}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('F') - } else { - DecodedKey::Unicode('f') - } - } - KeyCode::R => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0010}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('P') - } else { - DecodedKey::Unicode('p') - } - } - KeyCode::T => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0007}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('G') - } else { - DecodedKey::Unicode('g') - } - } - KeyCode::Y => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{000A}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('J') - } else { - DecodedKey::Unicode('j') - } - } - KeyCode::U => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{000C}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('L') - } else { - DecodedKey::Unicode('l') - } - } - KeyCode::I => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0015}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('U') - } else { - DecodedKey::Unicode('u') - } - } - KeyCode::O => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0019}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('Y') - } else { - DecodedKey::Unicode('y') - } - } - KeyCode::P => { - if modifiers.is_caps() { - DecodedKey::Unicode(':') - } else { - DecodedKey::Unicode(';') - } - } - KeyCode::Oem4 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('{') - } else { - DecodedKey::Unicode('[') - } - } - KeyCode::Oem6 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('}') - } else { - DecodedKey::Unicode(']') - } - } - KeyCode::Oem7 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('|') - } else { - DecodedKey::Unicode('\\') - } - } - KeyCode::A => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0001}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('A') - } else { - DecodedKey::Unicode('a') - } - } - KeyCode::S => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0012}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('R') - } else { - DecodedKey::Unicode('r') - } - } - KeyCode::D => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0013}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('S') - } else { - DecodedKey::Unicode('s') - } - } - KeyCode::F => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0014}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('T') - } else { - DecodedKey::Unicode('t') - } - } - KeyCode::G => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0004}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('D') - } else { - DecodedKey::Unicode('d') - } - } - KeyCode::H => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0008}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('H') - } else { - DecodedKey::Unicode('h') - } - } - KeyCode::J => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{000E}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('N') - } else { - DecodedKey::Unicode('n') - } - } - KeyCode::K => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0005}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('E') - } else { - DecodedKey::Unicode('e') - } - } - KeyCode::L => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0009}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('I') - } else { - DecodedKey::Unicode('i') - } - } - KeyCode::Oem1 => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{000F}') - } else if modifiers.is_shifted() { - DecodedKey::Unicode('O') - } else { - DecodedKey::Unicode('o') - } - } - KeyCode::Oem3 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('"') - } else { - DecodedKey::Unicode('\'') - } - } - // Enter gives LF, not CRLF or CR - KeyCode::Return => DecodedKey::Unicode(10.into()), - KeyCode::Z => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{001A}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('Z') - } else { - DecodedKey::Unicode('z') - } - } - KeyCode::X => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0018}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('X') - } else { - DecodedKey::Unicode('x') - } - } - KeyCode::C => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0003}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('C') - } else { - DecodedKey::Unicode('c') - } - } - KeyCode::V => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0016}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('V') - } else { - DecodedKey::Unicode('v') - } - } - KeyCode::B => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0002}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('B') - } else { - DecodedKey::Unicode('b') - } - } - KeyCode::N => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{000B}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('K') - } else { - DecodedKey::Unicode('k') - } - } - KeyCode::M => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{000D}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('M') - } else { - DecodedKey::Unicode('m') - } - } - KeyCode::OemComma => { - if modifiers.is_shifted() { - DecodedKey::Unicode('<') - } else { - DecodedKey::Unicode(',') - } - } - KeyCode::OemPeriod => { - if modifiers.is_shifted() { - DecodedKey::Unicode('>') - } else { - DecodedKey::Unicode('.') - } - } - KeyCode::Oem2 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('?') - } else { - DecodedKey::Unicode('/') - } - } - KeyCode::Spacebar => DecodedKey::Unicode(' '), - KeyCode::Delete => DecodedKey::Unicode(127.into()), - KeyCode::NumpadDivide => DecodedKey::Unicode('/'), - KeyCode::NumpadMultiply => DecodedKey::Unicode('*'), - KeyCode::NumpadSubtract => DecodedKey::Unicode('-'), - KeyCode::Numpad7 => { - if modifiers.numlock { - DecodedKey::Unicode('7') - } else { - DecodedKey::RawKey(KeyCode::Home) - } - } - KeyCode::Numpad8 => { - if modifiers.numlock { - DecodedKey::Unicode('8') - } else { - DecodedKey::RawKey(KeyCode::ArrowUp) - } - } - KeyCode::Numpad9 => { - if modifiers.numlock { - DecodedKey::Unicode('9') - } else { - DecodedKey::RawKey(KeyCode::PageUp) - } - } - KeyCode::NumpadAdd => DecodedKey::Unicode('+'), - KeyCode::Numpad4 => { - if modifiers.numlock { - DecodedKey::Unicode('4') - } else { - DecodedKey::RawKey(KeyCode::ArrowLeft) - } - } - KeyCode::Numpad5 => DecodedKey::Unicode('5'), - KeyCode::Numpad6 => { - if modifiers.numlock { - DecodedKey::Unicode('6') - } else { - DecodedKey::RawKey(KeyCode::ArrowRight) - } - } - KeyCode::Numpad1 => { - if modifiers.numlock { - DecodedKey::Unicode('1') - } else { - DecodedKey::RawKey(KeyCode::End) - } - } - KeyCode::Numpad2 => { - if modifiers.numlock { - DecodedKey::Unicode('2') - } else { - DecodedKey::RawKey(KeyCode::ArrowDown) - } - } - KeyCode::Numpad3 => { - if modifiers.numlock { - DecodedKey::Unicode('3') - } else { - DecodedKey::RawKey(KeyCode::PageDown) - } - } - KeyCode::Numpad0 => { - if modifiers.numlock { - DecodedKey::Unicode('0') - } else { - DecodedKey::RawKey(KeyCode::Insert) - } - } - KeyCode::NumpadPeriod => { - if modifiers.numlock { - DecodedKey::Unicode('.') - } else { - DecodedKey::Unicode(127.into()) - } - } - KeyCode::NumpadEnter => DecodedKey::Unicode(10.into()), - k => DecodedKey::RawKey(k), + // ========= Row 3 (QWERTY) ========= + KeyCode::E => modifiers.handle_ascii_2('F', handle_ctrl), + KeyCode::R => modifiers.handle_ascii_2('P', handle_ctrl), + KeyCode::T => modifiers.handle_ascii_2('G', handle_ctrl), + KeyCode::Y => modifiers.handle_ascii_2('J', handle_ctrl), + KeyCode::U => modifiers.handle_ascii_2('L', handle_ctrl), + KeyCode::I => modifiers.handle_ascii_2('U', handle_ctrl), + KeyCode::O => modifiers.handle_ascii_2('Y', handle_ctrl), + KeyCode::P => modifiers.handle_symbol2(';', ':'), + // ========= Row 4 (ASDFG) ========= + KeyCode::S => modifiers.handle_ascii_2('R', handle_ctrl), + KeyCode::D => modifiers.handle_ascii_2('S', handle_ctrl), + KeyCode::F => modifiers.handle_ascii_2('T', handle_ctrl), + KeyCode::G => modifiers.handle_ascii_2('D', handle_ctrl), + KeyCode::J => modifiers.handle_ascii_2('N', handle_ctrl), + KeyCode::K => modifiers.handle_ascii_2('E', handle_ctrl), + KeyCode::L => modifiers.handle_ascii_2('I', handle_ctrl), + KeyCode::Oem1 => modifiers.handle_ascii_2('O', handle_ctrl), + // ========= Row 5 (ZXCVB) ========= + KeyCode::N => modifiers.handle_ascii_2('K', handle_ctrl), + // ========= Fallback ========= + e => super::Us104Key.map_keycode(e, modifiers, handle_ctrl), } } + + fn get_physical(&self) -> PhysicalKeyboard { + PhysicalKeyboard::Ansi + } } diff --git a/src/layouts/de105.rs b/src/layouts/de105.rs index 96e57e7..c74cdda 100644 --- a/src/layouts/de105.rs +++ b/src/layouts/de105.rs @@ -1,254 +1,186 @@ //! German keyboard support -use crate::{DecodedKey, HandleControl, KeyCode, KeyboardLayout, Modifiers}; +use crate::{ + DecodedKey, HandleControl, KeyCode, KeyboardLayout, Modifiers, PhysicalKeyboard, QUO, SLS, +}; /// A standard German 102-key (or 105-key including Windows keys) keyboard. /// /// The top row spells `QWERTZ`. /// /// Has a 2-row high Enter key, with Oem5 next to the left shift (ISO format). +/// +/// These diagrams illustrate the conversion from [`KeyCode`] to Unicode. We +/// show either a Unicode glyph, or a hex number if the glyph isn't a +/// printable character. Blank spaces are passed through as +/// [`DecodedKey::RawKey`]. +/// +/// Run the `print_keyboard` example to re-generate these images. +/// +/// ## Unmodified +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ ^ │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ ß │ ´ │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ q │ w │ e │ r │ t │ z │ u │ i │ o │ p │ ü │ + │ 000a │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐ │ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │ a │ s │ d │ f │ g │ h │ j │ k │ l │ ö │ ä │ # │ │ │ 4 │ 5 │ 6 │ │ +/// ├────┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┴───────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ < │ y │ x │ c │ v │ b │ n │ m │ , │ . │ - │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├────┴┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ . │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +/// +/// ## Caps Lock +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ ^ │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ ß │ ´ │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ Q │ W │ E │ R │ T │ Z │ U │ I │ O │ P │ Ü │ + │ 000a │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐ │ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │ A │ S │ D │ F │ G │ H │ J │ K │ L │ Ö │ Ä │ # │ │ │ 4 │ 5 │ 6 │ │ +/// ├────┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┴───────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ < │ Y │ X │ C │ V │ B │ N │ M │ , │ . │ - │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├────┴┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ . │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +/// +/// ## Shifted +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ ° │ ! │ " │ § │ $ │ % │ & │ / │ ( │ ) │ = │ ? │ ` │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ Q │ W │ E │ R │ T │ Z │ U │ I │ O │ P │ Ü │ * │ 000a │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐ │ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │ A │ S │ D │ F │ G │ H │ J │ K │ L │ Ö │ Ä │ ' │ │ │ 4 │ 5 │ 6 │ │ +/// ├────┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┴───────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ > │ Y │ X │ C │ V │ B │ N │ M │ ; │ : │ _ │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├────┴┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ . │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +/// +/// ## Control +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ ^ │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ ß │ ´ │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │0011│0017│0005│0012│0014│001a│0015│0009│000f│0010│ ü │ + │ 000a │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐ │ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │0001│0013│0004│0006│0007│0008│000a│000b│000c│ ö │ ä │ # │ │ │ 4 │ 5 │ 6 │ │ +/// ├────┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┴───────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ < │0019│0018│0003│0016│0002│000e│000d│ , │ . │ - │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├────┴┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ . │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +/// +/// ## AltGr +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ ^ │ 1 │ ² │ ³ │ 4 │ 5 │ 6 │ { │ [ │ ] │ } │ \ │ ´ │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ @ │ w │ € │ r │ t │ z │ u │ i │ o │ p │ ü │ ~ │ 000a │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐ │ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │ a │ s │ d │ f │ g │ h │ j │ k │ l │ ö │ ä │ # │ │ │ 4 │ 5 │ 6 │ │ +/// ├────┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┴───────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ | │ y │ x │ c │ v │ b │ n │ µ │ , │ . │ - │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├────┴┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ . │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +/// +/// ## Shift AltGr +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ ° │ ! │ ² │ ³ │ $ │ % │ & │ { │ [ │ ] │ } │ \ │ ` │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ @ │ W │ € │ R │ T │ Z │ U │ I │ O │ P │ Ü │ ~ │ 000a │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐ │ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │ A │ S │ D │ F │ G │ H │ J │ K │ L │ Ö │ Ä │ ' │ │ │ 4 │ 5 │ 6 │ │ +/// ├────┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┴───────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ | │ Y │ X │ C │ V │ B │ N │ µ │ ; │ : │ _ │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├────┴┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ . │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` pub struct De105Key; impl KeyboardLayout for De105Key { + #[rustfmt::skip] fn map_keycode( &self, keycode: KeyCode, modifiers: &Modifiers, handle_ctrl: HandleControl, ) -> DecodedKey { - let map_to_unicode = handle_ctrl == HandleControl::MapLettersToUnicode; match keycode { - KeyCode::Escape => DecodedKey::Unicode(0x1B.into()), - KeyCode::Oem8 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('°') - } else { - DecodedKey::Unicode('^') - } - } - KeyCode::Key1 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('!') - } else { - DecodedKey::Unicode('1') - } - } - KeyCode::Key2 => { - if modifiers.is_altgr() { - DecodedKey::Unicode('²') - } else if modifiers.is_shifted() { - DecodedKey::Unicode('"') - } else { - DecodedKey::Unicode('2') - } - } - KeyCode::Key3 => { - if modifiers.is_altgr() { - DecodedKey::Unicode('³') - } else if modifiers.is_shifted() { - DecodedKey::Unicode('§') - } else { - DecodedKey::Unicode('3') - } - } - KeyCode::Key4 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('$') - } else { - DecodedKey::Unicode('4') - } - } - KeyCode::Key5 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('%') - } else { - DecodedKey::Unicode('5') - } - } - KeyCode::Key6 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('&') - } else { - DecodedKey::Unicode('6') - } - } - KeyCode::Key7 => { - if modifiers.is_altgr() { - DecodedKey::Unicode('{') - } else if modifiers.is_shifted() { - DecodedKey::Unicode('/') - } else { - DecodedKey::Unicode('7') - } - } - KeyCode::Key8 => { - if modifiers.is_altgr() { - DecodedKey::Unicode('[') - } else if modifiers.is_shifted() { - DecodedKey::Unicode('(') - } else { - DecodedKey::Unicode('8') - } - } - KeyCode::Key9 => { - if modifiers.is_altgr() { - DecodedKey::Unicode(']') - } else if modifiers.is_shifted() { - DecodedKey::Unicode(')') - } else { - DecodedKey::Unicode('9') - } - } - KeyCode::Key0 => { - if modifiers.is_altgr() { - DecodedKey::Unicode('}') - } else if modifiers.is_shifted() { - DecodedKey::Unicode('=') - } else { - DecodedKey::Unicode('0') - } - } - KeyCode::OemMinus => { - if modifiers.is_altgr() { - DecodedKey::Unicode('\\') - } else if modifiers.is_shifted() { - DecodedKey::Unicode('?') - } else { - DecodedKey::Unicode('ß') - } - } - KeyCode::OemPlus => { - if modifiers.is_shifted() { - DecodedKey::Unicode('`') - } else { - DecodedKey::Unicode('´') - } - } - KeyCode::Backspace => DecodedKey::Unicode(0x08.into()), - KeyCode::Tab => DecodedKey::Unicode(0x09.into()), - KeyCode::Q => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0011}') - } else if modifiers.is_altgr() { - DecodedKey::Unicode('@') - } else if modifiers.is_caps() { - DecodedKey::Unicode('Q') - } else { - DecodedKey::Unicode('q') - } - } - KeyCode::E => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0005}') - } else if modifiers.is_altgr() { - DecodedKey::Unicode('€') - } else if modifiers.is_caps() { - DecodedKey::Unicode('E') - } else { - DecodedKey::Unicode('e') - } - } - KeyCode::Y => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{001A}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('Z') - } else { - DecodedKey::Unicode('z') - } - } - KeyCode::Oem4 => { - if modifiers.is_caps() { - DecodedKey::Unicode('Ü') - } else { - DecodedKey::Unicode('ü') - } - } - KeyCode::Oem6 => { - if modifiers.is_altgr() { - DecodedKey::Unicode('~') - } else if modifiers.is_caps() { - DecodedKey::Unicode('*') - } else { - DecodedKey::Unicode('+') - } - } - KeyCode::Return => DecodedKey::Unicode(10.into()), - KeyCode::Oem7 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('\'') - } else { - DecodedKey::Unicode('#') - } - } - KeyCode::Oem1 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('Ö') - } else { - DecodedKey::Unicode('ö') - } - } - KeyCode::Oem3 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('Ä') - } else { - DecodedKey::Unicode('ä') - } - } - KeyCode::Z => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0019}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('Y') - } else { - DecodedKey::Unicode('y') - } - } - KeyCode::M => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{000D}') - } else if modifiers.is_altgr() { - DecodedKey::Unicode('µ') - } else if modifiers.is_caps() { - DecodedKey::Unicode('M') - } else { - DecodedKey::Unicode('m') - } - } - KeyCode::OemComma => { - if modifiers.is_shifted() { - DecodedKey::Unicode(';') - } else { - DecodedKey::Unicode(',') - } - } - KeyCode::OemPeriod => { - if modifiers.is_shifted() { - DecodedKey::Unicode(':') - } else { - DecodedKey::Unicode('.') - } - } - KeyCode::Oem2 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('_') - } else { - DecodedKey::Unicode('-') - } - } - KeyCode::Oem5 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('>') - } else if modifiers.is_altgr() { - DecodedKey::Unicode('|') - } else { - DecodedKey::Unicode('<') - } - } - e => { - let us = super::Us104Key; - us.map_keycode(e, modifiers, handle_ctrl) - } + // ========= Row 2 (the numbers) ========= + KeyCode::Oem8 => modifiers.handle_symbol2('^', '°'), + KeyCode::Key2 => modifiers.handle_symbol3('2', '"', '²'), + KeyCode::Key3 => modifiers.handle_symbol3('3', '§', '³'), + KeyCode::Key6 => modifiers.handle_symbol2('6', '&'), + KeyCode::Key7 => modifiers.handle_symbol3('7', '/', '{'), + KeyCode::Key8 => modifiers.handle_symbol3('8', '(', '['), + KeyCode::Key9 => modifiers.handle_symbol3('9', ')', ']'), + KeyCode::Key0 => modifiers.handle_symbol3('0', '=', '}'), + KeyCode::OemMinus => modifiers.handle_symbol3('ß', '?', SLS), + KeyCode::OemPlus => modifiers.handle_symbol2('´', '`'), + // ========= Row 3 (QWERTY) ========= + KeyCode::Q => modifiers.handle_ascii_3('Q', '@', handle_ctrl), + KeyCode::E => modifiers.handle_ascii_3('E', '€', handle_ctrl), + KeyCode::Y => modifiers.handle_ascii_2('Z', handle_ctrl), + KeyCode::Oem4 => modifiers.handle_letter2('ü', 'Ü'), + KeyCode::Oem6 => modifiers.handle_symbol3('+', '*', '~'), + // ========= Row 4 (ASDFG) ========= + KeyCode::Oem1 => modifiers.handle_letter2('ö', 'Ö'), + KeyCode::Oem3 => modifiers.handle_letter2('ä', 'Ä'), + KeyCode::Oem7 => modifiers.handle_symbol2('#', QUO), + // ========= Row 5 (ZXCVB) ========= + KeyCode::Oem5 => modifiers.handle_symbol3('<', '>', '|'), + KeyCode::Z => modifiers.handle_ascii_2('Y', handle_ctrl), + KeyCode::M => modifiers.handle_ascii_3('M', 'µ', handle_ctrl), + KeyCode::OemComma => modifiers.handle_symbol2(',', ';'), + KeyCode::OemPeriod => modifiers.handle_symbol2('.', ':'), + KeyCode::Oem2 => modifiers.handle_symbol2('-', '_'), + // ========= Fallback ========= + e => super::Us104Key.map_keycode(e, modifiers, handle_ctrl), } } + + fn get_physical(&self) -> PhysicalKeyboard { + PhysicalKeyboard::Iso + } } diff --git a/src/layouts/dvorak104.rs b/src/layouts/dvorak104.rs index 58e9c0f..631f2dd 100644 --- a/src/layouts/dvorak104.rs +++ b/src/layouts/dvorak104.rs @@ -1,304 +1,191 @@ //! Dvorak keyboard support -use crate::{DecodedKey, HandleControl, KeyCode, KeyboardLayout, Modifiers}; +use crate::{DecodedKey, HandleControl, KeyCode, KeyboardLayout, Modifiers, PhysicalKeyboard, QUO}; /// A Dvorak 101-key (or 104-key including Windows keys) keyboard. /// /// Has a 1-row high Enter key, with Oem5 above (ANSI layout). +/// +/// These diagrams illustrate the conversion from [`KeyCode`] to Unicode. We +/// show either a Unicode glyph, or a hex number if the glyph isn't a +/// printable character. Blank spaces are passed through as +/// [`DecodedKey::RawKey`]. +/// +/// Run the `print_keyboard` example to re-generate these images. +/// +/// ## Unmodified +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ ` │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ [ │ ] │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ ' │ , │ . │ p │ y │ f │ g │ c │ r │ l │ / │ = │ \ │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴────────┤ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │ a │ o │ e │ u │ i │ d │ h │ t │ n │ s │ - │ 000a │ │ 4 │ 5 │ 6 │ │ +/// ├──────┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────────────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ ; │ q │ j │ k │ x │ b │ m │ w │ v │ z │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├─────┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ . │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +/// +/// ## Caps Lock +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ ` │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ [ │ ] │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ ' │ , │ . │ P │ Y │ F │ G │ C │ R │ L │ / │ = │ \ │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴────────┤ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │ A │ O │ E │ U │ I │ D │ H │ T │ N │ S │ - │ 000a │ │ 4 │ 5 │ 6 │ │ +/// ├──────┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────────────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ ; │ Q │ J │ K │ X │ B │ M │ W │ V │ Z │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├─────┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ . │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +/// +/// ## Shifted +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ ~ │ ! │ @ │ # │ $ │ % │ ^ │ & │ * │ ( │ ) │ { │ } │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ " │ < │ > │ P │ Y │ F │ G │ C │ R │ L │ ? │ + │ | │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴────────┤ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │ A │ O │ E │ U │ I │ D │ H │ T │ N │ S │ _ │ 000a │ │ 4 │ 5 │ 6 │ │ +/// ├──────┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────────────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ : │ Q │ J │ K │ X │ B │ M │ W │ V │ Z │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├─────┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ . │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +/// +/// ## Control +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ ` │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ [ │ ] │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ ' │ , │ . │0010│0019│0006│0007│0003│0012│000c│ / │ = │ \ │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴────────┤ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │0001│000f│0005│0015│0009│0004│0008│0014│000e│0013│ - │ 000a │ │ 4 │ 5 │ 6 │ │ +/// ├──────┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────────────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ ; │0011│000a│000b│0018│0002│000d│0017│0016│001a│ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├─────┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ . │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +/// +/// ## AltGr +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ ` │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ [ │ ] │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ ' │ , │ . │ p │ y │ f │ g │ c │ r │ l │ / │ = │ \ │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴────────┤ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │ a │ o │ e │ u │ i │ d │ h │ t │ n │ s │ - │ 000a │ │ 4 │ 5 │ 6 │ │ +/// ├──────┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────────────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ ; │ q │ j │ k │ x │ b │ m │ w │ v │ z │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├─────┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ . │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +/// +/// ## Shift AltGr +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ ~ │ ! │ @ │ # │ $ │ % │ ^ │ & │ * │ ( │ ) │ { │ } │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ " │ < │ > │ P │ Y │ F │ G │ C │ R │ L │ ? │ + │ | │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴────────┤ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │ A │ O │ E │ U │ I │ D │ H │ T │ N │ S │ _ │ 000a │ │ 4 │ 5 │ 6 │ │ +/// ├──────┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────────────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ : │ Q │ J │ K │ X │ B │ M │ W │ V │ Z │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├─────┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ . │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` pub struct Dvorak104Key; impl KeyboardLayout for Dvorak104Key { + #[rustfmt::skip] fn map_keycode( &self, keycode: KeyCode, modifiers: &Modifiers, handle_ctrl: HandleControl, ) -> DecodedKey { - let map_to_unicode = handle_ctrl == HandleControl::MapLettersToUnicode; match keycode { - KeyCode::OemMinus => { - if modifiers.is_shifted() { - DecodedKey::Unicode('{') - } else { - DecodedKey::Unicode('[') - } - } - KeyCode::OemPlus => { - if modifiers.is_shifted() { - DecodedKey::Unicode('}') - } else { - DecodedKey::Unicode(']') - } - } - KeyCode::Q => { - if modifiers.is_shifted() { - DecodedKey::Unicode('"') - } else { - DecodedKey::Unicode('\'') - } - } - KeyCode::W => { - if modifiers.is_shifted() { - DecodedKey::Unicode('<') - } else { - DecodedKey::Unicode(',') - } - } - KeyCode::E => { - if modifiers.is_shifted() { - DecodedKey::Unicode('>') - } else { - DecodedKey::Unicode('.') - } - } - KeyCode::R => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0010}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('P') - } else { - DecodedKey::Unicode('p') - } - } - KeyCode::T => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0019}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('Y') - } else { - DecodedKey::Unicode('y') - } - } - KeyCode::Y => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0006}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('F') - } else { - DecodedKey::Unicode('f') - } - } - KeyCode::U => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0007}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('G') - } else { - DecodedKey::Unicode('g') - } - } - KeyCode::I => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0003}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('C') - } else { - DecodedKey::Unicode('c') - } - } - KeyCode::O => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0012}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('R') - } else { - DecodedKey::Unicode('r') - } - } - KeyCode::P => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{000C}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('L') - } else { - DecodedKey::Unicode('l') - } - } - KeyCode::Oem4 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('?') - } else { - DecodedKey::Unicode('/') - } - } - KeyCode::Oem6 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('+') - } else { - DecodedKey::Unicode('=') - } - } - KeyCode::S => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{000F}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('O') - } else { - DecodedKey::Unicode('o') - } - } - KeyCode::D => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0005}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('E') - } else { - DecodedKey::Unicode('e') - } - } - KeyCode::F => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0015}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('U') - } else { - DecodedKey::Unicode('u') - } - } - KeyCode::G => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0009}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('I') - } else { - DecodedKey::Unicode('i') - } - } - KeyCode::H => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0004}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('D') - } else { - DecodedKey::Unicode('d') - } - } - KeyCode::J => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0008}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('H') - } else { - DecodedKey::Unicode('h') - } - } - KeyCode::K => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0014}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('T') - } else { - DecodedKey::Unicode('t') - } - } - KeyCode::L => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{000E}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('N') - } else { - DecodedKey::Unicode('n') - } - } - KeyCode::Oem1 => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0013}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('S') - } else { - DecodedKey::Unicode('s') - } - } - KeyCode::Oem3 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('_') - } else { - DecodedKey::Unicode('-') - } - } - KeyCode::Z => { - if modifiers.is_shifted() { - DecodedKey::Unicode(':') - } else { - DecodedKey::Unicode(';') - } - } - KeyCode::X => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0011}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('Q') - } else { - DecodedKey::Unicode('q') - } - } - KeyCode::C => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{000A}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('J') - } else { - DecodedKey::Unicode('j') - } - } - KeyCode::V => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{000B}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('K') - } else { - DecodedKey::Unicode('k') - } - } - KeyCode::B => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0018}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('X') - } else { - DecodedKey::Unicode('x') - } - } - KeyCode::N => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0002}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('B') - } else { - DecodedKey::Unicode('b') - } - } - KeyCode::OemComma => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0017}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('W') - } else { - DecodedKey::Unicode('w') - } - } - KeyCode::OemPeriod => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0016}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('V') - } else { - DecodedKey::Unicode('v') - } - } - KeyCode::Oem2 => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{001A}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('Z') - } else { - DecodedKey::Unicode('z') - } - } - e => { - let us = super::Us104Key; - us.map_keycode(e, modifiers, handle_ctrl) - } + // ========= Row 2 (the numbers) ========= + KeyCode::OemMinus => modifiers.handle_symbol2('[', '{'), + KeyCode::OemPlus => modifiers.handle_symbol2(']', '}'), + // ========= Row 3 (QWERTY) ========= + KeyCode::Q => modifiers.handle_symbol2(QUO, '"'), + KeyCode::W => modifiers.handle_symbol2(',', '<'), + KeyCode::E => modifiers.handle_symbol2('.', '>'), + KeyCode::R => modifiers.handle_ascii_2('P', handle_ctrl), + KeyCode::T => modifiers.handle_ascii_2('Y', handle_ctrl), + KeyCode::Y => modifiers.handle_ascii_2('F', handle_ctrl), + KeyCode::U => modifiers.handle_ascii_2('G', handle_ctrl), + KeyCode::I => modifiers.handle_ascii_2('C', handle_ctrl), + KeyCode::O => modifiers.handle_ascii_2('R', handle_ctrl), + KeyCode::P => modifiers.handle_ascii_2('L', handle_ctrl), + KeyCode::Oem4 => modifiers.handle_symbol2('/', '?'), + KeyCode::Oem6 => modifiers.handle_symbol2('=', '+'), + // ========= Row 4 (ASDFG) ========= + KeyCode::S => modifiers.handle_ascii_2('O', handle_ctrl), + KeyCode::D => modifiers.handle_ascii_2('E', handle_ctrl), + KeyCode::F => modifiers.handle_ascii_2('U', handle_ctrl), + KeyCode::G => modifiers.handle_ascii_2('I', handle_ctrl), + KeyCode::H => modifiers.handle_ascii_2('D', handle_ctrl), + KeyCode::J => modifiers.handle_ascii_2('H', handle_ctrl), + KeyCode::K => modifiers.handle_ascii_2('T', handle_ctrl), + KeyCode::L => modifiers.handle_ascii_2('N', handle_ctrl), + KeyCode::Oem1 => modifiers.handle_ascii_2('S', handle_ctrl), + KeyCode::Oem3 => modifiers.handle_symbol2('-', '_'), + // ========= Row 5 (ZXCVB) ========= + KeyCode::Z => modifiers.handle_symbol2(';', ':'), + KeyCode::X => modifiers.handle_ascii_2('Q', handle_ctrl), + KeyCode::C => modifiers.handle_ascii_2('J', handle_ctrl), + KeyCode::V => modifiers.handle_ascii_2('K', handle_ctrl), + KeyCode::B => modifiers.handle_ascii_2('X', handle_ctrl), + KeyCode::N => modifiers.handle_ascii_2('B', handle_ctrl), + KeyCode::OemComma => modifiers.handle_ascii_2('W', handle_ctrl), + KeyCode::OemPeriod => modifiers.handle_ascii_2('V', handle_ctrl), + KeyCode::Oem2 => modifiers.handle_ascii_2('Z', handle_ctrl), + // ========= Fallback ========= + e => super::Us104Key.map_keycode(e, modifiers, handle_ctrl), } } + + fn get_physical(&self) -> PhysicalKeyboard { + PhysicalKeyboard::Ansi + } } diff --git a/src/layouts/dvorak_programmer104.rs b/src/layouts/dvorak_programmer104.rs index 7c3bf4c..b24eee4 100644 --- a/src/layouts/dvorak_programmer104.rs +++ b/src/layouts/dvorak_programmer104.rs @@ -1,485 +1,207 @@ //! Dvorak Programmer keyboard support -use crate::{DecodedKey, HandleControl, KeyCode, KeyboardLayout, Modifiers}; +use crate::{ + DecodedKey, HandleControl, KeyCode, KeyboardLayout, Modifiers, PhysicalKeyboard, QUO, SLS, +}; /// A Dvorak Programmer 101-key (or 104-key including Windows keys) keyboard. /// /// Has a 1-row high Enter key, with Oem5 above (ANSI layout). +/// +/// These diagrams illustrate the conversion from [`KeyCode`] to Unicode. We +/// show either a Unicode glyph, or a hex number if the glyph isn't a +/// printable character. Blank spaces are passed through as +/// [`DecodedKey::RawKey`]. +/// +/// Run the `print_keyboard` example to re-generate these images. +/// +/// ## Unmodified +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ $ │ & │ [ │ { │ } │ ( │ = │ * │ ) │ + │ ] │ ! │ = │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ ; │ , │ . │ p │ y │ f │ g │ c │ r │ l │ / │ @ │ \ │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴────────┤ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │ a │ o │ e │ u │ i │ d │ h │ t │ n │ s │ - │ 000a │ │ 4 │ 5 │ 6 │ │ +/// ├──────┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────────────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ ' │ q │ j │ k │ x │ b │ m │ w │ v │ z │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├─────┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ . │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +/// +/// ## Caps Lock +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ $ │ & │ [ │ { │ } │ ( │ = │ * │ ) │ + │ ] │ ! │ = │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ ; │ , │ . │ P │ Y │ F │ G │ C │ R │ L │ / │ @ │ \ │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴────────┤ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │ A │ O │ E │ U │ I │ D │ H │ T │ N │ S │ - │ 000a │ │ 4 │ 5 │ 6 │ │ +/// ├──────┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────────────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ ' │ Q │ J │ K │ X │ B │ M │ W │ V │ Z │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├─────┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ . │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +/// +/// ## Shifted +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ ~ │ % │ 7 │ 5 │ 3 │ 1 │ 9 │ 0 │ 2 │ 4 │ 6 │ 8 │ ` │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ : │ < │ > │ P │ Y │ F │ G │ C │ R │ L │ ? │ ^ │ | │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴────────┤ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │ A │ O │ E │ U │ I │ D │ H │ T │ N │ S │ _ │ 000a │ │ 4 │ 5 │ 6 │ │ +/// ├──────┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────────────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ " │ Q │ J │ K │ X │ B │ M │ W │ V │ Z │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├─────┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ . │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +/// +/// ## Control +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ $ │ & │ [ │ { │ } │ ( │ = │ * │ ) │ + │ ] │ ! │ = │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ ; │ , │ . │0010│0019│0006│0007│0003│0012│000c│ / │ @ │ \ │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴────────┤ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │0001│000f│0005│0015│0009│0004│0008│0014│000e│0013│ - │ 000a │ │ 4 │ 5 │ 6 │ │ +/// ├──────┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────────────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ ' │0011│000a│000b│0018│0002│000d│0017│0016│001a│ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├─────┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ . │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +/// +/// ## AltGr +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ $ │ & │ [ │ { │ } │ ( │ = │ * │ ) │ + │ ] │ ! │ = │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ ; │ , │ . │ p │ y │ f │ g │ c │ r │ l │ / │ @ │ \ │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴────────┤ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │ a │ o │ e │ u │ i │ d │ h │ t │ n │ s │ - │ 000a │ │ 4 │ 5 │ 6 │ │ +/// ├──────┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────────────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ ' │ q │ j │ k │ x │ b │ m │ w │ v │ z │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├─────┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ . │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +/// +/// ## Shift AltGr +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ ~ │ % │ 7 │ 5 │ 3 │ 1 │ 9 │ 0 │ 2 │ 4 │ 6 │ 8 │ ` │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ : │ < │ > │ P │ Y │ F │ G │ C │ R │ L │ ? │ ^ │ | │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴────────┤ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │ A │ O │ E │ U │ I │ D │ H │ T │ N │ S │ _ │ 000a │ │ 4 │ 5 │ 6 │ │ +/// ├──────┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────────────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ " │ Q │ J │ K │ X │ B │ M │ W │ V │ Z │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├─────┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ . │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` pub struct DVP104Key; impl KeyboardLayout for DVP104Key { + #[rustfmt::skip] fn map_keycode( &self, keycode: KeyCode, modifiers: &Modifiers, handle_ctrl: HandleControl, ) -> DecodedKey { - let map_to_unicode = handle_ctrl == HandleControl::MapLettersToUnicode; match keycode { - KeyCode::Oem8 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('~') - } else { - DecodedKey::Unicode('$') - } - } - KeyCode::Escape => DecodedKey::Unicode(0x1B.into()), - KeyCode::Key1 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('%') - } else { - DecodedKey::Unicode('&') - } - } - KeyCode::Key2 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('7') - } else { - DecodedKey::Unicode('[') - } - } - KeyCode::Key3 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('5') - } else { - DecodedKey::Unicode('{') - } - } - KeyCode::Key4 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('3') - } else { - DecodedKey::Unicode('}') - } - } - KeyCode::Key5 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('1') - } else { - DecodedKey::Unicode('(') - } - } - KeyCode::Key6 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('9') - } else { - DecodedKey::Unicode('=') - } - } - KeyCode::Key7 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('0') - } else { - DecodedKey::Unicode('*') - } - } - KeyCode::Key8 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('2') - } else { - DecodedKey::Unicode(')') - } - } - KeyCode::Key9 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('4') - } else { - DecodedKey::Unicode('+') - } - } - KeyCode::Key0 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('6') - } else { - DecodedKey::Unicode(']') - } - } - KeyCode::OemMinus => { - if modifiers.is_shifted() { - DecodedKey::Unicode('8') - } else { - DecodedKey::Unicode('!') - } - } - KeyCode::OemPlus => { - if modifiers.is_shifted() { - DecodedKey::Unicode('`') - } else { - DecodedKey::Unicode('=') - } - } - KeyCode::Backspace => DecodedKey::Unicode(0x08.into()), - KeyCode::Tab => DecodedKey::Unicode(0x09.into()), - KeyCode::Q => { - if modifiers.is_shifted() { - DecodedKey::Unicode(':') - } else { - DecodedKey::Unicode(';') - } - } - KeyCode::W => { - if modifiers.is_shifted() { - DecodedKey::Unicode('<') - } else { - DecodedKey::Unicode(',') - } - } - KeyCode::E => { - if modifiers.is_shifted() { - DecodedKey::Unicode('>') - } else { - DecodedKey::Unicode('.') - } - } - KeyCode::R => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0010}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('P') - } else { - DecodedKey::Unicode('p') - } - } - KeyCode::T => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0019}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('Y') - } else { - DecodedKey::Unicode('y') - } - } - KeyCode::Y => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0006}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('F') - } else { - DecodedKey::Unicode('f') - } - } - KeyCode::U => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0007}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('G') - } else { - DecodedKey::Unicode('g') - } - } - KeyCode::I => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0003}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('C') - } else { - DecodedKey::Unicode('c') - } - } - KeyCode::O => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0012}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('R') - } else { - DecodedKey::Unicode('r') - } - } - KeyCode::P => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{000C}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('L') - } else { - DecodedKey::Unicode('l') - } - } - KeyCode::Oem4 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('?') - } else { - DecodedKey::Unicode('/') - } - } - KeyCode::Oem6 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('^') - } else { - DecodedKey::Unicode('@') - } - } - KeyCode::Oem7 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('|') - } else { - DecodedKey::Unicode('\\') - } - } - KeyCode::A => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0001}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('A') - } else { - DecodedKey::Unicode('a') - } - } - KeyCode::S => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{000F}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('O') - } else { - DecodedKey::Unicode('o') - } - } - KeyCode::D => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0005}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('E') - } else { - DecodedKey::Unicode('e') - } - } - KeyCode::F => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0015}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('U') - } else { - DecodedKey::Unicode('u') - } - } - KeyCode::G => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0009}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('I') - } else { - DecodedKey::Unicode('i') - } - } - KeyCode::H => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0004}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('D') - } else { - DecodedKey::Unicode('d') - } - } - KeyCode::J => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0008}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('H') - } else { - DecodedKey::Unicode('h') - } - } - KeyCode::K => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0014}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('T') - } else { - DecodedKey::Unicode('t') - } - } - KeyCode::L => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{000E}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('N') - } else { - DecodedKey::Unicode('n') - } - } - KeyCode::Oem1 => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0013}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('S') - } else { - DecodedKey::Unicode('s') - } - } - KeyCode::Oem3 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('_') - } else { - DecodedKey::Unicode('-') - } - } - KeyCode::Return => DecodedKey::Unicode(10.into()), - KeyCode::Z => { - if modifiers.is_shifted() { - DecodedKey::Unicode('"') - } else { - DecodedKey::Unicode('\'') - } - } - KeyCode::X => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0011}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('Q') - } else { - DecodedKey::Unicode('q') - } - } - KeyCode::C => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{000A}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('J') - } else { - DecodedKey::Unicode('j') - } - } - KeyCode::V => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{000B}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('K') - } else { - DecodedKey::Unicode('k') - } - } - KeyCode::B => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0018}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('X') - } else { - DecodedKey::Unicode('x') - } - } - KeyCode::N => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0002}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('B') - } else { - DecodedKey::Unicode('b') - } - } - KeyCode::M => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{000D}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('M') - } else { - DecodedKey::Unicode('m') - } - } - KeyCode::OemComma => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0017}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('W') - } else { - DecodedKey::Unicode('w') - } - } - KeyCode::OemPeriod => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0016}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('V') - } else { - DecodedKey::Unicode('v') - } - } - KeyCode::Oem2 => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{001A}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('Z') - } else { - DecodedKey::Unicode('z') - } - } - KeyCode::Spacebar => DecodedKey::Unicode(' '), - KeyCode::Delete => DecodedKey::Unicode(127.into()), - KeyCode::NumpadDivide => DecodedKey::Unicode('/'), - KeyCode::NumpadMultiply => DecodedKey::Unicode('*'), - KeyCode::NumpadSubtract => DecodedKey::Unicode('-'), - KeyCode::Numpad7 => { - if modifiers.numlock { - DecodedKey::Unicode('7') - } else { - DecodedKey::RawKey(KeyCode::Home) - } - } - KeyCode::Numpad8 => { - if modifiers.numlock { - DecodedKey::Unicode('8') - } else { - DecodedKey::RawKey(KeyCode::ArrowUp) - } - } - KeyCode::Numpad9 => { - if modifiers.numlock { - DecodedKey::Unicode('9') - } else { - DecodedKey::RawKey(KeyCode::PageUp) - } - } - KeyCode::NumpadAdd => DecodedKey::Unicode('+'), - KeyCode::Numpad4 => { - if modifiers.numlock { - DecodedKey::Unicode('4') - } else { - DecodedKey::RawKey(KeyCode::ArrowLeft) - } - } - KeyCode::Numpad5 => DecodedKey::Unicode('5'), - KeyCode::Numpad6 => { - if modifiers.numlock { - DecodedKey::Unicode('6') - } else { - DecodedKey::RawKey(KeyCode::ArrowRight) - } - } - KeyCode::Numpad1 => { - if modifiers.numlock { - DecodedKey::Unicode('1') - } else { - DecodedKey::RawKey(KeyCode::End) - } - } - KeyCode::Numpad2 => { - if modifiers.numlock { - DecodedKey::Unicode('2') - } else { - DecodedKey::RawKey(KeyCode::ArrowDown) - } - } - KeyCode::Numpad3 => { - if modifiers.numlock { - DecodedKey::Unicode('3') - } else { - DecodedKey::RawKey(KeyCode::PageDown) - } - } - KeyCode::Numpad0 => { - if modifiers.numlock { - DecodedKey::Unicode('0') - } else { - DecodedKey::RawKey(KeyCode::Insert) - } - } - KeyCode::NumpadPeriod => { - if modifiers.numlock { - DecodedKey::Unicode('.') - } else { - DecodedKey::Unicode(127.into()) - } - } - KeyCode::NumpadEnter => DecodedKey::Unicode(10.into()), - k => DecodedKey::RawKey(k), + // ========= Row 2 (the numbers) ========= + KeyCode::Oem8 => modifiers.handle_symbol2('$', '~'), + KeyCode::Key1 => modifiers.handle_symbol2('&', '%'), + KeyCode::Key2 => modifiers.handle_symbol2('[', '7'), + KeyCode::Key3 => modifiers.handle_symbol2('{', '5'), + KeyCode::Key4 => modifiers.handle_symbol2('}', '3'), + KeyCode::Key5 => modifiers.handle_symbol2('(', '1'), + KeyCode::Key6 => modifiers.handle_symbol2('=', '9'), + KeyCode::Key7 => modifiers.handle_symbol2('*', '0'), + KeyCode::Key8 => modifiers.handle_symbol2(')', '2'), + KeyCode::Key9 => modifiers.handle_symbol2('+', '4'), + KeyCode::Key0 => modifiers.handle_symbol2(']', '6'), + KeyCode::OemMinus => modifiers.handle_symbol2('!', '8'), + KeyCode::OemPlus => modifiers.handle_symbol2('=', '`'), + // ========= Row 3 (QWERTY) ========= + KeyCode::Q => modifiers.handle_symbol2(';', ':'), + KeyCode::W => modifiers.handle_symbol2(',', '<'), + KeyCode::E => modifiers.handle_symbol2('.', '>'), + KeyCode::R => modifiers.handle_ascii_2('P', handle_ctrl), + KeyCode::T => modifiers.handle_ascii_2('Y', handle_ctrl), + KeyCode::Y => modifiers.handle_ascii_2('F', handle_ctrl), + KeyCode::U => modifiers.handle_ascii_2('G', handle_ctrl), + KeyCode::I => modifiers.handle_ascii_2('C', handle_ctrl), + KeyCode::O => modifiers.handle_ascii_2('R', handle_ctrl), + KeyCode::P => modifiers.handle_ascii_2('L', handle_ctrl), + KeyCode::Oem4 => modifiers.handle_symbol2('/', '?'), + KeyCode::Oem6 => modifiers.handle_symbol2('@', '^'), + KeyCode::Oem7 => modifiers.handle_symbol2(SLS, '|'), + // ========= Row 4 (ASDFG) ========= + KeyCode::A => modifiers.handle_ascii_2('A', handle_ctrl), + KeyCode::S => modifiers.handle_ascii_2('O', handle_ctrl), + KeyCode::D => modifiers.handle_ascii_2('E', handle_ctrl), + KeyCode::F => modifiers.handle_ascii_2('U', handle_ctrl), + KeyCode::G => modifiers.handle_ascii_2('I', handle_ctrl), + KeyCode::H => modifiers.handle_ascii_2('D', handle_ctrl), + KeyCode::J => modifiers.handle_ascii_2('H', handle_ctrl), + KeyCode::K => modifiers.handle_ascii_2('T', handle_ctrl), + KeyCode::L => modifiers.handle_ascii_2('N', handle_ctrl), + KeyCode::Oem1 => modifiers.handle_ascii_2('S', handle_ctrl), + KeyCode::Oem3 => modifiers.handle_symbol2('-', '_'), + // ========= Row 5 (ZXCVB) ========= + KeyCode::Z => modifiers.handle_symbol2(QUO, '"'), + KeyCode::X => modifiers.handle_ascii_2('Q', handle_ctrl), + KeyCode::C => modifiers.handle_ascii_2('J', handle_ctrl), + KeyCode::V => modifiers.handle_ascii_2('K', handle_ctrl), + KeyCode::B => modifiers.handle_ascii_2('X', handle_ctrl), + KeyCode::N => modifiers.handle_ascii_2('B', handle_ctrl), + KeyCode::M => modifiers.handle_ascii_2('M', handle_ctrl), + KeyCode::OemComma => modifiers.handle_ascii_2('W', handle_ctrl), + KeyCode::OemPeriod => modifiers.handle_ascii_2('V', handle_ctrl), + KeyCode::Oem2 => modifiers.handle_ascii_2('Z', handle_ctrl), + // ========= Fallback ========= + e => super::Us104Key.map_keycode(e, modifiers, handle_ctrl), } } + + fn get_physical(&self) -> PhysicalKeyboard { + PhysicalKeyboard::Ansi + } } diff --git a/src/layouts/fi_se105.rs b/src/layouts/fi_se105.rs index a59184e..39664df 100644 --- a/src/layouts/fi_se105.rs +++ b/src/layouts/fi_se105.rs @@ -1,226 +1,185 @@ //! Finnish/Swedish keyboard support -use crate::{DecodedKey, HandleControl, KeyCode, KeyboardLayout, Modifiers}; +use crate::{ + DecodedKey, HandleControl, KeyCode, KeyboardLayout, Modifiers, PhysicalKeyboard, QUO, SLS, +}; /// A standard Finnish/Swedish 102-key (or 105-key including Windows keys) keyboard. /// /// Has a 2-row high Enter key, with Oem5 next to the left shift (ISO format). +/// +/// These diagrams illustrate the conversion from [`KeyCode`] to Unicode. We +/// show either a Unicode glyph, or a hex number if the glyph isn't a +/// printable character. Blank spaces are passed through as +/// [`DecodedKey::RawKey`]. +/// +/// Run the `print_keyboard` example to re-generate these images. +/// +/// ## Unmodified +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ § │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ + │ ´ │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ q │ w │ e │ r │ t │ y │ u │ i │ o │ p │ å │ ¨ │ 000a │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐ │ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │ a │ s │ d │ f │ g │ h │ j │ k │ l │ ö │ ä │ ' │ │ │ 4 │ 5 │ 6 │ │ +/// ├────┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┴───────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ < │ z │ x │ c │ v │ b │ n │ m │ , │ . │ - │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├────┴┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ , │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +/// +/// ## Caps Lock +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ § │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ + │ ´ │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │ Å │ ¨ │ 000a │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐ │ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │ A │ S │ D │ F │ G │ H │ J │ K │ L │ Ö │ Ä │ ' │ │ │ 4 │ 5 │ 6 │ │ +/// ├────┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┴───────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ < │ Z │ X │ C │ V │ B │ N │ M │ , │ . │ - │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├────┴┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ , │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +/// +/// ## Shifted +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ ½ │ ! │ " │ # │ ¤ │ % │ & │ / │ ( │ ) │ = │ ? │ ` │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │ Å │ ^ │ 000a │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐ │ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │ A │ S │ D │ F │ G │ H │ J │ K │ L │ Ö │ Ä │ * │ │ │ 4 │ 5 │ 6 │ │ +/// ├────┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┴───────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ > │ Z │ X │ C │ V │ B │ N │ M │ ; │ : │ _ │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├────┴┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ , │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +/// +/// ## Control +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ § │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ + │ ´ │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │0011│0017│0005│0012│0014│0019│0015│0009│000f│0010│ å │ ¨ │ 000a │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐ │ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │0001│0013│0004│0006│0007│0008│000a│000b│000c│ ö │ ä │ ' │ │ │ 4 │ 5 │ 6 │ │ +/// ├────┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┴───────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ < │001a│0018│0003│0016│0002│000e│000d│ , │ . │ - │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├────┴┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ , │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +/// +/// ## AltGr +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ § │ 1 │ @ │ £ │ $ │ € │ 6 │ { │ [ │ ] │ } │ \ │ ´ │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ q │ w │ € │ r │ t │ y │ u │ i │ o │ p │ å │ ~ │ 000a │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐ │ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │ a │ s │ d │ f │ g │ h │ j │ k │ l │ ö │ ä │ ' │ │ │ 4 │ 5 │ 6 │ │ +/// ├────┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┴───────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ | │ z │ x │ c │ v │ b │ n │ µ │ , │ . │ - │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├────┴┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ , │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +/// +/// ## Shift AltGr +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ ½ │ ! │ @ │ £ │ $ │ € │ & │ { │ [ │ ] │ } │ \ │ ` │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ Q │ W │ € │ R │ T │ Y │ U │ I │ O │ P │ Å │ ~ │ 000a │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐ │ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │ A │ S │ D │ F │ G │ H │ J │ K │ L │ Ö │ Ä │ * │ │ │ 4 │ 5 │ 6 │ │ +/// ├────┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┴───────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ | │ Z │ X │ C │ V │ B │ N │ µ │ ; │ : │ _ │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├────┴┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ , │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` pub struct FiSe105Key; impl KeyboardLayout for FiSe105Key { + #[rustfmt::skip] fn map_keycode( &self, keycode: KeyCode, modifiers: &Modifiers, handle_ctrl: HandleControl, ) -> DecodedKey { - let map_to_unicode = handle_ctrl == HandleControl::MapLettersToUnicode; - let fallback = super::Us104Key; match keycode { // ========= Row 2 (the numbers) ========= - KeyCode::Oem8 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('½') - } else { - DecodedKey::Unicode('§') - } - } - KeyCode::Key2 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('"') - } else if modifiers.is_altgr() { - DecodedKey::Unicode('@') - } else { - DecodedKey::Unicode('2') - } - } - KeyCode::Key3 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('#') - } else if modifiers.is_altgr() { - DecodedKey::Unicode('£') - } else { - DecodedKey::Unicode('3') - } - } - KeyCode::Key4 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('¤') - } else if modifiers.is_altgr() { - DecodedKey::Unicode('$') - } else { - DecodedKey::Unicode('4') - } - } - KeyCode::Key5 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('%') - } else if modifiers.is_altgr() { - DecodedKey::Unicode('€') - } else { - DecodedKey::Unicode('5') - } - } - KeyCode::Key6 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('&') - } else { - DecodedKey::Unicode('6') - } - } - KeyCode::Key7 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('/') - } else if modifiers.is_altgr() { - DecodedKey::Unicode('{') - } else { - DecodedKey::Unicode('7') - } - } - KeyCode::Key8 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('(') - } else if modifiers.is_altgr() { - DecodedKey::Unicode('[') - } else { - DecodedKey::Unicode('8') - } - } - KeyCode::Key9 => { - if modifiers.is_shifted() { - DecodedKey::Unicode(')') - } else if modifiers.is_altgr() { - DecodedKey::Unicode(']') - } else { - DecodedKey::Unicode('9') - } - } - KeyCode::Key0 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('=') - } else if modifiers.is_altgr() { - DecodedKey::Unicode('}') - } else { - DecodedKey::Unicode('0') - } - } - KeyCode::OemMinus => { - if modifiers.is_shifted() { - DecodedKey::Unicode('?') - } else if modifiers.is_altgr() { - DecodedKey::Unicode('\\') - } else { - DecodedKey::Unicode('+') - } - } - KeyCode::OemPlus => { - if modifiers.is_shifted() { - DecodedKey::Unicode('`') - } else { - DecodedKey::Unicode('´') - } - } + KeyCode::Oem8 => modifiers.handle_symbol2('§', '½'), + KeyCode::Key2 => modifiers.handle_symbol3('2', '"', '@'), + KeyCode::Key3 => modifiers.handle_symbol3('3', '#', '£'), + KeyCode::Key4 => modifiers.handle_symbol3('4', '¤', '$'), + KeyCode::Key5 => modifiers.handle_symbol3('5', '%', '€'), + KeyCode::Key6 => modifiers.handle_symbol2('6', '&'), + KeyCode::Key7 => modifiers.handle_symbol3('7', '/', '{'), + KeyCode::Key8 => modifiers.handle_symbol3('8', '(', '['), + KeyCode::Key9 => modifiers.handle_symbol3('9', ')', ']'), + KeyCode::Key0 => modifiers.handle_symbol3('0', '=', '}'), + KeyCode::OemMinus => modifiers.handle_symbol3('+', '?', SLS), + KeyCode::OemPlus => modifiers.handle_symbol2('´', '`'), // ========= Row 3 (QWERTY) ========= - KeyCode::E => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0005}') - } else if modifiers.is_altgr() { - DecodedKey::Unicode('€') - } else if modifiers.is_caps() { - DecodedKey::Unicode('E') - } else { - DecodedKey::Unicode('e') - } - } - KeyCode::Oem4 => { - if modifiers.is_caps() { - DecodedKey::Unicode('Å') - } else { - DecodedKey::Unicode('å') - } - } - KeyCode::Oem6 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('^') - } else if modifiers.is_altgr() { - DecodedKey::Unicode('~') - } else { - DecodedKey::Unicode('¨') - } - } + KeyCode::E => modifiers.handle_ascii_3('E', '€', handle_ctrl), + KeyCode::Oem4 => modifiers.handle_letter2('å', 'Å'), + KeyCode::Oem6 => modifiers.handle_symbol3('¨', '^', '~'), // ========= Row 4 (ASDF) ========= - KeyCode::Oem1 => { - if modifiers.is_caps() { - DecodedKey::Unicode('Ö') - } else { - DecodedKey::Unicode('ö') - } - } - KeyCode::Oem3 => { - if modifiers.is_caps() { - DecodedKey::Unicode('Ä') - } else { - DecodedKey::Unicode('ä') - } - } - KeyCode::Oem7 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('*') - } else { - DecodedKey::Unicode('\'') - } - } + KeyCode::Oem1 => modifiers.handle_letter2('ö', 'Ö'), + KeyCode::Oem3 => modifiers.handle_letter2('ä', 'Ä'), + KeyCode::Oem7 => modifiers.handle_symbol2(QUO, '*'), // ========= Row 5 (ZXCV) ========= - KeyCode::Oem5 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('>') - } else if modifiers.is_altgr() { - DecodedKey::Unicode('|') - } else { - DecodedKey::Unicode('<') - } - } - KeyCode::M => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{000D}') - } else if modifiers.is_altgr() { - DecodedKey::Unicode('µ') - } else if modifiers.is_caps() { - DecodedKey::Unicode('M') - } else { - DecodedKey::Unicode('m') - } - } - KeyCode::OemComma => { - if modifiers.is_shifted() { - DecodedKey::Unicode(';') - } else { - DecodedKey::Unicode(',') - } - } - KeyCode::OemPeriod => { - if modifiers.is_shifted() { - DecodedKey::Unicode(':') - } else { - DecodedKey::Unicode('.') - } - } - KeyCode::Oem2 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('_') - } else { - DecodedKey::Unicode('-') - } - } + KeyCode::Oem5 => modifiers.handle_symbol3('<', '>', '|'), + KeyCode::M => modifiers.handle_ascii_3('M', 'µ', handle_ctrl), + KeyCode::OemComma => modifiers.handle_symbol2(',', ';'), + KeyCode::OemPeriod => modifiers.handle_symbol2('.', ':'), + KeyCode::Oem2 => modifiers.handle_symbol2('-', '_'), // ========= Row 6 (modifers and space bar) ========= - KeyCode::NumpadPeriod => { - if modifiers.numlock { - DecodedKey::Unicode(',') - } else { - fallback.map_keycode(keycode, modifiers, handle_ctrl) - } - } - e => fallback.map_keycode(e, modifiers, handle_ctrl), + KeyCode::NumpadPeriod if modifiers.numlock => DecodedKey::Unicode(','), + // ========= Fallback ========= + e => super::Us104Key.map_keycode(e, modifiers, handle_ctrl), } } + + fn get_physical(&self) -> PhysicalKeyboard { + PhysicalKeyboard::Iso + } } diff --git a/src/layouts/jis109.rs b/src/layouts/jis109.rs index 8bcf617..e4b1f43 100644 --- a/src/layouts/jis109.rs +++ b/src/layouts/jis109.rs @@ -1,6 +1,8 @@ //! JIS keyboard support -use crate::{DecodedKey, HandleControl, KeyCode, KeyboardLayout, Modifiers}; +use crate::{ + DecodedKey, HandleControl, KeyCode, KeyboardLayout, Modifiers, PhysicalKeyboard, QUO, SLS, +}; /// A standard Japan 106-key (or 109-key including Windows keys) keyboard. /// @@ -8,9 +10,137 @@ use crate::{DecodedKey, HandleControl, KeyCode, KeyboardLayout, Modifiers}; /// /// We used as a /// reference. +/// +/// These diagrams illustrate the conversion from [`KeyCode`] to Unicode. We +/// show either a Unicode glyph, or a hex number if the glyph isn't a +/// printable character. Blank spaces are passed through as +/// [`DecodedKey::RawKey`]. +/// +/// Run the `print_keyboard` example to re-generate these images. +/// +/// ## Unmodified +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ - │ ^ │ ¥ │0008│ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ q │ w │ e │ r │ t │ y │ u │ i │ o │ p │ @ │ [ │ 000a │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐ │ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │ a │ s │ d │ f │ g │ h │ j │ k │ l │ ; │ : │ ] │ │ │ 4 │ 5 │ 6 │ │ +/// ├──────┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┼───────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ z │ x │ c │ v │ b │ n │ m │ , │ . │ / │ \ │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├─────┬───┴─┬──┴──┬─┴───┬┴────┴────┴────┴────┴┬───┴─┬──┴──┬─┴──┬───┴┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ │ 0 │ . │ │ +/// └─────┴─────┴─────┴─────┴─────────────────────┴─────┴─────┴────┴────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +/// +/// ## Caps Lock +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ - │ ^ │ ¥ │0008│ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │ @ │ [ │ 000a │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐ │ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │ A │ S │ D │ F │ G │ H │ J │ K │ L │ ; │ : │ ] │ │ │ 4 │ 5 │ 6 │ │ +/// ├──────┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┼───────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ Z │ X │ C │ V │ B │ N │ M │ , │ . │ / │ \ │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├─────┬───┴─┬──┴──┬─┴───┬┴────┴────┴────┴────┴┬───┴─┬──┴──┬─┴──┬───┴┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ │ 0 │ . │ │ +/// └─────┴─────┴─────┴─────┴─────────────────────┴─────┴─────┴────┴────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +/// +/// ## Shifted +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ │ ! │ " │ # │ $ │ % │ & │ ' │ ( │ ) │ ~ │ = │ ¯ │ | │0008│ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │ ` │ { │ 000a │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐ │ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │ A │ S │ D │ F │ G │ H │ J │ K │ L │ + │ * │ } │ │ │ 4 │ 5 │ 6 │ │ +/// ├──────┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┼───────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ Z │ X │ C │ V │ B │ N │ M │ < │ > │ ? │ _ │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├─────┬───┴─┬──┴──┬─┴───┬┴────┴────┴────┴────┴┬───┴─┬──┴──┬─┴──┬───┴┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ │ 0 │ . │ │ +/// └─────┴─────┴─────┴─────┴─────────────────────┴─────┴─────┴────┴────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +/// +/// ## Control +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ - │ ^ │ ¥ │0008│ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │0011│0017│0005│0012│0014│0019│0015│0009│000f│0010│ @ │ [ │ 000a │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐ │ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │0001│0013│0004│0006│0007│0008│000a│000b│000c│ ; │ : │ ] │ │ │ 4 │ 5 │ 6 │ │ +/// ├──────┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┼───────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │001a│0018│0003│0016│0002│000e│000d│ , │ . │ / │ \ │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├─────┬───┴─┬──┴──┬─┴───┬┴────┴────┴────┴────┴┬───┴─┬──┴──┬─┴──┬───┴┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ │ 0 │ . │ │ +/// └─────┴─────┴─────┴─────┴─────────────────────┴─────┴─────┴────┴────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +/// +/// ## AltGr +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ - │ ^ │ ¥ │0008│ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ q │ w │ e │ r │ t │ y │ u │ i │ o │ p │ @ │ [ │ 000a │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐ │ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │ a │ s │ d │ f │ g │ h │ j │ k │ l │ ; │ : │ ] │ │ │ 4 │ 5 │ 6 │ │ +/// ├──────┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┼───────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ z │ x │ c │ v │ b │ n │ m │ , │ . │ / │ \ │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├─────┬───┴─┬──┴──┬─┴───┬┴────┴────┴────┴────┴┬───┴─┬──┴──┬─┴──┬───┴┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ │ 0 │ . │ │ +/// └─────┴─────┴─────┴─────┴─────────────────────┴─────┴─────┴────┴────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +/// +/// ## Shift AltGr +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ │ ! │ " │ # │ $ │ % │ & │ ' │ ( │ ) │ ~ │ = │ ¯ │ | │0008│ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │ ` │ { │ 000a │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐ │ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │ A │ S │ D │ F │ G │ H │ J │ K │ L │ + │ * │ } │ │ │ 4 │ 5 │ 6 │ │ +/// ├──────┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┼───────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ Z │ X │ C │ V │ B │ N │ M │ < │ > │ ? │ _ │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├─────┬───┴─┬──┴──┬─┴───┬┴────┴────┴────┴────┴┬───┴─┬──┴──┬─┴──┬───┴┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ │ 0 │ . │ │ +/// └─────┴─────┴─────┴─────┴─────────────────────┴─────┴─────┴────┴────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` pub struct Jis109Key; impl KeyboardLayout for Jis109Key { + #[rustfmt::skip] fn map_keycode( &self, keycode: KeyCode, @@ -18,161 +148,40 @@ impl KeyboardLayout for Jis109Key { handle_ctrl: HandleControl, ) -> DecodedKey { match keycode { - KeyCode::Oem8 => { - // hankaku/zenkaku/kanji - DecodedKey::RawKey(KeyCode::Oem8) - } - KeyCode::Escape => DecodedKey::Unicode(0x1B.into()), - KeyCode::Key1 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('!') - } else { - DecodedKey::Unicode('1') - } - } - KeyCode::Key2 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('"') - } else { - DecodedKey::Unicode('2') - } - } - KeyCode::Key3 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('#') - } else { - DecodedKey::Unicode('3') - } - } - KeyCode::Key4 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('$') - } else { - DecodedKey::Unicode('4') - } - } - KeyCode::Key5 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('%') - } else { - DecodedKey::Unicode('5') - } - } - KeyCode::Key6 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('&') - } else { - DecodedKey::Unicode('6') - } - } - KeyCode::Key7 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('\'') - } else { - DecodedKey::Unicode('7') - } - } - KeyCode::Key8 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('(') - } else { - DecodedKey::Unicode('8') - } - } - KeyCode::Key9 => { - if modifiers.is_shifted() { - DecodedKey::Unicode(')') - } else { - DecodedKey::Unicode('9') - } - } - KeyCode::Key0 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('~') - } else { - DecodedKey::Unicode('0') - } - } - KeyCode::OemMinus => { - if modifiers.is_shifted() { - DecodedKey::Unicode('=') - } else { - DecodedKey::Unicode('-') - } - } - KeyCode::OemPlus => { - if modifiers.is_shifted() { - DecodedKey::Unicode('¯') - } else { - DecodedKey::Unicode('^') - } - } - KeyCode::Oem4 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('`') - } else { - DecodedKey::Unicode('@') - } - } - KeyCode::Oem6 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('{') - } else { - DecodedKey::Unicode('[') - } - } - KeyCode::Oem7 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('}') - } else { - DecodedKey::Unicode(']') - } - } - KeyCode::Oem1 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('+') - } else { - DecodedKey::Unicode(';') - } - } - KeyCode::Oem3 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('*') - } else { - DecodedKey::Unicode(':') - } - } - KeyCode::Oem9 => { - // Muhenkan - DecodedKey::RawKey(keycode) - } - KeyCode::Oem10 => { - // Henkan/Zenkouho - DecodedKey::RawKey(keycode) - } - KeyCode::Oem11 => { - // Hiragana/Katakana - DecodedKey::RawKey(keycode) - } - KeyCode::Oem12 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('_') - } else { - DecodedKey::Unicode('\\') - } - } - KeyCode::Oem13 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('|') - } else { - DecodedKey::Unicode('¥') - } - } - - e => { - let us = super::Us104Key; - us.map_keycode(e, modifiers, handle_ctrl) - } + // ========= Row 2 (the numbers) ========= + // hankaku/zenkaku/kanji + KeyCode::Oem8 => DecodedKey::RawKey(keycode), + KeyCode::Key2 => modifiers.handle_symbol2('2', '"'), + KeyCode::Key6 => modifiers.handle_symbol2('6', '&'), + KeyCode::Key7 => modifiers.handle_symbol2('7', QUO), + KeyCode::Key8 => modifiers.handle_symbol2('8', '('), + KeyCode::Key9 => modifiers.handle_symbol2('9', ')'), + KeyCode::Key0 => modifiers.handle_symbol2('0', '~'), + KeyCode::OemMinus => modifiers.handle_symbol2('-', '='), + KeyCode::OemPlus => modifiers.handle_symbol2('^', '¯'), + KeyCode::Oem13 => modifiers.handle_symbol2('¥', '|'), + // ========= Row 3 (QWERTY) ========= + KeyCode::Oem4 => modifiers.handle_symbol2('@', '`'), + KeyCode::Oem6 => modifiers.handle_symbol2('[', '{'), + // ========= Row 4 (ASDFG) ========= + KeyCode::Oem1 => modifiers.handle_symbol2(';', '+'), + KeyCode::Oem3 => modifiers.handle_symbol2(':', '*'), + KeyCode::Oem7 => modifiers.handle_symbol2(']', '}'), + // ========= Row 5 (ZXCVB) ========= + KeyCode::Oem12 => modifiers.handle_symbol2(SLS, '_'), + // ========= Modifiers ========= + // Muhenkan + KeyCode::Oem9 => DecodedKey::RawKey(keycode), + // Henkan/Zenkouho + KeyCode::Oem10 => DecodedKey::RawKey(keycode), + // Hiragana/Katakana + KeyCode::Oem11 => DecodedKey::RawKey(keycode), + // ========= Fallback ========= + e => super::Us104Key.map_keycode(e, modifiers, handle_ctrl) } } + + fn get_physical(&self) -> PhysicalKeyboard { + PhysicalKeyboard::Jis + } } diff --git a/src/layouts/mod.rs b/src/layouts/mod.rs index 54bbc34..2369f7b 100644 --- a/src/layouts/mod.rs +++ b/src/layouts/mod.rs @@ -5,6 +5,8 @@ //! see [`Uk105Key`] and [`Us104Key`] as an example of that. mod dvorak_programmer104; +use crate::PhysicalKeyboard; + pub use self::dvorak_programmer104::DVP104Key; mod dvorak104; @@ -68,6 +70,21 @@ impl super::KeyboardLayout for AnyLayout { AnyLayout::FiSe105Key(inner) => inner.map_keycode(keycode, modifiers, handle_ctrl), } } + + fn get_physical(&self) -> PhysicalKeyboard { + match self { + AnyLayout::DVP104Key(inner) => inner.get_physical(), + AnyLayout::Dvorak104Key(inner) => inner.get_physical(), + AnyLayout::Us104Key(inner) => inner.get_physical(), + AnyLayout::Uk105Key(inner) => inner.get_physical(), + AnyLayout::Jis109Key(inner) => inner.get_physical(), + AnyLayout::Azerty(inner) => inner.get_physical(), + AnyLayout::Colemak(inner) => inner.get_physical(), + AnyLayout::De105Key(inner) => inner.get_physical(), + AnyLayout::No105Key(inner) => inner.get_physical(), + AnyLayout::FiSe105Key(inner) => inner.get_physical(), + } + } } impl super::KeyboardLayout for &AnyLayout { @@ -90,6 +107,21 @@ impl super::KeyboardLayout for &AnyLayout { AnyLayout::FiSe105Key(inner) => inner.map_keycode(keycode, modifiers, handle_ctrl), } } + + fn get_physical(&self) -> PhysicalKeyboard { + match self { + AnyLayout::DVP104Key(inner) => inner.get_physical(), + AnyLayout::Dvorak104Key(inner) => inner.get_physical(), + AnyLayout::Us104Key(inner) => inner.get_physical(), + AnyLayout::Uk105Key(inner) => inner.get_physical(), + AnyLayout::Jis109Key(inner) => inner.get_physical(), + AnyLayout::Azerty(inner) => inner.get_physical(), + AnyLayout::Colemak(inner) => inner.get_physical(), + AnyLayout::De105Key(inner) => inner.get_physical(), + AnyLayout::No105Key(inner) => inner.get_physical(), + AnyLayout::FiSe105Key(inner) => inner.get_physical(), + } + } } #[cfg(test)] diff --git a/src/layouts/no105.rs b/src/layouts/no105.rs index 1c3a8bb..f77ef1d 100644 --- a/src/layouts/no105.rs +++ b/src/layouts/no105.rs @@ -1,232 +1,185 @@ //! Norwegian keyboard support -use crate::{DecodedKey, HandleControl, KeyCode, KeyboardLayout, Modifiers}; +use crate::{ + DecodedKey, HandleControl, KeyCode, KeyboardLayout, Modifiers, PhysicalKeyboard, QUO, SLS, +}; /// A standard Norwegian 102-key (or 105-key including Windows keys) keyboard. /// /// Has a 2-row high Enter key, with Oem5 next to the left shift (ISO format). +/// +/// These diagrams illustrate the conversion from [`KeyCode`] to Unicode. We +/// show either a Unicode glyph, or a hex number if the glyph isn't a +/// printable character. Blank spaces are passed through as +/// [`DecodedKey::RawKey`]. +/// +/// Run the `print_keyboard` example to re-generate these images. +/// +/// ## Unmodified +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ | │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ + │ \ │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ q │ w │ e │ r │ t │ y │ u │ i │ o │ p │ å │ ¨ │ 000a │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐ │ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │ a │ s │ d │ f │ g │ h │ j │ k │ l │ ø │ æ │ ' │ │ │ 4 │ 5 │ 6 │ │ +/// ├────┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┴───────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ < │ z │ x │ c │ v │ b │ n │ m │ , │ . │ - │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├────┴┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ , │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +/// +/// ## Caps Lock +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ | │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ + │ \ │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │ Å │ ¨ │ 000a │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐ │ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │ A │ S │ D │ F │ G │ H │ J │ K │ L │ Ø │ Æ │ ' │ │ │ 4 │ 5 │ 6 │ │ +/// ├────┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┴───────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ < │ Z │ X │ C │ V │ B │ N │ M │ , │ . │ - │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├────┴┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ , │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +/// +/// ## Shifted +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ § │ ! │ " │ # │ ¤ │ % │ & │ / │ ( │ ) │ = │ ? │ ` │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │ Å │ ^ │ 000a │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐ │ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │ A │ S │ D │ F │ G │ H │ J │ K │ L │ Ø │ Æ │ * │ │ │ 4 │ 5 │ 6 │ │ +/// ├────┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┴───────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ > │ Z │ X │ C │ V │ B │ N │ M │ ; │ : │ _ │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├────┴┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ , │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +/// +/// ## Control +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ | │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ + │ \ │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │0011│0017│0005│0012│0014│0019│0015│0009│000f│0010│ å │ ¨ │ 000a │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐ │ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │0001│0013│0004│0006│0007│0008│000a│000b│000c│ ø │ æ │ ' │ │ │ 4 │ 5 │ 6 │ │ +/// ├────┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┴───────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ < │001a│0018│0003│0016│0002│000e│000d│ , │ . │ - │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├────┴┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ , │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +/// +/// ## AltGr +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ | │ 1 │ @ │ £ │ $ │ 5 │ 6 │ { │ [ │ ] │ } │ + │ ´ │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ q │ w │ € │ r │ t │ y │ u │ i │ o │ p │ å │ ~ │ 000a │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐ │ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │ a │ s │ d │ f │ g │ h │ j │ k │ l │ ø │ æ │ ' │ │ │ 4 │ 5 │ 6 │ │ +/// ├────┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┴───────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ < │ z │ x │ c │ v │ b │ n │ µ │ , │ . │ - │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├────┴┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ , │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +/// +/// ## Shift AltGr +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ § │ ! │ @ │ £ │ $ │ % │ & │ { │ [ │ ] │ } │ ? │ ´ │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ Q │ W │ € │ R │ T │ Y │ U │ I │ O │ P │ Å │ ~ │ 000a │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐ │ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │ A │ S │ D │ F │ G │ H │ J │ K │ L │ Ø │ Æ │ * │ │ │ 4 │ 5 │ 6 │ │ +/// ├────┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┴───────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ > │ Z │ X │ C │ V │ B │ N │ µ │ ; │ : │ _ │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├────┴┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ , │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` pub struct No105Key; impl KeyboardLayout for No105Key { + #[rustfmt::skip] fn map_keycode( &self, keycode: KeyCode, modifiers: &Modifiers, handle_ctrl: HandleControl, ) -> DecodedKey { - let map_to_unicode = handle_ctrl == HandleControl::MapLettersToUnicode; match keycode { - KeyCode::Escape => DecodedKey::Unicode(0x1B.into()), - KeyCode::Oem8 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('§') - } else { - DecodedKey::Unicode('|') - } - } - KeyCode::Key1 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('!') - } else { - DecodedKey::Unicode('1') - } - } - KeyCode::Key2 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('"') - } else if modifiers.is_altgr() { - DecodedKey::Unicode('@') - } else { - DecodedKey::Unicode('2') - } - } - KeyCode::Key3 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('#') - } else if modifiers.is_altgr() { - DecodedKey::Unicode('£') - } else { - DecodedKey::Unicode('3') - } - } - KeyCode::Key4 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('¤') - } else if modifiers.is_altgr() { - DecodedKey::Unicode('$') - } else { - DecodedKey::Unicode('4') - } - } - KeyCode::Key5 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('%') - } else if modifiers.is_altgr() { - DecodedKey::Unicode('€') - } else { - DecodedKey::Unicode('5') - } - } - KeyCode::Key6 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('&') - } else { - DecodedKey::Unicode('6') - } - } - KeyCode::Key7 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('/') - } else if modifiers.is_altgr() { - DecodedKey::Unicode('{') - } else { - DecodedKey::Unicode('7') - } - } - KeyCode::Key8 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('(') - } else if modifiers.is_altgr() { - DecodedKey::Unicode('[') - } else { - DecodedKey::Unicode('8') - } - } - KeyCode::Key9 => { - if modifiers.is_shifted() { - DecodedKey::Unicode(')') - } else if modifiers.is_altgr() { - DecodedKey::Unicode(']') - } else { - DecodedKey::Unicode('9') - } - } - KeyCode::Key0 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('=') - } else if modifiers.is_altgr() { - DecodedKey::Unicode('}') - } else { - DecodedKey::Unicode('0') - } - } - KeyCode::OemMinus => { - if modifiers.is_shifted() { - DecodedKey::Unicode('?') - } else { - DecodedKey::Unicode('+') - } - } - KeyCode::OemPlus => { - if modifiers.is_shifted() { - DecodedKey::Unicode('`') - } else if modifiers.is_altgr() { - DecodedKey::Unicode('´') - } else { - DecodedKey::Unicode('\\') - } - } - KeyCode::Backspace => DecodedKey::Unicode(0x08.into()), - KeyCode::Tab => DecodedKey::Unicode(0x09.into()), - KeyCode::E => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0005}') - } else if modifiers.is_altgr() { - DecodedKey::Unicode('€') - } else if modifiers.is_caps() { - DecodedKey::Unicode('E') - } else { - DecodedKey::Unicode('e') - } - } - KeyCode::Oem4 => { - if modifiers.is_caps() { - DecodedKey::Unicode('Å') - } else { - DecodedKey::Unicode('å') - } - } - KeyCode::Oem6 => { - if modifiers.is_altgr() { - DecodedKey::Unicode('~') - } else if modifiers.is_shifted() { - DecodedKey::Unicode('^') - } else { - DecodedKey::Unicode('¨') - } - } - KeyCode::Return => DecodedKey::Unicode(10.into()), - KeyCode::Oem7 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('*') - } else { - DecodedKey::Unicode('\'') - } - } - KeyCode::Oem1 => { - if modifiers.is_caps() { - DecodedKey::Unicode('Ø') - } else { - DecodedKey::Unicode('ø') - } - } - KeyCode::Oem3 => { - if modifiers.is_caps() { - DecodedKey::Unicode('Æ') - } else { - DecodedKey::Unicode('æ') - } - } - KeyCode::M => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{000D}') - } else if modifiers.is_altgr() { - DecodedKey::Unicode('µ') - } else if modifiers.is_caps() { - DecodedKey::Unicode('M') - } else { - DecodedKey::Unicode('m') - } - } - KeyCode::OemComma => { - if modifiers.is_shifted() { - DecodedKey::Unicode(';') - } else { - DecodedKey::Unicode(',') - } - } - KeyCode::OemPeriod => { - if modifiers.is_shifted() { - DecodedKey::Unicode(':') - } else { - DecodedKey::Unicode('.') - } - } - KeyCode::Oem2 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('_') - } else { - DecodedKey::Unicode('-') - } - } - KeyCode::Oem5 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('>') - } else { - DecodedKey::Unicode('<') - } - } - KeyCode::NumpadPeriod => { - if modifiers.numlock { - DecodedKey::Unicode(',') - } else { - DecodedKey::Unicode(127.into()) - } - } - e => { - let us = super::Us104Key; - us.map_keycode(e, modifiers, handle_ctrl) - } + // ========= Row 2 (the numbers) ========= + KeyCode::Oem8 => modifiers.handle_symbol2('|', '§'), + KeyCode::Key2 => modifiers.handle_symbol3('2', '"', '@'), + KeyCode::Key3 => modifiers.handle_symbol3('3', '#', '£'), + KeyCode::Key4 => modifiers.handle_symbol3('4', '¤', '$'), + KeyCode::Key5 => modifiers.handle_symbol2('5', '%'), + KeyCode::Key6 => modifiers.handle_symbol2('6', '&'), + KeyCode::Key7 => modifiers.handle_symbol3('7', '/', '{'), + KeyCode::Key8 => modifiers.handle_symbol3('8', '(', '['), + KeyCode::Key9 => modifiers.handle_symbol3('9', ')', ']'), + KeyCode::Key0 => modifiers.handle_symbol3('0', '=', '}'), + KeyCode::OemMinus => modifiers.handle_symbol2('+', '?'), + KeyCode::OemPlus => modifiers.handle_symbol3(SLS, '`', '´'), + // ========= Row 3 (QWERTY) ========= + KeyCode::E => modifiers.handle_ascii_3('E', '€', handle_ctrl), + KeyCode::Oem4 => modifiers.handle_letter2('å', 'Å'), + KeyCode::Oem6 => modifiers.handle_symbol3('¨', '^', '~'), + // ========= Row 4 (ASDF) ========= + KeyCode::Oem7 => modifiers.handle_symbol2(QUO, '*'), + KeyCode::Oem1 => modifiers.handle_letter2('ø', 'Ø'), + KeyCode::Oem3 => modifiers.handle_letter2('æ', 'Æ'), + // ========= Row 5 (ZXCV) ========= + KeyCode::Oem5 => modifiers.handle_symbol2('<', '>'), + KeyCode::M => modifiers.handle_ascii_3('M', 'µ', handle_ctrl), + KeyCode::OemComma => modifiers.handle_symbol2(',', ';'), + KeyCode::OemPeriod => modifiers.handle_symbol2('.', ':'), + KeyCode::Oem2 => modifiers.handle_symbol2('-', '_'), + // ========= Row 6 (modifers and space bar) ========= + KeyCode::NumpadPeriod if modifiers.numlock => DecodedKey::Unicode(','), + // ========= Fallback ========= + e => super::Us104Key.map_keycode(e, modifiers, handle_ctrl), } } + + fn get_physical(&self) -> PhysicalKeyboard { + PhysicalKeyboard::Iso + } } diff --git a/src/layouts/uk105.rs b/src/layouts/uk105.rs index a189913..88812ab 100644 --- a/src/layouts/uk105.rs +++ b/src/layouts/uk105.rs @@ -1,13 +1,145 @@ //! United Kingdom keyboard support -use crate::{DecodedKey, HandleControl, KeyCode, KeyboardLayout, Modifiers}; +use crate::{ + DecodedKey, HandleControl, KeyCode, KeyboardLayout, Modifiers, PhysicalKeyboard, QUO, SLS, +}; /// A standard United Kingdom 102-key (or 105-key including Windows keys) keyboard. /// /// Has a 2-row high Enter key, with Oem5 next to the left shift (ISO format). +/// +/// Based on US 101/104 key, with minor changes. +/// +/// These diagrams illustrate the conversion from [`KeyCode`] to Unicode. We +/// show either a Unicode glyph, or a hex number if the glyph isn't a +/// printable character. Blank spaces are passed through as +/// [`DecodedKey::RawKey`]. +/// +/// Run the `print_keyboard` example to re-generate these images. +/// +/// ## Unmodified +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ ` │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ - │ = │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ q │ w │ e │ r │ t │ y │ u │ i │ o │ p │ [ │ ] │ 000a │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐ │ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │ a │ s │ d │ f │ g │ h │ j │ k │ l │ ; │ ' │ # │ │ │ 4 │ 5 │ 6 │ │ +/// ├────┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┴───────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ \ │ z │ x │ c │ v │ b │ n │ m │ , │ . │ / │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├────┴┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ . │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +/// +/// ## Caps Lock +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ ` │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ - │ = │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │ [ │ ] │ 000a │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐ │ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │ A │ S │ D │ F │ G │ H │ J │ K │ L │ ; │ ' │ # │ │ │ 4 │ 5 │ 6 │ │ +/// ├────┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┴───────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ \ │ Z │ X │ C │ V │ B │ N │ M │ , │ . │ / │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├────┴┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ . │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +/// +/// ## Shifted +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ ¬ │ ! │ " │ £ │ $ │ % │ ^ │ & │ * │ ( │ ) │ _ │ + │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │ { │ } │ 000a │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐ │ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │ A │ S │ D │ F │ G │ H │ J │ K │ L │ : │ @ │ ~ │ │ │ 4 │ 5 │ 6 │ │ +/// ├────┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┴───────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ | │ Z │ X │ C │ V │ B │ N │ M │ < │ > │ ? │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├────┴┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ . │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +/// +/// ## Control +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ ` │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ - │ = │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │0011│0017│0005│0012│0014│0019│0015│0009│000f│0010│ [ │ ] │ 000a │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐ │ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │0001│0013│0004│0006│0007│0008│000a│000b│000c│ ; │ ' │ # │ │ │ 4 │ 5 │ 6 │ │ +/// ├────┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┴───────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ \ │001a│0018│0003│0016│0002│000e│000d│ , │ . │ / │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├────┴┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ . │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +/// +/// ## AltGr +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ ¦ │ 1 │ 2 │ 3 │ € │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ - │ = │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ q │ w │ é │ r │ t │ y │ ú │ í │ ó │ p │ [ │ ] │ 000a │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐ │ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │ á │ s │ d │ f │ g │ h │ j │ k │ l │ ; │ ' │ # │ │ │ 4 │ 5 │ 6 │ │ +/// ├────┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┴───────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ \ │ z │ x │ c │ v │ b │ n │ m │ , │ . │ / │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├────┴┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ . │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +/// +/// ## Shift AltGr +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ ¦ │ ! │ " │ £ │ € │ % │ ^ │ & │ * │ ( │ ) │ _ │ + │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ Q │ W │ É │ R │ T │ Y │ Ú │ Í │ Ó │ P │ { │ } │ 000a │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐ │ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │ Á │ S │ D │ F │ G │ H │ J │ K │ L │ : │ @ │ ~ │ │ │ 4 │ 5 │ 6 │ │ +/// ├────┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┴───────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ | │ Z │ X │ C │ V │ B │ N │ M │ < │ > │ ? │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├────┴┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ . │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` pub struct Uk105Key; impl KeyboardLayout for Uk105Key { + #[rustfmt::skip] fn map_keycode( &self, keycode: KeyCode, @@ -15,65 +147,25 @@ impl KeyboardLayout for Uk105Key { handle_ctrl: HandleControl, ) -> DecodedKey { match keycode { - KeyCode::Oem8 => { - if modifiers.is_altgr() { - DecodedKey::Unicode('|') - } else if modifiers.is_shifted() { - DecodedKey::Unicode('¬') - } else { - DecodedKey::Unicode('`') - } - } - KeyCode::Key2 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('"') - } else { - DecodedKey::Unicode('2') - } - } - KeyCode::Oem3 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('@') - } else { - DecodedKey::Unicode('\'') - } - } - KeyCode::Key3 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('£') - } else { - DecodedKey::Unicode('3') - } - } - KeyCode::Key4 => { - if modifiers.is_altgr() { - DecodedKey::Unicode('€') - } else if modifiers.is_shifted() { - DecodedKey::Unicode('$') - } else { - DecodedKey::Unicode('4') - } - } - KeyCode::Oem7 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('~') - } else { - DecodedKey::Unicode('#') - } - } - KeyCode::Oem5 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('|') - } else { - DecodedKey::Unicode('\\') - } - } - e => { - let us = super::Us104Key; - us.map_keycode(e, modifiers, handle_ctrl) - } + KeyCode::Key2 => modifiers.handle_symbol2('2', '"'), + KeyCode::Key3 => modifiers.handle_symbol2('3', '£'), + KeyCode::Key4 => modifiers.handle_symbol3('4', '$', '€'), + KeyCode::Oem3 => modifiers.handle_symbol2(QUO, '@'), + KeyCode::Oem5 => modifiers.handle_symbol2(SLS, '|'), + KeyCode::Oem7 => modifiers.handle_symbol2('#', '~'), + KeyCode::Oem8 => modifiers.handle_symbol3('`', '¬', '¦'), + KeyCode::E => modifiers.handle_ascii_4('E', 'é', 'É', handle_ctrl), + KeyCode::U => modifiers.handle_ascii_4('U', 'ú', 'Ú', handle_ctrl), + KeyCode::I => modifiers.handle_ascii_4('I', 'í', 'Í', handle_ctrl), + KeyCode::O => modifiers.handle_ascii_4('O', 'ó', 'Ó', handle_ctrl), + KeyCode::A => modifiers.handle_ascii_4('A', 'á', 'Á', handle_ctrl), + e => super::Us104Key.map_keycode(e, modifiers, handle_ctrl), } } + + fn get_physical(&self) -> PhysicalKeyboard { + PhysicalKeyboard::Iso + } } #[cfg(test)] diff --git a/src/layouts/us104.rs b/src/layouts/us104.rs index 6bcf85f..c9e0b64 100644 --- a/src/layouts/us104.rs +++ b/src/layouts/us104.rs @@ -1,488 +1,233 @@ -//! United States keyboard support +//! # United States keyboard support -use crate::{DecodedKey, HandleControl, KeyCode, KeyboardLayout, Modifiers}; +use crate::{ + DecodedKey, HandleControl, KeyCode, KeyboardLayout, Modifiers, PhysicalKeyboard, QUO, SLS, +}; /// A standard United States 101-key (or 104-key including Windows keys) keyboard. /// /// Has a 1-row high Enter key, with Oem5 above (ANSI layout). +/// +/// These diagrams illustrate the conversion from [`KeyCode`] to Unicode. We +/// show either a Unicode glyph, or a hex number if the glyph isn't a +/// printable character. Blank spaces are passed through as +/// [`DecodedKey::RawKey`]. +/// +/// Run the `print_keyboard` example to re-generate these images. +/// +/// ## Unmodified +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ ` │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ - │ = │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ q │ w │ e │ r │ t │ y │ u │ i │ o │ p │ [ │ ] │ \ │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴────────┤ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │ a │ s │ d │ f │ g │ h │ j │ k │ l │ ; │ ' │ 000a │ │ 4 │ 5 │ 6 │ │ +/// ├──────┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────────────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ z │ x │ c │ v │ b │ n │ m │ , │ . │ / │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├─────┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ . │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +/// +/// ## Caps Lock +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ ` │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ - │ = │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │ [ │ ] │ \ │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴────────┤ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │ A │ S │ D │ F │ G │ H │ J │ K │ L │ ; │ ' │ 000a │ │ 4 │ 5 │ 6 │ │ +/// ├──────┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────────────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ Z │ X │ C │ V │ B │ N │ M │ , │ . │ / │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├─────┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ . │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +/// +/// ## Shifted +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ ~ │ ! │ @ │ # │ $ │ % │ ^ │ & │ * │ ( │ ) │ _ │ + │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │ { │ } │ | │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴────────┤ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │ A │ S │ D │ F │ G │ H │ J │ K │ L │ : │ " │ 000a │ │ 4 │ 5 │ 6 │ │ +/// ├──────┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────────────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ Z │ X │ C │ V │ B │ N │ M │ < │ > │ ? │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├─────┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ . │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +/// +/// ## Control +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ ` │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ - │ = │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │0011│0017│0005│0012│0014│0019│0015│0009│000f│0010│ [ │ ] │ \ │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴────────┤ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │0001│0013│0004│0006│0007│0008│000a│000b│000c│ ; │ ' │ 000a │ │ 4 │ 5 │ 6 │ │ +/// ├──────┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────────────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │001a│0018│0003│0016│0002│000e│000d│ , │ . │ / │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├─────┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ . │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +/// +/// ## AltGr +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ ` │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ - │ = │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ q │ w │ e │ r │ t │ y │ u │ i │ o │ p │ [ │ ] │ \ │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴────────┤ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │ a │ s │ d │ f │ g │ h │ j │ k │ l │ ; │ ' │ 000a │ │ 4 │ 5 │ 6 │ │ +/// ├──────┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────────────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ z │ x │ c │ v │ b │ n │ m │ , │ . │ / │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├─────┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ . │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` +/// +/// ## Shift AltGr +/// +/// ```text +/// ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +/// │001b│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ +/// └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +/// +/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +/// │ ~ │ ! │ @ │ # │ $ │ % │ ^ │ & │ * │ ( │ ) │ _ │ + │ 0008 │ │ │ │ │ │ │ / │ * │ - │ +/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +/// │0009 │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │ { │ } │ | │ │007f│ │ │ │ 7 │ 8 │ 9 │ │ +/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴────────┤ └────┴────┴────┘ ├────┼────┼────┤ + │ +/// │ │ A │ S │ D │ F │ G │ H │ J │ K │ L │ : │ " │ 000a │ │ 4 │ 5 │ 6 │ │ +/// ├──────┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────────────┤ ┌────┐ ├────┼────┼────┼────┤ +/// │ │ Z │ X │ C │ V │ B │ N │ M │ < │ > │ ? │ │ │ │ │ 1 │ 2 │ 3 │ │ +/// ├─────┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤000a│ +/// │ │ │ │ 0020 │ │ │ │ │ │ │ │ │ │ 0 │ . │ │ +/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +/// ``` pub struct Us104Key; impl KeyboardLayout for Us104Key { + #[rustfmt::skip] fn map_keycode( &self, keycode: KeyCode, modifiers: &Modifiers, handle_ctrl: HandleControl, ) -> DecodedKey { - let map_to_unicode = handle_ctrl == HandleControl::MapLettersToUnicode; match keycode { - KeyCode::Oem8 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('~') - } else { - DecodedKey::Unicode('`') - } - } - KeyCode::Escape => DecodedKey::Unicode(0x1B.into()), - KeyCode::Key1 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('!') - } else { - DecodedKey::Unicode('1') - } - } - KeyCode::Key2 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('@') - } else { - DecodedKey::Unicode('2') - } - } - KeyCode::Key3 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('#') - } else { - DecodedKey::Unicode('3') - } - } - KeyCode::Key4 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('$') - } else { - DecodedKey::Unicode('4') - } - } - KeyCode::Key5 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('%') - } else { - DecodedKey::Unicode('5') - } - } - KeyCode::Key6 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('^') - } else { - DecodedKey::Unicode('6') - } - } - KeyCode::Key7 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('&') - } else { - DecodedKey::Unicode('7') - } - } - KeyCode::Key8 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('*') - } else { - DecodedKey::Unicode('8') - } - } - KeyCode::Key9 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('(') - } else { - DecodedKey::Unicode('9') - } - } - KeyCode::Key0 => { - if modifiers.is_shifted() { - DecodedKey::Unicode(')') - } else { - DecodedKey::Unicode('0') - } - } - KeyCode::OemMinus => { - if modifiers.is_shifted() { - DecodedKey::Unicode('_') - } else { - DecodedKey::Unicode('-') - } - } - KeyCode::OemPlus => { - if modifiers.is_shifted() { - DecodedKey::Unicode('+') - } else { - DecodedKey::Unicode('=') - } - } - KeyCode::Backspace => DecodedKey::Unicode(0x08.into()), - KeyCode::Tab => DecodedKey::Unicode(0x09.into()), - KeyCode::Q => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0011}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('Q') - } else { - DecodedKey::Unicode('q') - } - } - KeyCode::W => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0017}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('W') - } else { - DecodedKey::Unicode('w') - } - } - KeyCode::E => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0005}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('E') - } else { - DecodedKey::Unicode('e') - } - } - KeyCode::R => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0012}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('R') - } else { - DecodedKey::Unicode('r') - } - } - KeyCode::T => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0014}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('T') - } else { - DecodedKey::Unicode('t') - } - } - KeyCode::Y => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0019}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('Y') - } else { - DecodedKey::Unicode('y') - } - } - KeyCode::U => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0015}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('U') - } else { - DecodedKey::Unicode('u') - } - } - KeyCode::I => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0009}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('I') - } else { - DecodedKey::Unicode('i') - } - } - KeyCode::O => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{000F}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('O') - } else { - DecodedKey::Unicode('o') - } - } - KeyCode::P => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0010}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('P') - } else { - DecodedKey::Unicode('p') - } - } - KeyCode::Oem4 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('{') - } else { - DecodedKey::Unicode('[') - } - } - KeyCode::Oem6 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('}') - } else { - DecodedKey::Unicode(']') - } - } - KeyCode::Oem7 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('|') - } else { - DecodedKey::Unicode('\\') - } - } - KeyCode::A => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0001}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('A') - } else { - DecodedKey::Unicode('a') - } - } - KeyCode::S => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0013}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('S') - } else { - DecodedKey::Unicode('s') - } - } - KeyCode::D => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0004}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('D') - } else { - DecodedKey::Unicode('d') - } - } - KeyCode::F => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0006}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('F') - } else { - DecodedKey::Unicode('f') - } - } - KeyCode::G => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0007}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('G') - } else { - DecodedKey::Unicode('g') - } - } - KeyCode::H => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0008}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('H') - } else { - DecodedKey::Unicode('h') - } - } - KeyCode::J => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{000A}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('J') - } else { - DecodedKey::Unicode('j') - } - } - KeyCode::K => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{000B}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('K') - } else { - DecodedKey::Unicode('k') - } - } - KeyCode::L => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{000C}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('L') - } else { - DecodedKey::Unicode('l') - } - } - KeyCode::Oem1 => { - if modifiers.is_shifted() { - DecodedKey::Unicode(':') - } else { - DecodedKey::Unicode(';') - } - } - KeyCode::Oem3 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('"') - } else { - DecodedKey::Unicode('\'') - } - } - // Enter gives LF, not CRLF or CR - KeyCode::Return => DecodedKey::Unicode(10.into()), - KeyCode::Z => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{001A}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('Z') - } else { - DecodedKey::Unicode('z') - } - } - KeyCode::X => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0018}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('X') - } else { - DecodedKey::Unicode('x') - } - } - KeyCode::C => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0003}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('C') - } else { - DecodedKey::Unicode('c') - } - } - KeyCode::V => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0016}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('V') - } else { - DecodedKey::Unicode('v') - } - } - KeyCode::B => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{0002}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('B') - } else { - DecodedKey::Unicode('b') - } - } - KeyCode::N => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{000E}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('N') - } else { - DecodedKey::Unicode('n') - } - } - KeyCode::M => { - if map_to_unicode && modifiers.is_ctrl() { - DecodedKey::Unicode('\u{000D}') - } else if modifiers.is_caps() { - DecodedKey::Unicode('M') - } else { - DecodedKey::Unicode('m') - } - } - KeyCode::OemComma => { - if modifiers.is_shifted() { - DecodedKey::Unicode('<') - } else { - DecodedKey::Unicode(',') - } - } - KeyCode::OemPeriod => { - if modifiers.is_shifted() { - DecodedKey::Unicode('>') - } else { - DecodedKey::Unicode('.') - } - } - KeyCode::Oem2 => { - if modifiers.is_shifted() { - DecodedKey::Unicode('?') - } else { - DecodedKey::Unicode('/') - } - } - KeyCode::Spacebar => DecodedKey::Unicode(' '), - KeyCode::Delete => DecodedKey::Unicode(127.into()), - KeyCode::NumpadDivide => DecodedKey::Unicode('/'), - KeyCode::NumpadMultiply => DecodedKey::Unicode('*'), - KeyCode::NumpadSubtract => DecodedKey::Unicode('-'), - KeyCode::Numpad7 => { - if modifiers.numlock { - DecodedKey::Unicode('7') - } else { - DecodedKey::RawKey(KeyCode::Home) - } - } - KeyCode::Numpad8 => { - if modifiers.numlock { - DecodedKey::Unicode('8') - } else { - DecodedKey::RawKey(KeyCode::ArrowUp) - } - } - KeyCode::Numpad9 => { - if modifiers.numlock { - DecodedKey::Unicode('9') - } else { - DecodedKey::RawKey(KeyCode::PageUp) - } - } - KeyCode::NumpadAdd => DecodedKey::Unicode('+'), - KeyCode::Numpad4 => { - if modifiers.numlock { - DecodedKey::Unicode('4') - } else { - DecodedKey::RawKey(KeyCode::ArrowLeft) - } - } - KeyCode::Numpad5 => DecodedKey::Unicode('5'), - KeyCode::Numpad6 => { - if modifiers.numlock { - DecodedKey::Unicode('6') - } else { - DecodedKey::RawKey(KeyCode::ArrowRight) - } - } - KeyCode::Numpad1 => { - if modifiers.numlock { - DecodedKey::Unicode('1') - } else { - DecodedKey::RawKey(KeyCode::End) - } - } - KeyCode::Numpad2 => { - if modifiers.numlock { - DecodedKey::Unicode('2') - } else { - DecodedKey::RawKey(KeyCode::ArrowDown) - } - } - KeyCode::Numpad3 => { - if modifiers.numlock { - DecodedKey::Unicode('3') - } else { - DecodedKey::RawKey(KeyCode::PageDown) - } - } - KeyCode::Numpad0 => { - if modifiers.numlock { - DecodedKey::Unicode('0') - } else { - DecodedKey::RawKey(KeyCode::Insert) - } - } - KeyCode::NumpadPeriod => { - if modifiers.numlock { - DecodedKey::Unicode('.') - } else { - DecodedKey::Unicode(127.into()) - } - } - KeyCode::NumpadEnter => DecodedKey::Unicode(10.into()), - k => DecodedKey::RawKey(k), + // ========= Row 2 (the numbers) ========= + KeyCode::Oem8 => modifiers.handle_symbol2('`', '~'), + KeyCode::Escape => DecodedKey::Unicode('\u{001B}'), + KeyCode::Key1 => modifiers.handle_symbol2('1', '!'), + KeyCode::Key2 => modifiers.handle_symbol2('2', '@'), + KeyCode::Key3 => modifiers.handle_symbol2('3', '#'), + KeyCode::Key4 => modifiers.handle_symbol2('4', '$'), + KeyCode::Key5 => modifiers.handle_symbol2('5', '%'), + KeyCode::Key6 => modifiers.handle_symbol2('6', '^'), + KeyCode::Key7 => modifiers.handle_symbol2('7', '&'), + KeyCode::Key8 => modifiers.handle_symbol2('8', '*'), + KeyCode::Key9 => modifiers.handle_symbol2('9', '('), + KeyCode::Key0 => modifiers.handle_symbol2('0', ')'), + KeyCode::OemMinus => modifiers.handle_symbol2('-', '_'), + KeyCode::OemPlus => modifiers.handle_symbol2('=', '+'), + KeyCode::Backspace => DecodedKey::Unicode('\u{0008}'), + // ========= Row 3 (QWERTY) ========= + KeyCode::Tab => DecodedKey::Unicode('\u{0009}'), + KeyCode::Q => modifiers.handle_ascii_2('Q', handle_ctrl), + KeyCode::W => modifiers.handle_ascii_2('W', handle_ctrl), + KeyCode::E => modifiers.handle_ascii_2('E', handle_ctrl), + KeyCode::R => modifiers.handle_ascii_2('R', handle_ctrl), + KeyCode::T => modifiers.handle_ascii_2('T', handle_ctrl), + KeyCode::Y => modifiers.handle_ascii_2('Y', handle_ctrl), + KeyCode::U => modifiers.handle_ascii_2('U', handle_ctrl), + KeyCode::I => modifiers.handle_ascii_2('I', handle_ctrl), + KeyCode::O => modifiers.handle_ascii_2('O', handle_ctrl), + KeyCode::P => modifiers.handle_ascii_2('P', handle_ctrl), + KeyCode::Oem4 => modifiers.handle_symbol2('[', '{'), + KeyCode::Oem6 => modifiers.handle_symbol2(']', '}'), + KeyCode::Oem7 => modifiers.handle_symbol2(SLS, '|'), + // ========= Row 4 (ASDFG) ========= + KeyCode::A => modifiers.handle_ascii_2('A', handle_ctrl), + KeyCode::S => modifiers.handle_ascii_2('S', handle_ctrl), + KeyCode::D => modifiers.handle_ascii_2('D', handle_ctrl), + KeyCode::F => modifiers.handle_ascii_2('F', handle_ctrl), + KeyCode::G => modifiers.handle_ascii_2('G', handle_ctrl), + KeyCode::H => modifiers.handle_ascii_2('H', handle_ctrl), + KeyCode::J => modifiers.handle_ascii_2('J', handle_ctrl), + KeyCode::K => modifiers.handle_ascii_2('K', handle_ctrl), + KeyCode::L => modifiers.handle_ascii_2('L', handle_ctrl), + KeyCode::Oem1 => modifiers.handle_symbol2(';', ':'), + KeyCode::Oem3 => modifiers.handle_symbol2(QUO, '"'), + KeyCode::Return => DecodedKey::Unicode('\u{000A}'), + // ========= Row 5 (ZXCVB) ========= + KeyCode::Z => modifiers.handle_ascii_2('Z', handle_ctrl), + KeyCode::X => modifiers.handle_ascii_2('X', handle_ctrl), + KeyCode::C => modifiers.handle_ascii_2('C', handle_ctrl), + KeyCode::V => modifiers.handle_ascii_2('V', handle_ctrl), + KeyCode::B => modifiers.handle_ascii_2('B', handle_ctrl), + KeyCode::N => modifiers.handle_ascii_2('N', handle_ctrl), + KeyCode::M => modifiers.handle_ascii_2('M', handle_ctrl), + KeyCode::OemComma => modifiers.handle_symbol2(',', '<'), + KeyCode::OemPeriod => modifiers.handle_symbol2('.', '>'), + KeyCode::Oem2 => modifiers.handle_symbol2('/', '?'), + // ========= Unicode Specials ========= + KeyCode::Spacebar => DecodedKey::Unicode(' '), + KeyCode::Delete => DecodedKey::Unicode('\u{007f}'), + // ========= Numpad ========= + KeyCode::NumpadDivide => DecodedKey::Unicode('/'), + KeyCode::NumpadMultiply => DecodedKey::Unicode('*'), + KeyCode::NumpadSubtract => DecodedKey::Unicode('-'), + KeyCode::Numpad7 => modifiers.handle_num_pad('7', KeyCode::Home), + KeyCode::Numpad8 => modifiers.handle_num_pad('8', KeyCode::ArrowUp), + KeyCode::Numpad9 => modifiers.handle_num_pad('9', KeyCode::PageUp), + KeyCode::NumpadAdd => DecodedKey::Unicode('+'), + KeyCode::Numpad4 => modifiers.handle_num_pad('4', KeyCode::ArrowLeft), + KeyCode::Numpad5 => DecodedKey::Unicode('5'), + KeyCode::Numpad6 => modifiers.handle_num_pad('6', KeyCode::ArrowRight), + KeyCode::Numpad1 => modifiers.handle_num_pad('1', KeyCode::End), + KeyCode::Numpad2 => modifiers.handle_num_pad('2', KeyCode::ArrowDown), + KeyCode::Numpad3 => modifiers.handle_num_pad('3', KeyCode::PageDown), + KeyCode::Numpad0 => modifiers.handle_num_pad('0', KeyCode::Insert), + KeyCode::NumpadPeriod => modifiers.handle_num_del('.', '\u{007f}'), + KeyCode::NumpadEnter => DecodedKey::Unicode('\u{000A}'), + // ========= Fallback ========= + k => DecodedKey::RawKey(k), } } + + fn get_physical(&self) -> PhysicalKeyboard { + PhysicalKeyboard::Ansi + } } #[cfg(test)] @@ -551,4 +296,99 @@ mod test { assert_eq!(Some(DecodedKey::Unicode(unicode)), dec.process_keyevent(ev)); } } + + #[test] + fn lowercase() { + let modifiers = Modifiers { + capslock: false, + lalt: false, + lctrl: false, + lshift: false, + numlock: false, + ralt: false, + rctrl: false, + rctrl2: false, + rshift: false, + }; + assert_eq!( + modifiers.handle_ascii_2('A', HandleControl::MapLettersToUnicode), + DecodedKey::Unicode('a') + ); + } + + #[test] + fn uppercase() { + let modifiers = Modifiers { + capslock: true, + lalt: false, + lctrl: false, + lshift: false, + numlock: false, + ralt: false, + rctrl: false, + rctrl2: false, + rshift: false, + }; + assert_eq!( + modifiers.handle_ascii_2('A', HandleControl::MapLettersToUnicode), + DecodedKey::Unicode('A') + ); + } + + #[test] + fn shifted() { + let modifiers = Modifiers { + capslock: false, + lalt: false, + lctrl: false, + lshift: true, + numlock: false, + ralt: false, + rctrl: false, + rctrl2: false, + rshift: false, + }; + assert_eq!( + modifiers.handle_ascii_2('A', HandleControl::MapLettersToUnicode), + DecodedKey::Unicode('A') + ); + } + + #[test] + fn shift_caps() { + let modifiers = Modifiers { + capslock: true, + lalt: false, + lctrl: false, + lshift: true, + numlock: false, + ralt: false, + rctrl: false, + rctrl2: false, + rshift: false, + }; + assert_eq!( + modifiers.handle_ascii_2('A', HandleControl::MapLettersToUnicode), + DecodedKey::Unicode('a') + ); + } + + #[test] + fn ctrl() { + let modifiers = Modifiers { + capslock: true, + lalt: false, + lctrl: true, + lshift: true, + numlock: false, + ralt: false, + rctrl: false, + rctrl2: false, + rshift: false, + }; + assert_eq!( + modifiers.handle_ascii_2('A', HandleControl::MapLettersToUnicode), + DecodedKey::Unicode('\u{0001}') + ); + } } diff --git a/src/lib.rs b/src/lib.rs index 172102a..3f61270 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,19 +3,302 @@ //! Supports PS/2 Scan Code Set 1 and 2, on a variety of keyboard layouts. See //! [the OSDev Wiki](https://wiki.osdev.org/PS/2_Keyboard). //! -//! There are three basic steps to handling keyboard input. Your application may bypass some of these. +//! ## Supports: //! -//! * [`Ps2Decoder`] - converts 11-bit PS/2 words into bytes, removing the start/stop +//! - Scancode Set 1 (from the i8042 PC keyboard controller) +//! - Scancode Set 2 (direct from the AT or PS/2 interface keyboard) +//! - Several keyboard layouts: +//! +//! | Name | No. Keys | Description | Link | +//! | --------------------------------------- | -------- | ------------------------------------------------------------------------ | ----------------------------------------------------------------------------------- | +//! | [`Us104Key`](layouts::Us104Key) | 101/104 | North American standard English | [Wikipedia](https://en.wikipedia.org/wiki/QWERTY#United_States) | +//! | [`Uk105Key`](layouts::Uk105Key) | 102/105 | United Kingdom standard English | [Wikipedia](https://en.wikipedia.org/wiki/QWERTY#United_Kingdom) | +//! | [`Azerty`](layouts::Azerty) | 102/105 | Typically used in French locales | [Wikipedia](https://en.wikipedia.org/wiki/AZERTY) | +//! | [`De105Key`](layouts::De105Key) | 102/105 | German layout | [Wikipedia](https://en.wikipedia.org/wiki/QWERTZ) | +//! | [`FiSe105Key`](layouts::FiSe105Key) | 102/105 | Finnish/Swedish layout | [Wikipedia](https://en.wikipedia.org/wiki/QWERTY#Finnish%E2%80%93Swedish) | +//! | [`No105Key`](layouts::No105Key) | 102/105 | Norwegian layout | [Wikipedia](https://en.wikipedia.org/wiki/QWERTY#Norwegian) | +//! | [`Jis109Key`](layouts::Jis109Key) | 106/109 | JIS 109-key layout (Latin chars only) | [Wikipedia](https://en.wikipedia.org/wiki/Japanese_input_method#Japanese_keyboards) | +//! | [`Colemak`](layouts::Colemak) | 101/104 | A keyboard layout designed to make typing more efficient and comfortable | [Wikipedia](https://en.wikipedia.org/wiki/Colemak) | +//! | [`Dvorak104Key`](layouts::Dvorak104Key) | 101/104 | The more 'ergonomic' alternative to QWERTY | [Wikipedia](https://en.wikipedia.org/wiki/Dvorak_keyboard_layout) | +//! | [`DVP104Key`](layouts::DVP104Key) | 101/104 | Dvorak for Programmers | [Wikipedia](https://en.wikipedia.org/wiki/Dvorak_keyboard_layout#Programmer_Dvorak) | +//! +//! 101/104 keys is ANSI layout (wide Enter key) and 102/105 keys is ISO layout +//! (tall Enter key). The difference between 101 and 104 (and between 102 and +//! 105) comes from the two Windows keys and the Menu key that were added when +//! Windows 95 came out. JIS keyboards have extra keys, added by making the +//! space-bar and backspace keys shorter. +//! +//! ## Usage +//! +//! There are three basic steps to handling keyboard input. Your application +//! may bypass some of these. +//! +//! * `Ps2Decoder` - converts 11-bit PS/2 words into bytes, removing the start/stop //! bits and checking the parity bits. Only needed if you talk to the PS/2 //! keyboard over GPIO pins and not required if you talk to the i8042 PC keyboard //! controller. -//! * [`ScancodeSet`] - converts from Scancode Set 1 (i8042 PC keyboard controller) or -//! Scancode Set 2 (raw PS/2 keyboard output) into a symbolic [`KeyCode`] and an -//! up/down [`KeyState`]. -//! * [`EventDecoder`] - converts symbolic [`KeyCode`] and [`KeyState`] into a Unicode -//! characters (where possible) according to the currently selected `KeyboardLayout`. +//! * `ScancodeSet` - converts from Scancode Set 1 (i8042 PC keyboard controller) or +//! Scancode Set 2 (raw PS/2 keyboard output) into a symbolic `KeyCode` and an +//! up/down `KeyState`. +//! * `EventDecoder` - converts symbolic `KeyCode` and `KeyState` into a +//! Unicode characters (where possible) according to the currently selected +//! `KeyboardLayout`. +//! +//! There is also `Keyboard` which combines the above three functions into a +//! single object. +//! +//! See the [`examples`](./examples) folder for more details. +//! +//! ## Keycodes +//! +//! This crate uses symbolic keycodes to abstract over Scancode Set 1 and +//! Scancode Set 2. They represented by the `KeyCode` enum. The scancodes can +//! come from one of three supported physical keyboard layouts: 102/105 key +//! ISO, 101/104 key ANSI and 106/109-key JIS. Note that the symbolic +//! keycodes for letter keys are named after how the keys are used on a US or +//! UK English Keyboard. If you use a French AZERTY layout, the `KeyCode::Q` +//! key will produce the Unicode character `'A'`. +//! +//! ### 102/105 key [ISO](PhysicalKeyboard::Iso) +//! +//! This is the mapping of `KeyCode` to a 102/105-key ISO keyboard: +//! +//! ```text +//! ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +//! │Esc │ │ F1 │ F2 │ F3 │ F4 │ │ F5 │ F6 │ F7 │ F8 │ │ F9 │F10 │F11 │F12 │ │PrSc│Scrl│PBrk│ +//! └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +//! +//! ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +//! │Oem8│Key1│Key2│Key3│Key4│Key5│Key6│Key7│Key8│Key9│Key0│Oem─│Oem+│Backspace│ │Inse│Home│PgUp│ │NumL│Num/│Num*│Num─│ +//! ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +//! │ Tab │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │Oem4│Oem6│ Enter │ │Dele│End │PgDo│ │Num7│Num8│Num9│ │ +//! ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐ │ └────┴────┴────┘ ├────┼────┼────┤Num+│ +//! │CapsLo│ A │ S │ D │ F │ G │ H │ J │ K │ L │Oem1│Oem3│Oem7│ │ │Num4│Num5│Num6│ │ +//! ├────┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┴───────┤ ┌────┐ ├────┼────┼────┼────┤ +//! │LShf│Oem5│ Z │ X │ C │ V │ B │ N │ M │OemC│OemP│Oem2│ RShift │ │ Up │ │Num1│Num2│Num3│ │ +//! ├────┴┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤Num │ +//! │LCtrl│LWin │ Alt │ Space │AltGr│RWin │ Menu │RCtrl │ │Left│Down│Righ│ │Num0 │NumP│Ente│ +//! └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +//! ``` +//! +//! The 102-key is missing `LWin`, `RWin`, and `Menu`. +//! +//! (Reference: ) +//! +//! ### 101/104 key [ANSI](PhysicalKeyboard::Ansi) +//! +//! This is the mapping of `KeyCode` to a 101/104-key ANSI keyboard: +//! +//! ```text +//! ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +//! │Esc │ │ F1 │ F2 │ F3 │ F4 │ │ F5 │ F6 │ F7 │ F8 │ │ F9 │F10 │F11 │F12 │ │PrSc│Scrl│PBrk│ +//! └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +//! +//! ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +//! │Oem8│Key1│Key2│Key3│Key4│Key5│Key6│Key7│Key8│Key9│Key0│Oem─│Oem+│Backspace│ │Inse│Home│PgUp│ │NumL│Num/│Num*│Num─│ +//! ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +//! │ Tab │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │Oem4│Oem6│ Oem7 │ │Dele│End │PgDo│ │Num7│Num8│Num9│ │ +//! ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴────────┤ └────┴────┴────┘ ├────┼────┼────┤Num+│ +//! │CapsLo│ A │ S │ D │ F │ G │ H │ J │ K │ L │Oem1│Oem3│ Enter │ │Num4│Num5│Num6│ │ +//! ├──────┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────────────┤ ┌────┐ ├────┼────┼────┼────┤ +//! │ LShift │ Z │ X │ C │ V │ B │ N │ M │OemC│OemP│Oem2│ RShift │ │ Up │ │Num1│Num2│Num3│ │ +//! ├─────┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤Num │ +//! │LCtrl│LWin │ Alt │ Space │AltGr│RWin │ Menu │RCtrl │ │Left│Down│Righ│ │Num0 │NumP│Ente│ +//! └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +//! ``` +//! +//! Note that the `Oem5` key is missing on the 104-key ANSI keyboard. +//! +//! The 101-key is also missing `LWin`, `RWin`, and `Menu`. +//! +//! (Reference: ) +//! +//! ### 106/109 key [JIS](PhysicalKeyboard::Jis) +//! +//! This is the mapping of `KeyCode` to a 106/109-key JIS keyboard: //! -//! There is also [`Keyboard`] which combines the above three functions into a single object. +//! ```text +//! ┌────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┬────┐ ┌────┬────┬────┐ +//! │Esc │ │ F1 │ F2 │ F3 │ F4 │ │ F5 │ F6 │ F7 │ F8 │ │ F9 │F10 │F11 │F12 │ │PrSc│Scrl│PBrk│ +//! └────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┴────┘ └────┴────┴────┘ +//! +//! ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐ ┌────┬────┬────┐ ┌────┬────┬────┬────┐ +//! │Oem8│Key1│Key2│Key3│Key4│Key5│Key6│Key7│Key8│Key9│Key0│Oem─│Oem+│Om13│BkSp│ │Inse│Home│PgUp│ │NumL│Num/│Num*│Num─│ +//! ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤ ├────┼────┼────┤ ├────┼────┼────┼────┤ +//! │ Tab │ Q │ W │ E │ R │ T │ Y │ U │ I │ O │ P │Oem4│Oem6│ Enter │ │Dele│End │PgDo│ │Num7│Num8│Num9│ │ +//! ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐ │ └────┴────┴────┘ ├────┼────┼────┤Num+│ +//! │CapsLo│ A │ S │ D │ F │ G │ H │ J │ K │ L │Oem1│Oem3│Oem7│ │ │Num4│Num5│Num6│ │ +//! ├──────┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┴───────┤ ┌────┐ ├────┼────┼────┼────┤ +//! │LShift │ Z │ X │ C │ V │ B │ N │ M │OemC│OemP│Oem2│Oem12 │RShift │ │ Up │ │Num1│Num2│Num3│ │ +//! ├─────┬───┴─┬──┴──┬─┴───┬┴────┴────┴────┴────┴┬───┴─┬──┴──┬─┴──┬───┴┬──────┤ ┌────┼────┼────┐ ├────┴────┼────┤Num │ +//! │LCtrl│LWin │LAlt │Oem9 │ Space Bar │Oem10│Oem11│RWin│Menu│RCtrl │ │Left│Down│Righ│ │Num0 │NumP│Ente│ +//! └─────┴─────┴─────┴─────┴─────────────────────┴─────┴─────┴────┴────┴──────┘ └────┴────┴────┘ └─────────┴────┴────┘ +//! ``` +//! +//! Note that the `Oem5` is missing on the 109-key JIS layout, but `Oem9` +//! (Muhenkan), `Oem10` (Henkan/Zenkouho), `Oem11` +//! (Hiragana/Katakana), `Oem12` (Backslash) and `Oem13` (¥) are added. +//! +//! The 106-key is missing `LWin`, `RWin`, and `Menu`. +//! +//! (Reference: ) +//! +//! ### Conversion Table +//! +//! Scancode Set 1 and Scancode Set 2 can be losslessly converted. Indeed, this is +//! what the i8042 keyboard controller in your PC does - it takes Scancode Set 2 +//! from the keyboard and provides Scancode Set 1 to the Operating System. This +//! allowed them to change the keyboard design without breaking compatibility with +//! any MS-DOS applications that read raw scancodes from the keyboard. +//! +//! This table shows the correspondence between our symbolic KeyCode, Scancode Set 1 +//! and Scancode Set 2. We may extend this in the future to also handle USB HID +//! Scancodes. Any codes prefixed `0xE0` or `0xE1` are *extended* multi-byte +//! scancodes. Typically these are keys that were not on the IBM PC and PC/XT +//! keyboards so they they were added in such a way that if you ignored the 0xE0, +//! you got a reasonable result anyway. For example `ArrowLeft` is `0xE04B` in +//! Scancode Set 1 because `Numpad4` is `0x4B` and that was the left-arrow key on an +//! IBM PC or PC/XT. +//! +//! | Symbolic Key | Scancode Set 1 | Scancode Set 2 | +//! | -------------- | -------------- | -------------- | +//! | Escape | 0x01 | 0x76 | +//! | F1 | 0x3B | 0x05 | +//! | F2 | 0x3C | 0x06 | +//! | F3 | 0x3D | 0x04 | +//! | F4 | 0x3E | 0x0C | +//! | F5 | 0x3F | 0x03 | +//! | F6 | 0x40 | 0x0B | +//! | F7 | 0x41 | 0x83 | +//! | F8 | 0x42 | 0x0A | +//! | F9 | 0x43 | 0x01 | +//! | F10 | 0x44 | 0x09 | +//! | F11 | 0x57 | 0x78 | +//! | F12 | 0x58 | 0x07 | +//! | PrintScreen | 0xE037 | 0xE07C | +//! | SysRq | 0x54 | 0x7F | +//! | ScrollLock | 0x46 | 0x7E | +//! | PauseBreak | -- | -- | +//! | - | -- | -- | +//! | Oem8 | 0x29 | 0x0E | +//! | Key1 | 0x02 | 0x16 | +//! | Key2 | 0x03 | 0x1E | +//! | Key3 | 0x04 | 0x26 | +//! | Key4 | 0x05 | 0x25 | +//! | Key5 | 0x06 | 0x2E | +//! | Key6 | 0x07 | 0x36 | +//! | Key7 | 0x08 | 0x3D | +//! | Key8 | 0x09 | 0x3E | +//! | Key9 | 0x0A | 0x46 | +//! | Key0 | 0x0B | 0x45 | +//! | OemMinus | 0x0C | 0x4E | +//! | OemPlus | 0x0D | 0x55 | +//! | Backspace | 0x0E | 0x66 | +//! | Insert | 0xE052 | 0xE070 | +//! | Home | 0xE047 | 0xE06C | +//! | PageUp | 0xE049 | 0xE07D | +//! | NumpadLock | 0x45 | 0x77 | +//! | NumpadDivide | 0xE035 | 0xE04A | +//! | NumpadMultiply | 0x37 | 0x7C | +//! | NumpadSubtract | 0x4A | 0x7B | +//! | - | -- | -- | +//! | Tab | 0x0F | 0x0D | +//! | Q | 0x10 | 0x15 | +//! | W | 0x11 | 0x1D | +//! | E | 0x12 | 0x24 | +//! | R | 0x13 | 0x2D | +//! | T | 0x14 | 0x2C | +//! | Y | 0x15 | 0x35 | +//! | U | 0x16 | 0x3C | +//! | I | 0x17 | 0x43 | +//! | O | 0x18 | 0x44 | +//! | P | 0x19 | 0x4D | +//! | Oem4 | 0x1A | 0x54 | +//! | Oem6 | 0x1B | 0x5B | +//! | Oem5 | 0x56 | 0x61 | +//! | Oem7 | 0x2B | 0x5D | +//! | Delete | 0xE053 | 0xE071 | +//! | End | 0xE04F | 0xE069 | +//! | PageDown | 0xE051 | 0xE07A | +//! | Numpad7 | 0x47 | 0x6C | +//! | Numpad8 | 0x48 | 0x75 | +//! | Numpad9 | 0x49 | 0x7D | +//! | NumpadAdd | 0x4E | 0x79 | +//! | - | -- | -- | +//! | CapsLock | 0x3A | 0x58 | +//! | A | 0x1E | 0x1C | +//! | S | 0x1F | 0x1B | +//! | D | 0x20 | 0x23 | +//! | F | 0x21 | 0x2B | +//! | G | 0x22 | 0x34 | +//! | H | 0x23 | 0x33 | +//! | J | 0x24 | 0x3B | +//! | K | 0x25 | 0x42 | +//! | L | 0x26 | 0x4B | +//! | Oem1 | 0x27 | 0x4C | +//! | Oem3 | 0x28 | 0x52 | +//! | Return | 0x1C | 0x5A | +//! | Numpad4 | 0x4B | 0x6B | +//! | Numpad5 | 0x4C | 0x73 | +//! | Numpad6 | 0x4D | 0x74 | +//! | - | -- | -- | +//! | LShift | 0x2A | 0x12 | +//! | Z | 0x2C | 0x1A | +//! | X | 0x2D | 0x22 | +//! | C | 0x2E | 0x21 | +//! | V | 0x2F | 0x2A | +//! | B | 0x30 | 0x32 | +//! | N | 0x31 | 0x31 | +//! | M | 0x32 | 0x3A | +//! | OemComma | 0x33 | 0x41 | +//! | OemPeriod | 0x34 | 0x49 | +//! | Oem2 | 0x35 | 0x4A | +//! | RShift | 0x36 | 0x59 | +//! | ArrowUp | 0xE048 | 0xE075 | +//! | Numpad1 | 0x4F | 0x69 | +//! | Numpad2 | 0x50 | 0x72 | +//! | Numpad3 | 0x51 | 0x7A | +//! | NumpadEnter | 0xE01C | 0xE075 | +//! | - | -- | -- | +//! | LControl | 0x1D | 0x14 | +//! | LWin | 0xE05B | 0xE01F | +//! | LAlt | 0x38 | 0x11 | +//! | Spacebar | 0x39 | 0x29 | +//! | RAltGr | 0xE038 | 0xE011 | +//! | RWin | 0xE05C | 0xE027 | +//! | Apps | 0xE05C | 0xE02F | +//! | RControl | 0xE01D | 0xE014 | +//! | ArrowLeft | 0xE04B | 0xE06B | +//! | ArrowDown | 0xE050 | 0xE072 | +//! | ArrowRight | 0xE04D | 0xE074 | +//! | Numpad0 | 0x52 | 0x70 | +//! | NumpadPeriod | 0x53 | 0x71 | +//! | - | -- | -- | +//! | Oem9 | 0x7B | 0x67 | +//! | Oem10 | 0x79 | 0x64 | +//! | Oem11 | 0x70 | 0x13 | +//! | Oem12 | 0x73 | 0x51 | +//! | Oem13 | 0x7D | 0x6A | +//! | - | -- | -- | +//! | PrevTrack | 0xE010 | 0xE015 | +//! | NextTrack | 0xE019 | 0xE04D | +//! | Mute | 0xE020 | 0xE023 | +//! | Calculator | 0xE021 | 0xE02B | +//! | Play | 0xE022 | 0xE034 | +//! | Stop | 0xE024 | 0xE03B | +//! | VolumeDown | 0xE02E | 0xE021 | +//! | VolumeUp | 0xE030 | 0xE032 | +//! | WWWHome | 0xE032 | 0xE03A | +//! | TooManyKeys | -- | 0x00 | +//! | PowerOnTestOk | -- | 0xAA | +//! | RControl2 | 0xE11D | 0xE114 | +//! | RAlt2 | 0xE02A | 0xE012 | +//! +//! __Note 1:__ `PauseBreak` does not have a scancode because it's something we infer from a +//! sequence of other keypresses (`NumLock` with `RControl2` held). +//! +//! __Note 2:__ `SysReq` doesn't have a key on the diagram, because the scancode is +//! only generated when you do `Alt` + `PrintScreen`. #![cfg_attr(not(test), no_std)] @@ -394,6 +677,16 @@ pub struct KeyEvent { pub state: KeyState, } +/// Describes a physical keyboard +pub enum PhysicalKeyboard { + /// 102 or 105 key ISO, as used by UK English keyboards (and others) + Iso, + /// 101 or 104 key ANSI, as used by US English keyboards (and others) + Ansi, + /// 106 or 109 key JIS, as used by Japanese keyboards (and others) + Jis, +} + /// Describes a Keyboard Layout. /// /// Layouts might include "en_US", or "en_GB", or "de_GR". @@ -408,6 +701,9 @@ pub trait KeyboardLayout { modifiers: &Modifiers, handle_ctrl: HandleControl, ) -> DecodedKey; + + /// Which physical keyboard does this layout work on? + fn get_physical(&self) -> PhysicalKeyboard; } /// A mechanism to convert bytes from a Keyboard into [`KeyCode`] values. @@ -484,6 +780,9 @@ const EXTENDED_KEY_CODE: u8 = 0xE0; const EXTENDED2_KEY_CODE: u8 = 0xE1; const KEY_RELEASE_CODE: u8 = 0xF0; +const QUO: char = '\''; +const SLS: char = '\\'; + // **************************************************************************** // // Public Functions and Implementation @@ -837,12 +1136,6 @@ impl KeyEvent { } } -// **************************************************************************** -// -// Keyboard Layouts -// -// **************************************************************************** - impl Modifiers { pub const fn is_shifted(&self) -> bool { self.lshift | self.rshift @@ -863,6 +1156,167 @@ impl Modifiers { pub const fn is_caps(&self) -> bool { self.is_shifted() ^ self.capslock } + + /// Handle letter keys with standard ASCII 'A'..'Z' keycaps. + /// + /// ONLY pass 'A'..='Z' - nothing else. + /// + /// You will get a `DecodedKey::Unicode` value with the appropriate lower + /// or upper case letter, according to state of the the Caps Lock and + /// Shift modifiers. + pub(crate) fn handle_ascii_2(&self, letter: char, handle_ctrl: HandleControl) -> DecodedKey { + debug_assert!(letter.is_ascii_uppercase()); + if handle_ctrl == HandleControl::MapLettersToUnicode && self.is_ctrl() { + // Get a Control code, like Ctrl+C => U+0003 + const ASCII_UPPERCASE_START_OFFSET: u8 = 64; + DecodedKey::Unicode((letter as u8 - ASCII_UPPERCASE_START_OFFSET) as char) + } else if self.is_caps() { + // Capital letter + DecodedKey::Unicode(letter) + } else { + // Lowercase letter + const ASCII_UPPER_TO_LOWER_OFFSET: u8 = 32; + DecodedKey::Unicode((letter as u8 + ASCII_UPPER_TO_LOWER_OFFSET) as char) + } + } + + /// Handle letter keys with just two variants (lower and upper case). + /// + /// Designed for non-ASCII keys, this does not produce control codes. + /// + /// You will get a `DecodedKey::Unicode` value with the appropriate lower + /// or upper case letter, according to state of the the Caps Lock and + /// Shift modifiers. + /// + /// We make you pass both upper and lower case variants to avoid having to + /// use the `char::to_lowercase` function. + pub(crate) fn handle_letter2(&self, letter_lower: char, letter_upper: char) -> DecodedKey { + if self.is_caps() { + DecodedKey::Unicode(letter_upper) + } else { + DecodedKey::Unicode(letter_lower) + } + } + + /// Handle letter keys with standard ASCII 'A'..'Z' keycaps with two extra symbols. + /// + /// ONLY pass 'A'..='Z' - nothing else + /// + /// You will get a `DecodedKey::Unicode` value with the appropriate lower + /// or upper case letter, according to state of the the Caps Lock and + /// Shift modifiers. Or, if AltGr is held, you get either the alternate + /// character. Useful if your alternate character is e.g. `€`. + /// + /// We make you pass both upper and lower case variants to avoid having to + /// use the `char::to_lowercase` function. + pub(crate) fn handle_ascii_3( + &self, + letter_upper: char, + alt: char, + handle_ctrl: HandleControl, + ) -> DecodedKey { + debug_assert!(letter_upper.is_ascii_uppercase()); + if handle_ctrl == HandleControl::MapLettersToUnicode && self.is_ctrl() { + // Get a Control code, like Ctrl+C => U+0003 + const ASCII_UPPERCASE_START_OFFSET: u8 = 64; + DecodedKey::Unicode((letter_upper as u8 - ASCII_UPPERCASE_START_OFFSET) as char) + } else if self.ralt { + // Alternate character + DecodedKey::Unicode(alt) + } else if self.is_caps() { + // Capital letter + DecodedKey::Unicode(letter_upper) + } else { + // Lowercase letter + const ASCII_UPPER_TO_LOWER_OFFSET: u8 = 32; + DecodedKey::Unicode((letter_upper as u8 + ASCII_UPPER_TO_LOWER_OFFSET) as char) + } + } + + /// Handle letter keys with standard ASCII 'A'..'Z' keycaps with two extra symbols. + /// + /// ONLY pass 'A'..='Z' - nothing else + /// + /// You will get a `DecodedKey::Unicode` value with the appropriate lower + /// or upper case letter, according to state of the the Caps Lock and + /// Shift modifiers. Or, if AltGr is held, you get either the upper or + /// lower case alternate character. Useful if your alternate character is + /// e.g. `é` (or `É` if Shift or Caps Lock is enabled). + /// + /// We make you pass both upper and lower case variants to avoid having to + /// use the `char::to_lowercase` function. + pub(crate) fn handle_ascii_4( + &self, + letter_upper: char, + alt_letter_lower: char, + alt_letter_upper: char, + handle_ctrl: HandleControl, + ) -> DecodedKey { + debug_assert!(letter_upper.is_ascii_uppercase()); + if handle_ctrl == HandleControl::MapLettersToUnicode && self.is_ctrl() { + // Get a Control code, like Ctrl+C => U+0003 + const ASCII_UPPERCASE_START_OFFSET: u8 = 64; + DecodedKey::Unicode((letter_upper as u8 - ASCII_UPPERCASE_START_OFFSET) as char) + } else if self.ralt && self.is_caps() { + // Capital letter + DecodedKey::Unicode(alt_letter_upper) + } else if self.ralt { + // Lowercase letter + DecodedKey::Unicode(alt_letter_lower) + } else if self.is_caps() { + // Capital letter + DecodedKey::Unicode(letter_upper) + } else { + // Lowercase letter + const ASCII_UPPER_TO_LOWER_OFFSET: u8 = 32; + DecodedKey::Unicode((letter_upper as u8 + ASCII_UPPER_TO_LOWER_OFFSET) as char) + } + } + + /// Handle numpad keys which are either a character or a raw key + pub(crate) fn handle_num_pad(&self, letter: char, key: KeyCode) -> DecodedKey { + if self.numlock { + DecodedKey::Unicode(letter) + } else { + DecodedKey::RawKey(key) + } + } + + /// Handle numpad keys which produce a pair of characters + /// + /// This is usually just for Numpad Delete. + pub(crate) fn handle_num_del(&self, letter: char, other: char) -> DecodedKey { + if self.numlock { + DecodedKey::Unicode(letter) + } else { + DecodedKey::Unicode(other) + } + } + + /// Handle standard two-glyph shifted keys + /// + /// Caps Lock is ignored here - only shift matters. + pub(crate) fn handle_symbol2(&self, plain: char, shifted: char) -> DecodedKey { + if self.is_shifted() { + DecodedKey::Unicode(shifted) + } else { + DecodedKey::Unicode(plain) + } + } + + /// Handle standard three-glyph shifted keys + /// + /// Caps Lock is ignored here - only shift matters. AltGr gets you the + /// alternate letter, regardless of Shift status. + pub(crate) fn handle_symbol3(&self, plain: char, shifted: char, alt: char) -> DecodedKey { + if self.is_altgr() { + DecodedKey::Unicode(alt) + } else if self.is_shifted() { + DecodedKey::Unicode(shifted) + } else { + DecodedKey::Unicode(plain) + } + } } // ****************************************************************************