Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git
layer-surface: close if exclusive zones too large
It seems layer-shell clients such as waybar can commit bogus exclusive
zones larger than the width/height of the output. While this client
behavior is questionable at best, it must not cause river to crash or
otherwise misbehave.
Therefore, close layer surfaces causing the usable (not exclusive zone)
area of an output to be reduced below half of the width/height.
river/Output.zig | 26 +++++++++++++++++++++++---
1 file changed, 23 insertions(+), 3 deletions(-)
diff --git a/river/Output.zig b/river/Output.zig
index 6207588..3230fa3 100644
--- a/river/Output.zig
+++ b/river/Output.zig
@@ -360,16 +360,36 @@ fn sendLayerConfigures(
) void {
for ([_]zwlr.LayerShellV1.Layer{ .background, .bottom, .top, .overlay }) |layer| {
const tree = output.layerSurfaceTree(layer);
- var it = tree.children.iterator(.forward);
+ var it = tree.children.safeIterator(.forward);
while (it.next()) |node| {
assert(node.type == .tree);
if (@as(?*SceneNodeData, @ptrFromInt(node.data))) |node_data| {
const layer_surface = node_data.data.layer_surface;
const exclusive = layer_surface.wlr_layer_surface.current.exclusive_zone > 0;
- if (exclusive != (mode == .exclusive)) continue;
+ if (exclusive != (mode == .exclusive)) {
+ continue;
+ }
+
+ {
+ var new_usable_box = usable_box.*;
+
+ layer_surface.scene_layer_surface.configure(&full_box, &new_usable_box);
+
+ // Clients can request bogus exclusive zones larger than the output
+ // dimensions and river must handle this gracefully. It seems reasonable
+ // to close layer shell clients that would cause the usable area of the
+ // output to become less than half the width/height of its full dimensions.
+ if (new_usable_box.width < @divTrunc(full_box.width, 2) or
+ new_usable_box.height < @divTrunc(full_box.height, 2))
+ {
+ layer_surface.wlr_layer_surface.destroy();
+ continue;
+ }
+
+ usable_box.* = new_usable_box;
+ }
- layer_surface.scene_layer_surface.configure(&full_box, usable_box);
layer_surface.popup_tree.node.setPosition(
layer_surface.scene_layer_surface.tree.node.x,
layer_surface.scene_layer_surface.tree.node.y,