git.lucas.co / cce-compositor
Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git

commit5885e794effa38ed2fa0e51470dce3506ef2598c
parent163013883b
authorIsaac Freund <[email protected]>
date2026-04-24 12:44
OutputManager: fix assertion failure on hotplug

It is not correct to assert that wlr_output.global is non-null here.
The global is only created if the output already has a mode set, which
is not necessarily the case on hotplug.

To fix this, move the check after committing new modes and remove the
assertion for simplicity.

 river/OutputManager.zig | 21 ++++++++++++++-------
 1 file changed, 14 insertions(+), 7 deletions(-)

diff --git a/river/OutputManager.zig b/river/OutputManager.zig
index d737d1b..d2437ef 100644
--- a/river/OutputManager.zig
+++ b/river/OutputManager.zig
@@ -264,13 +264,6 @@ pub fn commitOutputState(om: *OutputManager) void {
                         log.err("out of memory", .{});
                         continue; // Try again next time
                     };
-                    // Adding the output to the layout creates the wl_output global
-                    if (!output.sent_wl_output) {
-                        if (output.object) |output_v1| {
-                            output_v1.sendWlOutput(wlr_output.global.?.getName(output_v1.getClient()));
-                            output.sent_wl_output = true;
-                        }
-                    }
                     if (server.lock_manager.lockSurfaceFromOutput(output)) |lock_surface| {
                         lock_surface.tree.node.setPosition(output.sent.x, output.sent.y);
                     }
@@ -378,6 +371,20 @@ pub fn commitOutputState(om: *OutputManager) void {
         var it = wm.sent.outputs.safeIterator(.forward);
         while (it.next()) |output| {
             const wlr_output = output.wlr_output orelse continue;
+
+            // The wl_output global is created by wlroots when the output is
+            // added to the wlr_output_layout and a mode is committed.
+            // Wlroots does not directly notify us when the wl_output global is created.
+            // However, we want send the river_output_v1.wl_output event as soon as
+            // possible and therefore need to check after committing a mode.
+            if (!output.sent_wl_output) {
+                if (wlr_output.global) |global| {
+                    if (output.object) |output_v1| {
+                        output_v1.sendWlOutput(global.getName(output_v1.getClient()));
+                        output.sent_wl_output = true;
+                    }
+                }
+            }
             switch (output.sent.state) {
                 .enabled => {
                     assert(wlr_output.enabled);