From 06c644f47e086e9364634704e5e651d5cd4d844d Mon Sep 17 00:00:00 2001 From: Thodoris Tsagkogeorgas Date: Sat, 17 Oct 2026 00:27:17 +0000 Subject: [PATCH] Escape stays in the sketch (#1804) (#1836) * claim: #1804 * Escape no longer leaves an open sketch (#1804) A second Escape after putting a tool down, or after clearing the selection, stays in the sketch. Finish Sketch is what leaves it. --- crates/ui-egui/src/sketch_shortcut_tests.rs | 23 +++++++++++++++++++++ crates/ui-egui/src/toolbar.rs | 5 ++--- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/crates/ui-egui/src/sketch_shortcut_tests.rs b/crates/ui-egui/src/sketch_shortcut_tests.rs index 5bd8403a..4a95a847 100644 --- a/crates/ui-egui/src/sketch_shortcut_tests.rs +++ b/crates/ui-egui/src/sketch_shortcut_tests.rs @@ -67,6 +67,29 @@ fn a_sketch_key_with_nothing_selected_asks_for_the_plane_then_starts_the_tool() assert!(h.app.dialog.is_none()); } +/// #1804: Escape puts down the sketch tool. Another Escape does not leave the sketch. +#[test] +fn a_second_escape_stays_in_the_sketch() { + let mut h = Harness::new(); + h.app.run("sketch.create", json!({"plane":"XY"})).unwrap(); + let sketch = h.app.session.active_sketch; + h.app.start("sketch.line"); + h.settle(); + assert_eq!(tool(&h), Some("sketch.line")); + press(&mut h, "Escape"); + assert!(tool(&h).is_none(), "the first Escape puts the tool down"); + assert_eq!(h.app.session.active_sketch, sketch); + press(&mut h, "Escape"); + assert_eq!(h.app.session.active_sketch, sketch, "a second Escape stays in the sketch"); + h.app.run("sketch.line", json!({"points":[[0,0],[10,0]]})).unwrap(); + h.app.session.selection = vec![Sel::SketchCurve { id: "l1".into() }]; + press(&mut h, "Escape"); + assert!(h.app.session.selection.is_empty(), "Escape still clears a selection"); + assert_eq!(h.app.session.active_sketch, sketch); + press(&mut h, "Escape"); + assert_eq!(h.app.session.active_sketch, sketch, "Escape after clearing the selection stays in the sketch"); +} + #[test] fn escape_drops_the_tool_waiting_for_a_sketch() { let mut h = Harness::new(); diff --git a/crates/ui-egui/src/toolbar.rs b/crates/ui-egui/src/toolbar.rs index 56cf0166..1b822d00 100644 --- a/crates/ui-egui/src/toolbar.rs +++ b/crates/ui-egui/src/toolbar.rs @@ -1348,10 +1348,9 @@ pub fn shortcuts(app: &mut SolveApp, ctx: &egui::Context) { } else if !app.session.selection.is_empty() || app.session.active_sketch.is_none() { app.tree.picked_joints.clear(); let _ = app.run("select.clear", json!({})); - } else { - // Nothing left to cancel: Esc finishes the sketch. - app.finish_sketch(); } + // An open sketch with nothing left to cancel stays open (#1804). Finish Sketch + // is what leaves it, so a second Escape after putting a tool down is harmless. } Key::S if !mods.shift && !mods.alt => { let at = ctx.input(|i| i.pointer.latest_pos());