From 021fa4a8460cd5f28e4b70d1ad682897ba4eace0 Mon Sep 17 00:00:00 2001 From: dotCooCoo Date: Fri, 30 Oct 2026 15:01:22 -0700 Subject: [PATCH] Shortcuts: Shift+Comma and Shift+Period follow their key positions only with Shift alone The key-position match for Shift+Comma and Shift+Period now applies only when Shift is the only modifier. Cmd/Ctrl+Shift and Alt+Shift presses at those keys keep their logical key, so the type-size shortcuts on German-like layouts behave as before. The typing test also checks that no paint command runs while text is edited. --- crates/ui-egui/src/shortcuts.rs | 4 ++++ crates/ui-egui/src/shortcuts/tests.rs | 25 +++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/crates/ui-egui/src/shortcuts.rs b/crates/ui-egui/src/shortcuts.rs index 504e84b2d..8b8355b07 100644 --- a/crates/ui-egui/src/shortcuts.rs +++ b/crates/ui-egui/src/shortcuts.rs @@ -736,6 +736,10 @@ fn dispatch(app: &mut VectorcraftApp, ctx: &egui::Context, accept: impl FnMut(&H for e in &mut i.events { if let egui::Event::Key { key, physical_key: Some(physical), modifiers, pressed: true, .. } = e && modifiers.shift + && !modifiers.command + && !modifiers.ctrl + && !modifiers.alt + && !modifiers.mac_cmd && matches!(*physical, Key::Comma | Key::Period) && *key != *physical && let (Some(logical), Some(position)) = (craft_keymap::Key::from_egui(*key), craft_keymap::Key::from_egui(*physical)) diff --git a/crates/ui-egui/src/shortcuts/tests.rs b/crates/ui-egui/src/shortcuts/tests.rs index 6bce0cc6f..56e552b31 100644 --- a/crates/ui-egui/src/shortcuts/tests.rs +++ b/crates/ui-egui/src/shortcuts/tests.rs @@ -1184,12 +1184,37 @@ fn plain_and_shifted_paint_keys_run_once_on_us_and_german_like_input() { (Key::Colon, Key::Period, Modifiers::SHIFT, ":"), (Key::Semicolon, Key::Comma, Modifiers::SHIFT, ";"), ] { + let journal_before = app.session.journal.len(); frame(&mut app, press(key, physical_key, mods, typed)); assert_eq!(crate::panels::current_paints(&app), paints_before, "typing {typed} keeps fill and stroke"); + assert!( + app.session.journal.since(journal_before).iter().all(|(command, _)| !command.starts_with("paint.")), + "typing {typed} runs no paint command" + ); } assert_eq!(text_and_layers(&mut app, id).0, "Hi,.<>:;"); } +#[test] +fn modified_german_like_punctuation_keeps_text_size() { + let mut app = VectorcraftApp::new(vectorcraft_engine::Session::new(), Default::default()); + app.session.execute("file.new", &json!({"width": 200, "height": 200})).unwrap(); + let id = app.session.execute("text.create", &json!({"x": 20, "y": 50, "text": "Hi", "size": 12})).unwrap()["id"].as_u64().unwrap(); + app.session.execute("select.set", &json!({"ids": [id]})).unwrap(); + for (key, physical_key) in [(Key::Colon, Key::Period), (Key::Semicolon, Key::Comma)] { + let modifiers = Modifiers::COMMAND | Modifiers::SHIFT; + frame( + &mut app, + vec![ + egui::Event::ModifiersChanged(modifiers), + egui::Event::Key { key, physical_key: Some(physical_key), pressed: true, repeat: false, modifiers }, + ], + ); + let range = app.session.execute("text.getRange", &json!({"id": id})).unwrap(); + assert_eq!(range["runs"][0]["style"]["size"], json!(12.0), "{key:?} keeps the text size"); + } +} + #[test] fn explicit_logical_shifted_binding_wins_over_position_alias() { let mut app = remembered_paint_app();