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 Run `sh -c ` on startup. \\ -log-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();