1+ use iced_core:: keyboard:: key:: { Code , Physical } ;
12use iced_core:: keyboard:: { Key , Modifiers } ;
23use std:: fmt;
34
@@ -27,28 +28,97 @@ pub struct KeyBind {
2728}
2829
2930impl KeyBind {
30- /// Checks if the given key and modifiers match the `KeyBind`.
31+ /// Checks if the given key and modifiers match the `KeyBind`, with an
32+ /// optional fallback to the physical key position for non-Latin keyboard
33+ /// layouts.
3134 ///
3235 /// # Arguments
3336 ///
3437 /// * `modifiers` - A `Modifiers` instance representing the current active modifiers.
3538 /// * `key` - A reference to the `Key` that is being checked.
39+ /// * `physical_key` - An optional reference to the physical key position,
40+ /// used as a fallback when the logical `key` does not match (e.g. on
41+ /// Cyrillic or other non-Latin layouts). Can be `None` for keys where
42+ /// the physical position is not relevant (e.g. `Key::Named`).
3643 ///
3744 /// # Returns
3845 ///
3946 /// * `bool` - `true` if the key and modifiers match the `KeyBind`, `false` otherwise.
40- pub fn matches ( & self , modifiers : Modifiers , key : & Key ) -> bool {
41- let key_eq = match ( key, & self . key ) {
42- // CapsLock and Shift change the case of Key::Character, so we compare these in a case insensitive way
43- ( Key :: Character ( a) , Key :: Character ( b) ) => a. eq_ignore_ascii_case ( b) ,
44- ( a, b) => a. eq ( b) ,
45- } ;
47+ pub fn matches ( & self , modifiers : Modifiers , key : & Key , physical_key : Option < & Physical > ) -> bool {
48+ let key_eq = self . key_eq ( key)
49+ || physical_key
50+ . and_then ( physical_key_to_latin)
51+ . is_some_and ( |latin| self . key_eq ( & latin) ) ;
4652 key_eq
4753 && modifiers. logo ( ) == self . modifiers . contains ( & Modifier :: Super )
4854 && modifiers. control ( ) == self . modifiers . contains ( & Modifier :: Ctrl )
4955 && modifiers. alt ( ) == self . modifiers . contains ( & Modifier :: Alt )
5056 && modifiers. shift ( ) == self . modifiers . contains ( & Modifier :: Shift )
5157 }
58+
59+ fn key_eq ( & self , key : & Key ) -> bool {
60+ match ( key, & self . key ) {
61+ // CapsLock and Shift change the case of Key::Character, so we compare these in a case insensitive way
62+ ( Key :: Character ( a) , Key :: Character ( b) ) => a. eq_ignore_ascii_case ( b) ,
63+ ( a, b) => a. eq ( b) ,
64+ }
65+ }
66+ }
67+
68+ /// Converts a physical key code to the corresponding US-layout Latin `Key`.
69+ ///
70+ /// This mapping is intentionally limited to keys that may produce different
71+ /// characters on non-Latin keyboard layouts (letters and punctuation). Keys
72+ /// like digits are not included because they remain the same across layouts.
73+ ///
74+ /// Only used as a fallback when the primary key comparison in
75+ /// [`KeyBind::matches`] does not match.
76+ fn physical_key_to_latin ( physical_key : & Physical ) -> Option < Key > {
77+ let code = match physical_key {
78+ Physical :: Code ( code) => code,
79+ Physical :: Unidentified ( _) => return None ,
80+ } ;
81+ let ch = match code {
82+ Code :: KeyA => "a" ,
83+ Code :: KeyB => "b" ,
84+ Code :: KeyC => "c" ,
85+ Code :: KeyD => "d" ,
86+ Code :: KeyE => "e" ,
87+ Code :: KeyF => "f" ,
88+ Code :: KeyG => "g" ,
89+ Code :: KeyH => "h" ,
90+ Code :: KeyI => "i" ,
91+ Code :: KeyJ => "j" ,
92+ Code :: KeyK => "k" ,
93+ Code :: KeyL => "l" ,
94+ Code :: KeyM => "m" ,
95+ Code :: KeyN => "n" ,
96+ Code :: KeyO => "o" ,
97+ Code :: KeyP => "p" ,
98+ Code :: KeyQ => "q" ,
99+ Code :: KeyR => "r" ,
100+ Code :: KeyS => "s" ,
101+ Code :: KeyT => "t" ,
102+ Code :: KeyU => "u" ,
103+ Code :: KeyV => "v" ,
104+ Code :: KeyW => "w" ,
105+ Code :: KeyX => "x" ,
106+ Code :: KeyY => "y" ,
107+ Code :: KeyZ => "z" ,
108+ Code :: Minus => "-" ,
109+ Code :: Equal => "=" ,
110+ Code :: BracketLeft => "[" ,
111+ Code :: BracketRight => "]" ,
112+ Code :: Backslash => "\\ " ,
113+ Code :: Semicolon => ";" ,
114+ Code :: Quote => "'" ,
115+ Code :: Backquote => "`" ,
116+ Code :: Comma => "," ,
117+ Code :: Period => "." ,
118+ Code :: Slash => "/" ,
119+ _ => return None ,
120+ } ;
121+ Some ( Key :: Character ( ch. into ( ) ) )
52122}
53123
54124impl fmt:: Display for KeyBind {
@@ -62,4 +132,4 @@ impl fmt::Display for KeyBind {
62132 other => write ! ( f, "{:?}" , other) ,
63133 }
64134 }
65- }
135+ }
0 commit comments