@@ -265,7 +265,14 @@ pub enum KeyboardAction {
265265/// Window IDs: 1-9 map to windows 1-9, 0 maps to window 10.
266266///
267267/// Note: Uses Alt on all platforms. On macOS, Cmd is also accepted (without Ctrl).
268- pub fn handle_window_manager_keyboard_press ( key : & icy_ui:: keyboard:: Key , modifiers : & icy_ui:: keyboard:: Modifiers ) -> Option < KeyboardAction > {
268+ /// `modified_key` must include the current keyboard layout and modifiers. This
269+ /// prevents Option+number combinations that produce punctuation on macOS from
270+ /// being mistaken for window shortcuts.
271+ pub fn handle_window_manager_keyboard_press (
272+ key : & icy_ui:: keyboard:: Key ,
273+ modified_key : & icy_ui:: keyboard:: Key ,
274+ modifiers : & icy_ui:: keyboard:: Modifiers ,
275+ ) -> Option < KeyboardAction > {
269276 use icy_ui:: keyboard:: key:: Named ;
270277
271278 // Handle Tab / Shift+Tab for focus navigation
@@ -283,7 +290,7 @@ pub fn handle_window_manager_keyboard_press(key: &icy_ui::keyboard::Key, modifie
283290 let is_alt_or_cmd = modifiers. alt ( ) || ( modifiers. command ( ) && !modifiers. control ( ) ) ;
284291
285292 if is_alt_or_cmd && !modifiers. shift ( ) {
286- if let icy_ui:: keyboard:: Key :: Character ( s) = key {
293+ if let icy_ui:: keyboard:: Key :: Character ( s) = modified_key {
287294 if let Some ( digit) = s. chars ( ) . next ( ) {
288295 if digit. is_ascii_digit ( ) {
289296 let target_id = digit. to_digit ( 10 ) . unwrap ( ) as usize ;
@@ -296,3 +303,34 @@ pub fn handle_window_manager_keyboard_press(key: &icy_ui::keyboard::Key, modifie
296303 }
297304 None
298305}
306+
307+ #[ cfg( test) ]
308+ mod tests {
309+ use super :: { handle_window_manager_keyboard_press, KeyboardAction } ;
310+ use icy_ui:: keyboard:: { Key , Modifiers } ;
311+
312+ #[ test]
313+ fn alt_digit_focuses_window ( ) {
314+ let key = Key :: Character ( "5" . into ( ) ) ;
315+ assert_eq ! (
316+ handle_window_manager_keyboard_press( & key, & key, & Modifiers :: ALT ) ,
317+ Some ( KeyboardAction :: FocusWindow ( 5 ) )
318+ ) ;
319+ }
320+
321+ #[ test]
322+ fn option_generated_characters_are_not_window_shortcuts ( ) {
323+ for ( unmodified, modified, modifiers) in [
324+ ( "5" , "[" , Modifiers :: ALT ) ,
325+ ( "6" , "]" , Modifiers :: ALT ) ,
326+ ( "7" , "|" , Modifiers :: ALT ) ,
327+ ( "8" , "{" , Modifiers :: ALT ) ,
328+ ( "9" , "}" , Modifiers :: ALT ) ,
329+ ( "7" , "\\ " , Modifiers :: ALT | Modifiers :: SHIFT ) ,
330+ ] {
331+ let unmodified_key = Key :: Character ( unmodified. into ( ) ) ;
332+ let modified_key = Key :: Character ( modified. into ( ) ) ;
333+ assert_eq ! ( handle_window_manager_keyboard_press( & unmodified_key, & modified_key, & modifiers) , None ) ;
334+ }
335+ }
336+ }
0 commit comments