diff --git a/river/LayerSurface.zig b/river/LayerSurface.zig index 65d7e28..ead75f6 100644 --- a/river/LayerSurface.zig +++ b/river/LayerSurface.zig @@ -21,6 +21,7 @@ const std = @import("std"); const wlr = @import("wlroots"); const wl = @import("wayland").server.wl; +const server = &@import("main.zig").server; const util = @import("util.zig"); const Box = @import("Box.zig"); @@ -109,7 +110,7 @@ fn handleUnmap(listener: *wl.Listener(*wlr.LayerSurfaceV1), wlr_layer_surface: * self.output.layers[@intCast(usize, @enumToInt(self.state.layer))].remove(self_node); // If the unmapped surface is focused, clear focus - var it = self.output.root.server.input_manager.seats.first; + var it = server.input_manager.seats.first; while (it) |node| : (it = node.next) { const seat = &node.data; if (seat.focused == .layer and seat.focused.layer == self) @@ -122,7 +123,7 @@ fn handleUnmap(listener: *wl.Listener(*wlr.LayerSurfaceV1), wlr_layer_surface: * // Ensure that focus is given to the appropriate view if there is no // other top/overlay layer surface to grab focus. - it = self.output.root.server.input_manager.seats.first; + it = server.input_manager.seats.first; while (it) |node| : (it = node.next) { const seat = &node.data; seat.focus(null); diff --git a/river/LayoutDemand.zig b/river/LayoutDemand.zig index 388a2c4..9518ae1 100644 --- a/river/LayoutDemand.zig +++ b/river/LayoutDemand.zig @@ -22,6 +22,7 @@ const wlr = @import("wlroots"); const wayland = @import("wayland"); const wl = wayland.server.wl; +const server = &@import("main.zig").server; const util = @import("util.zig"); const Layout = @import("Layout.zig"); @@ -46,13 +47,13 @@ view_boxen: []Box, timeout_timer: *wl.EventSource, pub fn init(layout: *Layout, views: u32) !Self { - const event_loop = layout.output.root.server.wl_server.getEventLoop(); + const event_loop = server.wl_server.getEventLoop(); const timeout_timer = try event_loop.addTimer(*Layout, handleTimeout, layout); errdefer timeout_timer.remove(); try timeout_timer.timerUpdate(timeout_ms); return Self{ - .serial = layout.output.root.server.wl_server.nextSerial(), + .serial = server.wl_server.nextSerial(), .views = @intCast(i32, views), .view_boxen = try util.gpa.alloc(Box, views), .timeout_timer = timeout_timer, @@ -86,7 +87,7 @@ pub fn pushViewDimensions(self: *Self, output: *Output, x: i32, y: i32, width: u // Here we apply the offset to align the coords with the origin of the // usable area and shrink the dimensions to accomodate the border size. - const border_width = output.root.server.config.border_width; + const border_width = server.config.border_width; self.view_boxen[self.view_boxen.len - @intCast(usize, self.views)] = .{ .x = x + output.usable_box.x + @intCast(i32, border_width), .y = y + output.usable_box.y + @intCast(i32, border_width), diff --git a/river/Output.zig b/river/Output.zig index 252a409..9ea74b6 100644 --- a/river/Output.zig +++ b/river/Output.zig @@ -25,8 +25,8 @@ const wayland = @import("wayland"); const wl = wayland.server.wl; const zwlr = wayland.server.zwlr; -const c = @import("c.zig"); const render = @import("render.zig"); +const server = &@import("main.zig").server; const util = @import("util.zig"); const Box = @import("Box.zig"); @@ -133,7 +133,7 @@ pub fn init(self: *Self, root: *Root, wlr_output: *wlr.Output) !void { } else { // Ensure that a cursor image at the output's scale factor is loaded // for each seat. - var it = root.server.input_manager.seats.first; + var it = server.input_manager.seats.first; while (it) |node| : (it = node.next) { const seat = &node.data; seat.cursor.xcursor_manager.load(wlr_output.scale) catch @@ -248,7 +248,7 @@ pub fn arrangeLayers(self: *Self) void { } } else null; - var it = self.root.server.input_manager.seats.first; + var it = server.input_manager.seats.first; while (it) |node| : (it = node.next) { const seat = &node.data; @@ -503,5 +503,5 @@ pub fn handleLayoutNamespaceChange(self: *Self) void { } pub fn layoutNamespace(self: Self) []const u8 { - return self.layout_namespace orelse self.root.server.config.default_layout_namespace; + return self.layout_namespace orelse server.config.default_layout_namespace; } diff --git a/river/Root.zig b/river/Root.zig index 68994c0..10a5f37 100644 --- a/river/Root.zig +++ b/river/Root.zig @@ -23,10 +23,10 @@ const assert = std.debug.assert; const wlr = @import("wlroots"); const wl = @import("wayland").server.wl; +const server = &@import("main.zig").server; const util = @import("util.zig"); const Output = @import("Output.zig"); -const Server = @import("Server.zig"); const View = @import("View.zig"); const ViewStack = @import("view_stack.zig").ViewStack; const XwaylandUnmanaged = @import("XwaylandUnmanaged.zig"); @@ -40,7 +40,6 @@ const DragIcon = @import("DragIcon.zig"); // encountered during normal usage. const min_size = 50; -server: *Server, new_output: wl.Listener(*wlr.Output) = wl.Listener(*wlr.Output).init(handleNewOutput), output_layout: *wlr.OutputLayout, @@ -76,7 +75,7 @@ xwayland_unmanaged_views: if (build_options.xwayland) std.TailQueue(XwaylandUnmanaged) else void = if (build_options.xwayland) - .{}, +.{}, /// Number of layout demands pending before the transaction may be started. pending_layout_demands: u32 = 0, @@ -86,7 +85,7 @@ pending_configures: u32 = 0, /// Handles timeout of transactions transaction_timer: *wl.EventSource, -pub fn init(self: *Self, server: *Server) !void { +pub fn init(self: *Self) !void { const output_layout = try wlr.OutputLayout.create(); errdefer output_layout.destroy(); @@ -97,7 +96,6 @@ pub fn init(self: *Self, server: *Server) !void { errdefer transaction_timer.remove(); self.* = .{ - .server = server, .output_layout = output_layout, .output_manager = try wlr.OutputManagerV1.create(server.wl_server), .power_manager = try wlr.OutputPowerManagerV1.create(server.wl_server), @@ -200,7 +198,7 @@ pub fn removeOutput(self: *Self, output: *Output) void { } // If any seat has the removed output focused, focus the fallback one - var seat_it = self.server.input_manager.seats.first; + var seat_it = server.input_manager.seats.first; while (seat_it) |seat_node| : (seat_it = seat_node.next) { const seat = &seat_node.data; if (seat.focused_output == output) { @@ -241,7 +239,7 @@ pub fn addOutput(self: *Self, output: *Output) void { while (self.noop_output.views.last) |n| n.view.sendToOutput(output); // Focus the new output with all seats - var it = self.server.input_manager.seats.first; + var it = server.input_manager.seats.first; while (it) |seat_node| : (it = seat_node.next) { const seat = &seat_node.data; seat.focusOutput(output); diff --git a/river/Server.zig b/river/Server.zig index 87b6922..d7ed2c4 100644 --- a/river/Server.zig +++ b/river/Server.zig @@ -113,7 +113,7 @@ pub fn init(self: *Self) !void { self.config = try Config.init(); try self.decoration_manager.init(self); - try self.root.init(self); + try self.root.init(); // Must be called after root is initialized try self.input_manager.init(self); try self.control.init(self); diff --git a/river/View.zig b/river/View.zig index 0606cc3..8ab0eff 100644 --- a/river/View.zig +++ b/river/View.zig @@ -24,6 +24,7 @@ const os = std.os; const wlr = @import("wlroots"); const wl = @import("wayland").server.wl; +const server = &@import("main.zig").server; const util = @import("util.zig"); const Box = @import("Box.zig"); @@ -147,14 +148,14 @@ pub fn init(self: *Self, output: *Output, tags: u32, surface: anytype) void { .output = output, .current = .{ .tags = tags, - .target_opacity = output.root.server.config.opacity.initial, + .target_opacity = server.config.opacity.initial, }, .pending = .{ .tags = tags, - .target_opacity = output.root.server.config.opacity.initial, + .target_opacity = server.config.opacity.initial, }, .saved_buffers = std.ArrayList(SavedBuffer).init(util.gpa), - .opacity = output.root.server.config.opacity.initial, + .opacity = server.config.opacity.initial, }; if (@TypeOf(surface) == *wlr.XdgSurface) { @@ -228,9 +229,9 @@ pub fn applyPending(self: *Self) void { // Restore configured opacity self.pending.target_opacity = if (self.pending.focus > 0) - self.output.root.server.config.opacity.focused + server.config.opacity.focused else - self.output.root.server.config.opacity.unfocused; + server.config.opacity.unfocused; } if (arrange_output) self.output.arrangeViews(); @@ -339,7 +340,6 @@ pub fn close(self: Self) void { .xwayland_view => |xwayland_view| xwayland_view.close(), } } - pub inline fn forEachPopupSurface( self: Self, comptime T: type, @@ -396,8 +396,7 @@ pub fn getConstraints(self: Self) Constraints { /// Modify the pending x/y of the view by the given deltas, clamping to the /// bounds of the output. pub fn move(self: *Self, delta_x: i32, delta_y: i32) void { - const config = &self.output.root.server.config; - const border_width = if (self.draw_borders) @intCast(i32, config.border_width) else 0; + const border_width = if (self.draw_borders) @intCast(i32, server.config.border_width) else 0; const output_resolution = self.output.getEffectiveResolution(); const max_x = @intCast(i32, output_resolution.width) - @intCast(i32, self.pending.box.width) - border_width; @@ -445,15 +444,13 @@ pub fn shouldTrackConfigure(self: Self) bool { /// Called by the impl when the surface is ready to be displayed pub fn map(self: *Self) void { - const root = self.output.root; - - self.pending.target_opacity = self.output.root.server.config.opacity.unfocused; + self.pending.target_opacity = server.config.opacity.unfocused; log.debug("view '{}' mapped", .{self.getTitle()}); if (self.foreign_toplevel_handle == null) { self.foreign_toplevel_handle = wlr.ForeignToplevelHandleV1.create( - root.server.foreign_toplevel_manager, + server.foreign_toplevel_manager, ) catch { log.crit("out of memory", .{}); self.surface.?.resource.getClient().postNoMemory(); @@ -476,7 +473,7 @@ pub fn map(self: *Self) void { // Focus the new view, assuming the seat is focusing the proper output // and there isn't something else like a fullscreen view grabbing focus. - var it = root.server.input_manager.seats.first; + var it = server.input_manager.seats.first; while (it) |seat_node| : (it = seat_node.next) seat_node.data.focus(self); self.surface.?.sendEnter(self.output.wlr_output); @@ -502,7 +499,7 @@ pub fn unmap(self: *Self) void { } // Inform all seats that the view has been unmapped so they can handle focus - var it = root.server.input_manager.seats.first; + var it = server.input_manager.seats.first; while (it) |node| : (it = node.next) { const seat = &node.data; seat.handleViewUnmap(self); @@ -521,7 +518,7 @@ pub fn notifyTitle(self: Self) void { if (self.getTitle()) |s| handle.setTitle(s); } // Send title to all status listeners attached to a seat which focuses this view - var seat_it = self.output.root.server.input_manager.seats.first; + var seat_it = server.input_manager.seats.first; while (seat_it) |seat_node| : (seat_it = seat_node.next) { if (seat_node.data.focused == .view and seat_node.data.focused.view == &self) { var client_it = seat_node.data.status_trackers.first; @@ -542,12 +539,11 @@ pub fn notifyAppId(self: Self) void { /// If the target opacity was reached, return true. fn incrementOpacity(self: *Self) bool { // TODO damage view when implementing damage based rendering - const config = &self.output.root.server.config; if (self.opacity < self.current.target_opacity) { - self.opacity += config.opacity.delta; + self.opacity += server.config.opacity.delta; if (self.opacity < self.current.target_opacity) return false; } else { - self.opacity -= config.opacity.delta; + self.opacity -= server.config.opacity.delta; if (self.opacity > self.current.target_opacity) return false; } self.opacity = self.current.target_opacity; @@ -562,7 +558,7 @@ fn killOpacityTimer(self: *Self) void { /// Set the timeout on a views opacity timer fn armOpacityTimer(self: *Self) void { - const delta_t = self.output.root.server.config.opacity.delta_t; + const delta_t = server.config.opacity.delta_t; self.opacity_timer.?.timerUpdate(delta_t) catch |err| { log.err("failed to update opacity timer: {}", .{err}); self.killOpacityTimer(); @@ -581,7 +577,7 @@ fn handleOpacityTimer(self: *Self) callconv(.C) c_int { /// Create an opacity timer for a view and arm it fn attachOpacityTimer(self: *Self) void { - const event_loop = self.output.root.server.wl_server.getEventLoop(); + const event_loop = server.wl_server.getEventLoop(); self.opacity_timer = event_loop.addTimer(*Self, handleOpacityTimer, self) catch { log.err("failed to create opacity timer for view '{}'", .{self.getTitle()}); return; diff --git a/river/XdgToplevel.zig b/river/XdgToplevel.zig index c8b278f..d1fb414 100644 --- a/river/XdgToplevel.zig +++ b/river/XdgToplevel.zig @@ -21,6 +21,7 @@ const std = @import("std"); const wlr = @import("wlroots"); const wl = @import("wayland").server.wl; +const server = &@import("main.zig").server; const util = @import("util.zig"); const Box = @import("Box.zig"); @@ -103,7 +104,6 @@ pub fn configure(self: Self) void { pub fn close(self: Self) void { self.xdg_surface.role_data.toplevel.sendClose(); } - pub inline fn forEachPopupSurface( self: Self, comptime T: type, @@ -157,7 +157,6 @@ fn handleDestroy(listener: *wl.Listener(*wlr.XdgSurface), xdg_surface: *wlr.XdgS fn handleMap(listener: *wl.Listener(*wlr.XdgSurface), xdg_surface: *wlr.XdgSurface) void { const self = @fieldParentPtr(Self, "map", listener); const view = self.view; - const root = view.output.root; const toplevel = self.xdg_surface.role_data.toplevel; // Add listeners that are only active while mapped @@ -198,7 +197,7 @@ fn handleMap(listener: *wl.Listener(*wlr.XdgSurface), xdg_surface: *wlr.XdgSurfa view.pending.box = view.float_box; } else { // Make views with app_ids listed in the float filter float - for (root.server.config.float_filter.items) |filter_app_id| { + for (server.config.float_filter.items) |filter_app_id| { if (std.mem.eql(u8, std.mem.span(app_id), std.mem.span(filter_app_id))) { view.current.float = true; view.pending.float = true; @@ -210,7 +209,7 @@ fn handleMap(listener: *wl.Listener(*wlr.XdgSurface), xdg_surface: *wlr.XdgSurfa // If the toplevel has an app_id which is not configured to use client side // decorations, inform it that it is tiled. - for (root.server.config.csd_filter.items) |filter_app_id| { + for (server.config.csd_filter.items) |filter_app_id| { if (std.mem.eql(u8, std.mem.span(app_id), filter_app_id)) { view.draw_borders = false; break; @@ -225,7 +224,6 @@ fn handleMap(listener: *wl.Listener(*wlr.XdgSurface), xdg_surface: *wlr.XdgSurfa /// Called when the surface is unmapped and will no longer be displayed. fn handleUnmap(listener: *wl.Listener(*wlr.XdgSurface), xdg_surface: *wlr.XdgSurface) void { const self = @fieldParentPtr(Self, "unmap", listener); - const root = self.view.output.root; self.view.unmap(); diff --git a/river/XwaylandView.zig b/river/XwaylandView.zig index 31987c1..ba383a3 100644 --- a/river/XwaylandView.zig +++ b/river/XwaylandView.zig @@ -22,6 +22,8 @@ const math = std.math; const wlr = @import("wlroots"); const wl = @import("wayland").server.wl; +const server = &@import("main.zig").server; + const Box = @import("Box.zig"); const View = @import("View.zig"); const ViewStack = @import("view_stack.zig").ViewStack; @@ -187,7 +189,7 @@ fn handleMap(listener: *wl.Listener(*wlr.XwaylandSurface), xwayland_surface: *wl view.pending.box = view.float_box; } else { // Make views with app_ids listed in the float filter float - for (root.server.config.float_filter.items) |filter_app_id| { + for (server.config.float_filter.items) |filter_app_id| { if (std.mem.eql(u8, std.mem.span(app_id), std.mem.span(filter_app_id))) { view.current.float = true; view.pending.float = true; diff --git a/river/command/move.zig b/river/command/move.zig index c089f1f..245b4b3 100644 --- a/river/command/move.zig +++ b/river/command/move.zig @@ -17,6 +17,8 @@ const std = @import("std"); +const server = &@import("../main.zig").server; + const Error = @import("../command.zig").Error; const PhysicalDirection = @import("../command.zig").PhysicalDirection; const Orientation = @import("../command.zig").Orientation; @@ -61,7 +63,7 @@ pub fn snap( return Error.InvalidPhysicalDirection; const view = getView(seat) orelse return; - const border_width = @intCast(i32, view.output.root.server.config.border_width); + const border_width = @intCast(i32, server.config.border_width); const output_box = view.output.getEffectiveResolution(); switch (direction) { .up => view.pending.box.y = border_width, @@ -89,7 +91,7 @@ pub fn resize( return Error.InvalidOrientation; const view = getView(seat) orelse return; - const border_width = @intCast(i32, view.output.root.server.config.border_width); + const border_width = @intCast(i32, server.config.border_width); const output_box = view.output.getEffectiveResolution(); switch (orientation) { .horizontal => { diff --git a/river/render.zig b/river/render.zig index 7357ed0..1e870e2 100644 --- a/river/render.zig +++ b/river/render.zig @@ -22,6 +22,7 @@ const wlr = @import("wlroots"); const wl = @import("wayland").server.wl; const pixman = @import("pixman"); +const server = &@import("main.zig").server; const util = @import("util.zig"); const Box = @import("Box.zig"); @@ -47,7 +48,6 @@ const SurfaceRenderData = struct { /// The rendering order in this function must be kept in sync with Cursor.surfaceAt() pub fn renderOutput(output: *Output) void { - const config = &output.root.server.config; const renderer = output.wlr_output.backend.getRenderer().?; var now: os.timespec = undefined; @@ -72,7 +72,7 @@ pub fn renderOutput(output: *Output) void { if (!view.destroying) renderViewPopups(output, view, &now); } else { // No fullscreen view, so render normal layers/views - renderer.clear(&config.background_color); + renderer.clear(&server.config.background_color); renderLayer(output, output.getLayer(.background).*, &now, .toplevels); renderLayer(output, output.getLayer(.bottom).*, &now, .toplevels); @@ -324,7 +324,7 @@ fn renderTexture( } fn renderBorders(output: *const Output, view: *View, now: *os.timespec) void { - const config = &output.root.server.config; + const config = &server.config; const color = if (view.current.focus != 0) &config.border_color_focused else &config.border_color_unfocused; const border_width = config.border_width; const actual_box = if (view.saved_buffers.items.len != 0) view.saved_surface_box else view.surface_box;