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

commitc32c76daa5af15bdf117f0c339d4a598f6f21f89
parent48e0f5b761
authorHugo Machet <[email protected]>
date2024-02-19 11:30
river: add -no-xwayland cli flag

Add a cli flag to disable xwayland at runtime even if river has been
built with xwayland support.

 doc/river.1.scd        |  3 +++
 river/Cursor.zig       | 25 ++++++++++++++-----------
 river/InputManager.zig |  6 +++++-
 river/Server.zig       | 24 ++++++++++++++++--------
 river/main.zig         |  5 ++++-
 5 files changed, 42 insertions(+), 21 deletions(-)

diff --git a/doc/river.1.scd b/doc/river.1.scd
index 972cad1..304be55 100644
--- a/doc/river.1.scd
+++ b/doc/river.1.scd
@@ -36,6 +36,9 @@ utility may be used to communicate with river over these protocols.
 	are logged.  At the *debug* log level, everything is logged including
 	verbose debug messages.
 
+*-no-xwayland*
+	Disable xwayland at runtime even if river has been built with support.
+
 # CONFIGURATION
 
 On startup river will run an executable file at $XDG_CONFIG_HOME/river/init if
diff --git a/river/Cursor.zig b/river/Cursor.zig
index f281876..a72fe64 100644
--- a/river/Cursor.zig
+++ b/river/Cursor.zig
@@ -249,17 +249,19 @@ pub fn setTheme(self: *Self, theme: ?[*:0]const u8, _size: ?u32) !void {
         if (theme) |t| if (c.setenv("XCURSOR_THEME", t, 1) < 0) return error.OutOfMemory;
 
         if (build_options.xwayland) {
-            try xcursor_manager.load(1);
-            const wlr_xcursor = xcursor_manager.getXcursor("left_ptr", 1).?;
-            const image = wlr_xcursor.images[0];
-            server.xwayland.setCursor(
-                image.buffer,
-                image.width * 4,
-                image.width,
-                image.height,
-                @intCast(image.hotspot_x),
-                @intCast(image.hotspot_y),
-            );
+            if (server.xwayland) |xwayland| {
+                try xcursor_manager.load(1);
+                const wlr_xcursor = xcursor_manager.getXcursor("left_ptr", 1).?;
+                const image = wlr_xcursor.images[0];
+                xwayland.setCursor(
+                    image.buffer,
+                    image.width * 4,
+                    image.width,
+                    image.height,
+                    @intCast(image.hotspot_x),
+                    @intCast(image.hotspot_y),
+                );
+            }
         }
     }
 
@@ -937,6 +939,7 @@ fn updateFocusFollowsCursorTarget(self: *Self) void {
             },
             .xwayland_override_redirect => {
                 assert(build_options.xwayland);
+                assert(server.xwayland != null);
                 self.focus_follows_cursor_target = null;
             },
         }
diff --git a/river/InputManager.zig b/river/InputManager.zig
index 4ce937a..a440c5a 100644
--- a/river/InputManager.zig
+++ b/river/InputManager.zig
@@ -88,7 +88,11 @@ pub fn init(self: *Self) !void {
     self.seats.prepend(seat_node);
     try seat_node.data.init(default_seat_name);
 
-    if (build_options.xwayland) server.xwayland.setSeat(self.defaultSeat().wlr_seat);
+    if (build_options.xwayland) {
+        if (server.xwayland) |xwayland| {
+            xwayland.setSeat(self.defaultSeat().wlr_seat);
+        }
+    }
 
     server.backend.events.new_input.add(&self.new_input);
     self.virtual_pointer_manager.events.new_virtual_pointer.add(&self.new_virtual_pointer);
diff --git a/river/Server.zig b/river/Server.zig
index 0922cfd..073de61 100644
--- a/river/Server.zig
+++ b/river/Server.zig
@@ -64,7 +64,7 @@ new_toplevel_decoration: wl.Listener(*wlr.XdgToplevelDecorationV1),
 layer_shell: *wlr.LayerShellV1,
 new_layer_surface: wl.Listener(*wlr.LayerSurfaceV1),
 
-xwayland: if (build_options.xwayland) *wlr.Xwayland else void,
+xwayland: if (build_options.xwayland) ?*wlr.Xwayland else void,
 new_xwayland_surface: if (build_options.xwayland) wl.Listener(*wlr.XwaylandSurface) else void,
 
 foreign_toplevel_manager: *wlr.ForeignToplevelManagerV1,
@@ -83,7 +83,7 @@ layout_manager: LayoutManager,
 idle_inhibitor_manager: IdleInhibitorManager,
 lock_manager: LockManager,
 
-pub fn init(self: *Self) !void {
+pub fn init(self: *Self, runtime_xwayland: bool) !void {
     self.wl_server = try wl.Server.create();
     errdefer self.wl_server.destroy();
 
@@ -130,9 +130,13 @@ pub fn init(self: *Self) !void {
     self.layer_shell.events.new_surface.add(&self.new_layer_surface);
 
     if (build_options.xwayland) {
-        self.xwayland = try wlr.Xwayland.create(self.wl_server, compositor, false);
-        self.new_xwayland_surface.setNotify(handleNewXwaylandSurface);
-        self.xwayland.events.new_surface.add(&self.new_xwayland_surface);
+        if (runtime_xwayland) {
+            self.xwayland = try wlr.Xwayland.create(self.wl_server, compositor, false);
+            self.new_xwayland_surface.setNotify(handleNewXwaylandSurface);
+            self.xwayland.?.events.new_surface.add(&self.new_xwayland_surface);
+        } else {
+            self.xwayland = null;
+        }
     }
 
     self.foreign_toplevel_manager = try wlr.ForeignToplevelManagerV1.create(self.wl_server);
@@ -177,8 +181,10 @@ pub fn deinit(self: *Self) void {
     self.request_activate.link.remove();
 
     if (build_options.xwayland) {
-        self.new_xwayland_surface.link.remove();
-        self.xwayland.destroy();
+        if (self.xwayland) |xwayland| {
+            self.new_xwayland_surface.link.remove();
+            xwayland.destroy();
+        }
     }
 
     self.wl_server.destroyClients();
@@ -205,7 +211,9 @@ pub fn start(self: Self) !void {
     // TODO: don't use libc's setenv
     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;
+        if (self.xwayland) |xwayland| {
+            if (c.setenv("DISPLAY", xwayland.display_name, 1) < 0) return error.SetenvError;
+        }
     }
 }
 
diff --git a/river/main.zig b/river/main.zig
index 7ddee30..69a783b 100644
--- a/river/main.zig
+++ b/river/main.zig
@@ -43,6 +43,7 @@ const usage: []const u8 =
     \\  -version           Print the version number and exit.
     \\  -c <command>       Run `sh -c <command>` on startup.
     \\  -log-level <level> Set the log level to error, warning, info, or debug.
+    \\  -no-xwayland       Disable xwayland even if built with support.
     \\
 ;
 
@@ -54,6 +55,7 @@ pub fn main() anyerror!void {
         .{ .name = "version", .kind = .boolean },
         .{ .name = "c", .kind = .arg },
         .{ .name = "log-level", .kind = .arg },
+        .{ .name = "no-xwayland", .kind = .boolean },
     }).parse(os.argv[1..]) catch {
         try io.getStdErr().writeAll(usage);
         os.exit(1);
@@ -87,6 +89,7 @@ pub fn main() anyerror!void {
             os.exit(1);
         }
     }
+    const enable_xwayland = !result.flags.@"no-xwayland";
     const startup_command = blk: {
         if (result.flags.c) |command| {
             break :blk try util.gpa.dupeZ(u8, command);
@@ -111,7 +114,7 @@ pub fn main() anyerror!void {
     try os.sigaction(os.SIG.PIPE, &sig_ign, null);
 
     log.info("river version {s}, initializing server", .{build_options.version});
-    try server.init();
+    try server.init(enable_xwayland);
     defer server.deinit();
 
     try server.start();