fix(ui): Edit text's drags end when its input is blocked

Edit text ignores input while a dialog, the palette, another window or
another tab has it. Only a drag of the objects selected together ended
then; a paragraph's move or rewrap, a picture's move, resize, turn or
crop and added content's move waited, and once the input came back with
the button up they landed wherever the pointer was.

While Edit text's input is blocked, `DocView::cancel_edit_text_gestures`
abandons them all, as the objects' already was.

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:46 +01:00
1 parent 607635c157
commit a9f592fd64
3 files changed
+50 -2

No files matched your search

+8 -2
View File
@@ -591,9 +591,15 @@ impl eframe::App for PdfCraftApp {
// opening a modal/palette, or returning to a window that lost focus.
let blocked = self.modal_open() || self.palette_open || !ctx.input(|i| i.focused);
for (index, view) in self.views.iter_mut().enumerate() {
view.objects.set_input_blocked(blocked || self.active != Some(index));
if blocked || self.active != Some(index) {
let shut = blocked || self.active != Some(index);
view.objects.set_input_blocked(shut);
if shut {
view.auto_scroll.cancel();
// Edit text ignores input while it is blocked: its drags end rather than wait, to
// land wherever the pointer is once it opens again.
if self.quick_tool == QuickTool::EditText {
view.cancel_edit_text_gestures();
}
}
}
// A field that refused its value this frame keeps the shortcut from saving or printing
+12
View File
@@ -890,6 +890,18 @@ impl DocView {
}
}
/// Abandon Edit text's pointer gestures (a paragraph moved or rewrapped, a picture moved,
/// resized, turned or cropped, added content moved, the objects' area selection or move), as
/// [`Self::cancel_pointer_gestures`] does: what they were previewing is not applied.
pub(crate) fn cancel_edit_text_gestures(&mut self) {
self.block_drag = None;
self.content.cancel_pointer_gesture();
self.objects.cancel_pointer_gesture();
if let Some(image) = &mut self.image_selection {
image.cancel_pointer_gesture();
}
}
/// A view of a newly opened document, shown as `defaults` say. Opening a file then applies
/// any layout or zoom the PDF itself asks for.
pub fn new(id: DocId, info: &DocInfo, defaults: ViewDefaults) -> Self {
+30
View File
@@ -7419,6 +7419,36 @@ fn an_add_text_click_pressed_beside_a_paragraph_starts_a_box_there() {
assert!(h.state().views[0].line_editor.is_none(), "the paragraph stays closed");
}
/// A paragraph drag in Edit text ends when Edit text's input is blocked (the window loses focus), as
/// a drag of the objects selected together does: nothing moves once the input comes back. It
/// waited, and moved the paragraph to wherever the pointer then was.
#[test]
fn a_paragraph_drag_ends_when_the_window_loses_focus() {
let mut h = edit_page(pdfcraft_ui_egui::QuickTool::EditText);
let id = h.state().views[0].id;
let before = h.state().session.get(id).unwrap().text_blocks(0)[0].rect;
let from = point_on(&h, (before[0] + before[2]) / 2.0, (before[1] + before[3]) / 2.0);
h.hover_at(from);
h.run_steps(1);
h.drag_at(from);
h.run_steps(1);
for k in 1..=4 {
h.hover_at(from + egui::vec2(0.0, 10.0 * k as f32));
h.run_steps(1);
}
assert!(h.state().views[0].block_drag.is_some(), "the paragraph is being moved");
h.input_mut().focused = false;
h.run_steps(2);
h.drop_at(from + egui::vec2(0.0, 40.0));
h.run_steps(2);
h.input_mut().focused = true;
h.hover_at(from + egui::vec2(0.0, 80.0));
h.run_steps(4);
assert!(h.state().views[0].block_drag.is_none(), "the drag is over");
assert_eq!(h.state().session.get(id).unwrap().text_blocks(0)[0].rect, before, "nothing moved");
assert!(!dirty(&h));
}
/// The rotate knob of a picture that fills its page lies past the page's edge, and a drag there
/// still turns the picture: the press is the page's whose knob it is.
#[test]