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

commit89b5ad840ef63a441877c5aecdd70c8e31b20f47
parent233bdf4815
authorLeon Henrik Plickat <[email protected]>
date2020-07-16 01:21
Implement csd_filter list

 river/Config.zig            | 10 ++++++++++
 river/Decoration.zig        | 31 +++++++++++++++++++++++++++----
 river/DecorationManager.zig |  6 +++++-
 river/View.zig              |  4 ++++
 river/XdgToplevel.zig       | 22 ++++++++++++++++------
 river/render.zig            |  4 ++--
 6 files changed, 64 insertions(+), 13 deletions(-)

diff --git a/river/Config.zig b/river/Config.zig
index 8028009..1be9ba0 100644
--- a/river/Config.zig
+++ b/river/Config.zig
@@ -52,6 +52,9 @@ modes: std.ArrayList(std.ArrayList(Mapping)),
 /// List of app_ids which will be started floating
 float_filter: std.ArrayList([*:0]const u8),
 
+/// List of app_ids which are allowed to use client side decorations
+csd_filter: std.ArrayList([]const u8),
+
 pub fn init(self: *Self) !void {
     self.background_color = [_]f32{ 0.0, 0.16862745, 0.21176471, 1.0 }; // Solarized base03
     self.border_width = 2;
@@ -73,8 +76,14 @@ pub fn init(self: *Self) !void {
     self.float_filter = std.ArrayList([*:0]const u8).init(util.gpa);
     errdefer self.float_filter.deinit();
 
+    self.csd_filter = std.ArrayList([]const u8).init(util.gpa);
+    errdefer self.csd_filter.deinit();
+
     // Float views with app_id "float"
     try self.float_filter.append("float");
+
+    // Client side decorations for views with app_id "csd"
+    try self.csd_filter.append("csd");
 }
 
 pub fn deinit(self: Self) void {
@@ -89,4 +98,5 @@ pub fn deinit(self: Self) void {
     self.modes.deinit();
 
     self.float_filter.deinit();
+    self.csd_filter.deinit();
 }
diff --git a/river/Decoration.zig b/river/Decoration.zig
index 44f48c2..7223117 100644
--- a/river/Decoration.zig
+++ b/river/Decoration.zig
@@ -22,6 +22,10 @@ const std = @import("std");
 const c = @import("c.zig");
 const util = @import("util.zig");
 
+const Server = @import("Server.zig");
+
+server: *Server,
+
 wlr_xdg_toplevel_decoration: *c.wlr_xdg_toplevel_decoration_v1,
 
 listen_destroy: c.wl_listener,
@@ -29,8 +33,11 @@ listen_request_mode: c.wl_listener,
 
 pub fn init(
     self: *Self,
+    server: *Server,
     wlr_xdg_toplevel_decoration: *c.wlr_xdg_toplevel_decoration_v1,
 ) void {
+    self.server = server;
+
     self.wlr_xdg_toplevel_decoration = wlr_xdg_toplevel_decoration;
 
     self.listen_destroy.notify = handleDestroy;
@@ -49,8 +56,24 @@ fn handleDestroy(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void {
 
 fn handleRequestMode(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void {
     const self = @fieldParentPtr(Self, "listen_request_mode", listener.?);
-    _ = c.wlr_xdg_toplevel_decoration_v1_set_mode(
-        self.wlr_xdg_toplevel_decoration,
-        .WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE,
-    );
+
+    const wlr_xdg_surface: *c.wlr_xdg_surface = self.wlr_xdg_toplevel_decoration.surface;
+    const wlr_xdg_toplevel: *c.wlr_xdg_toplevel = @field(wlr_xdg_surface, c.wlr_xdg_surface_union).toplevel;
+    const app_id: [*:0]const u8 = if (wlr_xdg_toplevel.app_id) |id| id else "NULL";
+
+    const use_csd = for (self.server.config.csd_filter.items) |filter_app_id| {
+        if (std.mem.eql(u8, std.mem.span(app_id), filter_app_id)) break true;
+    } else false;
+
+    if (use_csd) {
+        _ = c.wlr_xdg_toplevel_decoration_v1_set_mode(
+            self.wlr_xdg_toplevel_decoration,
+            .WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE,
+        );
+    } else {
+        _ = c.wlr_xdg_toplevel_decoration_v1_set_mode(
+            self.wlr_xdg_toplevel_decoration,
+            .WLR_XDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE,
+        );
+    }
 }
diff --git a/river/DecorationManager.zig b/river/DecorationManager.zig
index b44dcef..aa191d7 100644
--- a/river/DecorationManager.zig
+++ b/river/DecorationManager.zig
@@ -25,6 +25,8 @@ const util = @import("util.zig");
 const Decoration = @import("Decoration.zig");
 const Server = @import("Server.zig");
 
+server: *Server,
+
 wlr_xdg_decoration_manager: *c.wlr_xdg_decoration_manager_v1,
 
 decorations: std.SinglyLinkedList(Decoration),
@@ -35,6 +37,8 @@ pub fn init(self: *Self, server: *Server) !void {
     self.wlr_xdg_decoration_manager = c.wlr_xdg_decoration_manager_v1_create(server.wl_display) orelse
         return error.OutOfMemory;
 
+    self.server = server;
+
     self.listen_new_toplevel_decoration.notify = handleNewToplevelDecoration;
     c.wl_signal_add(
         &self.wlr_xdg_decoration_manager.events.new_toplevel_decoration,
@@ -50,5 +54,5 @@ fn handleNewToplevelDecoration(listener: ?*c.wl_listener, data: ?*c_void) callco
         c.wl_resource_post_no_memory(wlr_xdg_toplevel_decoration.resource);
         return;
     };
-    decoration.init(wlr_xdg_toplevel_decoration);
+    decoration.init(self.server, wlr_xdg_toplevel_decoration);
 }
diff --git a/river/View.zig b/river/View.zig
index cdd7d02..b405602 100644
--- a/river/View.zig
+++ b/river/View.zig
@@ -89,6 +89,8 @@ saved_buffers: std.ArrayList(SavedBuffer),
 /// view returns to floating mode.
 float_box: Box,
 
+draw_borders: bool,
+
 pub fn init(self: *Self, output: *Output, tags: u32, surface: var) void {
     self.output = output;
 
@@ -113,6 +115,8 @@ pub fn init(self: *Self, output: *Output, tags: u32, surface: var) void {
 
     self.saved_buffers = std.ArrayList(SavedBuffer).init(util.gpa);
 
+    self.draw_borders = true;
+
     if (@TypeOf(surface) == *c.wlr_xdg_surface) {
         self.impl = .{ .xdg_toplevel = undefined };
         self.impl.xdg_toplevel.init(self, surface);
diff --git a/river/XdgToplevel.zig b/river/XdgToplevel.zig
index 2ef46d3..3dfe837 100644
--- a/river/XdgToplevel.zig
+++ b/river/XdgToplevel.zig
@@ -189,13 +189,23 @@ fn handleMap(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void {
         }
     }
 
-    // If the toplevel has no parent, inform it that it is tiled. This
+    // If the toplevel has no parent and has an app_id which is not configured
+    // to use client side decorations, inform it that it is tiled. This
     // prevents firefox, for example, from drawing shadows around itself.
-    if (wlr_xdg_toplevel.parent == null)
-        _ = c.wlr_xdg_toplevel_set_tiled(
-            self.wlr_xdg_surface,
-            c.WLR_EDGE_LEFT | c.WLR_EDGE_RIGHT | c.WLR_EDGE_TOP | c.WLR_EDGE_BOTTOM,
-        );
+    if (wlr_xdg_toplevel.parent == null) {
+        const use_csd = for (root.server.config.csd_filter.items) |filter_app_id| {
+            if (std.mem.eql(u8, std.mem.span(app_id), filter_app_id)) break true;
+        } else false;
+
+        if (use_csd) {
+            view.draw_borders = false;
+        } else {
+            _ = c.wlr_xdg_toplevel_set_tiled(
+                self.wlr_xdg_surface,
+                c.WLR_EDGE_LEFT | c.WLR_EDGE_RIGHT | c.WLR_EDGE_TOP | c.WLR_EDGE_BOTTOM,
+            );
+        }
+    }
 
     view.map();
 }
diff --git a/river/render.zig b/river/render.zig
index 16d9d97..0ef67b5 100644
--- a/river/render.zig
+++ b/river/render.zig
@@ -88,7 +88,7 @@ pub fn renderOutput(output: *Output) void {
             if (view.focused) continue;
 
             renderView(output.*, view, &now);
-            renderBorders(output.*, view, &now);
+            if (view.draw_borders) renderBorders(output.*, view, &now);
         }
 
         // Render focused views
@@ -104,7 +104,7 @@ pub fn renderOutput(output: *Output) void {
             if (!view.focused) continue;
 
             renderView(output.*, view, &now);
-            renderBorders(output.*, view, &now);
+            if (view.draw_borders) renderBorders(output.*, view, &now);
         }
 
         if (build_options.xwayland) renderXwaylandUnmanaged(output.*, &now);