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

commitf6c7e539a5f95a798025dd4dff8549fc0300d8af
parenteca3977ce9
authorIsaac Freund <[email protected]>
date2020-05-02 15:51
Handle unmap on never-mapped layer surface

I don't think wlroots should be sending this, but we shouldn't crash
either.

Fixes https://github.com/ifreund/river/issues/19

 src/layer_surface.zig | 25 ++++++++++++++++++-------
 src/output.zig        |  2 +-
 2 files changed, 19 insertions(+), 8 deletions(-)

diff --git a/src/layer_surface.zig b/src/layer_surface.zig
index e4d4344..1acd321 100644
--- a/src/layer_surface.zig
+++ b/src/layer_surface.zig
@@ -36,11 +36,16 @@ pub const LayerSurface = struct {
         self.wlr_layer_surface = wlr_layer_surface;
         wlr_layer_surface.data = self;
 
-        self.mapped = false;
-
-        self.box = undefined;
         self.layer = layer;
 
+        // Temporarily set mapped to true and apply the pending state to allow
+        // for inital arrangement which sends the first configure.
+        self.mapped = true;
+        const stashed_state = wlr_layer_surface.current;
+        wlr_layer_surface.current = wlr_layer_surface.client_pending;
+        output.arrangeLayers();
+        wlr_layer_surface.current = stashed_state;
+
         // Set up listeners that are active for the entire lifetime of the layer surface
         self.listen_destroy.notify = handleDestroy;
         c.wl_signal_add(&self.wlr_layer_surface.events.destroy, &self.listen_destroy);
@@ -96,11 +101,17 @@ pub const LayerSurface = struct {
 
         Log.Debug.log("Layer surface '{}' unmapped.", .{self.wlr_layer_surface.namespace});
 
-        self.mapped = false;
+        // This is a bit ugly: we need to use the wlr bool here since surfaces
+        // may be closed during the inital configure since we set our mapped
+        // bool to true so that we can avoid making the arrange function even
+        // more complex.
+        if (self.wlr_layer_surface.mapped) {
+            // remove listeners only active while the layer surface is mapped
+            c.wl_list_remove(&self.listen_commit.link);
+            c.wl_list_remove(&self.listen_new_popup.link);
+        }
 
-        // remove listeners only active while the layer surface is mapped
-        c.wl_list_remove(&self.listen_commit.link);
-        c.wl_list_remove(&self.listen_new_popup.link);
+        self.mapped = false;
 
         // If the unmapped surface is focused, clear focus
         var it = self.output.root.server.input_manager.seats.first;
diff --git a/src/output.zig b/src/output.zig
index 5530b77..e3db173 100644
--- a/src/output.zig
+++ b/src/output.zig
@@ -347,7 +347,7 @@ pub const Output = struct {
 
             // If the value of exclusive_zone is greater than zero, then it exclusivly
             // occupies some area of the screen.
-            if (exclusive != (current_state.exclusive_zone > 0)) {
+            if (!layer_surface.mapped or exclusive != (current_state.exclusive_zone > 0)) {
                 continue;
             }