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

commitc2c9279a4672d92e4092619df72ec25e7c886b50
parentc03d6b62fb
authorIsaac Freund <[email protected]>
date2020-07-31 12:16
view: sidestep transaction for float/fullscreen

Transactions are only useful when multiple views need to atomically
change size together. Float/fullscreen views are independant of the
layout and should bypass the transaction system.

 river/Output.zig                    |  9 ++-------
 river/View.zig                      |  7 ++-----
 river/XdgToplevel.zig               | 12 ++++++------
 river/command/toggle_float.zig      |  8 +++++++-
 river/command/toggle_fullscreen.zig | 22 ++++++++++++++++++++--
 5 files changed, 37 insertions(+), 21 deletions(-)

diff --git a/river/Output.zig b/river/Output.zig
index a77efe2..ef6d443 100644
--- a/river/Output.zig
+++ b/river/Output.zig
@@ -296,17 +296,12 @@ fn layoutExternal(self: *Self, visible_count: u32, output_tags: u32) !void {
 pub fn arrangeViews(self: *Self) void {
     const full_area = Box.fromWlrBox(c.wlr_output_layout_get_box(self.root.wlr_output_layout, self.wlr_output).*);
 
-    // Make fullscreen views take the full area, count up views that will be
-    // arranged by the layout.
+    // Count up views that will be arranged by the layout
     var layout_count: u32 = 0;
     var it = ViewStack(View).pendingIterator(self.views.first, self.pending.tags);
     while (it.next()) |node| {
         const view = &node.view;
-        if (view.pending.fullscreen) {
-            view.pending.box = full_area;
-        } else if (!view.pending.float) {
-            layout_count += 1;
-        }
+        if (!view.pending.float) layout_count += 1;
     }
 
     // If the usable area has a zero dimension, trying to arrange the layout
diff --git a/river/View.zig b/river/View.zig
index 2b0dea1..ab90976 100644
--- a/river/View.zig
+++ b/river/View.zig
@@ -218,9 +218,6 @@ pub fn setFocused(self: *Self, focused: bool) void {
 /// Set the pending state to fullscren and inform the client. Should be
 /// followed by starting a transaction to apply the pending state.
 pub fn setFullscreen(self: *Self, fullscreen: bool) void {
-    // If transitionng from fullscreen -> float, return to the saved
-    // floating dimensions.
-    if (self.pending.fullscreen and self.pending.float) self.pending.box = self.float_box;
     self.pending.fullscreen = fullscreen;
     switch (self.impl) {
         .xdg_toplevel => |xdg_toplevel| xdg_toplevel.setFullscreen(fullscreen),
@@ -315,7 +312,7 @@ pub fn map(self: *Self) void {
 
     self.output.sendViewTags();
 
-    root.arrange();
+    if (self.pending.float) self.configure() else root.arrange();
 }
 
 /// Called by the impl when the surface will no longer be displayed
@@ -339,7 +336,7 @@ pub fn unmap(self: *Self) void {
 
     self.output.sendViewTags();
 
-    root.arrange();
+    if (!self.current.float and !self.current.fullscreen) root.arrange();
 }
 
 /// Destory the view and free the ViewStack node holding it.
diff --git a/river/XdgToplevel.zig b/river/XdgToplevel.zig
index 8636fcb..bf01edc 100644
--- a/river/XdgToplevel.zig
+++ b/river/XdgToplevel.zig
@@ -245,14 +245,14 @@ fn handleCommit(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void {
         view.surface_box = new_box;
 
         if (s == self.wlr_xdg_surface.configure_serial) {
-            // If this commit is in response to our configure, either notify
-            // the transaction code or apply the pending state immediately,
-            // depending on whether or not the view is floating.
+            // If this commit is in response to our configure and the view is
+            // part of the layout, notify the transaction code. If floating or
+            // fullscreen apply the pending state immediately.
             view.pending_serial = null;
-            if (view.current.float and view.pending.float)
-                view.current = view.pending
+            if (!view.pending.float and !view.pending.fullscreen)
+                view.output.root.notifyConfigured()
             else
-                view.output.root.notifyConfigured();
+                view.current = view.pending;
         } else {
             // If the client has not yet acked our configure, we need to send a
             // frame done event so that it commits another buffer. These
diff --git a/river/command/toggle_float.zig b/river/command/toggle_float.zig
index b392081..8f57454 100644
--- a/river/command/toggle_float.zig
+++ b/river/command/toggle_float.zig
@@ -39,8 +39,14 @@ pub fn toggleFloat(
         // Don't modify views which are the target of a cursor action
         if (seat.input_manager.isCursorActionTarget(view)) return;
 
-        if (!view.pending.float) view.pending.box = view.float_box;
         view.pending.float = !view.pending.float;
+
+        // If switching from layout to float, restore the previous floating dimensions
+        if (view.pending.float) {
+            view.pending.box = view.float_box;
+            view.configure();
+        }
+
         view.output.root.arrange();
     }
 }
diff --git a/river/command/toggle_fullscreen.zig b/river/command/toggle_fullscreen.zig
index c5ffb12..6e2ac2d 100644
--- a/river/command/toggle_fullscreen.zig
+++ b/river/command/toggle_fullscreen.zig
@@ -17,6 +17,9 @@
 
 const std = @import("std");
 
+const c = @import("../c.zig");
+
+const Box = @import("../Box.zig");
 const Error = @import("../command.zig").Error;
 const Seat = @import("../Seat.zig");
 
@@ -35,7 +38,22 @@ pub fn toggleFullscreen(
         // Don't modify views which are the target of a cursor action
         if (seat.input_manager.isCursorActionTarget(view)) return;
 
-        view.setFullscreen(!seat.focused.view.pending.fullscreen);
-        view.output.root.arrange();
+        view.setFullscreen(!view.pending.fullscreen);
+
+        if (view.pending.fullscreen) {
+            const output = view.output;
+            view.pending.box = Box.fromWlrBox(
+                c.wlr_output_layout_get_box(output.root.wlr_output_layout, output.wlr_output).*,
+            );
+            view.configure();
+        } else if (view.pending.float) {
+            // If transitioning from fullscreen -> float, return to the saved
+            // floating dimensions.
+            view.pending.box = view.float_box;
+            view.configure();
+        } else {
+            // Transitioning to layout, arrange and start a transaction
+            view.output.root.arrange();
+        }
     }
 }