mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-24 18:18:17 -06:00
fix: let a rebound Deselect All use Alt variants of Cmd+A and Cmd+Z (#2096)
The text editor's Select All and Undo arms ignored Alt, so a Deselect All rebound to Cmd+Alt+A or Cmd+Alt+Z was taken as Select All or Undo while a text edit was open. The arms now match exactly the chords the editor owns (Cmd/Ctrl+A, and Cmd/Ctrl+Z with or without Shift); their Alt variants fall through to the Deselect All binding match. Chords the editor owns still win over a rebound Deselect All, so Undo keeps working while typing. Test: a UI kittest rebinds Deselect All to each Alt variant and checks that Cmd+A and Cmd+Z still edit the text while the rebound chord ends the edit.
This commit is contained in:
@@ -486,12 +486,14 @@ fn keyboard(app: &mut EffectcraftApp, ui: &mut egui::Ui, viewer: Rect) {
|
||||
Key::Escape => {
|
||||
exec(app, "text.endEdit", json!({}));
|
||||
}
|
||||
// Cmd/Ctrl alone is Select All; with Shift it belongs to Deselect All,
|
||||
// which the binding match below handles, so don't eat the chord here.
|
||||
Key::A if cmd && !m.shift => {
|
||||
// The editor owns exactly Cmd/Ctrl+A (Select All) and Cmd/Ctrl+Z with or
|
||||
// without Shift (Undo, Redo). Other modifiers on those keys aren't editing
|
||||
// chords, so they fall through to the binding match below: Shift+A is
|
||||
// Deselect All's default, and Alt variants are free for a rebound one.
|
||||
Key::A if cmd && !m.shift && !m.alt => {
|
||||
exec(app, "text.setSelection", json!({"select": "all"}));
|
||||
}
|
||||
Key::Z if cmd => {
|
||||
Key::Z if cmd && !m.alt => {
|
||||
let _ = crate::menus::invoke(app, &ctx, if m.shift { "edit.redo" } else { "edit.undo" }, json!({}));
|
||||
}
|
||||
Key::Comma | Key::Period if cmd && m.shift => {
|
||||
|
||||
@@ -634,6 +634,28 @@ fn rebound_deselect_all_chord_forwards_from_inside_the_edit() {
|
||||
assert_eq!(layer_doc(&h.state().session, LayerId(lid)).unwrap().text, "Hello", "the text is kept");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deselect_all_rebound_onto_an_alt_variant_of_an_editor_chord_forwards() {
|
||||
let alt_cmd = |k| (k, Modifiers { alt: true, ..Modifiers::COMMAND });
|
||||
for (bound, (k, mods)) in [("Cmd+Alt+Z", alt_cmd(Key::Z)), ("Cmd+Alt+A", alt_cmd(Key::A))] {
|
||||
let mut a = app();
|
||||
a.session.execute("shortcuts.set", json!({"command": "edit.deselectAll", "keys": [bound]})).unwrap();
|
||||
let (mut h, lid) = type_tool_edit(a, "Hello");
|
||||
// The editor owns Cmd+A and Cmd+Z themselves, whatever Deselect All is bound to…
|
||||
key(&mut h, Key::A, Modifiers::COMMAND);
|
||||
let (_, _, a0, c0) = edited(&h);
|
||||
assert_eq!((a0, c0), (0, 5), "{bound}: Cmd+A still selects every character");
|
||||
type_text(&mut h, "Hi");
|
||||
key(&mut h, Key::Z, Modifiers::COMMAND);
|
||||
assert_eq!(edited(&h).1, "Hello", "{bound}: Cmd+Z still undoes the typing");
|
||||
// …but not their Alt variants, which belong to the rebound Deselect All.
|
||||
key(&mut h, k, mods);
|
||||
assert!(h.state().session.state.text_edit.is_none(), "{bound}: the rebound chord ends the edit");
|
||||
assert!(h.state().session.state.selected_layers.is_empty(), "{bound}: and deselects");
|
||||
assert_eq!(layer_doc(&h.state().session, LayerId(lid)).unwrap().text, "Hello", "{bound}: without undoing or selecting text");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bare_letter_rebinding_stays_typing_but_a_function_key_rebinding_forwards() {
|
||||
let mut a = app();
|
||||
|
||||
Reference in New Issue
Block a user