Architecture¶
Hermes separates product state from engine integration. That boundary lets most browser behavior run in fast Rust tests without initializing Servo, Slint, OpenGL, or a desktop event loop.
Layers¶
Hermes Desktop
Slint window, winit events, OpenGL surface, runtime composition
│
│ UI callbacks and presentation state
▼
Hermes UI
Slint components and UI-facing models
│
│ browser commands and events
▼
Talaria Core
tabs, navigation policy, state transitions, WebView contract
│
│ engine-neutral WebView calls
▼
Talaria Servo
Servo runtime, WebViews, delegates, rendering, media, blocking
│
▼
Servo, WebRender, Surfman, and GStreamer
Talaria Core¶
talaria-core owns the browser concepts that should survive an engine or UI replacement:
BrowserControllerowns tabs, the active tab, and the command queue.BrowserStateapplies engine events such as URL, title, icon, history, and load-state changes.BrowserCommanddescribes navigation and input without Servo types.WebViewis the trait implemented by an engine adapter.- Address resolution distinguishes supported URLs from DuckDuckGo search queries.
The controller coalesces adjacent pointer movement, scrolling, and focus commands for the same tab. This keeps high-frequency desktop input from growing an unbounded queue between frames.
Desktop composition¶
hermes-desktop creates the Slint window, selects the graphics backend, creates a ServoRuntime, and owns one ServoWebView per browser tab.
During each event-loop turn it:
- Reads pending Servo events and applies them to the matching tab.
- Ensures every model tab has a WebView and removes closed WebViews.
- Shows and resumes the active WebView while hiding and throttling the previous one.
- Updates viewport size and scale factor.
- Dispatches a bounded number of queued browser commands.
- Paints only when Servo has announced a new frame.
- Synchronizes the native UI from the active
BrowserState.
The bounded command drain prevents a burst of input from monopolizing a frame.
Command flow¶
Slint callback or winit input
→ BrowserController queue
→ TabCommand with a stable TabId
→ ServoWebView adapter
→ Servo WebView API
Commands carry a TabId, so switching tabs does not accidentally redirect already queued work to the newly active page.
Event flow¶
Servo WebViewDelegate
→ TabEvent over the runtime channel
→ BrowserController::handle_event
→ BrowserState::apply
→ Slint presentation model
The same stable TabId routes asynchronous title, favicon, load, and history updates back to the WebView that produced them.
Rendering ownership¶
Slint owns the native window and event loop. Servo renders into the OpenGL context shared by the desktop composition layer. A lightweight frame-ready signal avoids painting continuously when the page has not produced a new frame.
On Linux, Mesa and the desktop session choose the default graphics adapter. Hermes removes inherited DRI_PRIME overrides before graphics or media threads start, and the vendored Surfman patch avoids applying a process-global GPU preference during context creation.