From a067d62ad3975c120e624d8b346846d2527c086f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=B7=E7=94=B5=E8=8A=BD=E8=A1=A3?= Date: Mon, 18 May 2026 14:12:18 -0400 Subject: [PATCH] fix(servo): push DPR on first viewport apply MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The newly-created session was stamped with the request's hidpi factor, but `WebViewBuilder` defaults `hidpi_scale_factor` to 1.0 and we never override it. `apply_viewport`'s diff check then saw `session.dpr == request.dpr` and skipped `set_hidpi_scale`, leaving Servo at hidpi=1.0 forever. On Retina that collapses CSS pixels onto device pixels — the page lays out for a 2× viewport and renders at half size. Same shape applies to page zoom. Initialize the session with Servo's actual post-build defaults so the viewport diff is the source of truth for whether `set_hidpi_scale` and `set_page_zoom` need to run. --- crates/ely_app/src/services/servo_live.rs | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/crates/ely_app/src/services/servo_live.rs b/crates/ely_app/src/services/servo_live.rs index 7f07653..5127130 100644 --- a/crates/ely_app/src/services/servo_live.rs +++ b/crates/ely_app/src/services/servo_live.rs @@ -16,6 +16,16 @@ pub(crate) use types::{ ServoLiveEnsureRequest, ServoLiveError, ServoLiveFrame, ServoLiveSitePermission, }; +/// Servo's `WebViewBuilder` defaults the hidpi (device → CSS) scale to +/// 1.0 — see the contract documented on +/// [`ely_servo_host::HidpiScaleRequest`]. Mirroring the post-build state +/// in [`DirectWebViewSession`] makes the diff inside `apply_viewport` +/// the source of truth for whether `set_hidpi_scale` has to run. +const SERVO_DEFAULT_DEVICE_PIXEL_RATIO: f32 = 1.0; + +/// Servo's `WebViewBuilder` likewise defaults page zoom to 1.0 (100%). +const SERVO_DEFAULT_PAGE_ZOOM_PERCENT: u16 = 100; + pub(crate) struct ServoLiveClient { host: SoftwareServoHost, sessions: BTreeMap, @@ -132,8 +142,16 @@ impl ServoLiveClient { requested_url: None, width: request.width, height: request.height, - page_zoom_percent: request.page_zoom_percent, - device_pixel_ratio: request.device_pixel_ratio, + // Servo's WebViewBuilder defaults page zoom to 1.0 (100%) and + // hidpi scale to 1.0; record both as Servo's actual post-build + // state so `apply_viewport` pushes the embedder-requested + // values on the first ensure. Without this, a request whose + // zoom/DPR happens to equal the cached request value would + // bypass `set_page_zoom` / `set_hidpi_scale` and leave the + // WebView at Servo's defaults — on Retina that collapses CSS + // pixels onto device pixels and renders pages at half size. + page_zoom_percent: SERVO_DEFAULT_PAGE_ZOOM_PERCENT, + device_pixel_ratio: SERVO_DEFAULT_DEVICE_PIXEL_RATIO, native_surface_id, }, );