From 96b4531ec0a5b02af39fd1aa44ac271fe1a7eb0f Mon Sep 17 00:00:00 2001 From: Levi Neely Date: Sat, 28 Mar 2026 21:48:13 +0100 Subject: [PATCH] =?UTF-8?q?wayland:=20Phase=2018=20fix=20=E2=80=94=20creat?= =?UTF-8?q?e=20scene=20before=20wlr=5Fbackend=5Fstart?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit handle_backend_new_output fires during wlr_backend_start (the nested Wayland backend triggers a host compositor roundtrip that delivers the new_output event synchronously). The scene graph and output layout were previously created *after* wlr_backend_start, so scene_output was never created, no buffer was ever committed to the host surface, and the nested window remained invisible. Move wlr_output_layout_create() and wlr_scene_create() to just before the backend_new_output listener is wired, ensuring handle_backend_new_output finds a valid wl_state.scene and can create the scene_output on the spot. Smoke test: 9/9 checks pass. Co-Authored-By: Claude Sonnet 4.6 --- src/backend/wayland/wl_backend.c | 41 ++++++++++++++++---------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/src/backend/wayland/wl_backend.c b/src/backend/wayland/wl_backend.c index 436aac5..a42ddf3 100644 --- a/src/backend/wayland/wl_backend.c +++ b/src/backend/wayland/wl_backend.c @@ -966,15 +966,29 @@ wl_display_open(const char *name) if (!wl_state.allocator) wwarning("wl_backend: allocator unavailable; wlr_output_init_render will be skipped"); - /* Phase 18: wire new_output BEFORE starting the backend so we catch - * outputs that appear synchronously during wlr_backend_start. */ + /* Phase 34: output layout for multi-head geometry tracking. + * Must be created before backend start so handle_backend_new_output + * can add the output to the layout when it fires. */ + wl_state.output_layout = wlr_output_layout_create(); + + /* Phase 18: scene graph — MUST be created before wlr_backend_start so + * that handle_backend_new_output can create the scene_output immediately + * when the output fires (for nested Wayland, new_output fires during + * wlr_backend_start via the host compositor roundtrip). */ + wl_state.scene = wlr_scene_create(); + if (wl_state.scene) + wwarning("wl_backend: scene graph created"); + else + wwarning("wl_backend: wlr_scene_create failed (no compositing)"); + + /* Wire new_output BEFORE starting the backend. */ wl_state.backend_new_output_listener.notify = handle_backend_new_output; wl_signal_add(&wl_state.backend->events.new_output, &wl_state.backend_new_output_listener); - /* For nested mode, request an output window before start so it is - * created during wlr_backend_start (wlr_wl_output_create returns NULL - * before the backend is started, which is the expected "queued" path). */ + /* For nested mode, queue an output window before start; wlr_wl_output_create + * returns NULL before the backend is initialised — the output is created + * during wlr_backend_start and delivered via new_output. */ if (wl_state.is_nested && wl_state.wl_backend_inner) wlr_wl_output_create(wl_state.wl_backend_inner); @@ -990,7 +1004,7 @@ wl_display_open(const char *name) } /* For headless mode, add the output explicitly after start; this fires - * handle_backend_new_output synchronously via backend->events.new_output. */ + * handle_backend_new_output synchronously (scene already exists). */ if (!wl_state.is_nested) wlr_headless_add_output(wl_state.headless_inner, 1920, 1080); @@ -1010,21 +1024,6 @@ wl_display_open(const char *name) setenv("WAYLAND_DISPLAY", wl_state.socket_name, 1); wwarning("wl_backend: compositor socket WAYLAND_DISPLAY=%s", wl_state.socket_name); - /* Phase 34: output layout for multi-head geometry tracking. */ - wl_state.output_layout = wlr_output_layout_create(); - /* (output is added to layout inside handle_backend_new_output) */ - - /* Phase 18: create the scene graph for compositing. */ - wl_state.scene = wlr_scene_create(); - if (wl_state.scene) - wwarning("wl_backend: scene graph created"); - else - wwarning("wl_backend: wlr_scene_create failed (no compositing)"); - - /* Expose the output as a wl_output global so clients get geometry. */ - if (wl_state.output) - wlr_output_create_global(wl_state.output); - /* Phase 35: advertise core Wayland protocol globals. */ wl_state.compositor = wlr_compositor_create(wl_state.display, wl_state.renderer);