Merge pull request #1897 from storytold/fix/1881-typing-cmd-drag

Fix #1881: a Ctrl/Cmd drag while typing keeps what was typed
This commit is contained in:
BFlat
2026-10-14 12:38:12 +07:00
committed by GitHub
3 changed files with 31 additions and 0 deletions
+1
View File
@@ -457,6 +457,7 @@ pub(crate) fn unique_name(base: &str, taken: impl Fn(&str) -> bool) -> String {
(2..).map(|i| format!("{base} {i}")).find(|n| !taken(n)).unwrap_or_else(|| base.to_string())
}
pub(crate) use edit::{settle_interaction, typing_in_progress};
pub(crate) use vectorcraft_doc::range::parse_range;
/// A date param in Unix seconds that defaults to the clock: `None` when absent (now, see
+24
View File
@@ -150,6 +150,30 @@ fn undo_while_typing_takes_back_only_the_typing_and_redo_returns_it() {
assert_eq!(obj(&s, id).plain_text(), "abc!");
}
/// #1881: a Cmd/Ctrl drag while typing (the Selection tool lent to the Type tool) moves the type
/// and keeps what was typed, and typing goes on after it.
#[test]
fn a_cmd_drag_while_typing_moves_the_type_and_keeps_the_typing() {
let mut s = session();
let v = ViewInfo::default();
s.select_tool("type", v).unwrap();
click(&mut s, 200.0, 200.0);
let id = s.doc().unwrap().selection.objects[0];
s.tool_text("Hello", v).unwrap();
let before = s.doc().unwrap().doc.bounds_of(&[id], false).unwrap();
let (at, cmd) = (before.center(), Mods { cmd: true, ..Default::default() });
for (kind, dx) in [(PointerKind::Down, 0.0), (PointerKind::Drag, 100.0), (PointerKind::Up, 100.0)] {
s.pointer(&PointerEvent::new(kind, at.x + dx, at.y).with_mods(cmd), v).unwrap();
}
assert_eq!(obj(&s, id).plain_text(), "Hello", "the typing is kept");
let moved = s.doc().unwrap().doc.bounds_of(&[id], false).unwrap();
assert!(moved.x0 - before.x0 > 50.0, "the type moved: {before:?} → {moved:?}");
s.tool_text("!", v).unwrap();
assert_eq!(obj(&s, id).plain_text(), "Hello!");
let after = s.doc().unwrap().doc.bounds_of(&[id], false).unwrap();
assert!((after.x0 - moved.x0).abs() < 1e-6, "and stays where it was moved: {after:?}");
}
#[test]
fn undo_during_a_drag_takes_back_only_the_drag() {
let mut s = session();
+6
View File
@@ -115,6 +115,12 @@ impl Session {
return *ev;
}
let Some(id) = self.lent_tool(self.tool.id()) else { return *ev };
// Typing in progress is kept as its own step first: the lent tool's drag previews from the
// document its interaction started from, which would drop the typing (#1881).
if crate::cmd::typing_in_progress(self) {
// Fails only without a document, and then there is no typing to keep.
let _ = crate::cmd::settle_interaction(self);
}
let lent = self.make_tool(id);
self.lender = Some(std::mem::replace(&mut self.tool, lent));
PointerEvent { mods: Mods { cmd: false, ..ev.mods }, ..*ev }