From a2a5e8f4632374b4b322c0520b7e30e35e0d753a Mon Sep 17 00:00:00 2001 From: tesselslate Date: Mon, 4 Nov 2024 21:03:34 -0500 Subject: [PATCH 1/7] alpha-modifier-v1: implement protocol Implement the alpha-modifier-v1 protocol, which allows clients to offload alpha blending operations to the compositor. wlroots' scene graph code takes care of updating the opacity of wlr_scene_buffers with an associated wp_alpha_modifier_surface_v1. --- build.zig.zon | 4 ++-- river/Server.zig | 7 ++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/build.zig.zon b/build.zig.zon index b35b27e..39ce52b 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -12,8 +12,8 @@ .hash = "1220687c8c47a48ba285d26a05600f8700d37fc637e223ced3aa8324f3650bf52242", }, .@"zig-wlroots" = .{ - .url = "https://codeberg.org/ifreund/zig-wlroots/archive/e486223799648d27e8b91c5fe0ea4c088b74b707.tar.gz", - .hash = "1220aeb3317e16c38583839961c9d695fa60d23a3d506c8275fb0e8fa9849844f2f7", + .url = "https://codeberg.org/ifreund/zig-wlroots/archive/afbbbbe5579c750feed8de12b073fa50b0651137.tar.gz", + .hash = "122060ddef836b7872cb2088764a8bd2fb2e9254327673e8176b7f7a621ec897484f", }, .@"zig-xkbcommon" = .{ .url = "https://codeberg.org/ifreund/zig-xkbcommon/archive/v0.2.0.tar.gz", diff --git a/river/Server.zig b/river/Server.zig index 8fc7422..027e777 100644 --- a/river/Server.zig +++ b/river/Server.zig @@ -86,6 +86,8 @@ foreign_toplevel_manager: *wlr.ForeignToplevelManagerV1, tearing_control_manager: *wlr.TearingControlManagerV1, +alpha_modifier: *wlr.AlphaModifierV1, + input_manager: InputManager, root: Root, config: Config, @@ -163,6 +165,8 @@ pub fn init(server: *Server, runtime_xwayland: bool) !void { .tearing_control_manager = try wlr.TearingControlManagerV1.create(wl_server, 1), + .alpha_modifier = try wlr.AlphaModifierV1.create(wl_server), + .config = try Config.init(), .root = undefined, @@ -321,7 +325,8 @@ fn allowlist(server: *Server, global: *const wl.Global) bool { global == server.input_manager.tablet_manager.global or global == server.input_manager.pointer_gestures.global or global == server.idle_inhibit_manager.wlr_manager.global or - global == server.tearing_control_manager.global; + global == server.tearing_control_manager.global or + global == server.alpha_modifier.global; } /// Returns true if the global is blocked for security contexts From 5ca829bd5acea4c68abcf16332ccfe6202da4aeb Mon Sep 17 00:00:00 2001 From: Isaac Freund Date: Sun, 24 Nov 2024 15:11:42 +0100 Subject: [PATCH 2/7] docs: mention key repeat defaults --- doc/riverctl.1.scd | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/riverctl.1.scd b/doc/riverctl.1.scd index 3a3ac1b..d0476ea 100644 --- a/doc/riverctl.1.scd +++ b/doc/riverctl.1.scd @@ -422,7 +422,8 @@ matches everything while _\*\*_ and the empty string are invalid. *set-repeat* _rate_ _delay_ Set the keyboard repeat rate to _rate_ key repeats per second and - repeat delay to _delay_ milliseconds. + repeat delay to _delay_ milliseconds. The default is a rate of 25 + repeats per second and a delay of 600ms. *xcursor-theme* _theme_name_ [_size_] Set the xcursor theme to _theme_name_ and optionally set the _size_. From 4fba7505f3a40f9166f3742ff942d2c578460119 Mon Sep 17 00:00:00 2001 From: Isaac Freund Date: Tue, 17 Dec 2024 17:35:16 -0600 Subject: [PATCH 3/7] deps: update to latest zig-wayland --- build.zig | 10 +++++----- build.zig.zon | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/build.zig b/build.zig index 7dac615..12f02d7 100644 --- a/build.zig +++ b/build.zig @@ -100,11 +100,11 @@ pub fn build(b: *Build) !void { scanner.addSystemProtocol("unstable/pointer-gestures/pointer-gestures-unstable-v1.xml"); scanner.addSystemProtocol("unstable/xdg-decoration/xdg-decoration-unstable-v1.xml"); - scanner.addCustomProtocol("protocol/river-control-unstable-v1.xml"); - scanner.addCustomProtocol("protocol/river-status-unstable-v1.xml"); - scanner.addCustomProtocol("protocol/river-layout-v3.xml"); - scanner.addCustomProtocol("protocol/wlr-layer-shell-unstable-v1.xml"); - scanner.addCustomProtocol("protocol/wlr-output-power-management-unstable-v1.xml"); + scanner.addCustomProtocol(b.path("protocol/river-control-unstable-v1.xml")); + scanner.addCustomProtocol(b.path("protocol/river-status-unstable-v1.xml")); + scanner.addCustomProtocol(b.path("protocol/river-layout-v3.xml")); + scanner.addCustomProtocol(b.path("protocol/wlr-layer-shell-unstable-v1.xml")); + scanner.addCustomProtocol(b.path("protocol/wlr-output-power-management-unstable-v1.xml")); // Some of these versions may be out of date with what wlroots implements. // This is not a problem in practice though as long as river successfully compiles. diff --git a/build.zig.zon b/build.zig.zon index 39ce52b..d5aed98 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -8,8 +8,8 @@ .hash = "12209db20ce873af176138b76632931def33a10539387cba745db72933c43d274d56", }, .@"zig-wayland" = .{ - .url = "https://codeberg.org/ifreund/zig-wayland/archive/v0.2.0.tar.gz", - .hash = "1220687c8c47a48ba285d26a05600f8700d37fc637e223ced3aa8324f3650bf52242", + .url = "https://codeberg.org/ifreund/zig-wayland/archive/4761e625bcc8218650625edc4734710b29a9ff0b.tar.gz", + .hash = "1220e1b6f822bda107aa1e3eca277ac82e0d833ba3182cd6f6ec56521046dc37cccc", }, .@"zig-wlroots" = .{ .url = "https://codeberg.org/ifreund/zig-wlroots/archive/afbbbbe5579c750feed8de12b073fa50b0651137.tar.gz", From e575485f0daa9f0f5b58ad1477ed806c3c42444d Mon Sep 17 00:00:00 2001 From: Isaac Freund Date: Mon, 23 Dec 2024 14:14:35 -0600 Subject: [PATCH 4/7] deps: upgrade to latest zig-wayland --- build.zig | 7 ------- build.zig.zon | 4 ++-- river/Server.zig | 4 ++-- riverctl/main.zig | 4 ++-- rivertile/main.zig | 4 ++-- 5 files changed, 8 insertions(+), 15 deletions(-) diff --git a/build.zig b/build.zig index 12f02d7..9d1f4fa 100644 --- a/build.zig +++ b/build.zig @@ -185,9 +185,6 @@ pub fn build(b: *Build) !void { .flags = &.{ "-std=c99", "-O2" }, }); - // TODO: remove when zig issue #131 is implemented - scanner.addCSource(river); - river.pie = pie; river.root_module.omit_frame_pointer = omit_frame_pointer; @@ -211,8 +208,6 @@ pub fn build(b: *Build) !void { riverctl.linkLibC(); riverctl.linkSystemLibrary("wayland-client"); - scanner.addCSource(riverctl); - riverctl.pie = pie; riverctl.root_module.omit_frame_pointer = omit_frame_pointer; @@ -236,8 +231,6 @@ pub fn build(b: *Build) !void { rivertile.linkLibC(); rivertile.linkSystemLibrary("wayland-client"); - scanner.addCSource(rivertile); - rivertile.pie = pie; rivertile.root_module.omit_frame_pointer = omit_frame_pointer; diff --git a/build.zig.zon b/build.zig.zon index d5aed98..55ab6dc 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -8,8 +8,8 @@ .hash = "12209db20ce873af176138b76632931def33a10539387cba745db72933c43d274d56", }, .@"zig-wayland" = .{ - .url = "https://codeberg.org/ifreund/zig-wayland/archive/4761e625bcc8218650625edc4734710b29a9ff0b.tar.gz", - .hash = "1220e1b6f822bda107aa1e3eca277ac82e0d833ba3182cd6f6ec56521046dc37cccc", + .url = "https://codeberg.org/ifreund/zig-wayland/archive/bd8afd256fb6beed7d72e3580b00f33dea7155a1.tar.gz", + .hash = "1220218a0e5c2cd63a2311417f4d3f2411dd17d75815f67c704ee657bd846ecbc3e0", }, .@"zig-wlroots" = .{ .url = "https://codeberg.org/ifreund/zig-wlroots/archive/afbbbbe5579c750feed8de12b073fa50b0651137.tar.gz", diff --git a/river/Server.zig b/river/Server.zig index 027e777..401689a 100644 --- a/river/Server.zig +++ b/river/Server.zig @@ -303,8 +303,8 @@ fn allowlist(server: *Server, global: *const wl.Global) bool { // For other globals I like the current pointer comparison approach as it // should catch river accidentally exposing multiple copies of e.g. wl_shm // with an assertion failure. - return global.getInterface() == wl.Output.getInterface() or - global.getInterface() == wl.Seat.getInterface() or + return global.getInterface() == wl.Output.interface or + global.getInterface() == wl.Seat.interface or global == server.shm.global or global == server.single_pixel_buffer_manager.global or global == server.viewporter.global or diff --git a/riverctl/main.zig b/riverctl/main.zig index 13a36ae..06d083b 100644 --- a/riverctl/main.zig +++ b/riverctl/main.zig @@ -110,10 +110,10 @@ fn _main() !void { fn registryListener(registry: *wl.Registry, event: wl.Registry.Event, globals: *Globals) void { switch (event) { .global => |global| { - if (mem.orderZ(u8, global.interface, wl.Seat.getInterface().name) == .eq) { + if (mem.orderZ(u8, global.interface, wl.Seat.interface.name) == .eq) { assert(globals.seat == null); // TODO: support multiple seats globals.seat = registry.bind(global.name, wl.Seat, 1) catch @panic("out of memory"); - } else if (mem.orderZ(u8, global.interface, zriver.ControlV1.getInterface().name) == .eq) { + } else if (mem.orderZ(u8, global.interface, zriver.ControlV1.interface.name) == .eq) { globals.control = registry.bind(global.name, zriver.ControlV1, 1) catch @panic("out of memory"); } }, diff --git a/rivertile/main.zig b/rivertile/main.zig index 2590e7e..10dc6cc 100644 --- a/rivertile/main.zig +++ b/rivertile/main.zig @@ -382,9 +382,9 @@ pub fn main() !void { fn registryListener(registry: *wl.Registry, event: wl.Registry.Event, context: *Context) void { switch (event) { .global => |global| { - if (mem.orderZ(u8, global.interface, river.LayoutManagerV3.getInterface().name) == .eq) { + if (mem.orderZ(u8, global.interface, river.LayoutManagerV3.interface.name) == .eq) { context.layout_manager = registry.bind(global.name, river.LayoutManagerV3, 1) catch return; - } else if (mem.orderZ(u8, global.interface, wl.Output.getInterface().name) == .eq) { + } else if (mem.orderZ(u8, global.interface, wl.Output.interface.name) == .eq) { context.addOutput(registry, global.name) catch |err| fatal("failed to bind output: {}", .{err}); } }, From 9f8b689f8a6def0b58a4a0b14a757d8bf35547a9 Mon Sep 17 00:00:00 2001 From: Isaac Freund Date: Fri, 27 Dec 2024 09:49:14 -0600 Subject: [PATCH 5/7] security-context-v1: fix assertion failure There's a bit of subtlety I missed with the zig-wayland upgrade. Since zig-wayland now generates its own wl_interface structs the pointer comparison we used to do here is no longer sufficient. --- river/Server.zig | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/river/Server.zig b/river/Server.zig index 401689a..ea06842 100644 --- a/river/Server.zig +++ b/river/Server.zig @@ -19,6 +19,7 @@ const Server = @This(); const build_options = @import("build_options"); const std = @import("std"); const assert = std.debug.assert; +const mem = std.mem; const posix = std.posix; const wlr = @import("wlroots"); const wl = @import("wayland").server.wl; @@ -299,13 +300,16 @@ fn allowlist(server: *Server, global: *const wl.Global) bool { // such as wl_output and wl_seat since the wl_global_create() function will // advertise the global to clients and invoke this filter before returning // the new global pointer. - // + if ((mem.orderZ(u8, global.getInterface().name, "wl_output") == .eq) or + (mem.orderZ(u8, global.getInterface().name, "wl_seat") == .eq)) + { + return true; + } + // For other globals I like the current pointer comparison approach as it // should catch river accidentally exposing multiple copies of e.g. wl_shm // with an assertion failure. - return global.getInterface() == wl.Output.interface or - global.getInterface() == wl.Seat.interface or - global == server.shm.global or + return global == server.shm.global or global == server.single_pixel_buffer_manager.global or global == server.viewporter.global or global == server.fractional_scale_manager.global or From ab879e245cbc317e3a2f5ec0379143d4b25b3cfe Mon Sep 17 00:00:00 2001 From: Isaac Freund Date: Sun, 29 Dec 2024 16:09:44 -0600 Subject: [PATCH 6/7] Output: check scene damage before rendering This should fix adaptive sync/VRR, which was regressed by db7de8151. --- river/Output.zig | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/river/Output.zig b/river/Output.zig index d4490c3..34e49dd 100644 --- a/river/Output.zig +++ b/river/Output.zig @@ -542,6 +542,13 @@ fn handleFrame(listener: *wl.Listener(*wlr.Output), _: *wlr.Output) void { } fn renderAndCommit(output: *Output, scene_output: *wlr.SceneOutput) !void { + // TODO(wlroots): replace this with wlr_scene_output_needs_frame() + if (!output.wlr_output.needs_frame and !output.gamma_dirty and + !scene_output.pending_commit_damage.notEmpty()) + { + return; + } + var state = wlr.Output.State.init(); defer state.finish(); From 6abcc68a198d0246077aaaed8af08db224f16775 Mon Sep 17 00:00:00 2001 From: Isaac Freund Date: Mon, 30 Dec 2024 09:21:24 -0600 Subject: [PATCH 7/7] river: wrap monotonic time > 2^32-1 milliseconds Fixes: https://codeberg.org/river/river/issues/1176 --- river/Cursor.zig | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/river/Cursor.zig b/river/Cursor.zig index 235f29c..bb6334f 100644 --- a/river/Cursor.zig +++ b/river/Cursor.zig @@ -1091,8 +1091,13 @@ pub fn updateState(cursor: *Cursor) void { if (!cursor.hidden) { var now: posix.timespec = undefined; posix.clock_gettime(posix.CLOCK.MONOTONIC, &now) catch @panic("CLOCK_MONOTONIC not supported"); - const msec: u32 = @intCast(now.tv_sec * std.time.ms_per_s + - @divTrunc(now.tv_nsec, std.time.ns_per_ms)); + // 2^32-1 milliseconds is ~50 days, which is a realistic uptime. + // This means that we must wrap if the monotonic time is greater than + // 2^32-1 milliseconds and hope that clients don't get too confused. + const msec: u32 = @intCast(@rem( + now.tv_sec *% std.time.ms_per_s +% @divTrunc(now.tv_nsec, std.time.ns_per_ms), + math.maxInt(u32), + )); cursor.passthrough(msec); } },