Format Painter: paint a drag release only if the drag changed the selection

A Shift-press at the caret inside the edited text starts a text drag
without changing the selection; releasing it no longer repaints the
existing range.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
fchinu
2026-10-23 09:34:39 +02:00
co-authored by Claude Sonnet 5.5
parent 6e201094c6
commit da3e89695f
2 changed files with 27 additions and 6 deletions
+20
View File
@@ -561,3 +561,23 @@ fn format_painter_ignores_a_double_click_that_selects_nothing() {
assert!(s.painter.is_some(), "a click that left the selection alone keeps the painter");
assert!(bulleted(&mut s, 0));
}
#[test]
fn format_painter_ignores_a_shift_press_that_leaves_the_selection() {
use crate::tools::PointerKind::{Down, Up};
let (mut s, _) = painter_armed(false);
// Find the caret position under the point, then select from the line start to it.
pointer(&mut s, Down, 110.0, 90.0);
pointer(&mut s, Up, 110.0, 90.0);
let k = caret(&s);
assert!(k.1 > 0);
s.execute("text.select", &json!({"anchor": [k.0, 0], "caret": [k.0, k.1]})).unwrap();
// Shift-pressing at the caret keeps the range, so there is nothing new to paint.
let shift = Mods { shift: true, ..NONE };
for kind in [Down, Up] {
s.pointer(crate::tools::PointerEvent { kind, x: 110.0, y: 90.0, mods: shift, tol: 4.0, ..Default::default() }).unwrap();
}
assert_eq!(sel(&s), ((k.0, 0), k));
assert!(s.painter.is_some(), "the painter stays armed");
assert!(!bold_at(&mut s, (1, 0)));
}
+7 -6
View File
@@ -194,6 +194,8 @@ enum Drag {
},
TextSelect {
shape: ShapeId,
/// The text selection before the press, to tell whether the drag changed it.
before: Option<TextTarget>,
},
/// Dragging a table border: the right edge of column `index`, or the bottom edge of row
/// `index`. `start` is the table-local press point, `size` the column's width or the row's
@@ -582,8 +584,9 @@ impl Session {
ToolKind::Select => {}
}
// Clicking inside the text being edited moves the caret / starts a text selection.
let before = self.text_selection();
if let Some((shape, pos)) = self.place_caret(p, tol, mods.shift)? {
self.tool.drag = Some(Drag::TextSelect { shape });
self.tool.drag = Some(Drag::TextSelect { shape, before });
return Ok(json!({"caret": [pos.0, pos.1]}));
}
let hit = self.hit_test(p, tol);
@@ -939,7 +942,7 @@ impl Session {
};
self.tool.preview = Some(x);
}
Drag::TextSelect { shape } => {
Drag::TextSelect { shape, .. } => {
// The selection stays in the shape or table cell where it started.
let st = self.doc()?;
if let Some(t) = st.selection.text.as_ref().filter(|t| t.shape == shape) {
@@ -1134,10 +1137,8 @@ impl Session {
let _ = cmd::text::fit_text_box(self, id);
self.refit_after_resize(id)?;
}
Some(Drag::TextSelect { .. }) => {
if let Some(applied) = self.paint_text_selection()? {
out = applied;
}
Some(Drag::TextSelect { before, .. }) => {
out = self.paint_if_selection_changed(before, out)?;
self.commit();
}
Some(_) => self.commit(),