From c5de1641dc5574d13fad67ffdcf36c2b0def7585 Mon Sep 17 00:00:00 2001 From: Isaac Freund Date: Tue, 16 Jun 2020 22:08:36 +0200 Subject: [PATCH] code: create util.allocator and use globally river is not a library and passing a general purpose allocators around everywhere does not make sense and leads to ugly code. This does not prevent us from using local arenas if they are fitting. --- river/Config.zig | 15 ++++++++------- river/Control.zig | 20 ++++++++------------ river/Decoration.zig | 4 ++-- river/DecorationManager.zig | 5 +---- river/InputManager.zig | 4 ++-- river/LayerSurface.zig | 5 ++--- river/Output.zig | 32 +++++++++++++++++++------------- river/Root.zig | 2 +- river/Seat.zig | 17 +++++++---------- river/Server.zig | 18 +++++++----------- river/StatusManager.zig | 8 ++++---- river/View.zig | 11 +++-------- river/XdgPopup.zig | 6 ++---- river/XdgToplevel.zig | 3 +-- river/XwaylandUnmanaged.zig | 2 +- river/main.zig | 5 +++-- river/util.zig | 5 +++++ 17 files changed, 76 insertions(+), 86 deletions(-) diff --git a/river/Config.zig b/river/Config.zig index c0355ba..9791019 100644 --- a/river/Config.zig +++ b/river/Config.zig @@ -20,6 +20,7 @@ const Self = @This(); const std = @import("std"); const c = @import("c.zig"); +const util = @import("util.zig"); const Log = @import("log.zig").Log; const Server = @import("Server.zig"); @@ -49,29 +50,29 @@ modes: std.ArrayList(std.ArrayList(Mapping)), /// List of app_ids which will be started floating float_filter: std.ArrayList([*:0]const u8), -pub fn init(self: *Self, allocator: *std.mem.Allocator) !void { +pub fn init(self: *Self) !void { self.border_width = 2; self.border_color_focused = [_]f32{ 0.57647059, 0.63137255, 0.63137255, 1.0 }; // Solarized base1 self.border_color_unfocused = [_]f32{ 0.34509804, 0.43137255, 0.45882353, 1.0 }; // Solarized base0 self.view_padding = 8; self.outer_padding = 8; - self.mode_to_id = std.StringHashMap(usize).init(allocator); + self.mode_to_id = std.StringHashMap(usize).init(util.allocator); try self.mode_to_id.putNoClobber("normal", 0); - self.modes = std.ArrayList(std.ArrayList(Mapping)).init(allocator); - try self.modes.append(std.ArrayList(Mapping).init(allocator)); + self.modes = std.ArrayList(std.ArrayList(Mapping)).init(util.allocator); + try self.modes.append(std.ArrayList(Mapping).init(util.allocator)); - self.float_filter = std.ArrayList([*:0]const u8).init(allocator); + self.float_filter = std.ArrayList([*:0]const u8).init(util.allocator); // Float views with app_id "float" try self.float_filter.append("float"); } -pub fn deinit(self: Self, allocator: *std.mem.Allocator) void { +pub fn deinit(self: Self) void { self.mode_to_id.deinit(); for (self.modes.items) |mode| { - for (mode.items) |mapping| mapping.deinit(allocator); + for (mode.items) |mapping| mapping.deinit(util.allocator); mode.deinit(); } self.modes.deinit(); diff --git a/river/Control.zig b/river/Control.zig index 3da1f28..5a8657a 100644 --- a/river/Control.zig +++ b/river/Control.zig @@ -35,7 +35,6 @@ const implementation = c.struct_zriver_control_v1_interface{ .run_command = runCommand, }; -server: *Server, wl_global: *c.wl_global, args_map: std.AutoHashMap(u32, std.ArrayList([]const u8)), @@ -43,7 +42,6 @@ args_map: std.AutoHashMap(u32, std.ArrayList([]const u8)), listen_display_destroy: c.wl_listener, pub fn init(self: *Self, server: *Server) !void { - self.server = server; self.wl_global = c.wl_global_create( server.wl_display, &c.zriver_control_v1_interface, @@ -52,7 +50,7 @@ pub fn init(self: *Self, server: *Server) !void { bind, ) orelse return error.CantCreateWlGlobal; - self.args_map = std.AutoHashMap(u32, std.ArrayList([]const u8)).init(server.allocator); + self.args_map = std.AutoHashMap(u32, std.ArrayList([]const u8)).init(util.allocator); self.listen_display_destroy.notify = handleDisplayDestroy; c.wl_display_add_destroy_listener(server.wl_display, &self.listen_display_destroy); @@ -76,7 +74,7 @@ fn bind(wl_client: ?*c.wl_client, data: ?*c_void, version: u32, id: u32) callcon c.wl_client_post_no_memory(wl_client); return; }; - self.args_map.putNoClobber(id, std.ArrayList([]const u8).init(self.server.allocator)) catch { + self.args_map.putNoClobber(id, std.ArrayList([]const u8).init(util.allocator)) catch { c.wl_resource_destroy(wl_resource); c.wl_client_post_no_memory(wl_client); return; @@ -100,16 +98,15 @@ fn destroy(wl_client: ?*c.wl_client, wl_resource: ?*c.wl_resource) callconv(.C) fn addArgument(wl_client: ?*c.wl_client, wl_resource: ?*c.wl_resource, arg: ?[*:0]const u8) callconv(.C) void { const self = util.voidCast(Self, c.wl_resource_get_user_data(wl_resource).?); const id = c.wl_resource_get_id(wl_resource); - const allocator = self.server.allocator; - const owned_slice = std.mem.dupe(allocator, u8, std.mem.span(arg.?)) catch { + const owned_slice = std.mem.dupe(util.allocator, u8, std.mem.span(arg.?)) catch { c.wl_client_post_no_memory(wl_client); return; }; self.args_map.get(id).?.value.append(owned_slice) catch { c.wl_client_post_no_memory(wl_client); - allocator.free(owned_slice); + util.allocator.free(owned_slice); return; }; } @@ -124,7 +121,6 @@ fn runCommand( // This can be null if the seat is inert, in which case we ignore the request const wlr_seat_client = c.wlr_seat_client_from_resource(seat_wl_resource) orelse return; const seat = util.voidCast(Seat, wlr_seat_client.*.seat.*.data.?); - const allocator = self.server.allocator; const callback_resource = c.wl_resource_create( wl_client, @@ -140,14 +136,14 @@ fn runCommand( const args = self.args_map.get(c.wl_resource_get_id(wl_resource)).?.value.items; var failure_message: []const u8 = undefined; - command.run(allocator, seat, args, &failure_message) catch |err| { + command.run(util.allocator, seat, args, &failure_message) catch |err| { if (err == command.Error.CommandFailed) { - defer allocator.free(failure_message); - const out = std.cstr.addNullByte(allocator, failure_message) catch { + defer util.allocator.free(failure_message); + const out = std.cstr.addNullByte(util.allocator, failure_message) catch { c.zriver_command_callback_v1_send_failure(callback_resource, "out of memory"); return; }; - defer allocator.free(out); + defer util.allocator.free(out); c.zriver_command_callback_v1_send_failure(callback_resource, out); } else { c.zriver_command_callback_v1_send_failure( diff --git a/river/Decoration.zig b/river/Decoration.zig index b96450c..149fe8d 100644 --- a/river/Decoration.zig +++ b/river/Decoration.zig @@ -20,6 +20,7 @@ const Self = @This(); const std = @import("std"); const c = @import("c.zig"); +const util = @import("util.zig"); const DecorationManager = @import("DecorationManager.zig"); @@ -49,11 +50,10 @@ pub fn init( fn handleDestroy(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void { const self = @fieldParentPtr(Self, "listen_destroy", listener.?); - const allocator = self.decoration_manager.server.allocator; const node = @fieldParentPtr(std.SinglyLinkedList(Self).Node, "data", self); self.decoration_manager.decorations.remove(node); - allocator.destroy(node); + util.allocator.destroy(node); } fn handleRequestMode(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void { diff --git a/river/DecorationManager.zig b/river/DecorationManager.zig index 0e280d1..4a78025 100644 --- a/river/DecorationManager.zig +++ b/river/DecorationManager.zig @@ -25,8 +25,6 @@ const util = @import("util.zig"); const Decoration = @import("Decoration.zig"); const Server = @import("Server.zig"); -server: *Server, - wlr_xdg_decoration_manager: *c.wlr_xdg_decoration_manager_v1, decorations: std.SinglyLinkedList(Decoration), @@ -34,7 +32,6 @@ decorations: std.SinglyLinkedList(Decoration), listen_new_toplevel_decoration: c.wl_listener, pub fn init(self: *Self, server: *Server) !void { - self.server = server; self.wlr_xdg_decoration_manager = c.wlr_xdg_decoration_manager_v1_create(server.wl_display) orelse return error.CantCreateWlrXdgDecorationManager; @@ -49,7 +46,7 @@ fn handleNewToplevelDecoration(listener: ?*c.wl_listener, data: ?*c_void) callco const self = @fieldParentPtr(Self, "listen_new_toplevel_decoration", listener.?); const wlr_xdg_toplevel_decoration = util.voidCast(c.wlr_xdg_toplevel_decoration_v1, data.?); - const node = self.decorations.allocateNode(self.server.allocator) catch unreachable; + const node = self.decorations.allocateNode(util.allocator) catch unreachable; node.data.init(self, wlr_xdg_toplevel_decoration); self.decorations.prepend(node); } diff --git a/river/InputManager.zig b/river/InputManager.zig index 62acc2d..7c1337c 100644 --- a/river/InputManager.zig +++ b/river/InputManager.zig @@ -51,7 +51,7 @@ pub fn init(self: *Self, server: *Server) !void { self.seats = std.TailQueue(Seat).init(); - const seat_node = try server.allocator.create(std.TailQueue(Seat).Node); + const seat_node = try util.allocator.create(std.TailQueue(Seat).Node); try seat_node.data.init(self, default_seat_name); self.default_seat = &seat_node.data; self.seats.prepend(seat_node); @@ -78,7 +78,7 @@ pub fn init(self: *Self, server: *Server) !void { pub fn deinit(self: *Self) void { while (self.seats.pop()) |seat_node| { seat_node.data.deinit(); - self.server.allocator.destroy(seat_node); + util.allocator.destroy(seat_node); } } diff --git a/river/LayerSurface.zig b/river/LayerSurface.zig index c33678f..6fa6822 100644 --- a/river/LayerSurface.zig +++ b/river/LayerSurface.zig @@ -87,7 +87,7 @@ fn handleDestroy(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void { c.wl_list_remove(&self.listen_unmap.link); const node = @fieldParentPtr(std.TailQueue(Self).Node, "data", self); - output.root.server.allocator.destroy(node); + util.allocator.destroy(node); } fn handleMap(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void { @@ -189,9 +189,8 @@ fn handleCommit(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void { fn handleNewPopup(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void { const self = @fieldParentPtr(Self, "listen_new_popup", listener.?); const wlr_xdg_popup = util.voidCast(c.wlr_xdg_popup, data.?); - const allocator = self.output.root.server.allocator; // This will free itself on destroy - var xdg_popup = allocator.create(XdgPopup) catch unreachable; + var xdg_popup = util.allocator.create(XdgPopup) catch unreachable; xdg_popup.init(self.output, &self.box, wlr_xdg_popup); } diff --git a/river/Output.zig b/river/Output.zig index bc125b8..67c70e7 100644 --- a/river/Output.zig +++ b/river/Output.zig @@ -22,6 +22,7 @@ const std = @import("std"); const c = @import("c.zig"); const render = @import("render.zig"); +const util = @import("util.zig"); const Box = @import("Box.zig"); const LayerSurface = @import("LayerSurface.zig"); @@ -30,7 +31,8 @@ const Root = @import("Root.zig"); const View = @import("View.zig"); const ViewStack = @import("view_stack.zig").ViewStack; const OutputStatus = @import("OutputStatus.zig"); -/// Minimum width/height for surfaces. + +// Minimum width/height for surfaces. // This is needed, because external layouts and large padding and border sizes // may cause surfaces so small, that bugs in client applications are encountered, // or even surfaces of zero or negative size,which are a protocol error and would @@ -109,7 +111,7 @@ pub fn init(self: *Self, root: *Root, wlr_output: *c.wlr_output) !void { self.master_factor = 0.6; - self.layout = try std.fmt.allocPrint(self.root.server.allocator, "full", .{}); + self.layout = try std.fmt.allocPrint(util.allocator, "full", .{}); self.status_trackers = std.SinglyLinkedList(OutputStatus).init(); @@ -226,8 +228,6 @@ test "parse window configuration" { /// Execute an external layout function, parse its output and apply the layout /// to the output. fn layoutExternal(self: *Self, visible_count: u32, output_tags: u32) !void { - const allocator = self.root.server.allocator; - const border_width = self.root.server.config.border_width; const view_padding = self.root.server.config.view_padding; const outer_padding = self.root.server.config.outer_padding; @@ -237,13 +237,19 @@ fn layoutExternal(self: *Self, visible_count: u32, output_tags: u32) !void { const layout_height = @intCast(u32, self.usable_box.height) - outer_padding * 2; // Assemble command - const parameters = std.fmt.allocPrint(allocator, "{} {} {d} {} {}", .{ visible_count, self.master_count, self.master_factor, layout_width, layout_height }) catch @panic("Out of memory."); - defer allocator.free(parameters); - const layout_command = try std.mem.join(allocator, " ", &[_][]const u8{ + const parameters = std.fmt.allocPrint(util.allocator, "{} {} {d} {} {}", .{ + visible_count, + self.master_count, + self.master_factor, + layout_width, + layout_height, + }) catch @panic("Out of memory."); + defer util.allocator.free(parameters); + const layout_command = try std.mem.join(util.allocator, " ", &[_][]const u8{ self.layout, parameters, }); - defer allocator.free(layout_command); + defer util.allocator.free(layout_command); const cmd = [_][]const u8{ "/bin/sh", "-c", @@ -252,14 +258,14 @@ fn layoutExternal(self: *Self, visible_count: u32, output_tags: u32) !void { // Execute layout executable // TODO abort after 1 second - const child = try std.ChildProcess.init(&cmd, allocator); + const child = try std.ChildProcess.init(&cmd, util.allocator); defer child.deinit(); child.stdin_behavior = .Ignore; child.stdout_behavior = .Pipe; try std.ChildProcess.spawn(child); const max_output_size = 400 * 1024; - const buffer = try child.stdout.?.inStream().readAllAlloc(allocator, max_output_size); - defer allocator.free(buffer); + const buffer = try child.stdout.?.inStream().readAllAlloc(util.allocator, max_output_size); + defer util.allocator.free(buffer); const term = try child.wait(); switch (term) { .Exited, .Signal, .Stopped, .Unknown => |code| { @@ -270,7 +276,7 @@ fn layoutExternal(self: *Self, visible_count: u32, output_tags: u32) !void { } // Parse layout command output - var view_boxen = std.ArrayList(Box).init(self.root.server.allocator); + var view_boxen = std.ArrayList(Box).init(util.allocator); defer view_boxen.deinit(); var parse_it = std.mem.split(buffer, "\n"); while (parse_it.next()) |token| { @@ -621,7 +627,7 @@ fn handleDestroy(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void { // Remove the destroyed output from the list const node = @fieldParentPtr(std.TailQueue(Self).Node, "data", self); root.outputs.remove(node); - root.server.allocator.destroy(node); + util.allocator.destroy(node); // Arrange the root in case evacuated views affect the layout root.arrange(); diff --git a/river/Root.zig b/river/Root.zig index 806d0a5..70a1426 100644 --- a/river/Root.zig +++ b/river/Root.zig @@ -95,7 +95,7 @@ pub fn deinit(self: *Self) void { pub fn addOutput(self: *Self, wlr_output: *c.wlr_output) void { // TODO: Handle failure - const node = self.outputs.allocateNode(self.server.allocator) catch unreachable; + const node = self.outputs.allocateNode(util.allocator) catch unreachable; node.data.init(self, wlr_output) catch unreachable; self.outputs.append(node); diff --git a/river/Seat.zig b/river/Seat.zig index 40d64a9..b2676c3 100644 --- a/river/Seat.zig +++ b/river/Seat.zig @@ -103,13 +103,11 @@ pub fn init(self: *Self, input_manager: *InputManager, name: []const u8) !void { pub fn deinit(self: *Self) void { self.cursor.deinit(); - while (self.keyboards.pop()) |node| { - self.input_manager.server.allocator.destroy(node); - } + while (self.keyboards.pop()) |node| util.allocator.destroy(node); while (self.focus_stack.first) |node| { self.focus_stack.remove(node); - self.input_manager.server.allocator.destroy(node); + util.allocator.destroy(node); } } @@ -154,7 +152,7 @@ pub fn focus(self: *Self, _view: ?*View) void { } } else { // The view is not in the stack, so allocate a new node and prepend it - const new_focus_node = self.input_manager.server.allocator.create( + const new_focus_node = util.allocator.create( ViewStack(*View).Node, ) catch unreachable; new_focus_node.view = view_to_focus; @@ -258,7 +256,7 @@ pub fn handleViewUnmap(self: *Self, view: *View) void { while (it) |node| : (it = node.next) { if (node.view == view) { self.focus_stack.remove(node); - self.input_manager.server.allocator.destroy(node); + util.allocator.destroy(node); break; } } @@ -278,12 +276,11 @@ pub fn handleMapping(self: *Self, keysym: c.xkb_keysym_t, modifiers: u32) bool { for (modes.items[self.mode_id].items) |mapping| { if (modifiers == mapping.modifiers and keysym == mapping.keysym) { // Execute the bound command - const allocator = self.input_manager.server.allocator; var failure_message: []const u8 = undefined; - command.run(allocator, self, mapping.command_args, &failure_message) catch |err| { + command.run(util.allocator, self, mapping.command_args, &failure_message) catch |err| { // TODO: log the error if (err == command.Error.CommandFailed) - allocator.free(failure_message); + util.allocator.free(failure_message); }; return true; } @@ -314,7 +311,7 @@ pub fn addDevice(self: *Self, device: *c.wlr_input_device) !void { fn addKeyboard(self: *Self, device: *c.wlr_input_device) !void { c.wlr_seat_set_keyboard(self.wlr_seat, device); - const node = try self.keyboards.allocateNode(self.input_manager.server.allocator); + const node = try util.allocator.create(std.TailQueue(Keyboard).Node); try node.data.init(self, device); self.keyboards.append(node); } diff --git a/river/Server.zig b/river/Server.zig index 27eebba..6f99d18 100644 --- a/river/Server.zig +++ b/river/Server.zig @@ -36,8 +36,6 @@ const View = @import("View.zig"); const ViewStack = @import("view_stack.zig").ViewStack; const XwaylandUnmanaged = @import("XwaylandUnmanaged.zig"); -allocator: *std.mem.Allocator, - wl_display: *c.wl_display, wl_event_loop: *c.wl_event_loop, @@ -61,9 +59,7 @@ config: Config, control: Control, status_manager: StatusManager, -pub fn init(self: *Self, allocator: *std.mem.Allocator) !void { - self.allocator = allocator; - +pub fn init(self: *Self) !void { // The Wayland display is managed by libwayland. It handles accepting // clients from the Unix socket, managing Wayland globals, and so on. self.wl_display = c.wl_display_create() orelse @@ -120,7 +116,7 @@ pub fn init(self: *Self, allocator: *std.mem.Allocator) !void { c.wl_signal_add(&self.wlr_xwayland.events.new_surface, &self.listen_new_xwayland_surface); } - try self.config.init(self.allocator); + try self.config.init(); try self.decoration_manager.init(self); try self.root.init(self); // Must be called after root is initialized @@ -150,7 +146,7 @@ pub fn deinit(self: *Self) void { c.river_wlr_backend_destory(self.noop_backend); self.input_manager.deinit(); - self.config.deinit(self.allocator); + self.config.deinit(); } /// Create the socket, set WAYLAND_DISPLAY, and start the backend @@ -204,7 +200,7 @@ fn handleNewXdgSurface(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) v // The View will add itself to the output's view stack on map const output = self.input_manager.default_seat.focused_output; - const node = self.allocator.create(ViewStack(View).Node) catch unreachable; + const node = util.allocator.create(ViewStack(View).Node) catch unreachable; node.view.init(output, output.current_focused_tags, wlr_xdg_surface); } @@ -251,7 +247,7 @@ fn handleNewLayerSurface(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) // The layer surface will add itself to the proper list of the output on map const output = util.voidCast(Output, wlr_layer_surface.output.*.data.?); - const node = self.allocator.create(std.TailQueue(LayerSurface).Node) catch unreachable; + const node = util.allocator.create(std.TailQueue(LayerSurface).Node) catch unreachable; node.data.init(output, wlr_layer_surface); } @@ -263,7 +259,7 @@ fn handleNewXwaylandSurface(listener: ?*c.wl_listener, data: ?*c_void) callconv( Log.Debug.log("New unmanaged xwayland surface", .{}); // The unmanged surface will add itself to the list of unmanaged views // in Root when it is mapped. - const node = self.allocator.create(std.TailQueue(XwaylandUnmanaged).Node) catch unreachable; + const node = util.allocator.create(std.TailQueue(XwaylandUnmanaged).Node) catch unreachable; node.data.init(&self.root, wlr_xwayland_surface); return; } @@ -275,6 +271,6 @@ fn handleNewXwaylandSurface(listener: ?*c.wl_listener, data: ?*c_void) callconv( // The View will add itself to the output's view stack on map const output = self.input_manager.default_seat.focused_output; - const node = self.allocator.create(ViewStack(View).Node) catch unreachable; + const node = util.allocator.create(ViewStack(View).Node) catch unreachable; node.view.init(output, output.current_focused_tags, wlr_xwayland_surface); } diff --git a/river/StatusManager.zig b/river/StatusManager.zig index 69f77fb..0fe3d6e 100644 --- a/river/StatusManager.zig +++ b/river/StatusManager.zig @@ -92,9 +92,8 @@ fn getRiverOutputStatus( // This can be null if the output is inert, in which case we ignore the request const wlr_output = c.wlr_output_from_resource(output_wl_resource) orelse return; const output = util.voidCast(Output, wlr_output.*.data.?); - const allocator = self.server.allocator; - const node = allocator.create(std.SinglyLinkedList(OutputStatus).Node) catch { + const node = util.allocator.create(std.SinglyLinkedList(OutputStatus).Node) catch { c.wl_client_post_no_memory(wl_client); Log.Error.log("out of memory\n", .{}); return; @@ -107,6 +106,7 @@ fn getRiverOutputStatus( new_id, ) orelse { c.wl_client_post_no_memory(wl_client); + util.allocator.destroy(node); Log.Error.log("out of memory\n", .{}); return; }; @@ -125,9 +125,8 @@ fn getRiverSeatStatus( // This can be null if the seat is inert, in which case we ignore the request const wlr_seat_client = c.wlr_seat_client_from_resource(seat_wl_resource) orelse return; const seat = util.voidCast(Seat, wlr_seat_client.*.seat.*.data.?); - const allocator = self.server.allocator; - const node = allocator.create(std.SinglyLinkedList(SeatStatus).Node) catch { + const node = util.allocator.create(std.SinglyLinkedList(SeatStatus).Node) catch { c.wl_client_post_no_memory(wl_client); Log.Error.log("out of memory\n", .{}); return; @@ -140,6 +139,7 @@ fn getRiverSeatStatus( new_id, ) orelse { c.wl_client_post_no_memory(wl_client); + util.allocator.destroy(node); Log.Error.log("out of memory\n", .{}); return; }; diff --git a/river/View.zig b/river/View.zig index 6d6e147..0ff2344 100644 --- a/river/View.zig +++ b/river/View.zig @@ -88,12 +88,7 @@ pending_tags: ?u32, pending_serial: ?u32, -pub fn init( - self: *Self, - output: *Output, - tags: u32, - surface: var, -) void { +pub fn init(self: *Self, output: *Output, tags: u32, surface: var) void { self.output = output; self.wlr_surface = null; @@ -113,7 +108,7 @@ pub fn init( self.pending_serial = null; - self.saved_buffers = std.ArrayList(SavedBuffer).init(output.root.server.allocator); + self.saved_buffers = std.ArrayList(SavedBuffer).init(util.allocator); if (@TypeOf(surface) == *c.wlr_xdg_surface) { self.impl = .{ .xdg_toplevel = undefined }; @@ -323,5 +318,5 @@ pub fn unmap(self: *Self) void { pub fn destroy(self: *const Self) void { self.deinit(); const node = @fieldParentPtr(ViewStack(Self).Node, "view", self); - self.output.root.server.allocator.destroy(node); + util.allocator.destroy(node); } diff --git a/river/XdgPopup.zig b/river/XdgPopup.zig index d56b7a2..ca172ff 100644 --- a/river/XdgPopup.zig +++ b/river/XdgPopup.zig @@ -63,21 +63,19 @@ pub fn init( fn handleDestroy(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void { const self = @fieldParentPtr(Self, "listen_destroy", listener.?); - const allocator = self.output.root.server.allocator; c.wl_list_remove(&self.listen_destroy.link); c.wl_list_remove(&self.listen_new_popup.link); - allocator.destroy(self); + util.allocator.destroy(self); } /// Called when a new xdg popup is requested by the client fn handleNewPopup(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void { const self = @fieldParentPtr(Self, "listen_new_popup", listener.?); const wlr_xdg_popup = util.voidCast(c.wlr_xdg_popup, data.?); - const allocator = self.output.root.server.allocator; // This will free itself on destroy - var xdg_popup = allocator.create(Self) catch unreachable; + var xdg_popup = util.allocator.create(Self) catch unreachable; xdg_popup.init(self.output, self.parent_box, wlr_xdg_popup); } diff --git a/river/XdgToplevel.zig b/river/XdgToplevel.zig index f329d9a..a217742 100644 --- a/river/XdgToplevel.zig +++ b/river/XdgToplevel.zig @@ -244,9 +244,8 @@ fn handleCommit(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void { fn handleNewPopup(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void { const self = @fieldParentPtr(Self, "listen_new_popup", listener.?); const wlr_xdg_popup = util.voidCast(c.wlr_xdg_popup, data.?); - const allocator = self.view.output.root.server.allocator; // This will free itself on destroy - var xdg_popup = allocator.create(XdgPopup) catch unreachable; + var xdg_popup = util.allocator.create(XdgPopup) catch unreachable; xdg_popup.init(self.view.output, &self.view.current_box, wlr_xdg_popup); } diff --git a/river/XwaylandUnmanaged.zig b/river/XwaylandUnmanaged.zig index ca70fa8..f21f064 100644 --- a/river/XwaylandUnmanaged.zig +++ b/river/XwaylandUnmanaged.zig @@ -93,7 +93,7 @@ fn handleDestroy(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void { // Deallocate the node const node = @fieldParentPtr(std.TailQueue(Self).Node, "data", self); - self.root.server.allocator.destroy(node); + util.allocator.destroy(node); } /// Called when the xwayland surface is mapped, or ready to display on-screen. diff --git a/river/main.zig b/river/main.zig index 5b64241..0e95b5c 100644 --- a/river/main.zig +++ b/river/main.zig @@ -18,6 +18,7 @@ const std = @import("std"); const c = @import("c.zig"); +const util = @import("util.zig"); const Log = @import("log.zig").Log; const Server = @import("Server.zig"); @@ -63,14 +64,14 @@ pub fn main() !void { Log.Info.log("Initializing server", .{}); var server: Server = undefined; - try server.init(std.heap.c_allocator); + try server.init(); defer server.deinit(); try server.start(); if (startup_command) |cmd| { const child_args = [_][]const u8{ "/bin/sh", "-c", cmd }; - const child = try std.ChildProcess.init(&child_args, std.heap.c_allocator); + const child = try std.ChildProcess.init(&child_args, util.allocator); defer child.deinit(); try std.ChildProcess.spawn(child); } diff --git a/river/util.zig b/river/util.zig index c1064cb..28eb840 100644 --- a/river/util.zig +++ b/river/util.zig @@ -15,6 +15,11 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +const std = @import("std"); + +/// The global general-purpose allocator used throughout river's code +pub const allocator = std.heap.c_allocator; + /// Take a pointer to c_void and cast it to a pointer to T. This function /// exists to avoid having the verbosity of the required alignment casts all /// over the code.