Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git
river: remove rules
river/Config.zig | 42 ----------------
river/View.zig | 24 +--------
river/XdgDecoration.zig | 3 +-
river/XdgToplevel.zig | 3 +-
river/XwaylandView.zig | 3 +-
river/rule_list.zig | 131 ------------------------------------------------
6 files changed, 5 insertions(+), 201 deletions(-)
diff --git a/river/Config.zig b/river/Config.zig
index 66a284a..5b8535c 100644
--- a/river/Config.zig
+++ b/river/Config.zig
@@ -28,7 +28,6 @@ const util = @import("util.zig");
const Server = @import("Server.zig");
const Output = @import("Output.zig");
const Mode = @import("Mode.zig");
-const RuleList = @import("rule_list.zig").RuleList;
const View = @import("View.zig");
pub const Position = struct {
@@ -63,16 +62,6 @@ mode_to_id: std.StringHashMap(u32),
/// All user-defined keymap modes, indexed by mode id
modes: std.ArrayListUnmanaged(Mode),
-rules: struct {
- float: RuleList(bool) = .{},
- ssd: RuleList(bool) = .{},
- tags: RuleList(u32) = .{},
- output: RuleList([]const u8) = .{},
- position: RuleList(Position) = .{},
- dimensions: RuleList(Dimensions) = .{},
- fullscreen: RuleList(bool) = .{},
-} = .{},
-
/// Bitmask restricting the tags of newly created views.
spawn_tagmask: u32 = std.math.maxInt(u32),
@@ -125,37 +114,6 @@ pub fn deinit(config: *Config) void {
for (config.modes.items) |*mode| mode.deinit();
config.modes.deinit(util.gpa);
- config.rules.float.deinit();
- config.rules.ssd.deinit();
- config.rules.tags.deinit();
- for (config.rules.output.rules.items) |rule| {
- util.gpa.free(rule.value);
- }
- config.rules.output.deinit();
- config.rules.position.deinit();
- config.rules.dimensions.deinit();
- config.rules.fullscreen.deinit();
-
config.keymap.unref();
config.xkb_context.unref();
}
-
-pub fn outputRuleMatch(config: *Config, view: *View) !?*Output {
- const output_name = config.rules.output.match(view) orelse return null;
- var it = server.root.active_outputs.iterator(.forward);
- while (it.next()) |output| {
- const wlr_output = output.wlr_output;
- if (mem.eql(u8, output_name, mem.span(wlr_output.name))) return output;
-
- // This allows matching with "Maker Model Serial" instead of "Connector"
- const maker = wlr_output.make orelse "Unknown";
- const model = wlr_output.model orelse "Unknown";
- const serial = wlr_output.serial orelse "Unknown";
- const identifier = try fmt.allocPrint(util.gpa, "{s} {s} {s}", .{ maker, model, serial });
- defer util.gpa.free(identifier);
-
- if (mem.eql(u8, output_name, identifier)) return output;
- }
-
- return null;
-}
diff --git a/river/View.zig b/river/View.zig
index 7d10c12..defa951 100644
--- a/river/View.zig
+++ b/river/View.zig
@@ -576,28 +576,9 @@ pub fn map(view: *View) !void {
view.foreign_toplevel_handle.map();
- if (server.config.rules.float.match(view)) |float| {
- view.pending.float = float;
- }
- if (server.config.rules.fullscreen.match(view)) |fullscreen| {
- view.pending.fullscreen = fullscreen;
- }
- if (server.config.rules.ssd.match(view)) |ssd| {
- view.pending.ssd = ssd;
- }
+ const output = server.input_manager.defaultSeat().focused_output;
- if (server.config.rules.dimensions.match(view)) |dimensions| {
- view.pending.box.width = dimensions.width;
- view.pending.box.height = dimensions.height;
- }
-
- const output = try server.config.outputRuleMatch(view) orelse
- server.input_manager.defaultSeat().focused_output;
-
- if (server.config.rules.position.match(view)) |position| {
- view.pending.box.x = position.x;
- view.pending.box.y = position.y;
- } else if (output) |o| {
+ if (output) |o| {
// Center the initial pending box on the output
view.pending.box.x = @divTrunc(@max(0, o.usable_box.width - view.pending.box.width), 2);
view.pending.box.y = @divTrunc(@max(0, o.usable_box.height - view.pending.box.height), 2);
@@ -605,7 +586,6 @@ pub fn map(view: *View) !void {
view.pending.tags = blk: {
const default = if (output) |o| o.pending.tags else server.root.fallback_pending.tags;
- if (server.config.rules.tags.match(view)) |tags| break :blk tags;
const tags = default & server.config.spawn_tagmask;
break :blk if (tags != 0) tags else default;
};
diff --git a/river/XdgDecoration.zig b/river/XdgDecoration.zig
index eee0c1d..eda0664 100644
--- a/river/XdgDecoration.zig
+++ b/river/XdgDecoration.zig
@@ -75,8 +75,7 @@ fn handleRequestMode(
const toplevel: *XdgToplevel = @ptrFromInt(decoration.wlr_decoration.toplevel.base.data);
const view = toplevel.view;
- const ssd = server.config.rules.ssd.match(toplevel.view) orelse
- (decoration.wlr_decoration.requested_mode != .client_side);
+ const ssd = true;
if (view.pending.ssd != ssd) {
view.pending.ssd = ssd;
diff --git a/river/XdgToplevel.zig b/river/XdgToplevel.zig
index 2e7695e..b27036a 100644
--- a/river/XdgToplevel.zig
+++ b/river/XdgToplevel.zig
@@ -312,8 +312,7 @@ fn handleCommit(listener: *wl.Listener(*wlr.Surface), _: *wlr.Surface) void {
_ = toplevel.wlr_toplevel.setWmCapabilities(.{ .fullscreen = true });
if (toplevel.decoration) |decoration| {
- const ssd = server.config.rules.ssd.match(toplevel.view) orelse
- (decoration.wlr_decoration.requested_mode != .client_side);
+ const ssd = true;
_ = decoration.wlr_decoration.setMode(if (ssd) .server_side else .client_side);
toplevel.view.pending.ssd = ssd;
}
diff --git a/river/XwaylandView.zig b/river/XwaylandView.zig
index db91199..ba40554 100644
--- a/river/XwaylandView.zig
+++ b/river/XwaylandView.zig
@@ -289,8 +289,7 @@ fn handleSetDecorations(listener: *wl.Listener(void)) void {
const xwayland_view: *XwaylandView = @fieldParentPtr("set_decorations", listener);
const view = xwayland_view.view;
- const ssd = server.config.rules.ssd.match(view) orelse
- !xwayland_view.xwayland_surface.decorations.no_border;
+ const ssd = !xwayland_view.xwayland_surface.decorations.no_border;
if (view.pending.ssd != ssd) {
view.pending.ssd = ssd;
diff --git a/river/rule_list.zig b/river/rule_list.zig
deleted file mode 100644
index 1d0a6fb..0000000
--- a/river/rule_list.zig
+++ /dev/null
@@ -1,131 +0,0 @@
-// This file is part of river, a dynamic tiling wayland compositor.
-//
-// Copyright 2023 The River Developers
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, version 3.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <https://www.gnu.org/licenses/>.
-
-const std = @import("std");
-const assert = std.debug.assert;
-const mem = std.mem;
-
-const globber = @import("globber");
-const util = @import("util.zig");
-
-const View = @import("View.zig");
-
-pub const MaxGlobLen = struct {
- app_id: usize,
- title: usize,
-};
-
-pub fn RuleList(comptime T: type) type {
- return struct {
- const List = @This();
-
- const Rule = struct {
- app_id_glob: []const u8,
- title_glob: []const u8,
- value: T,
- };
-
- /// Ordered from most specific to most general.
- /// Ordered first by app-id generality then by title generality.
- rules: std.ArrayListUnmanaged(Rule) = .{},
-
- pub fn deinit(list: *List) void {
- for (list.rules.items) |rule| {
- util.gpa.free(rule.app_id_glob);
- util.gpa.free(rule.title_glob);
- }
- list.rules.deinit(util.gpa);
- }
-
- pub fn add(list: *List, rule: Rule) error{OutOfMemory}!void {
- const index = for (list.rules.items, 0..) |*existing, i| {
- if (mem.eql(u8, rule.app_id_glob, existing.app_id_glob) and
- mem.eql(u8, rule.title_glob, existing.title_glob))
- {
- existing.value = rule.value;
- return;
- }
-
- switch (globber.order(rule.app_id_glob, existing.app_id_glob)) {
- .lt => break i,
- .eq => {
- if (globber.order(rule.title_glob, existing.title_glob) == .lt) {
- break i;
- }
- },
- .gt => {},
- }
- } else list.rules.items.len;
-
- const owned_app_id_glob = try util.gpa.dupe(u8, rule.app_id_glob);
- errdefer util.gpa.free(owned_app_id_glob);
-
- const owned_title_glob = try util.gpa.dupe(u8, rule.title_glob);
- errdefer util.gpa.free(owned_title_glob);
-
- try list.rules.insert(util.gpa, index, .{
- .app_id_glob = owned_app_id_glob,
- .title_glob = owned_title_glob,
- .value = rule.value,
- });
- }
-
- pub fn del(list: *List, rule: struct { app_id_glob: []const u8, title_glob: []const u8 }) ?T {
- for (list.rules.items, 0..) |existing, i| {
- if (mem.eql(u8, rule.app_id_glob, existing.app_id_glob) and
- mem.eql(u8, rule.title_glob, existing.title_glob))
- {
- util.gpa.free(existing.app_id_glob);
- util.gpa.free(existing.title_glob);
- return list.rules.orderedRemove(i).value;
- }
- }
- return null;
- }
-
- /// Returns the value of the most specific rule matching the view.
- /// Returns null if no rule matches.
- pub fn match(list: *List, view: *View) ?T {
- assert(!view.destroying);
- const app_id = mem.sliceTo(view.getAppId(), 0) orelse "";
- const title = mem.sliceTo(view.getTitle(), 0) orelse "";
-
- for (list.rules.items) |rule| {
- if (globber.match(app_id, rule.app_id_glob) and
- globber.match(title, rule.title_glob))
- {
- return rule.value;
- }
- }
-
- return null;
- }
-
- /// Returns the length of the longest globs.
- pub fn getMaxGlobLen(list: *const List) MaxGlobLen {
- var app_id_len: usize = 0;
- var title_len: usize = 0;
- for (list.rules.items) |rule| {
- app_id_len = @max(app_id_len, rule.app_id_glob.len);
- title_len = @max(title_len, rule.title_glob.len);
- }
- return .{
- .app_id = app_id_len,
- .title = title_len,
- };
- }
- };
-}