Skip to main content

pc_keyboard/layouts/
uk105.rs

1//! United Kingdom keyboard support
2
3use crate::{
4    DecodedKey, HandleControl, KeyCode, KeyboardLayout, Modifiers, PhysicalKeyboard, QUO, SLS,
5};
6
7/// A standard United Kingdom 102-key (or 105-key including Windows keys) keyboard.
8///
9/// Has a 2-row high Enter key, with Oem5 next to the left shift (ISO format).
10///
11/// Based on US 101/104 key, with minor changes.
12///
13/// These diagrams illustrate the conversion from [`KeyCode`] to Unicode. We
14/// show either a Unicode glyph, or a hex number if the glyph isn't a
15/// printable character. Blank spaces are passed through as
16/// [`DecodedKey::RawKey`].
17///
18/// Run the `print_keyboard` example to re-generate these images.
19///
20/// ## Unmodified
21///
22/// ```text
23/// ┌────┐  ┌────┬────┬────┬────┐  ┌────┬────┬────┬────┐  ┌────┬────┬────┬────┐   ┌────┬────┬────┐
24/// │001b│  │    │    │    │    │  │    │    │    │    │  │    │    │    │    │   │    │    │    │
25/// └────┘  └────┴────┴────┴────┘  └────┴────┴────┴────┘  └────┴────┴────┴────┘   └────┴────┴────┘
26///
27/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐  ┌────┬────┬────┐  ┌────┬────┬────┬────┐
28/// │ `  │ 1  │ 2  │ 3  │ 4  │ 5  │ 6  │ 7  │ 8  │ 9  │ 0  │ -  │ =  │   0008  │  │    │    │    │  │    │ /  │ *  │ -  │
29/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤  ├────┼────┼────┤  ├────┼────┼────┼────┤
30/// │0009 │ q  │ w  │ e  │ r  │ t  │ y  │ u  │ i  │ o  │ p  │ [  │ ]  │  000a  │  │007f│    │    │  │ 7  │ 8  │ 9  │    │
31/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐       │  └────┴────┴────┘  ├────┼────┼────┤ +  │
32/// │      │ a  │ s  │ d  │ f  │ g  │ h  │ j  │ k  │ l  │ ;  │ '  │ #  │       │                    │ 4  │ 5  │ 6  │    │
33/// ├────┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┴───────┤       ┌────┐       ├────┼────┼────┼────┤
34/// │    │ \  │ z  │ x  │ c  │ v  │ b  │ n  │ m  │ ,  │ .  │ /  │              │       │    │       │ 1  │ 2  │ 3  │    │
35/// ├────┴┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤  ┌────┼────┼────┐  ├────┴────┼────┤000a│
36/// │     │     │     │             0020             │     │     │      │      │  │    │    │    │  │ 0       │ .  │    │
37/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘  └────┴────┴────┘  └─────────┴────┴────┘
38/// ```
39///
40/// ## Caps Lock
41///
42/// ```text
43/// ┌────┐  ┌────┬────┬────┬────┐  ┌────┬────┬────┬────┐  ┌────┬────┬────┬────┐   ┌────┬────┬────┐
44/// │001b│  │    │    │    │    │  │    │    │    │    │  │    │    │    │    │   │    │    │    │
45/// └────┘  └────┴────┴────┴────┘  └────┴────┴────┴────┘  └────┴────┴────┴────┘   └────┴────┴────┘
46///
47/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐  ┌────┬────┬────┐  ┌────┬────┬────┬────┐
48/// │ `  │ 1  │ 2  │ 3  │ 4  │ 5  │ 6  │ 7  │ 8  │ 9  │ 0  │ -  │ =  │   0008  │  │    │    │    │  │    │ /  │ *  │ -  │
49/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤  ├────┼────┼────┤  ├────┼────┼────┼────┤
50/// │0009 │ Q  │ W  │ E  │ R  │ T  │ Y  │ U  │ I  │ O  │ P  │ [  │ ]  │  000a  │  │007f│    │    │  │ 7  │ 8  │ 9  │    │
51/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐       │  └────┴────┴────┘  ├────┼────┼────┤ +  │
52/// │      │ A  │ S  │ D  │ F  │ G  │ H  │ J  │ K  │ L  │ ;  │ '  │ #  │       │                    │ 4  │ 5  │ 6  │    │
53/// ├────┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┴───────┤       ┌────┐       ├────┼────┼────┼────┤
54/// │    │ \  │ Z  │ X  │ C  │ V  │ B  │ N  │ M  │ ,  │ .  │ /  │              │       │    │       │ 1  │ 2  │ 3  │    │
55/// ├────┴┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤  ┌────┼────┼────┐  ├────┴────┼────┤000a│
56/// │     │     │     │             0020             │     │     │      │      │  │    │    │    │  │ 0       │ .  │    │
57/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘  └────┴────┴────┘  └─────────┴────┴────┘
58/// ```
59///
60/// ## Shifted
61///
62/// ```text
63/// ┌────┐  ┌────┬────┬────┬────┐  ┌────┬────┬────┬────┐  ┌────┬────┬────┬────┐   ┌────┬────┬────┐
64/// │001b│  │    │    │    │    │  │    │    │    │    │  │    │    │    │    │   │    │    │    │
65/// └────┘  └────┴────┴────┴────┘  └────┴────┴────┴────┘  └────┴────┴────┴────┘   └────┴────┴────┘
66///
67/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐  ┌────┬────┬────┐  ┌────┬────┬────┬────┐
68/// │ ¬  │ !  │ "  │ £  │ $  │ %  │ ^  │ &  │ *  │ (  │ )  │ _  │ +  │   0008  │  │    │    │    │  │    │ /  │ *  │ -  │
69/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤  ├────┼────┼────┤  ├────┼────┼────┼────┤
70/// │0009 │ Q  │ W  │ E  │ R  │ T  │ Y  │ U  │ I  │ O  │ P  │ {  │ }  │  000a  │  │007f│    │    │  │ 7  │ 8  │ 9  │    │
71/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐       │  └────┴────┴────┘  ├────┼────┼────┤ +  │
72/// │      │ A  │ S  │ D  │ F  │ G  │ H  │ J  │ K  │ L  │ :  │ @  │ ~  │       │                    │ 4  │ 5  │ 6  │    │
73/// ├────┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┴───────┤       ┌────┐       ├────┼────┼────┼────┤
74/// │    │ |  │ Z  │ X  │ C  │ V  │ B  │ N  │ M  │ <  │ >  │ ?  │              │       │    │       │ 1  │ 2  │ 3  │    │
75/// ├────┴┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤  ┌────┼────┼────┐  ├────┴────┼────┤000a│
76/// │     │     │     │             0020             │     │     │      │      │  │    │    │    │  │ 0       │ .  │    │
77/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘  └────┴────┴────┘  └─────────┴────┴────┘
78/// ```
79///
80/// ## Control
81///
82/// ```text
83/// ┌────┐  ┌────┬────┬────┬────┐  ┌────┬────┬────┬────┐  ┌────┬────┬────┬────┐   ┌────┬────┬────┐
84/// │001b│  │    │    │    │    │  │    │    │    │    │  │    │    │    │    │   │    │    │    │
85/// └────┘  └────┴────┴────┴────┘  └────┴────┴────┴────┘  └────┴────┴────┴────┘   └────┴────┴────┘
86///
87/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐  ┌────┬────┬────┐  ┌────┬────┬────┬────┐
88/// │ `  │ 1  │ 2  │ 3  │ 4  │ 5  │ 6  │ 7  │ 8  │ 9  │ 0  │ -  │ =  │   0008  │  │    │    │    │  │    │ /  │ *  │ -  │
89/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤  ├────┼────┼────┤  ├────┼────┼────┼────┤
90/// │0009 │0011│0017│0005│0012│0014│0019│0015│0009│000f│0010│ [  │ ]  │  000a  │  │007f│    │    │  │ 7  │ 8  │ 9  │    │
91/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐       │  └────┴────┴────┘  ├────┼────┼────┤ +  │
92/// │      │0001│0013│0004│0006│0007│0008│000a│000b│000c│ ;  │ '  │ #  │       │                    │ 4  │ 5  │ 6  │    │
93/// ├────┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┴───────┤       ┌────┐       ├────┼────┼────┼────┤
94/// │    │ \  │001a│0018│0003│0016│0002│000e│000d│ ,  │ .  │ /  │              │       │    │       │ 1  │ 2  │ 3  │    │
95/// ├────┴┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤  ┌────┼────┼────┐  ├────┴────┼────┤000a│
96/// │     │     │     │             0020             │     │     │      │      │  │    │    │    │  │ 0       │ .  │    │
97/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘  └────┴────┴────┘  └─────────┴────┴────┘
98/// ```
99///
100/// ## AltGr
101///
102/// ```text
103/// ┌────┐  ┌────┬────┬────┬────┐  ┌────┬────┬────┬────┐  ┌────┬────┬────┬────┐   ┌────┬────┬────┐
104/// │001b│  │    │    │    │    │  │    │    │    │    │  │    │    │    │    │   │    │    │    │
105/// └────┘  └────┴────┴────┴────┘  └────┴────┴────┴────┘  └────┴────┴────┴────┘   └────┴────┴────┘
106///
107/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐  ┌────┬────┬────┐  ┌────┬────┬────┬────┐
108/// │ ¦  │ 1  │ 2  │ 3  │ €  │ 5  │ 6  │ 7  │ 8  │ 9  │ 0  │ -  │ =  │   0008  │  │    │    │    │  │    │ /  │ *  │ -  │
109/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤  ├────┼────┼────┤  ├────┼────┼────┼────┤
110/// │0009 │ q  │ w  │ é  │ r  │ t  │ y  │ ú  │ í  │ ó  │ p  │ [  │ ]  │  000a  │  │007f│    │    │  │ 7  │ 8  │ 9  │    │
111/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐       │  └────┴────┴────┘  ├────┼────┼────┤ +  │
112/// │      │ á  │ s  │ d  │ f  │ g  │ h  │ j  │ k  │ l  │ ;  │ '  │ #  │       │                    │ 4  │ 5  │ 6  │    │
113/// ├────┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┴───────┤       ┌────┐       ├────┼────┼────┼────┤
114/// │    │ \  │ z  │ x  │ c  │ v  │ b  │ n  │ m  │ ,  │ .  │ /  │              │       │    │       │ 1  │ 2  │ 3  │    │
115/// ├────┴┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤  ┌────┼────┼────┐  ├────┴────┼────┤000a│
116/// │     │     │     │             0020             │     │     │      │      │  │    │    │    │  │ 0       │ .  │    │
117/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘  └────┴────┴────┘  └─────────┴────┴────┘
118/// ```
119///
120/// ## Shift AltGr
121///
122/// ```text
123/// ┌────┐  ┌────┬────┬────┬────┐  ┌────┬────┬────┬────┐  ┌────┬────┬────┬────┐   ┌────┬────┬────┐
124/// │001b│  │    │    │    │    │  │    │    │    │    │  │    │    │    │    │   │    │    │    │
125/// └────┘  └────┴────┴────┴────┘  └────┴────┴────┴────┘  └────┴────┴────┴────┘   └────┴────┴────┘
126///
127/// ┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬────┬─────────┐  ┌────┬────┬────┐  ┌────┬────┬────┬────┐
128/// │ ¦  │ !  │ "  │ £  │ €  │ %  │ ^  │ &  │ *  │ (  │ )  │ _  │ +  │   0008  │  │    │    │    │  │    │ /  │ *  │ -  │
129/// ├────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬────────┤  ├────┼────┼────┤  ├────┼────┼────┼────┤
130/// │0009 │ Q  │ W  │ É  │ R  │ T  │ Y  │ Ú  │ Í  │ Ó  │ P  │ {  │ }  │  000a  │  │007f│    │    │  │ 7  │ 8  │ 9  │    │
131/// ├─────┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┬───┴┐       │  └────┴────┴────┘  ├────┼────┼────┤ +  │
132/// │      │ Á  │ S  │ D  │ F  │ G  │ H  │ J  │ K  │ L  │ :  │ @  │ ~  │       │                    │ 4  │ 5  │ 6  │    │
133/// ├────┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴──┬─┴────┴───────┤       ┌────┐       ├────┼────┼────┼────┤
134/// │    │ |  │ Z  │ X  │ C  │ V  │ B  │ N  │ M  │ <  │ >  │ ?  │              │       │    │       │ 1  │ 2  │ 3  │    │
135/// ├────┴┬───┴─┬──┴──┬─┴────┴────┴────┴────┴────┴───┬┴────┼────┴┬──────┬──────┤  ┌────┼────┼────┐  ├────┴────┼────┤000a│
136/// │     │     │     │             0020             │     │     │      │      │  │    │    │    │  │ 0       │ .  │    │
137/// └─────┴─────┴─────┴──────────────────────────────┴─────┴─────┴──────┴──────┘  └────┴────┴────┘  └─────────┴────┴────┘
138/// ```
139pub struct Uk105Key;
140
141impl KeyboardLayout for Uk105Key {
142    #[rustfmt::skip]
143    fn map_keycode(
144        &self,
145        keycode: KeyCode,
146        modifiers: &Modifiers,
147        handle_ctrl: HandleControl,
148    ) -> DecodedKey {
149        match keycode {
150            KeyCode::Key2 => modifiers.handle_symbol2('2', '"'),
151            KeyCode::Key3 => modifiers.handle_symbol2('3', '£'),
152            KeyCode::Key4 => modifiers.handle_symbol3('4', '$', '€'),
153            KeyCode::Oem3 => modifiers.handle_symbol2(QUO, '@'),
154            KeyCode::Oem5 => modifiers.handle_symbol2(SLS, '|'),
155            KeyCode::Oem7 => modifiers.handle_symbol2('#', '~'),
156            KeyCode::Oem8 => modifiers.handle_symbol3('`', '¬', '¦'),
157            KeyCode::E    => modifiers.handle_ascii_4('E', 'é', 'É', handle_ctrl),
158            KeyCode::U    => modifiers.handle_ascii_4('U', 'ú', 'Ú', handle_ctrl),
159            KeyCode::I    => modifiers.handle_ascii_4('I', 'í', 'Í', handle_ctrl),
160            KeyCode::O    => modifiers.handle_ascii_4('O', 'ó', 'Ó', handle_ctrl),
161            KeyCode::A    => modifiers.handle_ascii_4('A', 'á', 'Á', handle_ctrl),
162            e => super::Us104Key.map_keycode(e, modifiers, handle_ctrl),
163        }
164    }
165
166    fn get_physical(&self) -> PhysicalKeyboard {
167        PhysicalKeyboard::Iso
168    }
169}
170
171#[cfg(test)]
172mod test {
173    use super::*;
174    use crate::{
175        EventDecoder, HandleControl, PS2Keyboard, ScancodeSet, ScancodeSet1, ScancodeSet2,
176    };
177
178    #[test]
179    fn layout() {
180        // Codes taken from https://kbdlayout.info/kbduk/overview+scancodes?arrangement=ISO105
181        let mut s = ScancodeSet1::new();
182        let mut dec = EventDecoder::new(Uk105Key, HandleControl::Ignore);
183        let data = [
184            (0x29, '`'),
185            (0x02, '1'),
186            (0x03, '2'),
187            (0x04, '3'),
188            (0x05, '4'),
189            (0x06, '5'),
190            (0x07, '6'),
191            (0x08, '7'),
192            (0x09, '8'),
193            (0x0a, '9'),
194            (0x0b, '0'),
195            (0x0c, '-'),
196            (0x0d, '='),
197            (0x0f, '\t'),
198            (0x10, 'q'),
199            (0x11, 'w'),
200            (0x12, 'e'),
201            (0x13, 'r'),
202            (0x14, 't'),
203            (0x15, 'y'),
204            (0x16, 'u'),
205            (0x17, 'i'),
206            (0x18, 'o'),
207            (0x19, 'p'),
208            (0x1a, '['),
209            (0x1b, ']'),
210            (0x1e, 'a'),
211            (0x1f, 's'),
212            (0x20, 'd'),
213            (0x21, 'f'),
214            (0x22, 'g'),
215            (0x23, 'h'),
216            (0x24, 'j'),
217            (0x25, 'k'),
218            (0x26, 'l'),
219            (0x27, ';'),
220            (0x28, '\''),
221            (0x2B, '#'),
222            (0x1c, '\n'),
223            (0x56, '\\'),
224            (0x2c, 'z'),
225            (0x2d, 'x'),
226            (0x2e, 'c'),
227            (0x2f, 'v'),
228            (0x30, 'b'),
229            (0x31, 'n'),
230            (0x32, 'm'),
231            (0x33, ','),
232            (0x34, '.'),
233            (0x35, '/'),
234        ];
235        for (code, unicode) in data {
236            let ev = s.advance_state(code).unwrap().unwrap();
237            assert_eq!(Some(DecodedKey::Unicode(unicode)), dec.process_keyevent(ev));
238        }
239    }
240
241    #[test]
242    fn test_hash() {
243        let mut k = PS2Keyboard::new(
244            ScancodeSet2::new(),
245            Uk105Key,
246            HandleControl::MapLettersToUnicode,
247        );
248        // As seen on a UK 105 key Dell PS/2 keyboard when pressing `~#`
249        let ev = k.add_byte(0x5D).unwrap().unwrap();
250        let decoded_key = k.process_keyevent(ev);
251        assert_eq!(decoded_key, Some(DecodedKey::Unicode('#')));
252    }
253
254    #[test]
255    fn test_backslash() {
256        let mut k = PS2Keyboard::new(
257            ScancodeSet2::new(),
258            Uk105Key,
259            HandleControl::MapLettersToUnicode,
260        );
261        // As seen on a UK 105 key Dell PS/2 keyboard when pressing `|\`
262        let ev = k.add_byte(0x61).unwrap().unwrap();
263        let decoded_key = k.process_keyevent(ev);
264        assert_eq!(decoded_key, Some(DecodedKey::Unicode('\\')));
265    }
266
267    #[test]
268    fn test_tilde() {
269        let mut k = PS2Keyboard::new(
270            ScancodeSet2::new(),
271            Uk105Key,
272            HandleControl::MapLettersToUnicode,
273        );
274        // As seen on a UK 105 key Dell PS/2 keyboard when pressing Shift and `~#`
275        let ev = k.add_byte(0x12).unwrap().unwrap();
276        let _ = k.process_keyevent(ev);
277        let ev = k.add_byte(0x5D).unwrap().unwrap();
278        let decoded_key = k.process_keyevent(ev);
279        assert_eq!(decoded_key, Some(DecodedKey::Unicode('~')));
280    }
281
282    #[test]
283    fn test_pipe() {
284        let mut k = PS2Keyboard::new(
285            ScancodeSet2::new(),
286            Uk105Key,
287            HandleControl::MapLettersToUnicode,
288        );
289        // As seen on a UK 105 key Dell PS/2 keyboard when pressing Shift and `|\`
290        let ev = k.add_byte(0x12).unwrap().unwrap();
291        let _ = k.process_keyevent(ev);
292        let ev = k.add_byte(0x61).unwrap().unwrap();
293        let decoded_key = k.process_keyevent(ev);
294        assert_eq!(decoded_key, Some(DecodedKey::Unicode('|')));
295    }
296}