web_surface_runtime.rs hit 628 lines because it carried four unrelated
concerns:
- session domain types (`WebSurfaceRuntimeScope`, `WebSurfaceSession`,
`WebSurfaceUrlChange`, …) and their config-dir / `session_for_scope`
helpers — these are the runtime's input vocabulary, not its control
flow.
- wire-side glue (scroll-input field marshalling, `pending_input_kind`
classifier, the latency tracing call, and the `From<&Site...>` impl
that lowers permissions to the Servo client) — these are the runtime's
output vocabulary.
- the runtime itself, plus its tests harness.
Split into:
- `web_surface_runtime.rs` (441 lines): WebSurfaceRuntime + Drop.
- `web_surface_runtime_session.rs`: the session types + helpers, with
`pub(super)`-exposed methods so the runtime can drive them.
- `web_surface_runtime_wire.rs`: the wire helpers and the From impl.
`web_surface_runtime` keeps re-exporting the URL-change / frame /
ensure-result types so existing call sites
(`web_surface_state.rs`, `web_surface.rs`, `web_surface_controller.rs`)
need no rewiring.
Root cause of the post-tab lag: the GPUI 16 ms timer was calling
`WebSurfaceRuntime::ensure_tab` and `tick` on the UI thread, and each
call did a synchronous `serde_json` write plus `read_line` against the
Servo sidecar over stdin/stdout. With even one visible tab, every
frame stalled on cross-process IPC.
Introduce `web_surface_worker.rs` — a per-profile worker thread that
owns the `ServoLiveClient`, drains a coalescing request queue
(latest Ensure/Poll per tab wins, no unbounded growth), and ships
results back through a `std::sync::mpsc` channel. `WebSurfaceRuntime`
now submits work non-blockingly and drains responses in `tick`; the
UI thread never blocks on the sidecar.
Adjacent in-flight cleanup riding along: hardware IOSurface
rendering-context completion (sidecar `live_protocol`,
`hardware_rendering_context`, GPUI BGRA surface shader), CSS viewport
size + device pixel ratio plumbing into `ServoLiveFrame`, and the
Send opt-ins for `CVPixelBuffer`-bearing types so frames can cross
the thread boundary.
Without continuous MouseMove events, Servo never updates hover state:
no cursor changes over links, no :hover CSS effects, no mouseenter
JavaScript events. The web page appears completely non-interactive.
Track mouse position from GPUI on_mouse_move through the full IPC
pipeline to Servo. Hover position is included with each ensure
request so Servo updates hover state at frame rate (~60fps).