river: make CSD-filters apply to existing views

This commit is contained in:
Leon Henrik Plickat
2021-06-22 13:13:08 +02:00
committed by Isaac Freund
parent 9ec04c764e
commit 968aef3459
4 changed files with 62 additions and 6 deletions

View File

@ -20,6 +20,8 @@ const std = @import("std");
const server = &@import("../main.zig").server;
const util = @import("../util.zig");
const View = @import("View.zig");
const ViewStack = @import("view_stack.zig").ViewStack;
const Error = @import("../command.zig").Error;
const Seat = @import("../Seat.zig");
@ -48,6 +50,7 @@ pub fn csdFilterAdd(
out: *?[]const u8,
) Error!void {
try modifyFilter(allocator, &server.config.csd_filter, args, .add);
csdFilterUpdateViews(args[1], .add);
}
pub fn csdFilterRemove(
@ -57,6 +60,7 @@ pub fn csdFilterRemove(
out: *?[]const u8,
) Error!void {
try modifyFilter(allocator, &server.config.csd_filter, args, .remove);
csdFilterUpdateViews(args[1], .remove);
}
fn modifyFilter(
@ -80,3 +84,47 @@ fn modifyFilter(
list.appendAssumeCapacity(try std.mem.dupe(allocator, u8, args[1]));
}
}
fn csdFilterUpdateViews(app_id: []const u8, operation: enum { add, remove }) void {
// There is no link between Decoration and View, so we need to iterate over
// both separately. Note that we do not need to arrange the outputs here; If
// the clients decoration mode changes, it will receive a configure event.
var decoration_it = server.decoration_manager.decorations.first;
while (decoration_it) |decoration_node| : (decoration_it = decoration_node.next) {
const xdg_toplevel_decoration = decoration_node.data.xdg_toplevel_decoration;
if (std.mem.eql(
u8,
std.mem.span(xdg_toplevel_decoration.surface.role_data.toplevel.app_id orelse return),
app_id,
)) {
_ = xdg_toplevel_decoration.setMode(switch (operation) {
.add => .client_side,
.remove => .server_side,
});
}
}
var output_it = server.root.outputs.first;
while (output_it) |output_node| : (output_it = output_node.next) {
var view_it = output_node.data.views.first;
while (view_it) |view_node| : (view_it = view_node.next) {
// CSD mode is not supported for XWayland views.
if (view_node.view.impl == .xwayland_view) continue;
const view_app_id = std.mem.span(view_node.view.getAppId() orelse continue);
if (std.mem.eql(u8, app_id, view_app_id)) {
const toplevel = view_node.view.impl.xdg_toplevel.xdg_surface.role_data.toplevel;
switch (operation) {
.add => {
view_node.view.draw_borders = false;
_ = toplevel.setTiled(.{ .top = false, .bottom = false, .left = false, .right = false });
},
.remove => {
view_node.view.draw_borders = true;
_ = toplevel.setTiled(.{ .top = true, .bottom = true, .left = true, .right = true });
},
}
}
}
}
}