1919//! X11 keyboard handling
2020
2121use x11rb:: protocol:: xproto:: { KeyButMask , KeyPressEvent , KeyReleaseEvent } ;
22+ use xkbcommon:: xkb as xkbc;
2223
2324use keyboard_types:: * ;
2425
2526use crate :: keyboard:: code_to_location;
2627
2728/// Convert a hardware scan code to a key.
28- ///
29- /// Note: this is a hardcoded layout. We need to detect the user's
30- /// layout from the system and apply it.
31- fn code_to_key ( code : Code , m : Modifiers ) -> Key {
29+ fn code_to_key ( code : Code , m : Modifiers , hw_code : xkbc:: Keycode , xkb_state : & xkbc:: State ) -> Key {
3230 fn a ( s : & str ) -> Key {
3331 Key :: Character ( s. into ( ) )
3432 }
@@ -39,6 +37,7 @@ fn code_to_key(code: Code, m: Modifiers) -> Key {
3937 Key :: Character ( base. into ( ) )
4038 }
4139 }
40+ let k = || Key :: Character ( xkb_state. key_get_utf8 ( hw_code) ) ;
4241 fn n ( mods : Modifiers , base : Key , num : & str ) -> Key {
4342 if mods. contains ( Modifiers :: NUM_LOCK ) != mods. contains ( Modifiers :: SHIFT ) {
4443 Key :: Character ( num. into ( ) )
@@ -47,55 +46,55 @@ fn code_to_key(code: Code, m: Modifiers) -> Key {
4746 }
4847 }
4948 match code {
50- Code :: KeyA => s ( m , "a" , "A" ) ,
51- Code :: KeyB => s ( m , "b" , "B" ) ,
52- Code :: KeyC => s ( m , "c" , "C" ) ,
53- Code :: KeyD => s ( m , "d" , "D" ) ,
54- Code :: KeyE => s ( m , "e" , "E" ) ,
55- Code :: KeyF => s ( m , "f" , "F" ) ,
56- Code :: KeyG => s ( m , "g" , "G" ) ,
57- Code :: KeyH => s ( m , "h" , "H" ) ,
58- Code :: KeyI => s ( m , "i" , "I" ) ,
59- Code :: KeyJ => s ( m , "j" , "J" ) ,
60- Code :: KeyK => s ( m , "k" , "K" ) ,
61- Code :: KeyL => s ( m , "l" , "L" ) ,
62- Code :: KeyM => s ( m , "m" , "M" ) ,
63- Code :: KeyN => s ( m , "n" , "N" ) ,
64- Code :: KeyO => s ( m , "o" , "O" ) ,
65- Code :: KeyP => s ( m , "p" , "P" ) ,
66- Code :: KeyQ => s ( m , "q" , "Q" ) ,
67- Code :: KeyR => s ( m , "r" , "R" ) ,
68- Code :: KeyS => s ( m , "s" , "S" ) ,
69- Code :: KeyT => s ( m , "t" , "T" ) ,
70- Code :: KeyU => s ( m , "u" , "U" ) ,
71- Code :: KeyV => s ( m , "v" , "V" ) ,
72- Code :: KeyW => s ( m , "w" , "W" ) ,
73- Code :: KeyX => s ( m , "x" , "X" ) ,
74- Code :: KeyY => s ( m , "y" , "Y" ) ,
75- Code :: KeyZ => s ( m , "z" , "Z" ) ,
49+ Code :: KeyA => k ( ) ,
50+ Code :: KeyB => k ( ) ,
51+ Code :: KeyC => k ( ) ,
52+ Code :: KeyD => k ( ) ,
53+ Code :: KeyE => k ( ) ,
54+ Code :: KeyF => k ( ) ,
55+ Code :: KeyG => k ( ) ,
56+ Code :: KeyH => k ( ) ,
57+ Code :: KeyI => k ( ) ,
58+ Code :: KeyJ => k ( ) ,
59+ Code :: KeyK => k ( ) ,
60+ Code :: KeyL => k ( ) ,
61+ Code :: KeyM => k ( ) ,
62+ Code :: KeyN => k ( ) ,
63+ Code :: KeyO => k ( ) ,
64+ Code :: KeyP => k ( ) ,
65+ Code :: KeyQ => k ( ) ,
66+ Code :: KeyR => k ( ) ,
67+ Code :: KeyS => k ( ) ,
68+ Code :: KeyT => k ( ) ,
69+ Code :: KeyU => k ( ) ,
70+ Code :: KeyV => k ( ) ,
71+ Code :: KeyW => k ( ) ,
72+ Code :: KeyX => k ( ) ,
73+ Code :: KeyY => k ( ) ,
74+ Code :: KeyZ => k ( ) ,
7675
77- Code :: Digit0 => s ( m , "0" , ")" ) ,
78- Code :: Digit1 => s ( m , "1" , "!" ) ,
79- Code :: Digit2 => s ( m , "2" , "@" ) ,
80- Code :: Digit3 => s ( m , "3" , "#" ) ,
81- Code :: Digit4 => s ( m , "4" , "$" ) ,
82- Code :: Digit5 => s ( m , "5" , "%" ) ,
83- Code :: Digit6 => s ( m , "6" , "^" ) ,
84- Code :: Digit7 => s ( m , "7" , "&" ) ,
85- Code :: Digit8 => s ( m , "8" , "*" ) ,
86- Code :: Digit9 => s ( m , "9" , "(" ) ,
76+ Code :: Digit0 => k ( ) ,
77+ Code :: Digit1 => k ( ) ,
78+ Code :: Digit2 => k ( ) ,
79+ Code :: Digit3 => k ( ) ,
80+ Code :: Digit4 => k ( ) ,
81+ Code :: Digit5 => k ( ) ,
82+ Code :: Digit6 => k ( ) ,
83+ Code :: Digit7 => k ( ) ,
84+ Code :: Digit8 => k ( ) ,
85+ Code :: Digit9 => k ( ) ,
8786
88- Code :: Backquote => s ( m , "`" , "~" ) ,
89- Code :: Minus => s ( m , "-" , "_" ) ,
90- Code :: Equal => s ( m , "=" , "+" ) ,
91- Code :: BracketLeft => s ( m , "[" , "{" ) ,
92- Code :: BracketRight => s ( m , "]" , "}" ) ,
93- Code :: Backslash => s ( m , " \\ " , "|" ) ,
94- Code :: Semicolon => s ( m , ";" , ":" ) ,
95- Code :: Quote => s ( m , "'" , " \" " ) ,
96- Code :: Comma => s ( m , "," , "<" ) ,
97- Code :: Period => s ( m , "." , ">" ) ,
98- Code :: Slash => s ( m , "/" , "?" ) ,
87+ Code :: Backquote => k ( ) ,
88+ Code :: Minus => k ( ) ,
89+ Code :: Equal => k ( ) ,
90+ Code :: BracketLeft => k ( ) ,
91+ Code :: BracketRight => k ( ) ,
92+ Code :: Backslash => k ( ) ,
93+ Code :: Semicolon => k ( ) ,
94+ Code :: Quote => k ( ) ,
95+ Code :: Comma => k ( ) ,
96+ Code :: Period => k ( ) ,
97+ Code :: Slash => k ( ) ,
9998
10099 Code :: Space => a ( " " ) ,
101100
@@ -383,22 +382,36 @@ pub(super) fn key_mods(mods: KeyButMask) -> Modifiers {
383382 ret
384383}
385384
386- pub ( super ) fn convert_key_press_event ( key_press : & KeyPressEvent ) -> KeyboardEvent {
385+ pub ( super ) fn convert_key_press_event (
386+ key_press : & KeyPressEvent , state : & mut xkbc:: State ,
387+ ) -> KeyboardEvent {
387388 let hw_keycode = key_press. detail ;
389+
390+ // Update the xkbc state
391+ let hw_code = hw_keycode. into ( ) ;
392+ state. update_key ( hw_code, xkbc:: KeyDirection :: Down ) ;
393+
388394 let code = hardware_keycode_to_code ( hw_keycode. into ( ) ) ;
389395 let modifiers = key_mods ( key_press. state ) ;
390- let key = code_to_key ( code, modifiers) ;
396+ let key = code_to_key ( code, modifiers, hw_code , state ) ;
391397 let location = code_to_location ( code) ;
392398 let state = KeyState :: Down ;
393399
394400 KeyboardEvent { code, key, modifiers, location, state, repeat : false , is_composing : false }
395401}
396402
397- pub ( super ) fn convert_key_release_event ( key_release : & KeyReleaseEvent ) -> KeyboardEvent {
403+ pub ( super ) fn convert_key_release_event (
404+ key_release : & KeyReleaseEvent , state : & mut xkbc:: State ,
405+ ) -> KeyboardEvent {
398406 let hw_keycode = key_release. detail ;
407+
408+ // Update the xkbc state
409+ let hw_code = hw_keycode. into ( ) ;
410+ state. update_key ( hw_code, xkbc:: KeyDirection :: Up ) ;
411+
399412 let code = hardware_keycode_to_code ( hw_keycode. into ( ) ) ;
400413 let modifiers = key_mods ( key_release. state ) ;
401- let key = code_to_key ( code, modifiers) ;
414+ let key = code_to_key ( code, modifiers, hw_code , state ) ;
402415 let location = code_to_location ( code) ;
403416 let state = KeyState :: Up ;
404417
0 commit comments