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,15 @@ fn code_to_key(code: Code, m: Modifiers) -> Key {
3937 Key :: Character ( base. into ( ) )
4038 }
4139 }
40+ fn k ( mods : Modifiers , base : & str , code : xkbc:: Keycode , state : & xkbc:: State ) -> Key {
41+ if mods. contains ( Modifiers :: CONTROL ) {
42+ // When ctrl is set, then state.key_get_utf8 return control sequence like \x1e.
43+ // TODO: handle this better?
44+ Key :: Character ( base. into ( ) )
45+ } else {
46+ Key :: Character ( state. key_get_utf8 ( code) )
47+ }
48+ }
4249 fn n ( mods : Modifiers , base : Key , num : & str ) -> Key {
4350 if mods. contains ( Modifiers :: NUM_LOCK ) != mods. contains ( Modifiers :: SHIFT ) {
4451 Key :: Character ( num. into ( ) )
@@ -47,55 +54,55 @@ fn code_to_key(code: Code, m: Modifiers) -> Key {
4754 }
4855 }
4956 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" ) ,
57+ Code :: KeyA => k ( m, "a" , hw_code , xkb_state ) ,
58+ Code :: KeyB => k ( m, "b" , hw_code , xkb_state ) ,
59+ Code :: KeyC => k ( m, "c" , hw_code , xkb_state ) ,
60+ Code :: KeyD => k ( m, "d" , hw_code , xkb_state ) ,
61+ Code :: KeyE => k ( m, "e" , hw_code , xkb_state ) ,
62+ Code :: KeyF => k ( m, "f" , hw_code , xkb_state ) ,
63+ Code :: KeyG => k ( m, "g" , hw_code , xkb_state ) ,
64+ Code :: KeyH => k ( m, "h" , hw_code , xkb_state ) ,
65+ Code :: KeyI => k ( m, "i" , hw_code , xkb_state ) ,
66+ Code :: KeyJ => k ( m, "j" , hw_code , xkb_state ) ,
67+ Code :: KeyK => k ( m, "k" , hw_code , xkb_state ) ,
68+ Code :: KeyL => k ( m, "l" , hw_code , xkb_state ) ,
69+ Code :: KeyM => k ( m, "m" , hw_code , xkb_state ) ,
70+ Code :: KeyN => k ( m, "n" , hw_code , xkb_state ) ,
71+ Code :: KeyO => k ( m, "o" , hw_code , xkb_state ) ,
72+ Code :: KeyP => k ( m, "p" , hw_code , xkb_state ) ,
73+ Code :: KeyQ => k ( m, "q" , hw_code , xkb_state ) ,
74+ Code :: KeyR => k ( m, "r" , hw_code , xkb_state ) ,
75+ Code :: KeyS => k ( m, "s" , hw_code , xkb_state ) ,
76+ Code :: KeyT => k ( m, "t" , hw_code , xkb_state ) ,
77+ Code :: KeyU => k ( m, "u" , hw_code , xkb_state ) ,
78+ Code :: KeyV => k ( m, "v" , hw_code , xkb_state ) ,
79+ Code :: KeyW => k ( m, "w" , hw_code , xkb_state ) ,
80+ Code :: KeyX => k ( m, "x" , hw_code , xkb_state ) ,
81+ Code :: KeyY => k ( m, "y" , hw_code , xkb_state ) ,
82+ Code :: KeyZ => k ( m, "z" , hw_code , xkb_state ) ,
7683
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" , "(" ) ,
84+ Code :: Digit0 => k ( m, "0" , hw_code , xkb_state ) ,
85+ Code :: Digit1 => k ( m, "1" , hw_code , xkb_state ) ,
86+ Code :: Digit2 => k ( m, "2" , hw_code , xkb_state ) ,
87+ Code :: Digit3 => k ( m, "3" , hw_code , xkb_state ) ,
88+ Code :: Digit4 => k ( m, "4" , hw_code , xkb_state ) ,
89+ Code :: Digit5 => k ( m, "5" , hw_code , xkb_state ) ,
90+ Code :: Digit6 => k ( m, "6" , hw_code , xkb_state ) ,
91+ Code :: Digit7 => k ( m, "7" , hw_code , xkb_state ) ,
92+ Code :: Digit8 => k ( m, "8" , hw_code , xkb_state ) ,
93+ Code :: Digit9 => k ( m, "9" , hw_code , xkb_state ) ,
8794
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, "/" , "?" ) ,
95+ Code :: Backquote => k ( m, "`" , hw_code , xkb_state ) ,
96+ Code :: Minus => k ( m, "-" , hw_code , xkb_state ) ,
97+ Code :: Equal => k ( m, "=" , hw_code , xkb_state ) ,
98+ Code :: BracketLeft => k ( m, "[" , hw_code , xkb_state ) ,
99+ Code :: BracketRight => k ( m, "]" , hw_code , xkb_state ) ,
100+ Code :: Backslash => k ( m, "\\ " , hw_code , xkb_state ) ,
101+ Code :: Semicolon => k ( m, ";" , hw_code , xkb_state ) ,
102+ Code :: Quote => k ( m, "'" , hw_code , xkb_state ) ,
103+ Code :: Comma => k ( m, "," , hw_code , xkb_state ) ,
104+ Code :: Period => k ( m, "." , hw_code , xkb_state ) ,
105+ Code :: Slash => k ( m, "/" , hw_code , xkb_state ) ,
99106
100107 Code :: Space => a ( " " ) ,
101108
@@ -383,22 +390,39 @@ pub(super) fn key_mods(mods: KeyButMask) -> Modifiers {
383390 ret
384391}
385392
386- pub ( super ) fn convert_key_press_event ( key_press : & KeyPressEvent ) -> KeyboardEvent {
393+ pub ( super ) fn convert_key_press_event (
394+ key_press : & KeyPressEvent , state : & mut xkbc:: State ,
395+ ) -> KeyboardEvent {
387396 let hw_keycode = key_press. detail ;
397+
398+ // Update the xkbc state
399+ let hw_code = hw_keycode. into ( ) ;
400+ state. update_key ( hw_code, xkbc:: KeyDirection :: Down ) ;
401+
388402 let code = hardware_keycode_to_code ( hw_keycode. into ( ) ) ;
389403 let modifiers = key_mods ( key_press. state ) ;
390- let key = code_to_key ( code, modifiers) ;
404+ let key = code_to_key ( code, modifiers, hw_code , state ) ;
391405 let location = code_to_location ( code) ;
392406 let state = KeyState :: Down ;
393407
394- KeyboardEvent { code, key, modifiers, location, state, repeat : false , is_composing : false }
408+ let ev =
409+ KeyboardEvent { code, key, modifiers, location, state, repeat : false , is_composing : false } ;
410+ println ! ( "GOT: {:?}" , ev) ;
411+ ev
395412}
396413
397- pub ( super ) fn convert_key_release_event ( key_release : & KeyReleaseEvent ) -> KeyboardEvent {
414+ pub ( super ) fn convert_key_release_event (
415+ key_release : & KeyReleaseEvent , state : & mut xkbc:: State ,
416+ ) -> KeyboardEvent {
398417 let hw_keycode = key_release. detail ;
418+
419+ // Update the xkbc state
420+ let hw_code = hw_keycode. into ( ) ;
421+ state. update_key ( hw_code, xkbc:: KeyDirection :: Up ) ;
422+
399423 let code = hardware_keycode_to_code ( hw_keycode. into ( ) ) ;
400424 let modifiers = key_mods ( key_release. state ) ;
401- let key = code_to_key ( code, modifiers) ;
425+ let key = code_to_key ( code, modifiers, hw_code , state ) ;
402426 let location = code_to_location ( code) ;
403427 let state = KeyState :: Up ;
404428
0 commit comments