diff --git a/include/bindings.c b/include/bindings.c index 0eaf76d..7b16c09 100644 --- a/include/bindings.c +++ b/include/bindings.c @@ -35,3 +35,7 @@ struct wlr_output *river_wlr_noop_add_output(struct wlr_backend *backend) { bool river_wlr_output_is_noop(struct wlr_output *output) { return wlr_output_is_noop(output); } + +void river_wlr_backend_destory(struct wlr_backend *backend) { + wlr_backend_destroy(backend); +} diff --git a/include/bindings.h b/include/bindings.h index d8b9358..9643836 100644 --- a/include/bindings.h +++ b/include/bindings.h @@ -31,5 +31,6 @@ struct wlr_session *river_wlr_backend_get_session(struct wlr_backend *backend); struct wlr_backend *river_wlr_noop_backend_create(struct wl_display *display); struct wlr_output *river_wlr_noop_add_output(struct wlr_backend *backend); bool river_wlr_output_is_noop(struct wlr_output *output); +void river_wlr_backend_destory(struct wlr_backend *backend); #endif // RIVER_BINDINGS_H diff --git a/river/Config.zig b/river/Config.zig index 541e82b..5f39fb3 100644 --- a/river/Config.zig +++ b/river/Config.zig @@ -62,6 +62,10 @@ pub fn init(self: *Self, allocator: *std.mem.Allocator) !void { pub fn deinit(self: Self, allocator: *std.mem.Allocator) void { self.mode_to_id.deinit(); - for (self.modes.items) |*mode| mode.deinit(); + for (self.modes.items) |mode| { + for (mode.items) |mapping| mapping.deinit(allocator); + mode.deinit(); + } self.modes.deinit(); + self.float_filter.deinit(); } diff --git a/river/Control.zig b/river/Control.zig index e9ae576..1c12b42 100644 --- a/river/Control.zig +++ b/river/Control.zig @@ -85,12 +85,13 @@ fn runCommand( const seat = self.server.input_manager.default_seat; var args = std.ArrayList([]const u8).init(allocator); + defer args.deinit(); var i: usize = 0; const data = @ptrCast([*]const u8, wl_array.?.data); while (i < wl_array.?.size) { const slice = std.mem.spanZ(@ptrCast([*:0]const u8, &data[i])); - args.append(std.mem.dupe(allocator, u8, slice) catch unreachable) catch unreachable; + args.append(slice) catch unreachable; i += slice.len + 1; } diff --git a/river/Decoration.zig b/river/Decoration.zig index 91c5bed..b96450c 100644 --- a/river/Decoration.zig +++ b/river/Decoration.zig @@ -27,6 +27,7 @@ const DecorationManager = @import("DecorationManager.zig"); decoration_manager: *DecorationManager, wlr_xdg_toplevel_decoration: *c.wlr_xdg_toplevel_decoration_v1, +listen_destroy: c.wl_listener, listen_request_mode: c.wl_listener, pub fn init( @@ -37,12 +38,24 @@ pub fn init( self.decoration_manager = decoration_manager; self.wlr_xdg_toplevel_decoration = wlr_xdg_toplevel_decoration; + self.listen_destroy.notify = handleDestroy; + c.wl_signal_add(&self.wlr_xdg_toplevel_decoration.events.destroy, &self.listen_destroy); + self.listen_request_mode.notify = handleRequestMode; c.wl_signal_add(&self.wlr_xdg_toplevel_decoration.events.request_mode, &self.listen_request_mode); handleRequestMode(&self.listen_request_mode, self.wlr_xdg_toplevel_decoration); } +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); +} + fn handleRequestMode(listener: ?*c.wl_listener, data: ?*c_void) callconv(.C) void { const self = @fieldParentPtr(Self, "listen_request_mode", listener.?); // TODO: we might need to take this configure serial and do a transaction diff --git a/river/Root.zig b/river/Root.zig index 562aa3c..fe07e7e 100644 --- a/river/Root.zig +++ b/river/Root.zig @@ -79,11 +79,17 @@ pub fn init(self: *Self, server: *Server) !void { } pub fn deinit(self: *Self) void { - while (self.outputs.pop()) |output_node| { - output_node.data.deinit(); - self.server.allocator.destroy(output_node); - } + // Need to remove these listeners as the noop output will be destroyed with + // the noop backend triggering the destroy event. However, + // Output.handleDestroy is not intended to handle the noop output being + // destroyed. + c.wl_list_remove(&self.noop_output.listen_destroy.link); + c.wl_list_remove(&self.noop_output.listen_frame.link); + c.wl_list_remove(&self.noop_output.listen_mode.link); + c.wlr_output_layout_destroy(self.wlr_output_layout); + + if (c.wl_event_source_remove(self.transaction_timer) < 0) unreachable; } pub fn addOutput(self: *Self, wlr_output: *c.wlr_output) void { diff --git a/river/Server.zig b/river/Server.zig index e46a619..f700746 100644 --- a/river/Server.zig +++ b/river/Server.zig @@ -136,13 +136,16 @@ pub fn init(self: *Self, allocator: *std.mem.Allocator) !void { /// Free allocated memory and clean up pub fn deinit(self: *Self) void { // Note: order is important here - if (build_options.xwayland) { - c.wlr_xwayland_destroy(self.wlr_xwayland); - } + if (build_options.xwayland) c.wlr_xwayland_destroy(self.wlr_xwayland); + c.wl_display_destroy_clients(self.wl_display); - c.wl_display_destroy(self.wl_display); - self.input_manager.deinit(); + self.root.deinit(); + + c.wl_display_destroy(self.wl_display); + c.river_wlr_backend_destory(self.noop_backend); + + self.input_manager.deinit(); self.config.deinit(self.allocator); }