@@ -8,7 +8,67 @@ use event::{
88} ;
99use platform_impl:: platform:: DEVICE_ID ;
1010
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 > {
1272 Some ( match scancode {
1373 0x00 => VirtualKeyCode :: A ,
1474 0x01 => VirtualKeyCode :: S ,
@@ -147,17 +207,18 @@ pub fn to_virtual_keycode(scancode: c_ushort) -> Option<VirtualKeyCode> {
147207// While F1-F20 have scancodes we can match on, we have to check against UTF-16
148208// constants for the rest.
149209// 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 ,
160218 } )
219+ }
220+
221+ None
161222}
162223
163224pub fn event_mods ( event : id ) -> ModifiersState {
@@ -172,6 +233,16 @@ pub fn event_mods(event: id) -> ModifiersState {
172233 }
173234}
174235
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+
175246pub unsafe fn modifier_event (
176247 ns_event : id ,
177248 keymask : NSEventModifierFlags ,
@@ -184,14 +255,14 @@ pub unsafe fn modifier_event(
184255 } else {
185256 ElementState :: Pressed
186257 } ;
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 ) ;
190261 Some ( WindowEvent :: KeyboardInput {
191262 device_id : DEVICE_ID ,
192263 input : KeyboardInput {
193264 state,
194- scancode,
265+ scancode : scancode as _ ,
195266 virtual_keycode,
196267 modifiers : event_mods ( ns_event) ,
197268 } ,
0 commit comments