View: handle map while no outputs are available

Currently views which are mapped while no outputs are available can
never actually get rendered because they have 0 tags and are stuck in
the hidden stack.

This commit fixes this and they should now be restored when a new output
becomes available.
This commit is contained in:
Isaac Freund 2023-11-09 16:36:39 +01:00
parent 927dceb071
commit 69b61602cf
No known key found for this signature in database
GPG Key ID: 86DED400DDFD7A11
2 changed files with 46 additions and 20 deletions

View File

@ -362,6 +362,9 @@ pub fn activateOutput(root: *Self, output: *Output) void {
// If we previously had no outputs, move all views to the new output and focus it.
if (first) {
const log = std.log.scoped(.output_manager);
log.debug("moving views from fallback stacks to new output", .{});
output.pending.tags = root.fallback.tags;
{
var it = root.fallback.pending.focus_stack.safeIterator(.reverse);

View File

@ -495,32 +495,55 @@ pub fn map(view: *Self) !void {
view.pending.ssd = ssd;
}
const focused_output = server.input_manager.defaultSeat().focused_output;
if (try server.config.outputRuleMatch(view) orelse focused_output) |output| {
if (server.config.rules.position.match(view)) |position| {
view.pending.box.x = position.x;
view.pending.box.y = position.y;
} else {
// Center the initial pending box on the output
view.pending.box.x = @divTrunc(@max(0, output.usable_box.width - view.pending.box.width), 2);
view.pending.box.y = @divTrunc(@max(0, output.usable_box.height - view.pending.box.height), 2);
}
if (server.config.rules.dimensions.match(view)) |dimensions| {
view.pending.box.width = dimensions.width;
view.pending.box.height = dimensions.height;
}
if (server.config.rules.dimensions.match(view)) |dimensions| {
view.pending.box.width = dimensions.width;
view.pending.box.height = dimensions.height;
}
const output = try server.config.outputRuleMatch(view) orelse
server.input_manager.defaultSeat().focused_output;
view.pending.tags = blk: {
if (server.config.rules.tags.match(view)) |tags| break :blk tags;
const tags = output.pending.tags & server.config.spawn_tagmask;
break :blk if (tags != 0) tags else output.pending.tags;
};
if (server.config.rules.position.match(view)) |position| {
view.pending.box.x = position.x;
view.pending.box.y = position.y;
} else if (output) |o| {
// Center the initial pending box on the output
view.pending.box.x = @divTrunc(@max(0, o.usable_box.width - view.pending.box.width), 2);
view.pending.box.y = @divTrunc(@max(0, o.usable_box.height - view.pending.box.height), 2);
}
view.setPendingOutput(output);
view.pending.tags = blk: {
const default = if (output) |o| o.pending.tags else server.root.fallback.tags;
if (server.config.rules.tags.match(view)) |tags| break :blk tags;
const tags = default & server.config.spawn_tagmask;
break :blk if (tags != 0) tags else default;
};
if (output) |o| {
view.setPendingOutput(o);
var it = server.input_manager.seats.first;
while (it) |seat_node| : (it = seat_node.next) seat_node.data.focus(view);
} else {
log.debug("no output available for newly mapped view, adding to fallback stacks", .{});
view.pending_wm_stack_link.remove();
view.pending_focus_stack_link.remove();
view.inflight_wm_stack_link.remove();
view.inflight_focus_stack_link.remove();
switch (server.config.attach_mode) {
.top => {
server.root.fallback.pending.wm_stack.prepend(view);
server.root.fallback.inflight.wm_stack.prepend(view);
},
.bottom => {
server.root.fallback.pending.wm_stack.append(view);
server.root.fallback.inflight.wm_stack.append(view);
},
}
server.root.fallback.pending.focus_stack.prepend(view);
server.root.fallback.inflight.focus_stack.prepend(view);
}
view.float_box = view.pending.box;