mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-11-06 10:47:27 +00:00
fix(ui): a camera click is located where it came up
Found in review (CodeRabbit): the last fix located a camera click by the pointer, which can have moved on by the end of the release's frame. A click pressed on page 2 and released on page 1, with the pointer back on page 2 by then, moved the quadrilateral to page 2. `PagePointer` keeps each release's position, so `PagePointer::released` gives where the click came up, and the click is located there. Test: `a_camera_click_released_off_its_page_moves_nothing`, seen failing without the fix. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
3 files changed
+31
-2
No files matched your search
@@ -78,6 +78,15 @@ impl PagePointer {
|
||||
pub(crate) fn pressed(&self) -> Option<Pos2> {
|
||||
first_press(&self.edges)
|
||||
}
|
||||
|
||||
/// Where this frame's last primary release was: where a click came up, which the pointer may
|
||||
/// have left by the frame's end.
|
||||
pub(crate) fn released(&self) -> Option<Pos2> {
|
||||
self.edges.iter().rev().find_map(|e| match e {
|
||||
Edge::Release(p) => Some(*p),
|
||||
Edge::Press(_) => None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether egui gives the drag to a widget that is not the pages' (a panel's tab, a floating panel's
|
||||
|
||||
@@ -99,8 +99,9 @@ pub(crate) fn page_input(resp: &egui::Response, xf: &PageXform, ptr: &PagePointe
|
||||
view.camera = Some(CameraQuad::inset(page, xf.pw, xf.ph));
|
||||
}
|
||||
// A press nobody holds on a page without the quadrilateral moves it there: a drag from where it
|
||||
// began, a click where it came up (egui has cleared the press's origin by its release).
|
||||
let at = if resp.clicked() { pointer } else { origin };
|
||||
// began, a click where it came up (egui has cleared the press's origin by its release, and the
|
||||
// pointer may have moved on in the same frame).
|
||||
let at = if resp.clicked() { ptr.released() } else { origin };
|
||||
if (resp.drag_started() || resp.clicked())
|
||||
&& press == PagePress::Free
|
||||
&& at.is_some_and(|p| xf.rect.contains(p))
|
||||
|
||||
@@ -1739,3 +1739,22 @@ fn a_camera_click_on_another_page_moves_the_quadrilateral_there() {
|
||||
mouse_click(&mut h, two.min + egui::vec2(100.0, 60.0));
|
||||
assert_eq!(h.state().views[0].camera.map(|q| q.page), Some(1));
|
||||
}
|
||||
|
||||
/// A camera click is located where it came up, not where the pointer went after it in the same
|
||||
/// frame: pressed on page 2 and released on page 1 (the gaps hidden), it moves nothing, though the
|
||||
/// pointer is back on page 2 by the frame's end. The pointer's last position used to move the
|
||||
/// quadrilateral to page 2.
|
||||
#[test]
|
||||
fn a_camera_click_released_off_its_page_moves_nothing() {
|
||||
let (mut h, seam) = touching_pages(|app| app.quick_tool = QuickTool::EnhanceCamera);
|
||||
assert_eq!(h.state().views[0].camera.map(|q| q.page), Some(0), "it starts on the current page");
|
||||
let (press, release, back) = (seam + egui::vec2(0.0, 2.0), seam - egui::vec2(0.0, 2.0), seam + egui::vec2(0.0, 40.0));
|
||||
h.hover_at(press);
|
||||
h.run_steps(1);
|
||||
h.drag_at(press);
|
||||
h.run_steps(1);
|
||||
let up = egui::Event::PointerButton { pos: release, button: egui::PointerButton::Primary, pressed: false, modifiers: egui::Modifiers::NONE };
|
||||
one_frame(&mut h, [up, egui::Event::PointerMoved(back)]);
|
||||
h.run_steps(2);
|
||||
assert_eq!(h.state().views[0].camera.map(|q| q.page), Some(0));
|
||||
}
|
||||
Reference in new issue
Block a user