constellation: Store pending viewport changes (#39447)

It is possible for viewport changes to be received before the
constellation adds a browsing context to its managed set when
navigating. When that happens, the viewport change is ignored, and eg.
the hidpi will keep the default 1.0 value.
On later page navigation, this value is not updated and leads to
incorrect display zooming. The initial page load is fine in the current
embedders because they update the compositor and webview renderer even
if the constellation is not fully ready.

Testing: Testing is difficult because it's device dependent, but I
reproduce 100% of the time running winit_minimal on a Pinephone Pro.

Signed-off-by: webbeef <me@webbeef.org>
This commit is contained in:
webbeef 2025-09-24 08:31:13 -07:00 committed by GitHub
parent f91dc33350
commit da221d4045
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -490,6 +490,10 @@ pub struct Constellation<STF, SWF> {
/// The image cache for the single-process mode /// The image cache for the single-process mode
image_cache: Box<dyn ImageCache>, image_cache: Box<dyn ImageCache>,
/// Pending viewport changes for browsing contexts that are not
/// yet known to the constellation.
pending_viewport_changes: HashMap<BrowsingContextId, ViewportDetails>,
} }
/// State needed to construct a constellation. /// State needed to construct a constellation.
@ -743,6 +747,7 @@ where
state.compositor_proxy.cross_process_compositor_api, state.compositor_proxy.cross_process_compositor_api,
rippy_data, rippy_data,
)), )),
pending_viewport_changes: Default::default(),
}; };
constellation.run(); constellation.run();
@ -1164,6 +1169,12 @@ where
return; return;
}, },
}; };
// Override the viewport details if we have a pending change for that browsing context.
let viewport_details = self
.pending_viewport_changes
.remove(&browsing_context_id)
.unwrap_or(viewport_details);
let browsing_context = BrowsingContext::new( let browsing_context = BrowsingContext::new(
bc_group_id, bc_group_id,
browsing_context_id, browsing_context_id,
@ -5036,7 +5047,7 @@ where
) { ) {
debug!( debug!(
"handle_change_viewport_details_msg: {:?}", "handle_change_viewport_details_msg: {:?}",
new_viewport_details.size.to_untyped() new_viewport_details
); );
let browsing_context_id = BrowsingContextId::from(webview_id); let browsing_context_id = BrowsingContextId::from(webview_id);
@ -5222,6 +5233,9 @@ where
)); ));
} }
} }
} else {
self.pending_viewport_changes
.insert(browsing_context_id, new_viewport_details);
} }
// Send resize message to any pending pipelines that aren't loaded yet. // Send resize message to any pending pipelines that aren't loaded yet.
@ -5306,6 +5320,8 @@ where
exit_mode, exit_mode,
); );
let _ = self.pending_viewport_changes.remove(&browsing_context_id);
let browsing_context = match self.browsing_contexts.remove(&browsing_context_id) { let browsing_context = match self.browsing_contexts.remove(&browsing_context_id) {
Some(ctx) => ctx, Some(ctx) => ctx,
None => { None => {