tearing-control-v1: implement
Implement the wp-tearing-control-v1 protocol allowing window to hint the compositor that they prefer async "tearing" page flips. Add tearing/no-tearing rules to allow the user to manually enabled/disable tearing for a window. Use async "tearing" page flips when a window that should be allowed to tear is fullscreen. This still requires several kernel patches to work with the wlroots atomic DRM backend. For now, either set WLR_DRM_NO_ATOMIC=1 or use a custom kernel that includes the unmerged patches (such as CachyOS). Closes: https://codeberg.org/river/river/issues/1094
This commit is contained in:
parent
db7de8151c
commit
066baa5753
@ -94,6 +94,7 @@ pub fn build(b: *Build) !void {
|
|||||||
scanner.addSystemProtocol("stable/xdg-shell/xdg-shell.xml");
|
scanner.addSystemProtocol("stable/xdg-shell/xdg-shell.xml");
|
||||||
scanner.addSystemProtocol("staging/cursor-shape/cursor-shape-v1.xml");
|
scanner.addSystemProtocol("staging/cursor-shape/cursor-shape-v1.xml");
|
||||||
scanner.addSystemProtocol("staging/ext-session-lock/ext-session-lock-v1.xml");
|
scanner.addSystemProtocol("staging/ext-session-lock/ext-session-lock-v1.xml");
|
||||||
|
scanner.addSystemProtocol("staging/tearing-control/tearing-control-v1.xml");
|
||||||
scanner.addSystemProtocol("unstable/pointer-constraints/pointer-constraints-unstable-v1.xml");
|
scanner.addSystemProtocol("unstable/pointer-constraints/pointer-constraints-unstable-v1.xml");
|
||||||
scanner.addSystemProtocol("unstable/pointer-gestures/pointer-gestures-unstable-v1.xml");
|
scanner.addSystemProtocol("unstable/pointer-gestures/pointer-gestures-unstable-v1.xml");
|
||||||
scanner.addSystemProtocol("unstable/tablet/tablet-unstable-v2.xml");
|
scanner.addSystemProtocol("unstable/tablet/tablet-unstable-v2.xml");
|
||||||
@ -124,6 +125,7 @@ pub fn build(b: *Build) !void {
|
|||||||
scanner.generate("zxdg_decoration_manager_v1", 1);
|
scanner.generate("zxdg_decoration_manager_v1", 1);
|
||||||
scanner.generate("ext_session_lock_manager_v1", 1);
|
scanner.generate("ext_session_lock_manager_v1", 1);
|
||||||
scanner.generate("wp_cursor_shape_manager_v1", 1);
|
scanner.generate("wp_cursor_shape_manager_v1", 1);
|
||||||
|
scanner.generate("wp_tearing_control_manager_v1", 1);
|
||||||
|
|
||||||
scanner.generate("zriver_control_v1", 1);
|
scanner.generate("zriver_control_v1", 1);
|
||||||
scanner.generate("zriver_status_manager_v1", 4);
|
scanner.generate("zriver_status_manager_v1", 4);
|
||||||
|
@ -12,8 +12,8 @@
|
|||||||
.hash = "1220687c8c47a48ba285d26a05600f8700d37fc637e223ced3aa8324f3650bf52242",
|
.hash = "1220687c8c47a48ba285d26a05600f8700d37fc637e223ced3aa8324f3650bf52242",
|
||||||
},
|
},
|
||||||
.@"zig-wlroots" = .{
|
.@"zig-wlroots" = .{
|
||||||
.url = "https://codeberg.org/ifreund/zig-wlroots/archive/ae6151f22ceb4ccd7efb1291dea573785918a7ec.tar.gz",
|
.url = "https://codeberg.org/ifreund/zig-wlroots/archive/e486223799648d27e8b91c5fe0ea4c088b74b707.tar.gz",
|
||||||
.hash = "12204d99aebfbf88f1ff3ab197362937b3d4bef4f45fde9c4ee0d569e095a2a25889",
|
.hash = "1220aeb3317e16c38583839961c9d695fa60d23a3d506c8275fb0e8fa9849844f2f7",
|
||||||
},
|
},
|
||||||
.@"zig-xkbcommon" = .{
|
.@"zig-xkbcommon" = .{
|
||||||
.url = "https://codeberg.org/ifreund/zig-xkbcommon/archive/v0.2.0.tar.gz",
|
.url = "https://codeberg.org/ifreund/zig-xkbcommon/archive/v0.2.0.tar.gz",
|
||||||
|
@ -307,11 +307,17 @@ matches everything while _\*\*_ and the empty string are invalid.
|
|||||||
- *fullscreen*: Make the view fullscreen. Applies only to new views.
|
- *fullscreen*: Make the view fullscreen. Applies only to new views.
|
||||||
- *no-fullscreen*: Don't make the view fullscreen. Applies only to
|
- *no-fullscreen*: Don't make the view fullscreen. Applies only to
|
||||||
new views.
|
new views.
|
||||||
|
- *tearing*: Enable tearing for view when fullscreen regardless of the
|
||||||
|
supplied tearing hint. Note that tearing additionally requires setting the
|
||||||
|
*allow-tearing* server option. Applies to new and existing views.
|
||||||
|
- *no-tearing*: Disable tearing for view regardless of the supplied
|
||||||
|
tearing hint. Applies to new and existing views.
|
||||||
|
|
||||||
Both *float* and *no-float* rules are added to the same list,
|
Both *float* and *no-float* rules are added to the same list,
|
||||||
which means that adding a *no-float* rule with the same arguments
|
which means that adding a *no-float* rule with the same arguments
|
||||||
as a *float* rule will overwrite it. The same holds for *ssd* and
|
as a *float* rule will overwrite it. The same holds for *ssd* and
|
||||||
*csd*, *fullscreen* and *no-fullscreen* rules.
|
*csd*, *fullscreen* and *no-fullscreen*, *tearing* and
|
||||||
|
*no-tearing* rules.
|
||||||
|
|
||||||
If multiple rules in a list match a given view the most specific
|
If multiple rules in a list match a given view the most specific
|
||||||
rule will be applied. For example with the following rules
|
rule will be applied. For example with the following rules
|
||||||
@ -364,6 +370,9 @@ matches everything while _\*\*_ and the empty string are invalid.
|
|||||||
Set the attach mode of the currently focused output, overriding the value of
|
Set the attach mode of the currently focused output, overriding the value of
|
||||||
default-attach-mode if any.
|
default-attach-mode if any.
|
||||||
|
|
||||||
|
*allow-tearing* *enabled*|*disabled*
|
||||||
|
Allow windows to tear if requested by either the program or the user.
|
||||||
|
|
||||||
*background-color* _0xRRGGBB_|_0xRRGGBBAA_
|
*background-color* _0xRRGGBB_|_0xRRGGBBAA_
|
||||||
Set the background color.
|
Set the background color.
|
||||||
|
|
||||||
|
@ -31,6 +31,11 @@ const Mode = @import("Mode.zig");
|
|||||||
const RuleList = @import("rule_list.zig").RuleList;
|
const RuleList = @import("rule_list.zig").RuleList;
|
||||||
const View = @import("View.zig");
|
const View = @import("View.zig");
|
||||||
|
|
||||||
|
pub const AllowTearing = enum {
|
||||||
|
disabled,
|
||||||
|
enabled,
|
||||||
|
};
|
||||||
|
|
||||||
pub const AttachMode = union(enum) {
|
pub const AttachMode = union(enum) {
|
||||||
top,
|
top,
|
||||||
bottom,
|
bottom,
|
||||||
@ -68,6 +73,9 @@ pub const Dimensions = struct {
|
|||||||
height: u31,
|
height: u31,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Whether to allow tearing page flips if a view requests it.
|
||||||
|
allow_tearing: AllowTearing = .disabled,
|
||||||
|
|
||||||
/// Color of background in RGBA with premultiplied alpha (alpha should only affect nested sessions)
|
/// Color of background in RGBA with premultiplied alpha (alpha should only affect nested sessions)
|
||||||
background_color: [4]f32 = [_]f32{ 0.0, 0.16862745, 0.21176471, 1.0 }, // Solarized base03
|
background_color: [4]f32 = [_]f32{ 0.0, 0.16862745, 0.21176471, 1.0 }, // Solarized base03
|
||||||
|
|
||||||
@ -98,6 +106,7 @@ rules: struct {
|
|||||||
position: RuleList(Position) = .{},
|
position: RuleList(Position) = .{},
|
||||||
dimensions: RuleList(Dimensions) = .{},
|
dimensions: RuleList(Dimensions) = .{},
|
||||||
fullscreen: RuleList(bool) = .{},
|
fullscreen: RuleList(bool) = .{},
|
||||||
|
tearing: RuleList(bool) = .{},
|
||||||
} = .{},
|
} = .{},
|
||||||
|
|
||||||
/// The selected focus_follows_cursor mode
|
/// The selected focus_follows_cursor mode
|
||||||
|
@ -538,10 +538,12 @@ fn handleFrame(listener: *wl.Listener(*wlr.Output), _: *wlr.Output) void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn renderAndCommit(output: *Output, scene_output: *wlr.SceneOutput) !void {
|
fn renderAndCommit(output: *Output, scene_output: *wlr.SceneOutput) !void {
|
||||||
if (output.gamma_dirty) {
|
|
||||||
var state = wlr.Output.State.init();
|
var state = wlr.Output.State.init();
|
||||||
defer state.finish();
|
defer state.finish();
|
||||||
|
|
||||||
|
if (!scene_output.buildState(&state, null)) return error.CommitFailed;
|
||||||
|
|
||||||
|
if (output.gamma_dirty) {
|
||||||
const control = server.root.gamma_control_manager.getControl(output.wlr_output);
|
const control = server.root.gamma_control_manager.getControl(output.wlr_output);
|
||||||
if (!wlr.GammaControlV1.apply(control, &state)) return error.OutOfMemory;
|
if (!wlr.GammaControlV1.apply(control, &state)) return error.OutOfMemory;
|
||||||
|
|
||||||
@ -553,15 +555,20 @@ fn renderAndCommit(output: *Output, scene_output: *wlr.SceneOutput) !void {
|
|||||||
// has a null LUT. The wayland backend for example has this behavior.
|
// has a null LUT. The wayland backend for example has this behavior.
|
||||||
state.committed.gamma_lut = false;
|
state.committed.gamma_lut = false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!scene_output.buildState(&state, null)) return error.CommitFailed;
|
if (output.allowTearing() and server.config.allow_tearing == .enabled) {
|
||||||
|
state.tearing_page_flip = true;
|
||||||
|
|
||||||
|
if (!output.wlr_output.testState(&state)) {
|
||||||
|
log.debug("tearing page flip test failed for {s}, retrying without tearing", .{output.wlr_output.name});
|
||||||
|
state.tearing_page_flip = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!output.wlr_output.commitState(&state)) return error.CommitFailed;
|
if (!output.wlr_output.commitState(&state)) return error.CommitFailed;
|
||||||
|
|
||||||
output.gamma_dirty = false;
|
if (output.gamma_dirty) output.gamma_dirty = false;
|
||||||
} else {
|
|
||||||
if (!scene_output.commit(null)) return error.CommitFailed;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (server.lock_manager.state == .locked or
|
if (server.lock_manager.state == .locked or
|
||||||
(server.lock_manager.state == .waiting_for_lock_surfaces and output.locked_content.node.enabled) or
|
(server.lock_manager.state == .waiting_for_lock_surfaces and output.locked_content.node.enabled) or
|
||||||
@ -635,6 +642,14 @@ fn setTitle(output: Output) void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn allowTearing(output: *Output) bool {
|
||||||
|
if (output.current.fullscreen) |fullscreen_view| {
|
||||||
|
return fullscreen_view.allowTearing();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn handleLayoutNamespaceChange(output: *Output) void {
|
pub fn handleLayoutNamespaceChange(output: *Output) void {
|
||||||
// The user changed the layout namespace of this output. Try to find a
|
// The user changed the layout namespace of this output. Try to find a
|
||||||
// matching layout.
|
// matching layout.
|
||||||
|
@ -84,6 +84,8 @@ screencopy_manager: *wlr.ScreencopyManagerV1,
|
|||||||
|
|
||||||
foreign_toplevel_manager: *wlr.ForeignToplevelManagerV1,
|
foreign_toplevel_manager: *wlr.ForeignToplevelManagerV1,
|
||||||
|
|
||||||
|
tearing_control_manager: *wlr.TearingControlManagerV1,
|
||||||
|
|
||||||
input_manager: InputManager,
|
input_manager: InputManager,
|
||||||
root: Root,
|
root: Root,
|
||||||
config: Config,
|
config: Config,
|
||||||
@ -159,6 +161,8 @@ pub fn init(server: *Server, runtime_xwayland: bool) !void {
|
|||||||
|
|
||||||
.foreign_toplevel_manager = try wlr.ForeignToplevelManagerV1.create(wl_server),
|
.foreign_toplevel_manager = try wlr.ForeignToplevelManagerV1.create(wl_server),
|
||||||
|
|
||||||
|
.tearing_control_manager = try wlr.TearingControlManagerV1.create(wl_server, 1),
|
||||||
|
|
||||||
.config = try Config.init(),
|
.config = try Config.init(),
|
||||||
|
|
||||||
.root = undefined,
|
.root = undefined,
|
||||||
|
@ -23,6 +23,7 @@ const math = std.math;
|
|||||||
const posix = std.posix;
|
const posix = std.posix;
|
||||||
const wlr = @import("wlroots");
|
const wlr = @import("wlroots");
|
||||||
const wl = @import("wayland").server.wl;
|
const wl = @import("wayland").server.wl;
|
||||||
|
const wp = @import("wayland").server.wp;
|
||||||
|
|
||||||
const server = &@import("main.zig").server;
|
const server = &@import("main.zig").server;
|
||||||
const util = @import("util.zig");
|
const util = @import("util.zig");
|
||||||
@ -59,6 +60,12 @@ const AttachRelativeMode = enum {
|
|||||||
below,
|
below,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const TearingMode = enum {
|
||||||
|
override_false,
|
||||||
|
override_true,
|
||||||
|
window_hint,
|
||||||
|
};
|
||||||
|
|
||||||
pub const State = struct {
|
pub const State = struct {
|
||||||
/// The output the view is currently assigned to.
|
/// The output the view is currently assigned to.
|
||||||
/// May be null if there are no outputs or for newly created views.
|
/// May be null if there are no outputs or for newly created views.
|
||||||
@ -177,6 +184,9 @@ foreign_toplevel_handle: ForeignToplevelHandle = .{},
|
|||||||
/// Connector name of the output this view occupied before an evacuation.
|
/// Connector name of the output this view occupied before an evacuation.
|
||||||
output_before_evac: ?[]const u8 = null,
|
output_before_evac: ?[]const u8 = null,
|
||||||
|
|
||||||
|
// Current tearing mode of the view. Defaults to using the window tearing hint.
|
||||||
|
tearing_mode: TearingMode = .window_hint,
|
||||||
|
|
||||||
pub fn create(impl: Impl) error{OutOfMemory}!*View {
|
pub fn create(impl: Impl) error{OutOfMemory}!*View {
|
||||||
assert(impl != .none);
|
assert(impl != .none);
|
||||||
|
|
||||||
@ -572,6 +582,17 @@ pub fn getAppId(view: View) ?[*:0]const u8 {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return true if the view can currently tear.
|
||||||
|
pub fn allowTearing(view: *View) bool {
|
||||||
|
switch (view.tearing_mode) {
|
||||||
|
TearingMode.override_false => return false,
|
||||||
|
TearingMode.override_true => return true,
|
||||||
|
TearingMode.window_hint => if (view.rootSurface()) |root_surface| {
|
||||||
|
return server.tearing_control_manager.hintFromSurface(root_surface) == .@"async";
|
||||||
|
} else return false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Clamp the width/height of the box to the constraints of the view
|
/// Clamp the width/height of the box to the constraints of the view
|
||||||
pub fn applyConstraints(view: *View, box: *wlr.Box) void {
|
pub fn applyConstraints(view: *View, box: *wlr.Box) void {
|
||||||
box.width = math.clamp(box.width, view.constraints.min_width, view.constraints.max_width);
|
box.width = math.clamp(box.width, view.constraints.min_width, view.constraints.max_width);
|
||||||
@ -640,6 +661,10 @@ pub fn map(view: *View) !void {
|
|||||||
view.pending.ssd = ssd;
|
view.pending.ssd = ssd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (server.config.rules.tearing.match(view)) |tearing| {
|
||||||
|
view.tearing_mode = if (tearing) .override_true else .override_false;
|
||||||
|
}
|
||||||
|
|
||||||
if (server.config.rules.dimensions.match(view)) |dimensions| {
|
if (server.config.rules.dimensions.match(view)) |dimensions| {
|
||||||
view.pending.box.width = dimensions.width;
|
view.pending.box.width = dimensions.width;
|
||||||
view.pending.box.height = dimensions.height;
|
view.pending.box.height = dimensions.height;
|
||||||
|
@ -41,6 +41,7 @@ const command_impls = std.StaticStringMap(
|
|||||||
).initComptime(
|
).initComptime(
|
||||||
.{
|
.{
|
||||||
// zig fmt: off
|
// zig fmt: off
|
||||||
|
.{ "allow-tearing", @import("command/config.zig").allowTearing },
|
||||||
.{ "attach-mode", @import("command/attach_mode.zig").defaultAttachMode },
|
.{ "attach-mode", @import("command/attach_mode.zig").defaultAttachMode },
|
||||||
.{ "background-color", @import("command/config.zig").backgroundColor },
|
.{ "background-color", @import("command/config.zig").backgroundColor },
|
||||||
.{ "border-color-focused", @import("command/config.zig").borderColorFocused },
|
.{ "border-color-focused", @import("command/config.zig").borderColorFocused },
|
||||||
|
@ -24,6 +24,17 @@ const Error = @import("../command.zig").Error;
|
|||||||
const Seat = @import("../Seat.zig");
|
const Seat = @import("../Seat.zig");
|
||||||
const Config = @import("../Config.zig");
|
const Config = @import("../Config.zig");
|
||||||
|
|
||||||
|
pub fn allowTearing(
|
||||||
|
_: *Seat,
|
||||||
|
args: []const [:0]const u8,
|
||||||
|
_: *?[]const u8,
|
||||||
|
) Error!void {
|
||||||
|
if (args.len < 2) return Error.NotEnoughArguments;
|
||||||
|
if (args.len > 2) return Error.TooManyArguments;
|
||||||
|
server.config.allow_tearing = std.meta.stringToEnum(Config.AllowTearing, args[1]) orelse
|
||||||
|
return Error.UnknownOption;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn borderWidth(
|
pub fn borderWidth(
|
||||||
_: *Seat,
|
_: *Seat,
|
||||||
args: []const [:0]const u8,
|
args: []const [:0]const u8,
|
||||||
|
@ -38,6 +38,8 @@ const Action = enum {
|
|||||||
dimensions,
|
dimensions,
|
||||||
fullscreen,
|
fullscreen,
|
||||||
@"no-fullscreen",
|
@"no-fullscreen",
|
||||||
|
tearing,
|
||||||
|
@"no-tearing",
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn ruleAdd(_: *Seat, args: []const [:0]const u8, _: *?[]const u8) Error!void {
|
pub fn ruleAdd(_: *Seat, args: []const [:0]const u8, _: *?[]const u8) Error!void {
|
||||||
@ -53,7 +55,7 @@ pub fn ruleAdd(_: *Seat, args: []const [:0]const u8, _: *?[]const u8) Error!void
|
|||||||
const action = std.meta.stringToEnum(Action, result.args[0]) orelse return Error.UnknownOption;
|
const action = std.meta.stringToEnum(Action, result.args[0]) orelse return Error.UnknownOption;
|
||||||
|
|
||||||
const positional_arguments_count: u8 = switch (action) {
|
const positional_arguments_count: u8 = switch (action) {
|
||||||
.float, .@"no-float", .ssd, .csd, .fullscreen, .@"no-fullscreen" => 1,
|
.float, .@"no-float", .ssd, .csd, .fullscreen, .@"no-fullscreen", .tearing, .@"no-tearing" => 1,
|
||||||
.tags, .output => 2,
|
.tags, .output => 2,
|
||||||
.position, .dimensions => 3,
|
.position, .dimensions => 3,
|
||||||
};
|
};
|
||||||
@ -83,6 +85,14 @@ pub fn ruleAdd(_: *Seat, args: []const [:0]const u8, _: *?[]const u8) Error!void
|
|||||||
apply_ssd_rules();
|
apply_ssd_rules();
|
||||||
server.root.applyPending();
|
server.root.applyPending();
|
||||||
},
|
},
|
||||||
|
.tearing, .@"no-tearing" => {
|
||||||
|
try server.config.rules.tearing.add(.{
|
||||||
|
.app_id_glob = app_id_glob,
|
||||||
|
.title_glob = title_glob,
|
||||||
|
.value = (action == .tearing),
|
||||||
|
});
|
||||||
|
apply_tearing_rules();
|
||||||
|
},
|
||||||
.tags => {
|
.tags => {
|
||||||
const tags = try fmt.parseInt(u32, result.args[1], 10);
|
const tags = try fmt.parseInt(u32, result.args[1], 10);
|
||||||
try server.config.rules.tags.add(.{
|
try server.config.rules.tags.add(.{
|
||||||
@ -177,6 +187,10 @@ pub fn ruleDel(_: *Seat, args: []const [:0]const u8, _: *?[]const u8) Error!void
|
|||||||
.fullscreen, .@"no-fullscreen" => {
|
.fullscreen, .@"no-fullscreen" => {
|
||||||
_ = server.config.rules.fullscreen.del(rule);
|
_ = server.config.rules.fullscreen.del(rule);
|
||||||
},
|
},
|
||||||
|
.tearing, .@"no-tearing" => {
|
||||||
|
_ = server.config.rules.tearing.del(rule);
|
||||||
|
apply_tearing_rules();
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,6 +205,17 @@ fn apply_ssd_rules() void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn apply_tearing_rules() void {
|
||||||
|
var it = server.root.views.iterator(.forward);
|
||||||
|
while (it.next()) |view| {
|
||||||
|
if (view.destroying) continue;
|
||||||
|
|
||||||
|
if (server.config.rules.tearing.match(view)) |tearing| {
|
||||||
|
view.tearing_mode = if (tearing) .override_true else .override_false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn listRules(_: *Seat, args: []const [:0]const u8, out: *?[]const u8) Error!void {
|
pub fn listRules(_: *Seat, args: []const [:0]const u8, out: *?[]const u8) Error!void {
|
||||||
if (args.len < 2) return error.NotEnoughArguments;
|
if (args.len < 2) return error.NotEnoughArguments;
|
||||||
if (args.len > 2) return error.TooManyArguments;
|
if (args.len > 2) return error.TooManyArguments;
|
||||||
@ -203,6 +228,7 @@ pub fn listRules(_: *Seat, args: []const [:0]const u8, out: *?[]const u8) Error!
|
|||||||
position,
|
position,
|
||||||
dimensions,
|
dimensions,
|
||||||
fullscreen,
|
fullscreen,
|
||||||
|
tearing,
|
||||||
}, args[1]) orelse return Error.UnknownOption;
|
}, args[1]) orelse return Error.UnknownOption;
|
||||||
const max_glob_len = switch (rule_list) {
|
const max_glob_len = switch (rule_list) {
|
||||||
inline else => |list| @field(server.config.rules, @tagName(list)).getMaxGlobLen(),
|
inline else => |list| @field(server.config.rules, @tagName(list)).getMaxGlobLen(),
|
||||||
@ -218,12 +244,13 @@ pub fn listRules(_: *Seat, args: []const [:0]const u8, out: *?[]const u8) Error!
|
|||||||
try writer.writeAll("action\n");
|
try writer.writeAll("action\n");
|
||||||
|
|
||||||
switch (rule_list) {
|
switch (rule_list) {
|
||||||
inline .float, .ssd, .output, .fullscreen => |list| {
|
inline .float, .ssd, .output, .fullscreen, .tearing => |list| {
|
||||||
const rules = switch (list) {
|
const rules = switch (list) {
|
||||||
.float => server.config.rules.float.rules.items,
|
.float => server.config.rules.float.rules.items,
|
||||||
.ssd => server.config.rules.ssd.rules.items,
|
.ssd => server.config.rules.ssd.rules.items,
|
||||||
.output => server.config.rules.output.rules.items,
|
.output => server.config.rules.output.rules.items,
|
||||||
.fullscreen => server.config.rules.fullscreen.rules.items,
|
.fullscreen => server.config.rules.fullscreen.rules.items,
|
||||||
|
.tearing => server.config.rules.tearing.rules.items,
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
};
|
};
|
||||||
for (rules) |rule| {
|
for (rules) |rule| {
|
||||||
@ -234,6 +261,7 @@ pub fn listRules(_: *Seat, args: []const [:0]const u8, out: *?[]const u8) Error!
|
|||||||
.ssd => if (rule.value) "ssd" else "csd",
|
.ssd => if (rule.value) "ssd" else "csd",
|
||||||
.output => rule.value,
|
.output => rule.value,
|
||||||
.fullscreen => if (rule.value) "fullscreen" else "no-fullscreen",
|
.fullscreen => if (rule.value) "fullscreen" else "no-fullscreen",
|
||||||
|
.tearing => if (rule.value) "tearing" else "no-tearing",
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
}});
|
}});
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user