Move Servo IPC off UI thread

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.
This commit is contained in:
2026-05-15 16:41:40 -04:00
parent f4c650c4d8
commit 90c029eddb
29 changed files with 2113 additions and 496 deletions
+11 -3
View File
@@ -11,6 +11,7 @@ use std::{
time::Duration,
};
use ely_design_system::spacing;
use ely_domain::UrlText;
use gpui::{
AnyWindowHandle, App, AppContext, Application, Bounds, Entity, Focusable, Menu, MenuItem,
@@ -51,6 +52,11 @@ actions!(
]
);
// Measured from the window's top-left to the close button origin.
// Places the macOS traffic lights inside the calm part of the corner curve.
const TRAFFIC_LIGHT_ORIGIN_X: f32 = spacing::SHELL_INSET + 34.0;
const TRAFFIC_LIGHT_ORIGIN_Y: f32 = spacing::SHELL_INSET + 22.0;
fn main() {
init_tracing();
let pending_deep_links = PendingDeepLinks::default();
@@ -73,8 +79,7 @@ fn main() {
// exactly the "fonts still wrong" the screenshot showed.
// Override the theme so every gpui-component sub-element uses
// Geist too.
gpui_component::Theme::global_mut(cx).font_family =
shell::chrome::SANS_FAMILY.into();
gpui_component::Theme::global_mut(cx).font_family = shell::chrome::SANS_FAMILY.into();
cx.on_action(quit);
bind_shortcuts(cx);
cx.on_action(open_private_window);
@@ -185,7 +190,10 @@ fn open_browser_window(cx: &mut App, mode: BrowserWindowMode) -> Option<BrowserW
titlebar: Some(TitlebarOptions {
title: Some(mode.title().into()),
appears_transparent: true,
traffic_light_position: Some(point(px(18.0), px(24.0))),
traffic_light_position: Some(point(
px(TRAFFIC_LIGHT_ORIGIN_X),
px(TRAFFIC_LIGHT_ORIGIN_Y),
)),
}),
window_bounds: Some(WindowBounds::Windowed(bounds)),
..WindowOptions::default()