diff --git a/crates/engine/src/open.rs b/crates/engine/src/open.rs
index cfa50dadfa..e2736fbf4d 100644
--- a/crates/engine/src/open.rs
+++ b/crates/engine/src/open.rs
@@ -27,6 +27,14 @@ pub struct PreparedDocument {
}
impl OpenContext {
+ /// This context with Highlight fields `on`, which the document's scripts read as
+ /// `app.runtimeHighlight` while it opens. A new document opens with the remembered setting
+ /// while the session keeps the one of the document in front, which its scripts read.
+ pub fn with_highlight(mut self, on: bool) -> Self {
+ self.highlight = on;
+ self
+ }
+
/// Prepare a document without mutating the session that supplied this context.
pub fn prepare_open(
&self,
diff --git a/crates/ui-egui/src/app/files.rs b/crates/ui-egui/src/app/files.rs
index 5db8e515e2..39caf91032 100644
--- a/crates/ui-egui/src/app/files.rs
+++ b/crates/ui-egui/src/app/files.rs
@@ -106,9 +106,10 @@ impl PdfCraftApp {
if let Some(ctx) = &self.ctx {
worker.set_context(ctx);
}
- self.session.set_field_highlight(self.view_defaults.highlight_fields);
- let receiver =
- worker.submit(token, self.session.open_context(), request.name.clone(), request.path.clone(), request.password, request.input)?;
+ // A new document opens with the remembered Highlight fields, which its scripts read; the
+ // session keeps the document in front's.
+ let context = self.session.open_context().with_highlight(self.view_defaults.highlight_fields);
+ let receiver = worker.submit(token, context, request.name.clone(), request.path.clone(), request.password, request.input)?;
self.next_open_token = token;
self.pending_opens.push(PendingOpen {
token,
@@ -226,9 +227,10 @@ impl PdfCraftApp {
activate: bool,
) -> Result<(), String> {
use pdfcraft_render::OpenError;
- // A new document opens with the remembered Highlight fields, which its scripts read.
- self.session.set_field_highlight(self.view_defaults.highlight_fields);
- let prepared = match self.session.prepare_open(name, path.clone(), bytes.clone(), password) {
+ // A new document opens with the remembered Highlight fields, which its scripts read; the
+ // session keeps the document in front's.
+ let context = self.session.open_context().with_highlight(self.view_defaults.highlight_fields);
+ let prepared = match context.prepare_open(name, path.clone(), bytes.clone(), password) {
Ok(prepared) => prepared,
Err(e @ (OpenError::NeedsPassword | OpenError::WrongPassword)) => {
let error = matches!(e, OpenError::WrongPassword).then(|| "Incorrect password. Try again.".to_string());
diff --git a/crates/ui-egui/tests/it/xfa.rs b/crates/ui-egui/tests/it/xfa.rs
index 8012b4a928..de01dfb82a 100644
--- a/crates/ui-egui/tests/it/xfa.rs
+++ b/crates/ui-egui/tests/it/xfa.rs
@@ -231,6 +231,42 @@ fn a_secured_dynamic_xfa_form_shows_its_layout_and_its_security() {
h.get_by_label("Security settings");
}
+/// Opening another document doesn't change the field highlight the document in front's scripts
+/// read: the new one opens with the remembered Highlight fields in its own open context. Before,
+/// the open set the session's value, so an edit of the first document handled before the next
+/// frame read the new document's default as `app.runtimeHighlight`.
+#[test]
+fn opening_another_document_keeps_the_highlight_the_one_in_front_reads() {
+ let script = |js: &str| format!(r#""#);
+ let xdp = format!(
+ r##"
+
+
+
+
+ {look}
+
+
+
+
+"##,
+ look = script("xfa.form.form.seen.rawValue = String(app.runtimeHighlight);"),
+ );
+ let mut h = open(pdfcraft_xfa::fixtures::shell(&xdp));
+ let app = h.state_mut();
+ // The document in front has Highlight fields on; the remembered setting is off.
+ app.view_defaults.highlight_fields = false;
+ app.views[0].highlight_fields = true;
+ h.run_steps(2);
+ let app = h.state_mut();
+ let first = app.views[0].id;
+ app.open_bytes("next.pdf", None, pdfcraft_xfa::fixtures::shell(&pdfcraft_xfa::fixtures::template(1))).unwrap();
+ // Before the next frame, the first document's script reads its own setting.
+ app.session.apply(first, pdfcraft_engine::Edit::XfaEvent { som: "form[0].look[0]".into(), activity: "click".into() }).unwrap();
+ let seen = app.session.get(first).unwrap().form.iter().find(|f| f.name == "seen").map(|f| f.value.clone()).unwrap_or_default();
+ assert_eq!(seen, vec!["true".to_string()], "the first document's script reads its own Highlight fields");
+}
+
/// A form that turns field highlighting on (`app.runtimeHighlight = true` in a `layout:ready`
/// script) gets it, and so does the next document, as with the Highlight fields button.
#[test]