diff --git a/crates/ui-egui/src/tools/edit_text_ui/image.rs b/crates/ui-egui/src/tools/edit_text_ui/image.rs index 7a7ad701a2..b63f876298 100644 --- a/crates/ui-egui/src/tools/edit_text_ui/image.rs +++ b/crates/ui-egui/src/tools/edit_text_ui/image.rs @@ -782,13 +782,16 @@ pub(crate) fn image_input(cx: &ImageCx<'_>, images: &[pdfcraft_engine::PageImage } // A drag of the selected picture takes what its press was on ([`body_hit`], [`handle_hit`]): - // the rotate knob turns it, a grip resizes it, the picture itself moves. + // the rotate knob turns it, a grip resizes it, the picture itself moves. The knob and the + // grips take it from the press, so a move too short to be a drag of the page counts; the + // picture waits for that, as a click selects. + let at_press = |part| matches!(part, PicturePart::Knob | PicturePart::Corner(_)); if gate - && ptr.drag_started && let Some(o) = ptr.origin && let PagePress::Mine(Owner::Picture { index, part }) = press && (index == i || part == PicturePart::OverSelected) - && let Some(s) = view.image_selection.as_mut() + && (ptr.drag_started || at_press(part) && ptr.pressed().is_some()) + && let Some(s) = view.image_selection.as_mut().filter(|s| s.drag.is_none()) { match part { PicturePart::Knob => { diff --git a/crates/ui-egui/tests/it/editing.rs b/crates/ui-egui/tests/it/editing.rs index cd82d95aec..d40a52e373 100644 --- a/crates/ui-egui/tests/it/editing.rs +++ b/crates/ui-egui/tests/it/editing.rs @@ -7435,6 +7435,39 @@ fn a_drag_from_the_selected_picture_under_another_moves_the_selected_one() { assert_eq!(selected, Some(1), "a click selects the one on top"); } +/// A move too short to be a drag of the page still resizes the selected picture from its grip, as +/// the grip takes its drag from the press. +#[test] +fn a_short_drag_from_a_picture_grip_resizes_it() { + let mut h = picture_pages(false); + let id = h.state().views[0].id; + let before = h.state().session.get(id).unwrap().page_images(0)[0].matrix; + // The picture shows at x 30..160, y 170..250: its lower right grip, moved 3 px. + let grip = page_at(&h, 0, 160.0, 170.0); + h.hover_at(grip); + h.run_steps(1); + h.drag_at(grip); + h.run_steps(1); + h.hover_at(grip + egui::vec2(3.0, 0.0)); + h.run_steps(1); + h.drop_at(grip + egui::vec2(3.0, 0.0)); + h.run_steps(3); + assert_ne!(h.state().session.get(id).unwrap().page_images(0)[0].matrix, before, "the picture is resized"); +} + +/// A click on a selected picture's grip that doesn't move resizes nothing: no edit, and the picture +/// stays selected. +#[test] +fn a_click_on_a_picture_grip_changes_nothing() { + let mut h = picture_pages(false); + let id = h.state().views[0].id; + let before = h.state().session.get(id).unwrap().edit_generation(); + let grip = page_at(&h, 0, 160.0, 170.0); + slipping_click(&mut h, grip, grip); + assert_eq!(h.state().session.get(id).unwrap().edit_generation(), before, "no edit"); + assert!(h.state().views[0].image_selection.is_some(), "the picture stays selected"); +} + /// In the page grid, Delete deletes the page chosen there. The picture selected before the grid /// opened is not on screen, and stays. #[test]