fix(servo): resize through WebView only, never the rendering context
Servo's reference embedder (\`examples/winit_minimal.rs\`) handles
resize with a single call: \`webview.resize(new_size)\`. The Servo
paint pipeline behind that call:
1. early-returns if \`rendering_context.size() == new_size\`,
2. otherwise calls \`rendering_context.resize\` itself,
3. updates \`webview_renderer.rect\` so the compositor relays out
the page at the new device viewport,
4. sends \`transaction.set_document_view(...)\` so WebRender's
document viewport matches the surface,
5. flags the painter \`needs_repaint(RepaintReason::Resize)\`.
Our \`runtime.rs::resize\` called \`webview.rendering_context.resize\`
*before* \`webview.webview.resize\`. surfman accepted the new size, so
the painter saw \`rendering_context.size() == new_size\` and took the
early-return path — steps 3, 4, and 5 never ran. The compositor
kept the original (creation-time) viewport rect while we presented
a much larger surface. The page ended up laid out for a tiny
viewport and either rendered into the top-left of a sea of cleared
background (StableLance) or never painted any pipeline at all
(google.com appeared totally blank).
Drop the direct \`rendering_context.resize\` call and route through
\`WebView::resize\` exactly as the reference embedder does. The
debounce in \`record_viewport_size\` still collapses a sidebar /
window-edge animation into a single trailing-edge resize, so we
also avoid hammering Servo with per-frame surface mutations.
This commit is contained in:
@@ -270,8 +270,24 @@ impl ServoHost for SoftwareServoHost {
|
|||||||
.get(&request.webview_id)
|
.get(&request.webview_id)
|
||||||
.ok_or_else(|| ServoHostError::WebViewNotFound { id: request.webview_id.clone() })?;
|
.ok_or_else(|| ServoHostError::WebViewNotFound { id: request.webview_id.clone() })?;
|
||||||
|
|
||||||
|
// `WebView::resize` is the single entry point — it routes through
|
||||||
|
// `paint().resize_rendering_context`, which:
|
||||||
|
// 1. early-returns if `rendering_context.size() == new_size`;
|
||||||
|
// 2. calls `rendering_context.resize` itself;
|
||||||
|
// 3. calls `webview_renderer.set_rect(new_viewport_rect)` so the
|
||||||
|
// compositor relays out the page at the new size; and
|
||||||
|
// 4. sends `transaction.set_document_view(...)` so WebRender's
|
||||||
|
// document viewport matches the surface.
|
||||||
|
//
|
||||||
|
// Calling `rendering_context.resize` *ourselves* before that path
|
||||||
|
// is what produced the original bug: surfman saw the new size,
|
||||||
|
// Servo's early-return then skipped steps 3 and 4, and the page
|
||||||
|
// stayed laid out at the original size while we presented a
|
||||||
|
// larger surface — content collapsed to the top-left of a giant
|
||||||
|
// viewport (StableLance) or rendered nothing at all (Google).
|
||||||
|
// The Servo `winit_minimal` reference embedder calls
|
||||||
|
// `webview.resize` and nothing else; mirror that exactly.
|
||||||
let size = PhysicalSize::new(request.width, request.height);
|
let size = PhysicalSize::new(request.width, request.height);
|
||||||
webview.rendering_context.resize(size);
|
|
||||||
webview.webview.resize(size);
|
webview.webview.resize(size);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user