M3: a two-page spread's display time waits for both pages; the parity row says what full screen does

Review (CodeRabbit): in two-page view the /Dur timer started once the
current page had rendered, so the spread could turn while its other page
still showed Rendering…; it now waits for every page on screen. The
ui-parity row says full screen shows a fitted page or spread and that
background clicks and keys turn pages while clicks on page objects don't.
The doc comment of presentation_click_state is back on its function.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pq7HyCfwzyRXj4VfQAVVdv
This commit is contained in:
mtlcl410andClaude Opus 5.5 committed 2026-10-31 15:21:54 +08:00
1 parent 2d21753b1e
commit bdda289585
4 files changed
+45 -6

No files matched your search

+3 -3
View File
@@ -2873,9 +2873,6 @@ fn shown_row(view: &DocView, rects: &[Rect]) -> Vec<usize> {
}
}
/// Full screen: a click on the document goes forward a page and a shift-click back, as in
/// Acrobat, unless the click did something else (a link, a word selected). Decided once the pages
/// have had the click. `Some(back)` on the frame of a click, `back` when it was a shift-click.
/// The pages' context menu, except in full screen, where a right-click turns back a page instead
/// ([`presentation_click_state`]).
fn page_context_menu(resp: &egui::Response, presenting: bool, add: impl FnOnce(&mut egui::Ui)) {
@@ -2884,6 +2881,9 @@ fn page_context_menu(resp: &egui::Response, presenting: bool, add: impl FnOnce(&
}
}
/// Full screen: a click on the document goes forward a page and a shift-click back, as in
/// Acrobat, unless the click did something else (a link, a word selected). Decided once the pages
/// have had the click. `Some(back)` on the frame of a click, `back` when it was a shift-click.
fn presentation_click_state(ui: &egui::Ui, view: &DocView, navigation_rect: Rect, enabled: bool) -> Option<bool> {
let presenting = view.presentation.is_some() && enabled;
// A right-click goes back a page, as a left click goes forward (*Adobe Acrobat Help*, 2019,
+4 -2
View File
@@ -122,8 +122,10 @@ pub(super) fn frame(
Some(Turn { from_page, from, to_page: page, effect, seconds, started: None })
});
// Its display time starts once the page is on screen, not while it still says Rendering…
// (or at once for a page the renderer can't draw, which never will be).
let ready = view.pages.contains_key(&page) || view.errors.contains_key(&page);
// (or at once for a page the renderer can't draw, which never will be). In two-page view
// that is every page of the spread, so the spread isn't turned before both were shown.
let drawn = |p: &usize| view.pages.contains_key(p) || view.errors.contains_key(p);
let ready = drawn(&page) && view.screen_rects.iter().all(|(p, _)| drawn(p));
view.presenter.shown = if turn.is_some() || !ready { None } else { Some((page, now)) };
view.presenter.turn = turn;
}
+37
View File
@@ -2147,3 +2147,40 @@ fn a_display_time_starts_once_the_page_has_rendered() {
presenter_frame(&ctx, &mut v, &info, 6.6);
assert_eq!(v.current, 1, "its second on screen is up");
}
/// In two-page view a display time counts from when the whole spread is on screen: one page of
/// it still showing Rendering… holds the spread (#5316 review).
#[test]
fn a_display_time_in_two_page_view_waits_for_the_whole_spread() {
use pdfcraft_render::PageTransition;
let page = pdfcraft_render::PageInfo { width: 300.0, height: 400.0, label: String::new(), crop: [0.0, 0.0, 300.0, 400.0], rotation: 0 };
let timed = PageTransition {
page: 0,
style: None,
duration: 1.0,
horizontal: false,
inward: false,
direction: Some(0),
scale: 1.0,
opaque: false,
display: Some(1.0),
};
let info = DocInfo { pages: vec![page.clone(), page.clone(), page.clone(), page], transitions: vec![timed], ..Default::default() };
let mut v = DocView::new(DocId(1), &info, ViewDefaults { layout: PageLayout::TwoUp, continuous: false, ..Default::default() });
v.enter_presentation();
let ctx = egui::Context::default();
let tex = |ctx: &egui::Context| ctx.load_texture("page", egui::ColorImage::new([4, 4], vec![Color32::WHITE; 16]), Default::default());
let r = Rect::from_min_size(Pos2::ZERO, egui::vec2(300.0, 400.0));
v.screen_rects = vec![(0, r), (1, r.translate(egui::vec2(300.0, 0.0)))];
v.pages.insert(0, super::cache::PageTex { tag: 0, tex: tex(&ctx) });
for now in [0.0, 1.0, 2.0, 5.0] {
presenter_frame(&ctx, &mut v, &info, now);
}
assert_eq!(v.current, 0, "page 2 of the spread is still rendering: the spread's second has not started");
v.pages.insert(1, super::cache::PageTex { tag: 0, tex: tex(&ctx) });
presenter_frame(&ctx, &mut v, &info, 5.5);
presenter_frame(&ctx, &mut v, &info, 6.0);
assert_eq!(v.current, 0, "half of its second on screen");
presenter_frame(&ctx, &mut v, &info, 6.6);
assert_eq!(v.current, 2, "its second on screen is up: the next spread");
}
+1 -1
View File
@@ -31,7 +31,7 @@ No dump of Acrobat's menu tree has been diffed against the registry yet (gap 24)
| Document tabs | yes | yes, with unsaved marker | shipped |
| Multiple windows, drag a tab out | yes | no | planned |
| Split window, spreadsheet split | yes | no | planned |
| Read mode, full screen | yes | yes; full screen is one fitted page at a time on black, click/keys turn pages (#1459), a right-click or Shift+Enter goes back, page transitions and display times play (#379), a still pointer hides | shipped; loop after the last page and the full-screen preferences planned |
| Read mode, full screen | yes | yes; full screen is one fitted page or spread at a time on black, and background clicks and keys turn pages while clicks on links, comments, fields and other page objects do not (#1459), a right-click or Shift+Enter goes back, page transitions and display times play (#379), a still pointer hides | shipped; loop after the last page and the full-screen preferences planned |
| Light, dark, system theme | yes | yes | shipped |
| Side panels: thumbnails, bookmarks, attachments, layers, comments, fields, signatures | yes | yes; panels keep their width (#704); the Pages inspector has a 50–150% thumbnail size slider and buttons (#3808) | shipped |
| Destinations, articles, model tree, Tags, Order, Content panels | yes | no | planned |