@@ -8,7 +8,67 @@ use event::{
8
8
} ;
9
9
use platform_impl:: platform:: DEVICE_ID ;
10
10
11
- pub fn to_virtual_keycode ( scancode : c_ushort ) -> Option < VirtualKeyCode > {
11
+ pub fn char_to_keycode ( c : char ) -> Option < VirtualKeyCode > {
12
+ // We only translate keys that are affected by keyboard layout.
13
+ //
14
+ // Note that since keys are translated in a somewhat "dumb" way (reading character)
15
+ // there is a concern that some combination, i.e. Cmd+char, causes the wrong
16
+ // letter to be received, and so we receive the wrong key.
17
+ //
18
+ // Implementation reference: https://github.com/WebKit/webkit/blob/82bae82cf0f329dbe21059ef0986c4e92fea4ba6/Source/WebCore/platform/cocoa/KeyEventCocoa.mm#L626
19
+ Some ( match c {
20
+ 'a' | 'A' => VirtualKeyCode :: A ,
21
+ 'b' | 'B' => VirtualKeyCode :: B ,
22
+ 'c' | 'C' => VirtualKeyCode :: C ,
23
+ 'd' | 'D' => VirtualKeyCode :: D ,
24
+ 'e' | 'E' => VirtualKeyCode :: E ,
25
+ 'f' | 'F' => VirtualKeyCode :: F ,
26
+ 'g' | 'G' => VirtualKeyCode :: G ,
27
+ 'h' | 'H' => VirtualKeyCode :: H ,
28
+ 'i' | 'I' => VirtualKeyCode :: I ,
29
+ 'j' | 'J' => VirtualKeyCode :: J ,
30
+ 'k' | 'K' => VirtualKeyCode :: K ,
31
+ 'l' | 'L' => VirtualKeyCode :: L ,
32
+ 'm' | 'M' => VirtualKeyCode :: M ,
33
+ 'n' | 'N' => VirtualKeyCode :: N ,
34
+ 'o' | 'O' => VirtualKeyCode :: O ,
35
+ 'p' | 'P' => VirtualKeyCode :: P ,
36
+ 'q' | 'Q' => VirtualKeyCode :: Q ,
37
+ 'r' | 'R' => VirtualKeyCode :: R ,
38
+ 's' | 'S' => VirtualKeyCode :: S ,
39
+ 't' | 'T' => VirtualKeyCode :: T ,
40
+ 'u' | 'U' => VirtualKeyCode :: U ,
41
+ 'v' | 'V' => VirtualKeyCode :: V ,
42
+ 'w' | 'W' => VirtualKeyCode :: W ,
43
+ 'x' | 'X' => VirtualKeyCode :: X ,
44
+ 'y' | 'Y' => VirtualKeyCode :: Y ,
45
+ 'z' | 'Z' => VirtualKeyCode :: Z ,
46
+ '1' | '!' => VirtualKeyCode :: Key1 ,
47
+ '2' | '@' => VirtualKeyCode :: Key2 ,
48
+ '3' | '#' => VirtualKeyCode :: Key3 ,
49
+ '4' | '$' => VirtualKeyCode :: Key4 ,
50
+ '5' | '%' => VirtualKeyCode :: Key5 ,
51
+ '6' | '^' => VirtualKeyCode :: Key6 ,
52
+ '7' | '&' => VirtualKeyCode :: Key7 ,
53
+ '8' | '*' => VirtualKeyCode :: Key8 ,
54
+ '9' | '(' => VirtualKeyCode :: Key9 ,
55
+ '0' | ')' => VirtualKeyCode :: Key0 ,
56
+ '=' | '+' => VirtualKeyCode :: Equals ,
57
+ '-' | '_' => VirtualKeyCode :: Minus ,
58
+ ']' | '}' => VirtualKeyCode :: RBracket ,
59
+ '[' | '{' => VirtualKeyCode :: LBracket ,
60
+ '\'' | '"' => VirtualKeyCode :: Apostrophe ,
61
+ ';' | ':' => VirtualKeyCode :: Semicolon ,
62
+ '\\' | '|' => VirtualKeyCode :: Backslash ,
63
+ ',' | '<' => VirtualKeyCode :: Comma ,
64
+ '/' | '?' => VirtualKeyCode :: Slash ,
65
+ '.' | '>' => VirtualKeyCode :: Period ,
66
+ '`' | '~' => VirtualKeyCode :: Grave ,
67
+ _ => return None ,
68
+ } )
69
+ }
70
+
71
+ pub fn scancode_to_keycode ( scancode : c_ushort ) -> Option < VirtualKeyCode > {
12
72
Some ( match scancode {
13
73
0x00 => VirtualKeyCode :: A ,
14
74
0x01 => VirtualKeyCode :: S ,
@@ -147,17 +207,18 @@ pub fn to_virtual_keycode(scancode: c_ushort) -> Option<VirtualKeyCode> {
147
207
// While F1-F20 have scancodes we can match on, we have to check against UTF-16
148
208
// constants for the rest.
149
209
// https://developer.apple.com/documentation/appkit/1535851-function-key_unicodes?preferredLanguage=occ
150
- pub fn check_function_keys ( string : & Option < String > ) -> Option < VirtualKeyCode > {
151
- string
152
- . as_ref ( )
153
- . and_then ( |string| string. encode_utf16 ( ) . next ( ) )
154
- . and_then ( |character| match character {
155
- 0xf718 => Some ( VirtualKeyCode :: F21 ) ,
156
- 0xf719 => Some ( VirtualKeyCode :: F22 ) ,
157
- 0xf71a => Some ( VirtualKeyCode :: F23 ) ,
158
- 0xf71b => Some ( VirtualKeyCode :: F24 ) ,
159
- _ => None ,
210
+ pub fn check_function_keys ( string : & String ) -> Option < VirtualKeyCode > {
211
+ if let Some ( ch) = string. encode_utf16 ( ) . next ( ) {
212
+ return Some ( match ch {
213
+ 0xf718 => VirtualKeyCode :: F21 ,
214
+ 0xf719 => VirtualKeyCode :: F22 ,
215
+ 0xf71a => VirtualKeyCode :: F23 ,
216
+ 0xf71b => VirtualKeyCode :: F24 ,
217
+ _ => return None ,
160
218
} )
219
+ }
220
+
221
+ None
161
222
}
162
223
163
224
pub fn event_mods ( event : id ) -> ModifiersState {
@@ -172,6 +233,16 @@ pub fn event_mods(event: id) -> ModifiersState {
172
233
}
173
234
}
174
235
236
+ pub fn get_scancode ( event : cocoa:: base:: id ) -> c_ushort {
237
+ // In AppKit, `keyCode` refers to the position (scancode) of a key rather than its character,
238
+ // and there is no easy way to navtively retrieve the layout-dependent character.
239
+ // In winit, we use keycode to refer to the key's character, and so this function aligns
240
+ // AppKit's terminology with ours.
241
+ unsafe {
242
+ msg_send ! [ event, keyCode]
243
+ }
244
+ }
245
+
175
246
pub unsafe fn modifier_event (
176
247
ns_event : id ,
177
248
keymask : NSEventModifierFlags ,
@@ -184,14 +255,14 @@ pub unsafe fn modifier_event(
184
255
} else {
185
256
ElementState :: Pressed
186
257
} ;
187
- let keycode = NSEvent :: keyCode ( ns_event ) ;
188
- let scancode = keycode as u32 ;
189
- let virtual_keycode = to_virtual_keycode ( keycode ) ;
258
+
259
+ let scancode = get_scancode ( ns_event ) ;
260
+ let virtual_keycode = scancode_to_keycode ( scancode ) ;
190
261
Some ( WindowEvent :: KeyboardInput {
191
262
device_id : DEVICE_ID ,
192
263
input : KeyboardInput {
193
264
state,
194
- scancode,
265
+ scancode : scancode as _ ,
195
266
virtual_keycode,
196
267
modifiers : event_mods ( ns_event) ,
197
268
} ,
0 commit comments