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.
This commit is contained in:
Isaac Freund 2020-06-16 22:08:36 +02:00
parent fb8d855ec9
commit c5de1641dc
No known key found for this signature in database
GPG key ID: 86DED400DDFD7A11
17 changed files with 76 additions and 86 deletions

View file

@ -20,6 +20,7 @@ const Self = @This();
const std = @import("std"); const std = @import("std");
const c = @import("c.zig"); const c = @import("c.zig");
const util = @import("util.zig");
const Log = @import("log.zig").Log; const Log = @import("log.zig").Log;
const Server = @import("Server.zig"); const Server = @import("Server.zig");
@ -49,29 +50,29 @@ modes: std.ArrayList(std.ArrayList(Mapping)),
/// List of app_ids which will be started floating /// List of app_ids which will be started floating
float_filter: std.ArrayList([*:0]const u8), 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_width = 2;
self.border_color_focused = [_]f32{ 0.57647059, 0.63137255, 0.63137255, 1.0 }; // Solarized base1 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.border_color_unfocused = [_]f32{ 0.34509804, 0.43137255, 0.45882353, 1.0 }; // Solarized base0
self.view_padding = 8; self.view_padding = 8;
self.outer_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); try self.mode_to_id.putNoClobber("normal", 0);
self.modes = std.ArrayList(std.ArrayList(Mapping)).init(allocator); self.modes = std.ArrayList(std.ArrayList(Mapping)).init(util.allocator);
try self.modes.append(std.ArrayList(Mapping).init(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" // Float views with app_id "float"
try self.float_filter.append("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(); self.mode_to_id.deinit();
for (self.modes.items) |mode| { for (self.modes.items) |mode| {
for (mode.items) |mapping| mapping.deinit(allocator); for (mode.items) |mapping| mapping.deinit(util.allocator);
mode.deinit(); mode.deinit();
} }
self.modes.deinit(); self.modes.deinit();

View file

@ -35,7 +35,6 @@ const implementation = c.struct_zriver_control_v1_interface{
.run_command = runCommand, .run_command = runCommand,
}; };
server: *Server,
wl_global: *c.wl_global, wl_global: *c.wl_global,
args_map: std.AutoHashMap(u32, std.ArrayList([]const u8)), 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, listen_display_destroy: c.wl_listener,
pub fn init(self: *Self, server: *Server) !void { pub fn init(self: *Self, server: *Server) !void {
self.server = server;
self.wl_global = c.wl_global_create( self.wl_global = c.wl_global_create(
server.wl_display, server.wl_display,
&c.zriver_control_v1_interface, &c.zriver_control_v1_interface,
@ -52,7 +50,7 @@ pub fn init(self: *Self, server: *Server) !void {
bind, bind,
) orelse return error.CantCreateWlGlobal; ) 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; self.listen_display_destroy.notify = handleDisplayDestroy;
c.wl_display_add_destroy_listener(server.wl_display, &self.listen_display_destroy); 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); c.wl_client_post_no_memory(wl_client);
return; 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_resource_destroy(wl_resource);
c.wl_client_post_no_memory(wl_client); c.wl_client_post_no_memory(wl_client);
return; 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 { 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 self = util.voidCast(Self, c.wl_resource_get_user_data(wl_resource).?);
const id = c.wl_resource_get_id(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); c.wl_client_post_no_memory(wl_client);
return; return;
}; };
self.args_map.get(id).?.value.append(owned_slice) catch { self.args_map.get(id).?.value.append(owned_slice) catch {
c.wl_client_post_no_memory(wl_client); c.wl_client_post_no_memory(wl_client);
allocator.free(owned_slice); util.allocator.free(owned_slice);
return; return;
}; };
} }
@ -124,7 +121,6 @@ fn runCommand(
// This can be null if the seat is inert, in which case we ignore the request // 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 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 seat = util.voidCast(Seat, wlr_seat_client.*.seat.*.data.?);
const allocator = self.server.allocator;
const callback_resource = c.wl_resource_create( const callback_resource = c.wl_resource_create(
wl_client, wl_client,
@ -140,14 +136,14 @@ fn runCommand(
const args = self.args_map.get(c.wl_resource_get_id(wl_resource)).?.value.items; const args = self.args_map.get(c.wl_resource_get_id(wl_resource)).?.value.items;
var failure_message: []const u8 = undefined; 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) { if (err == command.Error.CommandFailed) {
defer allocator.free(failure_message); defer util.allocator.free(failure_message);
const out = std.cstr.addNullByte(allocator, failure_message) catch { const out = std.cstr.addNullByte(util.allocator, failure_message) catch {
c.zriver_command_callback_v1_send_failure(callback_resource, "out of memory"); c.zriver_command_callback_v1_send_failure(callback_resource, "out of memory");
return; return;
}; };
defer allocator.free(out); defer util.allocator.free(out);
c.zriver_command_callback_v1_send_failure(callback_resource, out); c.zriver_command_callback_v1_send_failure(callback_resource, out);
} else { } else {
c.zriver_command_callback_v1_send_failure( c.zriver_command_callback_v1_send_failure(

View file

@ -20,6 +20,7 @@ const Self = @This();
const std = @import("std"); const std = @import("std");
const c = @import("c.zig"); const c = @import("c.zig");
const util = @import("util.zig");
const DecorationManager = @import("DecorationManager.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 { fn handleDestroy(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void {
const self = @fieldParentPtr(Self, "listen_destroy", listener.?); const self = @fieldParentPtr(Self, "listen_destroy", listener.?);
const allocator = self.decoration_manager.server.allocator;
const node = @fieldParentPtr(std.SinglyLinkedList(Self).Node, "data", self); const node = @fieldParentPtr(std.SinglyLinkedList(Self).Node, "data", self);
self.decoration_manager.decorations.remove(node); 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 { fn handleRequestMode(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void {

View file

@ -25,8 +25,6 @@ const util = @import("util.zig");
const Decoration = @import("Decoration.zig"); const Decoration = @import("Decoration.zig");
const Server = @import("Server.zig"); const Server = @import("Server.zig");
server: *Server,
wlr_xdg_decoration_manager: *c.wlr_xdg_decoration_manager_v1, wlr_xdg_decoration_manager: *c.wlr_xdg_decoration_manager_v1,
decorations: std.SinglyLinkedList(Decoration), decorations: std.SinglyLinkedList(Decoration),
@ -34,7 +32,6 @@ decorations: std.SinglyLinkedList(Decoration),
listen_new_toplevel_decoration: c.wl_listener, listen_new_toplevel_decoration: c.wl_listener,
pub fn init(self: *Self, server: *Server) !void { 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 self.wlr_xdg_decoration_manager = c.wlr_xdg_decoration_manager_v1_create(server.wl_display) orelse
return error.CantCreateWlrXdgDecorationManager; 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 self = @fieldParentPtr(Self, "listen_new_toplevel_decoration", listener.?);
const wlr_xdg_toplevel_decoration = util.voidCast(c.wlr_xdg_toplevel_decoration_v1, data.?); 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); node.data.init(self, wlr_xdg_toplevel_decoration);
self.decorations.prepend(node); self.decorations.prepend(node);
} }

View file

@ -51,7 +51,7 @@ pub fn init(self: *Self, server: *Server) !void {
self.seats = std.TailQueue(Seat).init(); 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); try seat_node.data.init(self, default_seat_name);
self.default_seat = &seat_node.data; self.default_seat = &seat_node.data;
self.seats.prepend(seat_node); self.seats.prepend(seat_node);
@ -78,7 +78,7 @@ pub fn init(self: *Self, server: *Server) !void {
pub fn deinit(self: *Self) void { pub fn deinit(self: *Self) void {
while (self.seats.pop()) |seat_node| { while (self.seats.pop()) |seat_node| {
seat_node.data.deinit(); seat_node.data.deinit();
self.server.allocator.destroy(seat_node); util.allocator.destroy(seat_node);
} }
} }

View file

@ -87,7 +87,7 @@ fn handleDestroy(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void {
c.wl_list_remove(&self.listen_unmap.link); c.wl_list_remove(&self.listen_unmap.link);
const node = @fieldParentPtr(std.TailQueue(Self).Node, "data", self); 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 { 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 { fn handleNewPopup(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void {
const self = @fieldParentPtr(Self, "listen_new_popup", listener.?); const self = @fieldParentPtr(Self, "listen_new_popup", listener.?);
const wlr_xdg_popup = util.voidCast(c.wlr_xdg_popup, data.?); const wlr_xdg_popup = util.voidCast(c.wlr_xdg_popup, data.?);
const allocator = self.output.root.server.allocator;
// This will free itself on destroy // 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); xdg_popup.init(self.output, &self.box, wlr_xdg_popup);
} }

View file

@ -22,6 +22,7 @@ const std = @import("std");
const c = @import("c.zig"); const c = @import("c.zig");
const render = @import("render.zig"); const render = @import("render.zig");
const util = @import("util.zig");
const Box = @import("Box.zig"); const Box = @import("Box.zig");
const LayerSurface = @import("LayerSurface.zig"); const LayerSurface = @import("LayerSurface.zig");
@ -30,7 +31,8 @@ const Root = @import("Root.zig");
const View = @import("View.zig"); const View = @import("View.zig");
const ViewStack = @import("view_stack.zig").ViewStack; const ViewStack = @import("view_stack.zig").ViewStack;
const OutputStatus = @import("OutputStatus.zig"); 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 // This is needed, because external layouts and large padding and border sizes
// may cause surfaces so small, that bugs in client applications are encountered, // 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 // 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.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(); 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 /// Execute an external layout function, parse its output and apply the layout
/// to the output. /// to the output.
fn layoutExternal(self: *Self, visible_count: u32, output_tags: u32) !void { 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 border_width = self.root.server.config.border_width;
const view_padding = self.root.server.config.view_padding; const view_padding = self.root.server.config.view_padding;
const outer_padding = self.root.server.config.outer_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; const layout_height = @intCast(u32, self.usable_box.height) - outer_padding * 2;
// Assemble command // 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."); const parameters = std.fmt.allocPrint(util.allocator, "{} {} {d} {} {}", .{
defer allocator.free(parameters); visible_count,
const layout_command = try std.mem.join(allocator, " ", &[_][]const u8{ 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, self.layout,
parameters, parameters,
}); });
defer allocator.free(layout_command); defer util.allocator.free(layout_command);
const cmd = [_][]const u8{ const cmd = [_][]const u8{
"/bin/sh", "/bin/sh",
"-c", "-c",
@ -252,14 +258,14 @@ fn layoutExternal(self: *Self, visible_count: u32, output_tags: u32) !void {
// Execute layout executable // Execute layout executable
// TODO abort after 1 second // 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(); defer child.deinit();
child.stdin_behavior = .Ignore; child.stdin_behavior = .Ignore;
child.stdout_behavior = .Pipe; child.stdout_behavior = .Pipe;
try std.ChildProcess.spawn(child); try std.ChildProcess.spawn(child);
const max_output_size = 400 * 1024; const max_output_size = 400 * 1024;
const buffer = try child.stdout.?.inStream().readAllAlloc(allocator, max_output_size); const buffer = try child.stdout.?.inStream().readAllAlloc(util.allocator, max_output_size);
defer allocator.free(buffer); defer util.allocator.free(buffer);
const term = try child.wait(); const term = try child.wait();
switch (term) { switch (term) {
.Exited, .Signal, .Stopped, .Unknown => |code| { .Exited, .Signal, .Stopped, .Unknown => |code| {
@ -270,7 +276,7 @@ fn layoutExternal(self: *Self, visible_count: u32, output_tags: u32) !void {
} }
// Parse layout command output // 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(); defer view_boxen.deinit();
var parse_it = std.mem.split(buffer, "\n"); var parse_it = std.mem.split(buffer, "\n");
while (parse_it.next()) |token| { 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 // Remove the destroyed output from the list
const node = @fieldParentPtr(std.TailQueue(Self).Node, "data", self); const node = @fieldParentPtr(std.TailQueue(Self).Node, "data", self);
root.outputs.remove(node); root.outputs.remove(node);
root.server.allocator.destroy(node); util.allocator.destroy(node);
// Arrange the root in case evacuated views affect the layout // Arrange the root in case evacuated views affect the layout
root.arrange(); root.arrange();

View file

@ -95,7 +95,7 @@ pub fn deinit(self: *Self) void {
pub fn addOutput(self: *Self, wlr_output: *c.wlr_output) void { pub fn addOutput(self: *Self, wlr_output: *c.wlr_output) void {
// TODO: Handle failure // 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; node.data.init(self, wlr_output) catch unreachable;
self.outputs.append(node); self.outputs.append(node);

View file

@ -103,13 +103,11 @@ pub fn init(self: *Self, input_manager: *InputManager, name: []const u8) !void {
pub fn deinit(self: *Self) void { pub fn deinit(self: *Self) void {
self.cursor.deinit(); self.cursor.deinit();
while (self.keyboards.pop()) |node| { while (self.keyboards.pop()) |node| util.allocator.destroy(node);
self.input_manager.server.allocator.destroy(node);
}
while (self.focus_stack.first) |node| { while (self.focus_stack.first) |node| {
self.focus_stack.remove(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 { } else {
// The view is not in the stack, so allocate a new node and prepend it // 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, ViewStack(*View).Node,
) catch unreachable; ) catch unreachable;
new_focus_node.view = view_to_focus; 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) { while (it) |node| : (it = node.next) {
if (node.view == view) { if (node.view == view) {
self.focus_stack.remove(node); self.focus_stack.remove(node);
self.input_manager.server.allocator.destroy(node); util.allocator.destroy(node);
break; 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| { for (modes.items[self.mode_id].items) |mapping| {
if (modifiers == mapping.modifiers and keysym == mapping.keysym) { if (modifiers == mapping.modifiers and keysym == mapping.keysym) {
// Execute the bound command // Execute the bound command
const allocator = self.input_manager.server.allocator;
var failure_message: []const u8 = undefined; 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 // TODO: log the error
if (err == command.Error.CommandFailed) if (err == command.Error.CommandFailed)
allocator.free(failure_message); util.allocator.free(failure_message);
}; };
return true; 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 { fn addKeyboard(self: *Self, device: *c.wlr_input_device) !void {
c.wlr_seat_set_keyboard(self.wlr_seat, device); 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); try node.data.init(self, device);
self.keyboards.append(node); self.keyboards.append(node);
} }

View file

@ -36,8 +36,6 @@ const View = @import("View.zig");
const ViewStack = @import("view_stack.zig").ViewStack; const ViewStack = @import("view_stack.zig").ViewStack;
const XwaylandUnmanaged = @import("XwaylandUnmanaged.zig"); const XwaylandUnmanaged = @import("XwaylandUnmanaged.zig");
allocator: *std.mem.Allocator,
wl_display: *c.wl_display, wl_display: *c.wl_display,
wl_event_loop: *c.wl_event_loop, wl_event_loop: *c.wl_event_loop,
@ -61,9 +59,7 @@ config: Config,
control: Control, control: Control,
status_manager: StatusManager, status_manager: StatusManager,
pub fn init(self: *Self, allocator: *std.mem.Allocator) !void { pub fn init(self: *Self) !void {
self.allocator = allocator;
// The Wayland display is managed by libwayland. It handles accepting // The Wayland display is managed by libwayland. It handles accepting
// clients from the Unix socket, managing Wayland globals, and so on. // clients from the Unix socket, managing Wayland globals, and so on.
self.wl_display = c.wl_display_create() orelse 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); 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.decoration_manager.init(self);
try self.root.init(self); try self.root.init(self);
// Must be called after root is initialized // 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); c.river_wlr_backend_destory(self.noop_backend);
self.input_manager.deinit(); self.input_manager.deinit();
self.config.deinit(self.allocator); self.config.deinit();
} }
/// Create the socket, set WAYLAND_DISPLAY, and start the backend /// 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 // The View will add itself to the output's view stack on map
const output = self.input_manager.default_seat.focused_output; 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); 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 // 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 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); 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", .{}); Log.Debug.log("New unmanaged xwayland surface", .{});
// The unmanged surface will add itself to the list of unmanaged views // The unmanged surface will add itself to the list of unmanaged views
// in Root when it is mapped. // 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); node.data.init(&self.root, wlr_xwayland_surface);
return; 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 // The View will add itself to the output's view stack on map
const output = self.input_manager.default_seat.focused_output; 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); node.view.init(output, output.current_focused_tags, wlr_xwayland_surface);
} }

View file

@ -92,9 +92,8 @@ fn getRiverOutputStatus(
// This can be null if the output is inert, in which case we ignore the request // 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 wlr_output = c.wlr_output_from_resource(output_wl_resource) orelse return;
const output = util.voidCast(Output, wlr_output.*.data.?); 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); c.wl_client_post_no_memory(wl_client);
Log.Error.log("out of memory\n", .{}); Log.Error.log("out of memory\n", .{});
return; return;
@ -107,6 +106,7 @@ fn getRiverOutputStatus(
new_id, new_id,
) orelse { ) orelse {
c.wl_client_post_no_memory(wl_client); c.wl_client_post_no_memory(wl_client);
util.allocator.destroy(node);
Log.Error.log("out of memory\n", .{}); Log.Error.log("out of memory\n", .{});
return; return;
}; };
@ -125,9 +125,8 @@ fn getRiverSeatStatus(
// This can be null if the seat is inert, in which case we ignore the request // 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 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 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); c.wl_client_post_no_memory(wl_client);
Log.Error.log("out of memory\n", .{}); Log.Error.log("out of memory\n", .{});
return; return;
@ -140,6 +139,7 @@ fn getRiverSeatStatus(
new_id, new_id,
) orelse { ) orelse {
c.wl_client_post_no_memory(wl_client); c.wl_client_post_no_memory(wl_client);
util.allocator.destroy(node);
Log.Error.log("out of memory\n", .{}); Log.Error.log("out of memory\n", .{});
return; return;
}; };

View file

@ -88,12 +88,7 @@ pending_tags: ?u32,
pending_serial: ?u32, pending_serial: ?u32,
pub fn init( pub fn init(self: *Self, output: *Output, tags: u32, surface: var) void {
self: *Self,
output: *Output,
tags: u32,
surface: var,
) void {
self.output = output; self.output = output;
self.wlr_surface = null; self.wlr_surface = null;
@ -113,7 +108,7 @@ pub fn init(
self.pending_serial = null; 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) { if (@TypeOf(surface) == *c.wlr_xdg_surface) {
self.impl = .{ .xdg_toplevel = undefined }; self.impl = .{ .xdg_toplevel = undefined };
@ -323,5 +318,5 @@ pub fn unmap(self: *Self) void {
pub fn destroy(self: *const Self) void { pub fn destroy(self: *const Self) void {
self.deinit(); self.deinit();
const node = @fieldParentPtr(ViewStack(Self).Node, "view", self); const node = @fieldParentPtr(ViewStack(Self).Node, "view", self);
self.output.root.server.allocator.destroy(node); util.allocator.destroy(node);
} }

View file

@ -63,21 +63,19 @@ pub fn init(
fn handleDestroy(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void { fn handleDestroy(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void {
const self = @fieldParentPtr(Self, "listen_destroy", listener.?); 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_destroy.link);
c.wl_list_remove(&self.listen_new_popup.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 /// Called when a new xdg popup is requested by the client
fn handleNewPopup(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 self = @fieldParentPtr(Self, "listen_new_popup", listener.?);
const wlr_xdg_popup = util.voidCast(c.wlr_xdg_popup, data.?); const wlr_xdg_popup = util.voidCast(c.wlr_xdg_popup, data.?);
const allocator = self.output.root.server.allocator;
// This will free itself on destroy // 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); xdg_popup.init(self.output, self.parent_box, wlr_xdg_popup);
} }

View file

@ -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 { fn handleNewPopup(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void {
const self = @fieldParentPtr(Self, "listen_new_popup", listener.?); const self = @fieldParentPtr(Self, "listen_new_popup", listener.?);
const wlr_xdg_popup = util.voidCast(c.wlr_xdg_popup, data.?); 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 // 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); xdg_popup.init(self.view.output, &self.view.current_box, wlr_xdg_popup);
} }

View file

@ -93,7 +93,7 @@ fn handleDestroy(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void {
// Deallocate the node // Deallocate the node
const node = @fieldParentPtr(std.TailQueue(Self).Node, "data", self); 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. /// Called when the xwayland surface is mapped, or ready to display on-screen.

View file

@ -18,6 +18,7 @@
const std = @import("std"); const std = @import("std");
const c = @import("c.zig"); const c = @import("c.zig");
const util = @import("util.zig");
const Log = @import("log.zig").Log; const Log = @import("log.zig").Log;
const Server = @import("Server.zig"); const Server = @import("Server.zig");
@ -63,14 +64,14 @@ pub fn main() !void {
Log.Info.log("Initializing server", .{}); Log.Info.log("Initializing server", .{});
var server: Server = undefined; var server: Server = undefined;
try server.init(std.heap.c_allocator); try server.init();
defer server.deinit(); defer server.deinit();
try server.start(); try server.start();
if (startup_command) |cmd| { if (startup_command) |cmd| {
const child_args = [_][]const u8{ "/bin/sh", "-c", 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(); defer child.deinit();
try std.ChildProcess.spawn(child); try std.ChildProcess.spawn(child);
} }

View file

@ -15,6 +15,11 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>. // along with this program. If not, see <https://www.gnu.org/licenses/>.
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 /// 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 /// exists to avoid having the verbosity of the required alignment casts all
/// over the code. /// over the code.