diff --git a/build.zig b/build.zig index 7dac615..9d1f4fa 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. @@ -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 b35b27e..55ab6dc 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -8,12 +8,12 @@ .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/bd8afd256fb6beed7d72e3580b00f33dea7155a1.tar.gz", + .hash = "1220218a0e5c2cd63a2311417f4d3f2411dd17d75815f67c704ee657bd846ecbc3e0", }, .@"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/doc/riverctl.1.scd b/doc/riverctl.1.scd index 5972ef9..af92f45 100644 --- a/doc/riverctl.1.scd +++ b/doc/riverctl.1.scd @@ -430,7 +430,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_. diff --git a/river/Cursor.zig b/river/Cursor.zig index ab7fb36..f81b5c8 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); } }, 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(); diff --git a/river/Server.zig b/river/Server.zig index 8fc7422..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; @@ -86,6 +87,8 @@ foreign_toplevel_manager: *wlr.ForeignToplevelManagerV1, tearing_control_manager: *wlr.TearingControlManagerV1, +alpha_modifier: *wlr.AlphaModifierV1, + input_manager: InputManager, root: Root, config: Config, @@ -163,6 +166,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, @@ -295,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.getInterface() or - global.getInterface() == wl.Seat.getInterface() 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 @@ -321,7 +329,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 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}); } },