f743ae41
Decouple rendering from visibility; fix v5 compositor bootstrap
a73x 2026-04-17 06:20
Always render when there is pending work — only gate the frame-callback commit (flush) on canRender(), so the surface gets its first buffer before wl_surface.enter arrives. Fixes the bootstrap deadlock where visible() required enteredCount > 0 but the compositor won't send enter until a buffer is attached. Also drops xdg_wm_base bind from v6 to v5 for compositors (e.g. sway) that don't yet advertise v6. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
diff --git a/src/main.zig b/src/main.zig index cac9e5a..083552b 100644 --- a/src/main.zig +++ b/src/main.zig @@ -270,7 +270,7 @@ fn runTerminal(alloc: std.mem.Allocator) !void { while (!window.should_close and p.isChildAlive()) { const repeat_timeout_ms = remainingRepeatTimeoutMs(keyboard.nextRepeatDeadlineNs()); const timeout = computePollTimeoutMs(repeat_timeout_ms, render_pending and frame_loop.canRender()); const timeout = computePollTimeoutMs(repeat_timeout_ms, render_pending); try frame_loop.waitForWork(&pollfds_extra, timeout); // PTY output @@ -350,7 +350,6 @@ fn runTerminal(alloc: std.mem.Allocator) !void { } if (!shouldRenderFrame(render_pending, false, false)) continue; if (!bench_unthrottled and !frame_loop.canRender()) continue; // hidden — no Vulkan at all // applyPendingScale — Vulkan work, gated on canRender(). if (scale_pending) { @@ -625,7 +624,7 @@ fn runTerminal(alloc: std.mem.Allocator) !void { frame_ring.push(frame_timing); clearConsumedDirtyFlags(&term.render_state.dirty, dirty_rows, refresh_plan); if (!bench_unthrottled) try frame_loop.commitRender(); if (!bench_unthrottled and frame_loop.canRender()) try frame_loop.commitRender(); render_pending = false; } diff --git a/src/wayland.zig b/src/wayland.zig index 7afebf7..fef2858 100644 --- a/src/wayland.zig +++ b/src/wayland.zig @@ -1220,7 +1220,7 @@ fn registryListener( } else if (std.mem.eql(u8, iface, std.mem.span(wl.DataDeviceManager.interface.name))) { conn.globals.data_device_manager = registry.bind(g.name, wl.DataDeviceManager, 3) catch return; } else if (std.mem.eql(u8, iface, std.mem.span(xdg.WmBase.interface.name))) { conn.globals.wm_base = registry.bind(g.name, xdg.WmBase, 6) catch return; conn.globals.wm_base = registry.bind(g.name, xdg.WmBase, 5) catch return; } else if (std.mem.eql(u8, iface, std.mem.span(wl.Seat.interface.name))) { conn.globals.seat = registry.bind(g.name, wl.Seat, 9) catch return; } else if (std.mem.eql(u8, iface, std.mem.span(wl.Output.interface.name))) {