diff --git a/crates/ui-egui/src/dialogs.rs b/crates/ui-egui/src/dialogs.rs index 812b6c210..a56019464 100644 --- a/crates/ui-egui/src/dialogs.rs +++ b/crates/ui-egui/src/dialogs.rs @@ -897,7 +897,9 @@ fn dialogs(app: &mut PdfCraftApp, ctx: &egui::Context) { return; } Dialog::Preferences => { - close = crate::js_ui::preferences_body(ui, app, &t); + // The settings outgrow a short window: scroll them rather than run off the screen. + let max = (ui.ctx().content_rect().height() - 120.0).max(200.0); + close = egui::ScrollArea::vertical().max_height(max).show(ui, |ui| crate::js_ui::preferences_body(ui, app, &t)).inner; return; } Dialog::RecognizeText => { diff --git a/crates/ui-egui/tests/date_format.rs b/crates/ui-egui/tests/date_format.rs index 0fbe9760e..0606e021d 100644 --- a/crates/ui-egui/tests/date_format.rs +++ b/crates/ui-egui/tests/date_format.rs @@ -19,6 +19,9 @@ fn shows(h: &Harness<'static, PdfCraftApp>, text: &str) -> bool { } fn retype(h: &mut Harness<'static, PdfCraftApp>, text: &str) { + // The preferences scroll; bring the field into view before clicking it. + h.get_by_role_and_label(Role::TextInput, "Pattern").scroll_to_me(); + h.run_steps(4); h.get_by_role_and_label(Role::TextInput, "Pattern").click(); h.run_steps(1); h.key_press_modifiers(Modifiers::COMMAND, Key::A); diff --git a/crates/ui-egui/tests/javascript.rs b/crates/ui-egui/tests/javascript.rs index a5c5a6aff..2d525104b 100644 --- a/crates/ui-egui/tests/javascript.rs +++ b/crates/ui-egui/tests/javascript.rs @@ -94,6 +94,9 @@ fn document_scripts_and_preferences() { assert_eq!(h.state().session.get(id).unwrap().document_scripts()[0].0, "init"); h.state_mut().dialog = Some(Dialog::Preferences); h.run_steps(2); + // Below the fold in a 900-point window: the preferences scroll to it. + h.get_by_label("Enable Acrobat JavaScript").scroll_to_me(); + h.run_steps(4); h.get_by_label("Enable Acrobat JavaScript").click(); h.run_steps(2); assert!(!h.state().session.javascript()); diff --git a/crates/ui-egui/tests/ui.rs b/crates/ui-egui/tests/ui.rs index ded8c0ca9..b4c62bd3e 100644 --- a/crates/ui-egui/tests/ui.rs +++ b/crates/ui-egui/tests/ui.rs @@ -800,6 +800,8 @@ fn preferences_selects_default_workspace_for_next_open() { use pdfcraft_ui_egui::Mode; let mut h = harness(|app| app.set_option("dialog", "preferences").unwrap()); h.get_by_label("Default workspace mode"); + h.get_by_role_and_label(Role::RadioButton, "Read").scroll_to_me(); + h.run_steps(4); h.get_by_role_and_label(Role::RadioButton, "Read").click(); h.run_steps(2); assert_eq!(h.state().default_mode, Mode::Read); diff --git a/crates/ui-egui/tests/ui_group/bulk_fields.rs b/crates/ui-egui/tests/ui_group/bulk_fields.rs index b2c75c262..1ddf07b1a 100644 --- a/crates/ui-egui/tests/ui_group/bulk_fields.rs +++ b/crates/ui-egui/tests/ui_group/bulk_fields.rs @@ -89,6 +89,9 @@ fn shared_properties_preserve_mixed_values_and_undo_the_whole_change() { h.state_mut().bulk_field_props.as_mut().unwrap().required.value = true; h.get_by_label("Appearance").click(); h.run_steps(4); + // Below the fold of the dialog's scroll area with the roomier rows (#487). + h.get_by_label("Line Thickness:").scroll_to_me(); + h.run_steps(4); h.get_by_label("Line Thickness:").click(); h.run_steps(4); h.state_mut().bulk_field_props.as_mut().unwrap().width.value = 4.0; diff --git a/crates/ui-egui/tests/ui_group/identity.rs b/crates/ui-egui/tests/ui_group/identity.rs index 9a4e3c38f..52581fe6a 100644 --- a/crates/ui-egui/tests/ui_group/identity.rs +++ b/crates/ui-egui/tests/ui_group/identity.rs @@ -29,7 +29,9 @@ fn the_identity_name_signs_new_comments_and_is_remembered() { }); h.run_steps(4); h.get_by_label_contains("Name on new comments"); - // Replace the name in the field. + // Replace the name in the field (the preferences scroll to it in a 900-point window). + h.get_by_role_and_label(Role::TextInput, "Name on new comments").scroll_to_me(); + h.run_steps(4); h.get_by_role_and_label(Role::TextInput, "Name on new comments").click(); h.run_steps(1); h.key_press_modifiers(Modifiers::COMMAND, Key::A); diff --git a/crates/ui-egui/tests/ui_group/text_select.rs b/crates/ui-egui/tests/ui_group/text_select.rs index fc8d19a81..12b89aa24 100644 --- a/crates/ui-egui/tests/ui_group/text_select.rs +++ b/crates/ui-egui/tests/ui_group/text_select.rs @@ -79,6 +79,16 @@ fn quick_clicks_with_the_highlighter_mark_only_the_word() { click(&mut h, at); } h.run_steps(3); + // Under load the mark can land a few frames later; wait for it (egui's clock is fixed per + // frame, so waiting can't turn the clicks into a different run). + for _ in 0..200 { + let app = h.state(); + if app.session.get(app.views[0].id).is_some_and(|d| !d.info.annotations.is_empty()) && !app.render_pending() { + break; + } + std::thread::sleep(std::time::Duration::from_millis(5)); + h.run_steps(1); + } let app = h.state(); let doc = app.session.get(app.views[0].id).unwrap(); let marks: Vec<(&str, usize)> = doc.info.annotations.iter().map(|a| (a.subtype.as_str(), a.quads.len())).collect(); diff --git a/crates/ui-egui/tests/view.rs b/crates/ui-egui/tests/view.rs index e1963d331..e6890f9b1 100644 --- a/crates/ui-egui/tests/view.rs +++ b/crates/ui-egui/tests/view.rs @@ -376,6 +376,8 @@ fn preferences_set_the_default_zoom() { let mut h = harness(&[]); assert!(h.state_mut().execute("app.preferences")); h.run_steps(3); + h.get_by_label("Zoom to page level").scroll_to_me(); + h.run_steps(4); h.get_by_label("Zoom to page level").click(); h.run_steps(2); assert!(h.state_mut().execute("create.blank"));