Fix crash when windows arrive before seat/output

I found this when trying to restart beansprout after a separate crash.

Basically, the .window handler used to put new
windows on seat.focused_output for new windows,
but after a restart this is still null even when
an output (and windows) already exist.
Windows became orphans with output=null, breaking
the focused_window.output == focused_output assert
This commit is contained in:
Ben Buhse 2026-02-17 20:44:21 -06:00
commit 6f68850a70
No known key found for this signature in database
GPG key ID: 7916ACFCD38FD0B4

View file

@ -212,12 +212,32 @@ fn windowManagerV1Listener(window_manager_v1: *river.WindowManagerV1, event: riv
// If there was already an output, but no seats, set the first output as focused
if (wm.outputs.first()) |output| {
seat.pending_manage.output = .{ .output = output };
// Adopt any orphan windows that arrived before we had a seat
var it = wm.orphan_windows.iterator(.forward);
while (it.next()) |window| {
window.pending_manage.pending_output = .{ .output = output };
}
if (wm.orphan_windows.first()) |first| {
seat.pending_manage.window = .{ .window = first };
seat.pending_manage.should_warp_pointer = true;
}
output.windows.appendList(&wm.orphan_windows);
}
},
.window => |ev| {
// TODO: Support multiple seats
const seat = wm.seats.first() orelse @panic("Failed to get seat");
const focused_output = seat.focused_output;
const seat = wm.seats.first();
const focused_output = if (seat) |s|
s.focused_output orelse if (s.pending_manage.output) |pending_output|
switch (pending_output) {
.output => |output| output,
.clear_focus => null,
}
else
wm.outputs.first()
else
wm.outputs.first();
const window_list = if (focused_output) |output|
&output.windows
else
@ -228,8 +248,10 @@ fn windowManagerV1Listener(window_manager_v1: *river.WindowManagerV1, event: riv
.top => window_list.prepend(window),
.bottom => window_list.append(window),
}
seat.pending_manage.window = .{ .window = window };
seat.pending_manage.should_warp_pointer = true;
if (seat) |s| {
s.pending_manage.window = .{ .window = window };
s.pending_manage.should_warp_pointer = true;
}
},
else => |ev| {
log.debug("unhandled event: {s}", .{@tagName(ev)});