git.lucas.co / cce-compositor
Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git

commite8c9100cd91201b8ec68158148ff36e721ea95d6
parent714b0214cb
authorIsaac Freund <[email protected]>
date2022-11-05 00:29
deps: update to Zig 0.10

 .builds/alpine.yml         |  8 +++---
 .builds/archlinux.yml      |  8 +++---
 .builds/freebsd.yml        |  8 +++---
 README.md                  |  2 +-
 build.zig                  | 12 ++++-----
 common/flags.zig           | 10 ++++----
 deps/zig-pixman            |  2 +-
 deps/zig-wayland           |  2 +-
 deps/zig-wlroots           |  2 +-
 deps/zig-xkbcommon         |  2 +-
 river/Control.zig          |  2 +-
 river/Cursor.zig           | 23 +++++++----------
 river/LayerSurface.zig     |  2 +-
 river/LayoutDemand.zig     |  2 +-
 river/LayoutManager.zig    |  2 +-
 river/LockManager.zig      |  2 +-
 river/Root.zig             |  2 +-
 river/Seat.zig             | 11 +++-----
 river/Server.zig           |  7 +++---
 river/StatusManager.zig    |  2 +-
 river/View.zig             | 28 +++++++++++++--------
 river/VoidView.zig         | 62 ----------------------------------------------
 river/command.zig          |  2 +-
 river/command/input.zig    |  6 ++---
 river/command/keyboard.zig |  2 +-
 river/command/map.zig      |  2 +-
 river/main.zig             |  5 ++--
 river/render.zig           |  2 +-
 river/util.zig             |  5 ++--
 river/view_stack.zig       |  4 +--
 30 files changed, 81 insertions(+), 148 deletions(-)

diff --git a/.builds/alpine.yml b/.builds/alpine.yml
index cb976a5..7249771 100644
--- a/.builds/alpine.yml
+++ b/.builds/alpine.yml
@@ -39,11 +39,11 @@ tasks:
       sudo ninja -C build/ install
       cd ..
 
-      wget -nv https://ziglang.org/download/0.9.1/zig-linux-x86_64-0.9.1.tar.xz
+      wget -nv https://ziglang.org/download/0.10.0/zig-linux-x86_64-0.10.0.tar.xz
       # Remove a lot of useless lines from tar output.
-      tar -xvf zig-linux-x86_64-0.9.1.tar.xz 1>/dev/null
-      sudo mv zig-linux-x86_64-0.9.1/zig /usr/bin/
-      sudo mv zig-linux-x86_64-0.9.1/lib /usr/lib/zig
+      tar -xvf zig-linux-x86_64-0.10.0.tar.xz 1>/dev/null
+      sudo mv zig-linux-x86_64-0.10.0/zig /usr/bin/
+      sudo mv zig-linux-x86_64-0.10.0/lib /usr/lib/zig
   - build: |
       cd river
       zig build
diff --git a/.builds/archlinux.yml b/.builds/archlinux.yml
index 4aeae1d..a1a9769 100644
--- a/.builds/archlinux.yml
+++ b/.builds/archlinux.yml
@@ -37,11 +37,11 @@ tasks:
       sudo ninja -C build/ install
       cd ..
 
-      wget -nv https://ziglang.org/download/0.9.1/zig-linux-x86_64-0.9.1.tar.xz
+      wget -nv https://ziglang.org/download/0.10.0/zig-linux-x86_64-0.10.0.tar.xz
       # Remove a lot of useless lines from tar output.
-      tar -xvf zig-linux-x86_64-0.9.1.tar.xz 1>/dev/null
-      sudo mv zig-linux-x86_64-0.9.1/zig /usr/bin/
-      sudo mv zig-linux-x86_64-0.9.1/lib /usr/lib/zig
+      tar -xvf zig-linux-x86_64-0.10.0.tar.xz 1>/dev/null
+      sudo mv zig-linux-x86_64-0.10.0/zig /usr/bin/
+      sudo mv zig-linux-x86_64-0.10.0/lib /usr/lib/zig
   - build: |
       cd river
       zig build
diff --git a/.builds/freebsd.yml b/.builds/freebsd.yml
index 094185f..ea807da 100644
--- a/.builds/freebsd.yml
+++ b/.builds/freebsd.yml
@@ -41,11 +41,11 @@ tasks:
       sudo ninja -C build/ install
       cd ..
 
-      wget -nv https://ziglang.org/download/0.9.1/zig-freebsd-x86_64-0.9.1.tar.xz
+      wget -nv https://ziglang.org/download/0.10.0/zig-freebsd-x86_64-0.10.0.tar.xz
       # Remove a lot of useless lines from tar output.
-      tar -xvf zig-freebsd-x86_64-0.9.1.tar.xz 1>/dev/null
-      sudo mv zig-freebsd-x86_64-0.9.1/zig /usr/bin/
-      sudo mv zig-freebsd-x86_64-0.9.1/lib /usr/lib/zig
+      tar -xvf zig-freebsd-x86_64-0.10.0.tar.xz 1>/dev/null
+      sudo mv zig-freebsd-x86_64-0.10.0/zig /usr/bin/
+      sudo mv zig-freebsd-x86_64-0.10.0/lib /usr/lib/zig
   - build: |
       cd river
       zig build
diff --git a/README.md b/README.md
index 7a3eef0..26a8444 100644
--- a/README.md
+++ b/README.md
@@ -39,7 +39,7 @@ To compile river first ensure that you have the following dependencies
 installed. The "development" versions are required if applicable to your
 distribution.
 
-- [zig](https://ziglang.org/download/) 0.9
+- [zig](https://ziglang.org/download/) 0.10
 - wayland
 - wayland-protocols
 - [wlroots](https://gitlab.freedesktop.org/wlroots/wlroots) 0.16
diff --git a/build.zig b/build.zig
index f950996..e6e4824 100644
--- a/build.zig
+++ b/build.zig
@@ -141,7 +141,7 @@ pub fn build(b: *zbs.Builder) !void {
         riverctl.addPackagePath("flags", "common/flags.zig");
         riverctl.addPackage(.{
             .name = "wayland",
-            .path = .{ .generated = &scanner.result },
+            .source = .{ .generated = &scanner.result },
         });
         riverctl.linkLibC();
         riverctl.linkSystemLibrary("wayland-client");
@@ -163,7 +163,7 @@ pub fn build(b: *zbs.Builder) !void {
         rivertile.addPackagePath("flags", "common/flags.zig");
         rivertile.addPackage(.{
             .name = "wayland",
-            .path = .{ .generated = &scanner.result },
+            .source = .{ .generated = &scanner.result },
         });
         rivertile.linkLibC();
         rivertile.linkSystemLibrary("wayland-client");
@@ -229,19 +229,19 @@ pub fn build(b: *zbs.Builder) !void {
 fn addServerDeps(exe: *zbs.LibExeObjStep, scanner: *ScanProtocolsStep) void {
     const wayland = zbs.Pkg{
         .name = "wayland",
-        .path = .{ .generated = &scanner.result },
+        .source = .{ .generated = &scanner.result },
     };
     const xkbcommon = zbs.Pkg{
         .name = "xkbcommon",
-        .path = .{ .path = "deps/zig-xkbcommon/src/xkbcommon.zig" },
+        .source = .{ .path = "deps/zig-xkbcommon/src/xkbcommon.zig" },
     };
     const pixman = zbs.Pkg{
         .name = "pixman",
-        .path = .{ .path = "deps/zig-pixman/pixman.zig" },
+        .source = .{ .path = "deps/zig-pixman/pixman.zig" },
     };
     const wlroots = zbs.Pkg{
         .name = "wlroots",
-        .path = .{ .path = "deps/zig-wlroots/src/wlroots.zig" },
+        .source = .{ .path = "deps/zig-wlroots/src/wlroots.zig" },
         .dependencies = &[_]zbs.Pkg{ wayland, xkbcommon, pixman },
     };
 
diff --git a/common/flags.zig b/common/flags.zig
index 5188106..cde7cad 100644
--- a/common/flags.zig
+++ b/common/flags.zig
@@ -36,25 +36,25 @@ pub fn parser(comptime Arg: type, comptime flags: []const Flag) type {
             flags: Flags,
 
             pub const Flags = flags_type: {
-                var fields: []const std.builtin.TypeInfo.StructField = &.{};
+                var fields: []const std.builtin.Type.StructField = &.{};
                 inline for (flags) |flag| {
-                    const field: std.builtin.TypeInfo.StructField = switch (flag.kind) {
+                    const field: std.builtin.Type.StructField = switch (flag.kind) {
                         .boolean => .{
                             .name = flag.name,
                             .field_type = bool,
-                            .default_value = false,
+                            .default_value = &false,
                             .is_comptime = false,
                             .alignment = @alignOf(bool),
                         },
                         .arg => .{
                             .name = flag.name,
                             .field_type = ?[:0]const u8,
-                            .default_value = @as(??[:0]const u8, @as(?[:0]const u8, null)),
+                            .default_value = &@as(?[:0]const u8, null),
                             .is_comptime = false,
                             .alignment = @alignOf(?[:0]const u8),
                         },
                     };
-                    fields = fields ++ [_]std.builtin.TypeInfo.StructField{field};
+                    fields = fields ++ [_]std.builtin.Type.StructField{field};
                 }
                 break :flags_type @Type(.{ .Struct = .{
                     .layout = .Auto,
diff --git a/deps/zig-pixman b/deps/zig-pixman
index d381567..4a49ba1 160000
--- a/deps/zig-pixman
+++ b/deps/zig-pixman
@@ -1 +1 @@
-Subproject commit d381567de9b6e40dd7f4c6e0b5740f94ebd8c9d7
+Subproject commit 4a49ba13eb9ebb0c0f991de924328e3d615bf283
diff --git a/deps/zig-wayland b/deps/zig-wayland
index 2f69a48..71d2195 160000
--- a/deps/zig-wayland
+++ b/deps/zig-wayland
@@ -1 +1 @@
-Subproject commit 2f69a48a4a29c4cd9834bf276848392e34795407
+Subproject commit 71d21959b4671a848f1d198f6bb919f54d541f41
diff --git a/deps/zig-wlroots b/deps/zig-wlroots
index 8e6f5c4..04bcd67 160000
--- a/deps/zig-wlroots
+++ b/deps/zig-wlroots
@@ -1 +1 @@
-Subproject commit 8e6f5c4d65830d5f01ee0f7c8314ebd12b3da570
+Subproject commit 04bcd67d520f736f8223e2699a363be763c3c418
diff --git a/deps/zig-xkbcommon b/deps/zig-xkbcommon
index c97f8e1..bfd1f97 160000
--- a/deps/zig-xkbcommon
+++ b/deps/zig-xkbcommon
@@ -1 +1 @@
-Subproject commit c97f8e18dddda04414067cf8fbfdaa7682dcb44a
+Subproject commit bfd1f97c277c32fddb77dee45979d2f472595d19
diff --git a/river/Control.zig b/river/Control.zig
index 0041fb5..9f17764 100644
--- a/river/Control.zig
+++ b/river/Control.zig
@@ -54,7 +54,7 @@ fn handleServerDestroy(listener: *wl.Listener(*wl.Server), _: *wl.Server) void {
 }
 
 /// Called when a client binds our global
-fn bind(client: *wl.Client, self: *Self, version: u32, id: u32) callconv(.C) void {
+fn bind(client: *wl.Client, self: *Self, version: u32, id: u32) void {
     const control = zriver.ControlV1.create(client, version, id) catch {
         client.postNoMemory();
         return;
diff --git a/river/Cursor.zig b/river/Cursor.zig
index 24aa5a1..38eb6f6 100644
--- a/river/Cursor.zig
+++ b/river/Cursor.zig
@@ -218,7 +218,7 @@ pub fn setTheme(self: *Self, theme: ?[*:0]const u8, _size: ?u32) !void {
     while (it) |node| : (it = node.next) {
         const wlr_output = node.data.wlr_output;
         self.xcursor_manager.load(wlr_output.scale) catch
-            log.err("failed to load xcursor theme '{s}' at scale {}", .{ theme, wlr_output.scale });
+            log.err("failed to load xcursor theme '{?s}' at scale {}", .{ theme, wlr_output.scale });
     }
 
     // If this cursor belongs to the default seat, set the xcursor environment
@@ -227,12 +227,12 @@ pub fn setTheme(self: *Self, theme: ?[*:0]const u8, _size: ?u32) !void {
     if (self.seat == server.input_manager.defaultSeat()) {
         const size_str = try std.fmt.allocPrintZ(util.gpa, "{}", .{size});
         defer util.gpa.free(size_str);
-        if (c.setenv("XCURSOR_SIZE", size_str, 1) < 0) return error.OutOfMemory;
+        if (c.setenv("XCURSOR_SIZE", size_str.ptr, 1) < 0) return error.OutOfMemory;
         if (theme) |t| if (c.setenv("XCURSOR_THEME", t, 1) < 0) return error.OutOfMemory;
 
         if (build_options.xwayland) {
             self.xcursor_manager.load(1) catch {
-                log.err("failed to load xcursor theme '{s}' at scale 1", .{theme});
+                log.err("failed to load xcursor theme '{?s}' at scale 1", .{theme});
                 return;
             };
             const wlr_xcursor = self.xcursor_manager.getXcursor("left_ptr", 1).?;
@@ -649,7 +649,7 @@ pub fn unhide(self: *Self) void {
     self.updateState();
 }
 
-fn handleHideCursorTimeout(self: *Self) callconv(.C) c_int {
+fn handleHideCursorTimeout(self: *Self) c_int {
     log.debug("hide cursor timeout", .{});
     self.hide();
     return 0;
@@ -1159,16 +1159,11 @@ fn warp(self: *Self) void {
                 .width = view.current.box.width,
                 .height = view.current.box.height,
             },
-            .xwayland_override_redirect => |or_window| blk: {
-                assert(build_options.xwayland);
-                // TODO(zig): remove this line when updating to the self hosted compiler.
-                if (!build_options.xwayland) return;
-                break :blk wlr.Box{
-                    .x = or_window.xwayland_surface.x,
-                    .y = or_window.xwayland_surface.y,
-                    .width = or_window.xwayland_surface.width,
-                    .height = or_window.xwayland_surface.height,
-                };
+            .xwayland_override_redirect => |or_window| wlr.Box{
+                .x = or_window.xwayland_surface.x,
+                .y = or_window.xwayland_surface.y,
+                .width = or_window.xwayland_surface.width,
+                .height = or_window.xwayland_surface.height,
             },
         },
     };
diff --git a/river/LayerSurface.zig b/river/LayerSurface.zig
index 2cc02db..9a56a73 100644
--- a/river/LayerSurface.zig
+++ b/river/LayerSurface.zig
@@ -151,7 +151,7 @@ fn handleCommit(listener: *wl.Listener(*wlr.Surface), _: *wlr.Surface) void {
         return;
     }
 
-    if (self.wlr_layer_surface.current.committed != 0) {
+    if (@bitCast(u32, self.wlr_layer_surface.current.committed) != 0) {
         // If the layer changed, move the LayerSurface to the proper list
         if (self.wlr_layer_surface.current.layer != self.layer) {
             const node = @fieldParentPtr(std.TailQueue(Self).Node, "data", self);
diff --git a/river/LayoutDemand.zig b/river/LayoutDemand.zig
index 931b1a3..10384ae 100644
--- a/river/LayoutDemand.zig
+++ b/river/LayoutDemand.zig
@@ -66,7 +66,7 @@ pub fn deinit(self: *const Self) void {
 
 /// Destroy the LayoutDemand on timeout.
 /// All further responses to the event will simply be ignored.
-fn handleTimeout(layout: *Layout) callconv(.C) c_int {
+fn handleTimeout(layout: *Layout) c_int {
     log.info(
         "layout demand for layout '{s}' on output '{s}' timed out",
         .{ layout.namespace, layout.output.wlr_output.name },
diff --git a/river/LayoutManager.zig b/river/LayoutManager.zig
index 31c0e5e..9a46262 100644
--- a/river/LayoutManager.zig
+++ b/river/LayoutManager.zig
@@ -48,7 +48,7 @@ fn handleServerDestroy(listener: *wl.Listener(*wl.Server), _: *wl.Server) void {
     self.global.destroy();
 }
 
-fn bind(client: *wl.Client, _: ?*anyopaque, version: u32, id: u32) callconv(.C) void {
+fn bind(client: *wl.Client, _: ?*anyopaque, version: u32, id: u32) void {
     const layout_manager = river.LayoutManagerV3.create(client, version, id) catch {
         client.postNoMemory();
         log.err("out of memory", .{});
diff --git a/river/LockManager.zig b/river/LockManager.zig
index 66deff6..1fb897d 100644
--- a/river/LockManager.zig
+++ b/river/LockManager.zig
@@ -122,7 +122,7 @@ fn handleLock(listener: *wl.Listener(*wlr.SessionLockV1), lock: *wlr.SessionLock
     lock.events.destroy.add(&manager.destroy);
 }
 
-fn handleLockSurfacesTimeout(manager: *LockManager) callconv(.C) c_int {
+fn handleLockSurfacesTimeout(manager: *LockManager) c_int {
     log.err("waiting for lock surfaces timed out, imperfect frames may be shown", .{});
 
     assert(manager.state == .waiting_for_lock_surfaces);
diff --git a/river/Root.zig b/river/Root.zig
index e5adad6..be4d694 100644
--- a/river/Root.zig
+++ b/river/Root.zig
@@ -318,7 +318,7 @@ pub fn startTransaction(self: *Self) void {
     }
 }
 
-fn handleTransactionTimeout(self: *Self) callconv(.C) c_int {
+fn handleTransactionTimeout(self: *Self) c_int {
     std.log.scoped(.transaction).err("timeout occurred, some imperfect frames may be shown", .{});
 
     self.pending_configures = 0;
diff --git a/river/Seat.zig b/river/Seat.zig
index c08aad9..627e2f9 100644
--- a/river/Seat.zig
+++ b/river/Seat.zig
@@ -49,7 +49,7 @@ const PointerConstraint = @import("PointerConstraint.zig");
 
 pub const FocusTarget = union(enum) {
     view: *View,
-    xwayland_override_redirect: if (build_options.xwayland) *XwaylandOverrideRedirect else void,
+    xwayland_override_redirect: if (build_options.xwayland) *XwaylandOverrideRedirect else noreturn,
     layer: *LayerSurface,
     lock_surface: *LockSurface,
     none: void,
@@ -224,12 +224,7 @@ pub fn setFocusRaw(self: *Self, new_focus: FocusTarget) void {
     // Obtain the target surface
     const target_surface = switch (new_focus) {
         .view => |target_view| target_view.surface.?,
-        .xwayland_override_redirect => |target_override_redirect| blk: {
-            assert(build_options.xwayland);
-            // TODO(zig): remove this line when updating to the self hosted compiler.
-            if (!build_options.xwayland) return;
-            break :blk target_override_redirect.xwayland_surface.surface;
-        },
+        .xwayland_override_redirect => |target_or| target_or.xwayland_surface.surface,
         .layer => |target_layer| target_layer.wlr_layer_surface.surface,
         .lock_surface => |lock_surface| lock_surface.wlr_lock_surface.surface,
         .none => null,
@@ -454,7 +449,7 @@ pub fn clearRepeatingMapping(self: *Self) void {
 }
 
 /// Repeat key mapping
-fn handleMappingRepeatTimeout(self: *Self) callconv(.C) c_int {
+fn handleMappingRepeatTimeout(self: *Self) c_int {
     if (self.repeating_mapping) |mapping| {
         const rate = server.config.repeat_rate;
         const ms_delay = if (rate > 0) 1000 / rate else 0;
diff --git a/river/Server.zig b/river/Server.zig
index 8cd3614..34c0207 100644
--- a/river/Server.zig
+++ b/river/Server.zig
@@ -170,15 +170,14 @@ pub fn start(self: Self) !void {
     const socket = try self.wl_server.addSocketAuto(&buf);
     try self.backend.start();
     // TODO: don't use libc's setenv
-    if (c.setenv("WAYLAND_DISPLAY", socket, 1) < 0) return error.SetenvError;
+    if (c.setenv("WAYLAND_DISPLAY", socket.ptr, 1) < 0) return error.SetenvError;
     if (build_options.xwayland) {
         if (c.setenv("DISPLAY", self.xwayland.display_name, 1) < 0) return error.SetenvError;
     }
 }
 
 /// Handle SIGINT and SIGTERM by gracefully stopping the server
-fn terminate(signal: c_int, wl_server: *wl.Server) callconv(.C) c_int {
-    _ = signal;
+fn terminate(_: c_int, wl_server: *wl.Server) c_int {
     wl_server.terminate();
     return 0;
 }
@@ -248,7 +247,7 @@ fn handleNewXwaylandSurface(listener: *wl.Listener(*wlr.XwaylandSurface), xwayla
     const self = @fieldParentPtr(Self, "new_xwayland_surface", listener);
 
     log.debug(
-        "new xwayland surface: title='{s}', class='{s}', override redirect={}",
+        "new xwayland surface: title='{?s}', class='{?s}', override redirect={}",
         .{ xwayland_surface.title, xwayland_surface.class, xwayland_surface.override_redirect },
     );
 
diff --git a/river/StatusManager.zig b/river/StatusManager.zig
index d5532e3..3a957d1 100644
--- a/river/StatusManager.zig
+++ b/river/StatusManager.zig
@@ -50,7 +50,7 @@ fn handleServerDestroy(listener: *wl.Listener(*wl.Server), _: *wl.Server) void {
     self.global.destroy();
 }
 
-fn bind(client: *wl.Client, _: ?*anyopaque, version: u32, id: u32) callconv(.C) void {
+fn bind(client: *wl.Client, _: ?*anyopaque, version: u32, id: u32) void {
     const status_manager = zriver.StatusManagerV1.create(client, version, id) catch {
         client.postNoMemory();
         log.err("out of memory", .{});
diff --git a/river/View.zig b/river/View.zig
index 46db9cd..56740f8 100644
--- a/river/View.zig
+++ b/river/View.zig
@@ -31,7 +31,7 @@ const Output = @import("Output.zig");
 const Seat = @import("Seat.zig");
 const ViewStack = @import("view_stack.zig").ViewStack;
 const XdgToplevel = @import("XdgToplevel.zig");
-const XwaylandView = if (build_options.xwayland) @import("XwaylandView.zig") else @import("VoidView.zig");
+const XwaylandView = @import("XwaylandView.zig");
 
 const log = std.log.scoped(.view);
 
@@ -44,7 +44,7 @@ pub const Constraints = struct {
 
 const Impl = union(enum) {
     xdg_toplevel: XdgToplevel,
-    xwayland_view: XwaylandView,
+    xwayland_view: if (build_options.xwayland) XwaylandView else noreturn,
 };
 
 const State = struct {
@@ -204,7 +204,11 @@ pub fn needsConfigure(self: Self) bool {
 pub fn configure(self: *Self) void {
     switch (self.impl) {
         .xdg_toplevel => |*xdg_toplevel| xdg_toplevel.configure(),
-        .xwayland_view => |*xwayland_view| xwayland_view.configure(),
+        .xwayland_view => |*xwayland_view| {
+            // TODO(zig): remove this uneeded if statement
+            // https://github.com/ziglang/zig/issues/13655
+            if (build_options.xwayland) xwayland_view.configure();
+        },
     }
 }
 
@@ -237,7 +241,7 @@ fn saveBuffersIterator(
     surface_x: c_int,
     surface_y: c_int,
     saved_buffers: *std.ArrayListUnmanaged(SavedBuffer),
-) callconv(.C) void {
+) void {
     if (surface.buffer) |buffer| {
         var source_box: wlr.FBox = undefined;
         surface.getBufferSourceBox(&source_box);
@@ -320,7 +324,7 @@ fn sendEnter(self: *Self, output: *Output) void {
     self.forEachSurface(*wlr.Output, sendEnterIterator, output.wlr_output);
 }
 
-fn sendEnterIterator(surface: *wlr.Surface, _: c_int, _: c_int, wlr_output: *wlr.Output) callconv(.C) void {
+fn sendEnterIterator(surface: *wlr.Surface, _: c_int, _: c_int, wlr_output: *wlr.Output) void {
     surface.sendEnter(wlr_output);
 }
 
@@ -328,7 +332,7 @@ fn sendLeave(self: *Self, output: *Output) void {
     self.forEachSurface(*wlr.Output, sendLeaveIterator, output.wlr_output);
 }
 
-fn sendLeaveIterator(surface: *wlr.Surface, _: c_int, _: c_int, wlr_output: *wlr.Output) callconv(.C) void {
+fn sendLeaveIterator(surface: *wlr.Surface, _: c_int, _: c_int, wlr_output: *wlr.Output) void {
     surface.sendLeave(wlr_output);
 }
 
@@ -351,7 +355,11 @@ fn setFullscreen(self: *Self, fullscreen: bool) void {
     if (self.foreign_toplevel_handle) |handle| handle.setFullscreen(fullscreen);
     switch (self.impl) {
         .xdg_toplevel => |xdg_toplevel| xdg_toplevel.setFullscreen(fullscreen),
-        .xwayland_view => |*xwayland_view| xwayland_view.setFullscreen(fullscreen),
+        .xwayland_view => |*xwayland_view| {
+            // TODO(zig): remove this uneeded if statement
+            // https://github.com/ziglang/zig/issues/13655
+            if (build_options.xwayland) xwayland_view.setFullscreen(fullscreen);
+        },
     }
 }
 
@@ -366,7 +374,7 @@ pub fn setResizing(self: Self, resizing: bool) void {
 pub inline fn forEachSurface(
     self: Self,
     comptime T: type,
-    iterator: fn (surface: *wlr.Surface, sx: c_int, sy: c_int, data: T) callconv(.C) void,
+    comptime iterator: fn (surface: *wlr.Surface, sx: c_int, sy: c_int, data: T) void,
     user_data: T,
 ) void {
     switch (self.impl) {
@@ -479,7 +487,7 @@ pub fn shouldTrackConfigure(self: Self) bool {
 
 /// Called by the impl when the surface is ready to be displayed
 pub fn map(self: *Self) !void {
-    log.debug("view '{s}' mapped", .{self.getTitle()});
+    log.debug("view '{?s}' mapped", .{self.getTitle()});
 
     {
         assert(self.foreign_toplevel_handle == null);
@@ -515,7 +523,7 @@ pub fn map(self: *Self) !void {
 
 /// Called by the impl when the surface will no longer be displayed
 pub fn unmap(self: *Self) void {
-    log.debug("view '{s}' unmapped", .{self.getTitle()});
+    log.debug("view '{?s}' unmapped", .{self.getTitle()});
 
     if (self.saved_buffers.items.len == 0) self.saveBuffers();
 
diff --git a/river/VoidView.zig b/river/VoidView.zig
deleted file mode 100644
index 4337763..0000000
--- a/river/VoidView.zig
+++ /dev/null
@@ -1,62 +0,0 @@
-// This file is part of river, a dynamic tiling wayland compositor.
-//
-// Copyright 2020 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 Self = @This();
-
-const std = @import("std");
-const wlr = @import("wlroots");
-
-const View = @import("View.zig");
-
-pub fn needsConfigure(_: Self) bool {
-    unreachable;
-}
-
-pub fn configure(_: Self) void {
-    unreachable;
-}
-
-pub fn lastSetFullscreenState(_: Self) bool {
-    unreachable;
-}
-
-pub fn setActivated(_: Self, _: bool) void {
-    unreachable;
-}
-
-pub fn setFullscreen(_: Self, _: bool) void {
-    unreachable;
-}
-
-pub fn close(_: Self) void {
-    unreachable;
-}
-
-pub fn surfaceAt(_: Self, _: f64, _: f64, _: *f64, _: *f64) ?*wlr.Surface {
-    unreachable;
-}
-
-pub fn getTitle(_: Self) ?[*:0]const u8 {
-    unreachable;
-}
-
-pub fn getAppId(_: Self) ?[*:0]const u8 {
-    unreachable;
-}
-
-pub fn getConstraints(_: Self) View.Constraints {
-    unreachable;
-}
diff --git a/river/command.zig b/river/command.zig
index 0515963..8e541d7 100644
--- a/river/command.zig
+++ b/river/command.zig
@@ -38,7 +38,7 @@ pub const Orientation = enum {
 
 // zig fmt: off
 const command_impls = std.ComptimeStringMap(
-    fn (*Seat, []const [:0]const u8, *?[]const u8) Error!void,
+    *const fn (*Seat, []const [:0]const u8, *?[]const u8) Error!void,
     .{
         .{ "attach-mode",               @import("command/attach_mode.zig").attachMode },
         .{ "background-color",          @import("command/config.zig").backgroundColor },
diff --git a/river/command/input.zig b/river/command/input.zig
index 7023c5a..f30f600 100644
--- a/river/command/input.zig
+++ b/river/command/input.zig
@@ -49,7 +49,7 @@ pub fn listInputs(
         if (prev) try input_list.appendSlice("\n");
         prev = true;
 
-        try writer.print("{s}\n\tconfigured: {s}\n", .{
+        try writer.print("{s}\n\tconfigured: {}\n", .{
             device.identifier,
             configured,
         });
@@ -110,7 +110,7 @@ pub fn listInputConfigs(
             try writer.print("\tpointer-accel: {d}\n", .{pointer_accel.value});
         }
         if (input_config.scroll_method) |scroll_method| {
-            try writer.print("\tscroll-method: {s}\n", .{scroll_method});
+            try writer.print("\tscroll-method: {s}\n", .{@tagName(scroll_method)});
         }
         if (input_config.scroll_button) |scroll_button| {
             try writer.print("\tscroll-button: {s}\n", .{
@@ -195,7 +195,7 @@ pub fn input(
         input_config.scroll_method = meta.stringToEnum(InputConfig.ScrollMethod, args[3]) orelse
             return Error.UnknownOption;
     } else if (mem.eql(u8, "scroll-button", args[2])) {
-        const ret = c.libevdev_event_code_from_name(c.EV_KEY, args[3]);
+        const ret = c.libevdev_event_code_from_name(c.EV_KEY, args[3].ptr);
         if (ret < 1) return Error.InvalidButton;
         input_config.scroll_button = InputConfig.ScrollButton{ .button = @intCast(u32, ret) };
     } else {
diff --git a/river/command/keyboard.zig b/river/command/keyboard.zig
index 5e0d9b5..93f5cb9 100644
--- a/river/command/keyboard.zig
+++ b/river/command/keyboard.zig
@@ -44,7 +44,7 @@ pub fn keyboardLayout(
 
     const rule_names = xkb.RuleNames{
         .layout = result.args[0],
-        // TODO(zig) these should coerce without this hack with the selfhosted compiler.
+        // TODO(zig) these should eventually coerce without this hack.
         .rules = if (result.flags.rules) |s| s else null,
         .model = if (result.flags.model) |s| s else null,
         .variant = if (result.flags.variant) |s| s else null,
diff --git a/river/command/map.zig b/river/command/map.zig
index 6782d12..c5bcd51 100644
--- a/river/command/map.zig
+++ b/river/command/map.zig
@@ -242,7 +242,7 @@ fn pointerMappingExists(
 }
 
 fn parseEventCode(name: [:0]const u8, out: *?[]const u8) !u32 {
-    const event_code = c.libevdev_event_code_from_name(c.EV_KEY, name);
+    const event_code = c.libevdev_event_code_from_name(c.EV_KEY, name.ptr);
     if (event_code < 1) {
         out.* = try fmt.allocPrint(util.gpa, "unknown button {s}", .{name});
         return Error.Other;
diff --git a/river/main.zig b/river/main.zig
index 700b08e..ac7be9c 100644
--- a/river/main.zig
+++ b/river/main.zig
@@ -99,12 +99,11 @@ pub fn main() anyerror!void {
     // Ignore SIGPIPE so we don't get killed when writing to a socket that
     // has had its read end closed by another process.
     const sig_ign = os.Sigaction{
-        // TODO(zig): Remove this casting after https://github.com/ziglang/zig/pull/12410
-        .handler = .{ .handler = @intToPtr(os.Sigaction.handler_fn, @ptrToInt(os.SIG.IGN)) },
+        .handler = .{ .handler = os.SIG.IGN },
         .mask = os.empty_sigset,
         .flags = 0,
     };
-    os.sigaction(os.SIG.PIPE, &sig_ign, null);
+    try os.sigaction(os.SIG.PIPE, &sig_ign, null);
 
     std.log.info("initializing server", .{});
     try server.init();
diff --git a/river/render.zig b/river/render.zig
index 9642eac..f441ff3 100644
--- a/river/render.zig
+++ b/river/render.zig
@@ -323,7 +323,7 @@ fn renderSurfaceIterator(
     surface_x: c_int,
     surface_y: c_int,
     rdata: *SurfaceRenderData,
-) callconv(.C) void {
+) void {
     const texture = surface.getTexture() orelse return;
 
     var source_box: wlr.FBox = undefined;
diff --git a/river/util.zig b/river/util.zig
index fd1ac74..62e7e97 100644
--- a/river/util.zig
+++ b/river/util.zig
@@ -28,10 +28,9 @@ pub fn post_fork_pre_execve() void {
     if (c.setsid() < 0) unreachable;
     if (os.system.sigprocmask(os.SIG.SETMASK, &os.empty_sigset, null) < 0) unreachable;
     const sig_dfl = os.Sigaction{
-        // TODO(zig): Remove this casting after https://github.com/ziglang/zig/pull/12410
-        .handler = .{ .handler = @intToPtr(?os.Sigaction.handler_fn, @ptrToInt(os.SIG.DFL)) },
+        .handler = .{ .handler = os.SIG.DFL },
         .mask = os.empty_sigset,
         .flags = 0,
     };
-    os.sigaction(os.SIG.PIPE, &sig_dfl, null);
+    os.sigaction(os.SIG.PIPE, &sig_dfl, null) catch @panic("sigaction before fork failed");
 }
diff --git a/river/view_stack.zig b/river/view_stack.zig
index ab4589b..4c50ac1 100644
--- a/river/view_stack.zig
+++ b/river/view_stack.zig
@@ -161,7 +161,7 @@ pub fn ViewStack(comptime T: type) type {
                 it: ?*Node,
                 dir: Direction,
                 context: Context,
-                filter: fn (*View, Context) bool,
+                filter: *const fn (*View, Context) bool,
 
                 /// Returns the next node in iteration order which passes the
                 /// filter, or null if done.
@@ -184,7 +184,7 @@ pub fn ViewStack(comptime T: type) type {
             start: ?*Node,
             dir: Direction,
             context: anytype,
-            filter: fn (*View, @TypeOf(context)) bool,
+            filter: *const fn (*View, @TypeOf(context)) bool,
         ) Iter(@TypeOf(context)) {
             return .{ .it = start, .dir = dir, .context = context, .filter = filter };
         }