diff --git a/crates/engine/src/tests_textedit.rs b/crates/engine/src/tests_textedit.rs index b098fb04..a306f953 100644 --- a/crates/engine/src/tests_textedit.rs +++ b/crates/engine/src/tests_textedit.rs @@ -113,8 +113,15 @@ fn type_tool_typing_is_one_undo_step() { assert!(!s.in_interaction(), "moving the caret commits"); assert_eq!(undo_labels(&s).last().map(String::as_str), Some("Typing")); s.tool_text("!", v).unwrap(); - key(&mut s, ToolKey::Escape, Mods::default()); + // #1686: Escape is the tool's while editing, and asks the UI for the Selection tool. + assert!(s.tool_claims_key(ToolKey::Escape, v)); + let r = s.tool_key(ToolKey::Escape, Mods::default(), v).unwrap(); + assert!(r.iter().any(|r| matches!(r, UiRequest::SwitchTool(t) if t == "selection")), "{r:?}"); + assert!(!s.tool_claims_key(ToolKey::Escape, v)); assert_eq!(obj(&s, id).plain_text(), "Hello worl!d"); + // #1686: Escape ends editing, the type still selected; the UI goes on to the Selection tool. + assert!(!s.tool_wants_text()); + assert_eq!(s.doc().unwrap().selection.objects, vec![id]); s.execute("edit.undo", &json!({})).unwrap(); assert_eq!(obj(&s, id).plain_text(), "Hello world"); s.execute("edit.undo", &json!({})).unwrap(); diff --git a/crates/tools/src/text.rs b/crates/tools/src/text.rs index 564220ad..9eb2d379 100644 --- a/crates/tools/src/text.rs +++ b/crates/tools/src/text.rs @@ -381,6 +381,10 @@ impl Tool for TypeTool { fn wants_text(&self) -> bool { self.editing.is_some() } + /// Escape while editing is the tool's: it goes on to the Selection tool (#1686). + fn claims_key(&self, _: &ToolContext, key: ToolKey) -> bool { + key == ToolKey::Escape && self.editing.is_some() + } fn pointer(&mut self, cx: &ToolContext, ev: &PointerEvent) -> Vec { match ev.kind { PointerKind::Down => { @@ -522,7 +526,13 @@ impl Tool for TypeTool { self.goal_x = None; } match key { - ToolKey::Escape => self.finish(cx), + // Escape ends editing and goes to the Selection tool, the type selected: the keyboard + // is free for tool shortcuts again (#1686). + ToolKey::Escape => { + let mut out = self.finish(cx); + out.push(Action::SwitchTool("selection".into())); + out + } ToolKey::Enter => self.replace(cx, "\n", None), ToolKey::Tab => self.replace(cx, "\t", None), ToolKey::Backspace | ToolKey::Delete if a != b => self.replace(cx, "", None),