mirror of
https://github.com/marcoallegretti/WEFT_OS.git
synced 2026-03-26 17:03:09 +00:00
feat(servo-shell): dispatch shell client event queue in servo event loop
Wire ShellClient into App so its Wayland event queue is dispatched each frame via about_to_wait. This ensures configure, focus_changed, and window_closed events from the compositor are processed. window_closed now triggers a clean Servo shutdown. The EGL rendering path (WindowRenderingContext + surfman eglSwapBuffers) produces frames transparently via Mesa DMA-BUF buffer sharing; no explicit zwp_linux_dmabuf_v1 code is required in the shell. Remaining: ZweftShellWindowV1 is created with surface=null; sharing the winit wl_surface with the shell client connection is not currently feasible without refactoring to a single shared Wayland connection.
This commit is contained in:
parent
c244a58844
commit
3ee2f283d8
3 changed files with 43 additions and 13 deletions
|
|
@ -64,19 +64,28 @@ On Fedora/RHEL: `mesa-libGL-devel openssl-devel dbus-devel systemd-devel libxkbc
|
|||
Default: `SoftwareRenderingContext` (CPU rasterisation) blitted to a
|
||||
`softbuffer`-backed winit window.
|
||||
|
||||
EGL path (scaffolded): set `WEFT_EGL_RENDERING=1` at runtime. The embedder
|
||||
attempts `WindowRenderingContext::new` using the winit display and window
|
||||
handles. If construction fails it falls back to software automatically.
|
||||
When the EGL path is active Servo presents directly to the EGL surface;
|
||||
the softbuffer blit is skipped. Full DMA-BUF export to the Wayland
|
||||
compositor is not yet wired (`RenderingCtx::Egl` blit body is a no-op).
|
||||
EGL path: set `WEFT_EGL_RENDERING=1` at runtime. The embedder attempts
|
||||
`WindowRenderingContext::new` using the winit display and window handles.
|
||||
If construction fails it falls back to software automatically.
|
||||
When the EGL path is active Servo presents directly to the EGL surface via
|
||||
surfman's `eglSwapBuffers`; the softbuffer blit is skipped. Mesa handles
|
||||
DMA-BUF buffer sharing with the compositor transparently.
|
||||
|
||||
## Known gaps at this pin
|
||||
|
||||
- **GAP-1**: ~~Wayland input events not forwarded to Servo~~ **Resolved** — keyboard and
|
||||
mouse events forwarded via `webview.notify_input_event`; key mapping in `keyutils.rs`.
|
||||
- **GAP-2**: EGL `WindowRenderingContext` path scaffolded (`WEFT_EGL_RENDERING=1`);
|
||||
DMA-BUF export to the Wayland compositor (linux-dmabuf-unstable-v1) not yet wired.
|
||||
- **GAP-2**: EGL `WindowRenderingContext` path scaffolded (`WEFT_EGL_RENDERING=1`).
|
||||
When EGL is active, Servo presents frames via surfman's `eglSwapBuffers`; Mesa handles
|
||||
DMA-BUF buffer sharing with the compositor transparently — no explicit
|
||||
`zwp_linux_dmabuf_v1` code is needed in the shell for basic rendering.
|
||||
The `zweft_shell_manager_v1` event queue is now dispatched each frame so `configure`,
|
||||
`focus_changed`, and `window_closed` events are processed; `window_closed` triggers a
|
||||
clean Servo shutdown.
|
||||
Remaining gap: the `ZweftShellWindowV1` is created with `surface = null`; the winit
|
||||
`wl_surface` is not yet associated with the shell window slot (requires sharing a single
|
||||
Wayland connection between winit and the shell client, which is not currently feasible
|
||||
without significant refactoring).
|
||||
- **GAP-3**: WebGPU adapter on Mesa may fail CTS — validation task, requires Mesa GPU hardware.
|
||||
- **GAP-4**: ~~CSS Grid~~ **Grid resolved** (Taffy-backed, fully wired).
|
||||
~~CSS `backdrop-filter` unimplemented~~ **`backdrop-filter` resolved** (servo/servo issue
|
||||
|
|
|
|||
|
|
@ -99,6 +99,7 @@ struct App {
|
|||
shutting_down: bool,
|
||||
modifiers: ModifiersState,
|
||||
cursor_pos: servo::euclid::default::Point2D<f32>,
|
||||
shell_client: Option<crate::shell_client::ShellClient>,
|
||||
}
|
||||
|
||||
impl App {
|
||||
|
|
@ -107,6 +108,7 @@ impl App {
|
|||
waker: WeftEventLoopWaker,
|
||||
ws_port: u16,
|
||||
app_rx: mpsc::Receiver<crate::appd_ws::AppdCmd>,
|
||||
shell_client: Option<crate::shell_client::ShellClient>,
|
||||
) -> Self {
|
||||
Self {
|
||||
url,
|
||||
|
|
@ -123,6 +125,7 @@ impl App {
|
|||
shutting_down: false,
|
||||
modifiers: ModifiersState::default(),
|
||||
cursor_pos: servo::euclid::default::Point2D::zero(),
|
||||
shell_client,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -246,6 +249,18 @@ impl ApplicationHandler<ServoWake> for App {
|
|||
event_loop.exit();
|
||||
return;
|
||||
}
|
||||
if let Some(sc) = &mut self.shell_client {
|
||||
match sc.dispatch_pending() {
|
||||
Ok(false) => {
|
||||
self.shutting_down = true;
|
||||
if let Some(servo) = &self.servo {
|
||||
servo.start_shutting_down();
|
||||
}
|
||||
}
|
||||
Err(e) => tracing::warn!("shell client dispatch error: {e}"),
|
||||
Ok(true) => {}
|
||||
}
|
||||
}
|
||||
while let Ok(cmd) = self.app_rx.try_recv() {
|
||||
match cmd {
|
||||
crate::appd_ws::AppdCmd::Launch { session_id, app_id } => {
|
||||
|
|
@ -418,7 +433,11 @@ fn app_store_roots() -> Vec<PathBuf> {
|
|||
roots
|
||||
}
|
||||
|
||||
pub fn run(html_path: &Path, ws_port: u16) -> anyhow::Result<()> {
|
||||
pub fn run(
|
||||
html_path: &Path,
|
||||
ws_port: u16,
|
||||
shell_client: Option<crate::shell_client::ShellClient>,
|
||||
) -> anyhow::Result<()> {
|
||||
let url_str = format!("file://{}", html_path.display());
|
||||
let raw_url =
|
||||
ServoUrl::parse(&url_str).map_err(|e| anyhow::anyhow!("invalid URL {url_str}: {e}"))?;
|
||||
|
|
@ -436,7 +455,7 @@ pub fn run(html_path: &Path, ws_port: u16) -> anyhow::Result<()> {
|
|||
let waker_for_thread = waker.clone();
|
||||
crate::appd_ws::spawn_appd_listener(ws_port, app_tx, Box::new(move || waker_for_thread.wake()));
|
||||
|
||||
let mut app = App::new(url, waker, ws_port, app_rx);
|
||||
let mut app = App::new(url, waker, ws_port, app_rx, shell_client);
|
||||
event_loop
|
||||
.run_app(&mut app)
|
||||
.map_err(|e| anyhow::anyhow!("event loop run: {e}"))
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ fn run() -> anyhow::Result<()> {
|
|||
let ws_port = appd_ws_port();
|
||||
tracing::info!(ws_port, "appd WebSocket port");
|
||||
|
||||
let _shell = match shell_client::ShellClient::connect() {
|
||||
let shell = match shell_client::ShellClient::connect() {
|
||||
Ok(c) => {
|
||||
tracing::info!("shell window registered with compositor");
|
||||
Some(c)
|
||||
|
|
@ -45,7 +45,7 @@ fn run() -> anyhow::Result<()> {
|
|||
}
|
||||
};
|
||||
|
||||
embed_servo(&wayland_display, &html_path, ws_port)
|
||||
embed_servo(&wayland_display, &html_path, ws_port, shell)
|
||||
}
|
||||
|
||||
fn system_ui_html_path() -> anyhow::Result<PathBuf> {
|
||||
|
|
@ -86,12 +86,14 @@ fn embed_servo(
|
|||
_wayland_display: &str,
|
||||
html_path: &std::path::Path,
|
||||
ws_port: u16,
|
||||
shell_client: Option<shell_client::ShellClient>,
|
||||
) -> anyhow::Result<()> {
|
||||
#[cfg(feature = "servo-embed")]
|
||||
return embedder::run(html_path, ws_port);
|
||||
return embedder::run(html_path, ws_port, shell_client);
|
||||
|
||||
#[cfg(not(feature = "servo-embed"))]
|
||||
{
|
||||
let _ = shell_client;
|
||||
tracing::warn!(
|
||||
path = %html_path.display(),
|
||||
ws_port,
|
||||
|
|
|
|||
Loading…
Reference in a new issue