river: fix various fullscreen related bugs

This commit is contained in:
Isaac Freund 2023-02-28 22:56:12 +01:00
parent e11d4dc0de
commit 8cb5ca9041
No known key found for this signature in database
GPG Key ID: 86DED400DDFD7A11
5 changed files with 118 additions and 94 deletions

2
deps/zig-wayland vendored

@ -1 +1 @@
Subproject commit dd9ffa05cca1b5001523a309c646738c65e86aeb
Subproject commit e9484c814801b520cbe4ed719cceb4d0a59f1341

View File

@ -406,6 +406,8 @@ fn handleMode(listener: *wl.Listener(*wlr.Output), _: *wlr.Output) void {
var it = self.layers.fullscreen.children.iterator(.forward);
const background_color_rect = @fieldParentPtr(wlr.SceneRect, "node", it.next().?);
background_color_rect.setSize(width, height);
std.log.info("new output mode, width: {}, height: {}", .{ width, height });
}
server.root.applyPending();

View File

@ -377,21 +377,14 @@ pub fn applyPending(root: *Self) void {
}
}
{
var output_it = root.outputs.first;
while (output_it) |node| : (output_it = node.next) {
const output = &node.data;
if (output.inflight.fullscreen) |view| {
if (!view.pending.fullscreen or view.pending.tags & output.pending.tags == 0) {
output.inflight.fullscreen = null;
view.setFullscreen(false);
view.pending.box = view.post_fullscreen_box;
}
}
// Iterate the focus stack in order to ensure the currently focused/most
// recently focused view that requests fullscreen is given fullscreen.
var fullscreen_found = false;
{
var it = output.pending.focus_stack.iterator(.forward);
while (it.next()) |view| {
@ -405,8 +398,17 @@ pub fn applyPending(root: *Self) void {
view.pending.box = view.float_box;
}
if (output.inflight.fullscreen == null) {
if (view.pending.fullscreen and view.pending.tags & output.pending.tags != 0) {
if (!fullscreen_found and view.pending.fullscreen and
view.pending.tags & output.pending.tags != 0)
{
fullscreen_found = true;
if (output.inflight.fullscreen != view) {
if (output.inflight.fullscreen) |old| {
old.setFullscreen(false);
old.pending.box = old.post_fullscreen_box;
old.inflight.box = old.pending.box;
}
output.inflight.fullscreen = view;
view.setFullscreen(true);
@ -421,6 +423,7 @@ pub fn applyPending(root: *Self) void {
&view.pending.box.width,
&view.pending.box.height,
);
view.inflight.box = view.pending.box;
}
}
@ -430,6 +433,9 @@ pub fn applyPending(root: *Self) void {
view.inflight = view.pending;
}
}
if (!fullscreen_found) {
output.inflight.fullscreen = null;
}
{
var it = output.pending.wm_stack.iterator(.forward);
@ -440,7 +446,15 @@ pub fn applyPending(root: *Self) void {
}
output.inflight.tags = output.pending.tags;
}
}
{
// Layout demands can't be sent until after the inflight stacks of
// all outputs have been updated.
var output_it = root.outputs.first;
while (output_it) |node| : (output_it = node.next) {
const output = &node.data;
assert(output.inflight.layout_demand == null);
if (output.layout) |layout| {
var layout_count: u32 = 0;
@ -461,6 +475,7 @@ pub fn applyPending(root: *Self) void {
}
}
}
}
if (root.inflight_layout_demands == 0) {
root.sendConfigures();
@ -570,29 +585,15 @@ fn commitTransaction(root: *Self) void {
}
output.current.tags = output.inflight.tags;
if (output.inflight.fullscreen != output.current.fullscreen) {
if (output.current.fullscreen) |view| {
if (view.inflight.output) |new_output| {
view.tree.node.reparent(new_output.layers.views);
} else {
view.tree.node.reparent(root.hidden.tree);
}
}
if (output.inflight.fullscreen) |view| {
assert(view.inflight.output == output);
view.tree.node.reparent(output.layers.fullscreen);
}
output.current.fullscreen = output.inflight.fullscreen;
output.layers.fullscreen.node.setEnabled(output.current.fullscreen != null);
}
var focus_stack_it = output.inflight.focus_stack.iterator(.forward);
while (focus_stack_it.next()) |view| {
assert(view.inflight.output == output);
view.inflight_serial = null;
if (view.current.output != output) {
if (view.current.output != output or
(output.current.fullscreen == view and output.inflight.fullscreen != view))
{
view.tree.node.reparent(output.layers.views);
view.popup_tree.node.reparent(output.layers.popups);
}
@ -600,12 +601,24 @@ fn commitTransaction(root: *Self) void {
const enabled = view.current.tags & output.current.tags != 0;
view.tree.node.setEnabled(enabled);
view.popup_tree.node.setEnabled(enabled);
if (output.inflight.fullscreen != view) {
// TODO this approach for syncing the order will likely cause over-damaging.
view.tree.node.lowerToBottom();
}
view.updateCurrent();
}
if (output.inflight.fullscreen != output.current.fullscreen) {
if (output.inflight.fullscreen) |view| {
assert(view.inflight.output == output);
assert(view.current.output == output);
view.tree.node.reparent(output.layers.fullscreen);
}
output.current.fullscreen = output.inflight.fullscreen;
output.layers.fullscreen.node.setEnabled(output.current.fullscreen != null);
}
output.status.handleTransactionCommit(output);
}

View File

@ -193,19 +193,25 @@ pub fn updateCurrent(view: *Self) void {
view.tree.node.setPosition(box.x, box.y);
view.popup_tree.node.setPosition(box.x, box.y);
const enable_borders = view.draw_borders and !view.current.fullscreen;
const border_width: c_int = config.border_width;
view.borders.left.node.setEnabled(enable_borders);
view.borders.left.node.setPosition(-border_width, -border_width);
view.borders.left.setSize(border_width, box.height + 2 * border_width);
view.borders.left.setColor(color);
view.borders.right.node.setEnabled(enable_borders);
view.borders.right.node.setPosition(box.width, -border_width);
view.borders.right.setSize(border_width, box.height + 2 * border_width);
view.borders.right.setColor(color);
view.borders.top.node.setEnabled(enable_borders);
view.borders.top.node.setPosition(0, -border_width);
view.borders.top.setSize(box.width, border_width);
view.borders.top.setColor(color);
view.borders.bottom.node.setEnabled(enable_borders);
view.borders.bottom.node.setPosition(0, box.height);
view.borders.bottom.setSize(box.width, border_width);
view.borders.bottom.setColor(color);

View File

@ -33,6 +33,9 @@ pub fn toggleFullscreen(
const view = seat.focused.view;
view.pending.fullscreen = !view.pending.fullscreen;
// It is possible to end up with multiple fullscreen views in which
// case making one non-fullscreen should switch focus to the next.
seat.focus(null);
server.root.applyPending();
}
}