fix(ui): a comment's gesture whose release the pages missed applies nothing

`fix(ui): a comment's move, resize or reshape ends` ended a comment's move, resize or reshape once the button was
up, and applied it where the pointer then was: when the pages missed
the release (the page scrolled out of range, a tab switch, a tool
switched mid-drag), the comment jumped to wherever the pointer next
showed up over its page, and while the pointer stayed off the pages the
gesture waited for it.

Only a drag that stops on the page applies its gesture now; one that
ends with the button up and no drag stopped there ends with nothing
applied, whether the pointer is on the page or not. The test hovers away
from the move's start, where the jump shows.

Found in review.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
alehelandClaude Opus 5.5 committed 2026-11-04 19:37:47 +01:00
1 parent 58fa110d2d
commit c10f87f673
2 files changed
+16 -8

No files matched your search

+10 -4
View File
@@ -226,12 +226,18 @@ fn select_input(
CommentPart::Body => {}
}
}
if matches!(cv.gesture, Some(Gesture::Move { page, .. } | Gesture::Resize { page, .. } | Gesture::Reshape { page, .. }) if page == cx.page) {
let live =
matches!(cv.gesture, Some(Gesture::Move { page, .. } | Gesture::Resize { page, .. } | Gesture::Reshape { page, .. }) if page == cx.page);
if live {
consumed = true;
}
// A move, resize or reshape ends where its drag stops, or once the button is up when the pages
// missed its release.
if (resp.drag_stopped() || !cx.ptr.primary_down)
// A move, resize or reshape ends where its drag stops. One whose release the pages missed (the
// button is up, and no drag stopped here) ends with nothing applied: where it came up is not
// known, and the pointer may be anywhere by now.
if live && !resp.drag_stopped() && !cx.ptr.primary_down {
cv.gesture = None;
}
if resp.drag_stopped()
&& let Some(p) = pointer
{
match cv.gesture.clone() {
+6 -4
View File
@@ -1639,9 +1639,9 @@ fn a_right_click_selects_its_comment_though_a_gesture_was_left_over() {
assert_eq!(h.state().views[0].comments.selected, Some((0, 1)), "the note under the right-click is selected");
}
/// A comment's move ends once its button is up, though the pages missed its release: a drag elsewhere
/// later moves nothing. The move waited for the next drag's end on the page, and took the comment
/// there.
/// A comment's move ends once its button is up, though the pages missed its release, and applies
/// nothing: where it came up is not known, and the pointer has moved on. A drag elsewhere later moves
/// nothing either. The move waited for the next drag's end on the page, and took the comment there.
#[test]
fn a_comment_move_whose_release_the_pages_missed_ends_once_the_button_is_up() {
let mut h = open(stacked_comments_pdf(), "150", false);
@@ -1652,9 +1652,11 @@ fn a_comment_move_whose_release_the_pages_missed_ends_once_the_button_is_up() {
let before = rect(&h);
let bottom = at(&h, 60.0, 160.0);
h.state_mut().views[0].comments.gesture = Some(pdfcraft_ui_egui::comments::Gesture::Move { page: 0, index: 0, from: bottom });
h.hover_at(bottom);
let elsewhere = at(&h, 250.0, 100.0);
h.hover_at(elsewhere);
h.run_steps(2);
assert!(h.state().views[0].comments.gesture.is_none(), "the move is over");
assert_eq!(rect(&h), before, "and moved nothing to where the pointer turned up");
let blank = at(&h, 250.0, 60.0);
mouse_drag(&mut h, blank, egui::vec2(30.0, 0.0));
assert_eq!(rect(&h), before, "nothing moved the comment");