This commit is contained in:
Alexander Rosenberg 2025-01-06 20:14:25 -08:00
commit c1fc15dbc6
Signed by: Zander671
GPG Key ID: 5FD0394ADBD72730
8 changed files with 43 additions and 28 deletions

View File

@ -100,11 +100,11 @@ pub fn build(b: *Build) !void {
scanner.addSystemProtocol("unstable/pointer-gestures/pointer-gestures-unstable-v1.xml"); scanner.addSystemProtocol("unstable/pointer-gestures/pointer-gestures-unstable-v1.xml");
scanner.addSystemProtocol("unstable/xdg-decoration/xdg-decoration-unstable-v1.xml"); scanner.addSystemProtocol("unstable/xdg-decoration/xdg-decoration-unstable-v1.xml");
scanner.addCustomProtocol("protocol/river-control-unstable-v1.xml"); scanner.addCustomProtocol(b.path("protocol/river-control-unstable-v1.xml"));
scanner.addCustomProtocol("protocol/river-status-unstable-v1.xml"); scanner.addCustomProtocol(b.path("protocol/river-status-unstable-v1.xml"));
scanner.addCustomProtocol("protocol/river-layout-v3.xml"); scanner.addCustomProtocol(b.path("protocol/river-layout-v3.xml"));
scanner.addCustomProtocol("protocol/wlr-layer-shell-unstable-v1.xml"); scanner.addCustomProtocol(b.path("protocol/wlr-layer-shell-unstable-v1.xml"));
scanner.addCustomProtocol("protocol/wlr-output-power-management-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. // 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. // 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" }, .flags = &.{ "-std=c99", "-O2" },
}); });
// TODO: remove when zig issue #131 is implemented
scanner.addCSource(river);
river.pie = pie; river.pie = pie;
river.root_module.omit_frame_pointer = omit_frame_pointer; river.root_module.omit_frame_pointer = omit_frame_pointer;
@ -211,8 +208,6 @@ pub fn build(b: *Build) !void {
riverctl.linkLibC(); riverctl.linkLibC();
riverctl.linkSystemLibrary("wayland-client"); riverctl.linkSystemLibrary("wayland-client");
scanner.addCSource(riverctl);
riverctl.pie = pie; riverctl.pie = pie;
riverctl.root_module.omit_frame_pointer = omit_frame_pointer; riverctl.root_module.omit_frame_pointer = omit_frame_pointer;
@ -236,8 +231,6 @@ pub fn build(b: *Build) !void {
rivertile.linkLibC(); rivertile.linkLibC();
rivertile.linkSystemLibrary("wayland-client"); rivertile.linkSystemLibrary("wayland-client");
scanner.addCSource(rivertile);
rivertile.pie = pie; rivertile.pie = pie;
rivertile.root_module.omit_frame_pointer = omit_frame_pointer; rivertile.root_module.omit_frame_pointer = omit_frame_pointer;

View File

@ -8,12 +8,12 @@
.hash = "12209db20ce873af176138b76632931def33a10539387cba745db72933c43d274d56", .hash = "12209db20ce873af176138b76632931def33a10539387cba745db72933c43d274d56",
}, },
.@"zig-wayland" = .{ .@"zig-wayland" = .{
.url = "https://codeberg.org/ifreund/zig-wayland/archive/v0.2.0.tar.gz", .url = "https://codeberg.org/ifreund/zig-wayland/archive/bd8afd256fb6beed7d72e3580b00f33dea7155a1.tar.gz",
.hash = "1220687c8c47a48ba285d26a05600f8700d37fc637e223ced3aa8324f3650bf52242", .hash = "1220218a0e5c2cd63a2311417f4d3f2411dd17d75815f67c704ee657bd846ecbc3e0",
}, },
.@"zig-wlroots" = .{ .@"zig-wlroots" = .{
.url = "https://codeberg.org/ifreund/zig-wlroots/archive/e486223799648d27e8b91c5fe0ea4c088b74b707.tar.gz", .url = "https://codeberg.org/ifreund/zig-wlroots/archive/afbbbbe5579c750feed8de12b073fa50b0651137.tar.gz",
.hash = "1220aeb3317e16c38583839961c9d695fa60d23a3d506c8275fb0e8fa9849844f2f7", .hash = "122060ddef836b7872cb2088764a8bd2fb2e9254327673e8176b7f7a621ec897484f",
}, },
.@"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",

View File

@ -430,7 +430,8 @@ matches everything while _\*\*_ and the empty string are invalid.
*set-repeat* _rate_ _delay_ *set-repeat* _rate_ _delay_
Set the keyboard repeat rate to _rate_ key repeats per second and 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_] *xcursor-theme* _theme_name_ [_size_]
Set the xcursor theme to _theme_name_ and optionally set the _size_. Set the xcursor theme to _theme_name_ and optionally set the _size_.

View File

@ -1091,8 +1091,13 @@ pub fn updateState(cursor: *Cursor) void {
if (!cursor.hidden) { if (!cursor.hidden) {
var now: posix.timespec = undefined; var now: posix.timespec = undefined;
posix.clock_gettime(posix.CLOCK.MONOTONIC, &now) catch @panic("CLOCK_MONOTONIC not supported"); 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 + // 2^32-1 milliseconds is ~50 days, which is a realistic uptime.
@divTrunc(now.tv_nsec, std.time.ns_per_ms)); // 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); cursor.passthrough(msec);
} }
}, },

View File

@ -542,6 +542,13 @@ 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 {
// 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(); var state = wlr.Output.State.init();
defer state.finish(); defer state.finish();

View File

@ -19,6 +19,7 @@ const Server = @This();
const build_options = @import("build_options"); const build_options = @import("build_options");
const std = @import("std"); const std = @import("std");
const assert = std.debug.assert; const assert = std.debug.assert;
const mem = std.mem;
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;
@ -86,6 +87,8 @@ foreign_toplevel_manager: *wlr.ForeignToplevelManagerV1,
tearing_control_manager: *wlr.TearingControlManagerV1, tearing_control_manager: *wlr.TearingControlManagerV1,
alpha_modifier: *wlr.AlphaModifierV1,
input_manager: InputManager, input_manager: InputManager,
root: Root, root: Root,
config: Config, 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), .tearing_control_manager = try wlr.TearingControlManagerV1.create(wl_server, 1),
.alpha_modifier = try wlr.AlphaModifierV1.create(wl_server),
.config = try Config.init(), .config = try Config.init(),
.root = undefined, .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 // 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 // advertise the global to clients and invoke this filter before returning
// the new global pointer. // 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 // For other globals I like the current pointer comparison approach as it
// should catch river accidentally exposing multiple copies of e.g. wl_shm // should catch river accidentally exposing multiple copies of e.g. wl_shm
// with an assertion failure. // with an assertion failure.
return global.getInterface() == wl.Output.getInterface() or return global == server.shm.global or
global.getInterface() == wl.Seat.getInterface() or
global == server.shm.global or
global == server.single_pixel_buffer_manager.global or global == server.single_pixel_buffer_manager.global or
global == server.viewporter.global or global == server.viewporter.global or
global == server.fractional_scale_manager.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.tablet_manager.global or
global == server.input_manager.pointer_gestures.global or global == server.input_manager.pointer_gestures.global or
global == server.idle_inhibit_manager.wlr_manager.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 /// Returns true if the global is blocked for security contexts

View File

@ -110,10 +110,10 @@ fn _main() !void {
fn registryListener(registry: *wl.Registry, event: wl.Registry.Event, globals: *Globals) void { fn registryListener(registry: *wl.Registry, event: wl.Registry.Event, globals: *Globals) void {
switch (event) { switch (event) {
.global => |global| { .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 assert(globals.seat == null); // TODO: support multiple seats
globals.seat = registry.bind(global.name, wl.Seat, 1) catch @panic("out of memory"); 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"); globals.control = registry.bind(global.name, zriver.ControlV1, 1) catch @panic("out of memory");
} }
}, },

View File

@ -382,9 +382,9 @@ pub fn main() !void {
fn registryListener(registry: *wl.Registry, event: wl.Registry.Event, context: *Context) void { fn registryListener(registry: *wl.Registry, event: wl.Registry.Event, context: *Context) void {
switch (event) { switch (event) {
.global => |global| { .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; 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}); context.addOutput(registry, global.name) catch |err| fatal("failed to bind output: {}", .{err});
} }
}, },