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

commitf7a7f8ca2cb948712093b575cefdb4aca1fd483f
parent5b978a7ad0
authorIsaac Freund <[email protected]>
date2021-04-27 18:56
cursor: handle popup subsurfaces properly

I added the required functions in wlroots 0.13.0, so use them.

 river/Cursor.zig | 62 +++++++++++++++++++++++++++++---------------------------
 1 file changed, 32 insertions(+), 30 deletions(-)

diff --git a/river/Cursor.zig b/river/Cursor.zig
index cdf1516..69cc2dc 100644
--- a/river/Cursor.zig
+++ b/river/Cursor.zig
@@ -426,7 +426,6 @@ fn handleRequestSetCursor(
 /// returns the surface if found and sets the sx/sy parametes to the
 /// surface coordinates.
 fn surfaceAt(self: Self, lx: f64, ly: f64, sx: *f64, sy: *f64) ?*wlr.Surface {
-    // Find the output to check
     const root = self.seat.input_manager.server.root;
     const wlr_output = root.output_layout.outputAt(lx, ly) orelse return null;
     const output = @intToPtr(*Output, wlr_output.data);
@@ -436,37 +435,46 @@ fn surfaceAt(self: Self, lx: f64, ly: f64, sx: *f64, sy: *f64) ?*wlr.Surface {
     var oy = ly;
     root.output_layout.outputCoords(wlr_output, &ox, &oy);
 
-    // Check overlay layer incl. popups
-    if (layerSurfaceAt(output.*, output.getLayer(.overlay).*, ox, oy, sx, sy, false)) |s| return s;
+    // Check surfaces in the reverse order they are rendered in:
+    // 1. overlay layer (+ popups)
+    // 2. top, bottom, background popups
+    // 3. top layer
+    // 4. views
+    // 5. bottom, background layers
+    if (layerSurfaceAt(output.getLayer(.overlay).*, ox, oy, sx, sy)) |s| return s;
 
-    // Check top-background popups only
-    for ([_]zwlr.LayerShellV1.Layer{ .top, .bottom, .background }) |layer|
-        if (layerSurfaceAt(output.*, output.getLayer(layer).*, ox, oy, sx, sy, true)) |s| return s;
+    for ([_]zwlr.LayerShellV1.Layer{ .top, .bottom, .background }) |layer| {
+        if (layerPopupSurfaceAt(output.getLayer(layer).*, ox, oy, sx, sy)) |s| return s;
+    }
 
-    // Check top layer
-    if (layerSurfaceAt(output.*, output.getLayer(.top).*, ox, oy, sx, sy, false)) |s| return s;
+    if (layerSurfaceAt(output.getLayer(.top).*, ox, oy, sx, sy)) |s| return s;
 
-    // Check views
     if (viewSurfaceAt(output.*, ox, oy, sx, sy)) |s| return s;
 
-    // Check the bottom-background layers
-    for ([_]zwlr.LayerShellV1.Layer{ .bottom, .background }) |layer|
-        if (layerSurfaceAt(output.*, output.getLayer(layer).*, ox, oy, sx, sy, false)) |s| return s;
+    for ([_]zwlr.LayerShellV1.Layer{ .bottom, .background }) |layer| {
+        if (layerSurfaceAt(output.getLayer(layer).*, ox, oy, sx, sy)) |s| return s;
+    }
 
     return null;
 }
 
-/// Find the topmost surface on the given layer at ox,oy. Will only check
-/// popups if popups_only is true.
-fn layerSurfaceAt(
-    output: Output,
-    layer: std.TailQueue(LayerSurface),
-    ox: f64,
-    oy: f64,
-    sx: *f64,
-    sy: *f64,
-    popups_only: bool,
-) ?*wlr.Surface {
+/// Find the topmost popup surface on the given layer at ox,oy.
+fn layerPopupSurfaceAt(layer: std.TailQueue(LayerSurface), ox: f64, oy: f64, sx: *f64, sy: *f64) ?*wlr.Surface {
+    var it = layer.first;
+    while (it) |node| : (it = node.next) {
+        const layer_surface = &node.data;
+        if (layer_surface.wlr_layer_surface.popupSurfaceAt(
+            ox - @intToFloat(f64, layer_surface.box.x),
+            oy - @intToFloat(f64, layer_surface.box.y),
+            sx,
+            sy,
+        )) |found| return found;
+    }
+    return null;
+}
+
+/// Find the topmost surface (or popup surface) on the given layer at ox,oy.
+fn layerSurfaceAt(layer: std.TailQueue(LayerSurface), ox: f64, oy: f64, sx: *f64, sy: *f64) ?*wlr.Surface {
     var it = layer.first;
     while (it) |node| : (it = node.next) {
         const layer_surface = &node.data;
@@ -475,13 +483,7 @@ fn layerSurfaceAt(
             oy - @intToFloat(f64, layer_surface.box.y),
             sx,
             sy,
-        )) |found| {
-            if (!popups_only) {
-                return found;
-            } else if (found.isXdgSurface() and wlr.XdgSurface.fromWlrSurface(found).role == .popup) {
-                return found;
-            }
-        }
+        )) |found| return found;
     }
     return null;
 }