diff --git a/src/backend/wayland/wl_backend.c b/src/backend/wayland/wl_backend.c index 3e89a3d..74a75bc 100644 --- a/src/backend/wayland/wl_backend.c +++ b/src/backend/wayland/wl_backend.c @@ -1349,6 +1349,7 @@ handle_xwayland_server_destroy(struct wl_listener *listener, void *data) (void)listener; (void)data; wwarning("wl_backend: XWayland server exited"); + wl_state.xwayland_ready = true; /* break the wait loop */ } static void @@ -2402,7 +2403,7 @@ wl_display_open(const char *name) * renders through XWayland, making the WM visible on-screen. * The ready signal fires once Xwayland's socket accepts connections. */ wl_state.xwayland = wlr_xwayland_create(wl_state.display, - wl_state.compositor, false); + wl_state.compositor, true); if (wl_state.xwayland) { /* Wire server destroy signal to detect early failure (e.g. stale * display lock → Xwayland exits before ready fires). */ @@ -2492,14 +2493,12 @@ wl_display_open(const char *name) * handle_xwayland_ready() calls XOpenDisplay and stores the result in * wl_state.x_display, then sets xwayland_ready = true to break the loop. * If XWayland is not available, return NULL (pure Wayland path). */ + /* XWayland is lazy — it starts when the first X11 client connects. + * No need to wait for it at startup. Mark as ready so the rest of + * init proceeds without blocking. */ if (wl_state.xwayland) { - wwarning("wl_backend: waiting for XWayland ready signal..."); - struct wl_event_loop *ev_loop = - wl_display_get_event_loop(wl_state.display); - while (!wl_state.xwayland_ready) { - wl_display_flush_clients(wl_state.display); - wl_event_loop_dispatch(ev_loop, 10); - } + wwarning("wl_backend: XWayland configured (lazy mode) — starts on first X11 client"); + wl_state.xwayland_ready = true; if (wl_state.x_display) { wwarning("wl_backend: XWayland bridge ready — Display*=%p, full WM UI enabled", (void *)wl_state.x_display);