From 064b9b97e4c93ca2e00f98a07fc6dbcb3966ce96 Mon Sep 17 00:00:00 2001 From: zenith391 <39484230+zenith391@users.noreply.github.com> Date: Wed, 17 Jul 2024 21:50:33 +0200 Subject: [PATCH] fix: fix compile error on GTK backend's Monitor.getInternalName and properly deinit --- src/backends/gtk/Monitor.zig | 14 ++++++++++++-- src/backends/win32/Monitor.zig | 8 ++++++++ src/data.zig | 11 +++++++++-- src/monitor.zig | 33 +++++++++++++++++++++++---------- 4 files changed, 52 insertions(+), 14 deletions(-) diff --git a/src/backends/gtk/Monitor.zig b/src/backends/gtk/Monitor.zig index ce71304d..a79cb964 100644 --- a/src/backends/gtk/Monitor.zig +++ b/src/backends/gtk/Monitor.zig @@ -27,6 +27,14 @@ pub fn getList() []Monitor { } } +pub fn deinitAllPeers() void { + if (monitor_list) |list| { + for (list) |*monitor| monitor.deinit(); + lib.internal.lasting_allocator.free(list); + monitor_list = null; + } +} + pub fn getName(self: *Monitor) []const u8 { // TODO: detect if GTK version is >= 4.10 and use c.gdk_monitor_get_description if so is the case. return std.mem.span(c.gdk_monitor_get_connector(self.peer)); @@ -37,9 +45,10 @@ pub fn getInternalName(self: *Monitor) []const u8 { return internal_name; } else { self.internal_name = std.mem.concat(lib.internal.lasting_allocator, u8, &.{ - std.mem.span(c.gdk_monitor_get_manufacturer(self.peer) orelse ""), - std.mem.span(c.gdk_monitor_get_model(self.peer) orelse ""), + std.mem.span(c.gdk_monitor_get_manufacturer(self.peer) orelse @as([:0]const u8, "").ptr), + std.mem.span(c.gdk_monitor_get_model(self.peer) orelse @as([:0]const u8, "").ptr), }) catch @panic("OOM"); + return self.internal_name.?; } } @@ -95,5 +104,6 @@ pub fn getVideoMode(self: *Monitor, index: usize) lib.VideoMode { pub fn deinit(self: *Monitor) void { if (self.internal_name) |internal_name| { lib.internal.lasting_allocator.free(internal_name); + self.internal_name = null; } } diff --git a/src/backends/win32/Monitor.zig b/src/backends/win32/Monitor.zig index 2a3f7b4b..e1568e57 100644 --- a/src/backends/win32/Monitor.zig +++ b/src/backends/win32/Monitor.zig @@ -83,6 +83,14 @@ pub fn getList() []Monitor { } } +pub fn deinitAllPeers() void { + if (monitor_list) |list| { + for (list) |*monitor| monitor.deinit(); + lib.internal.lasting_allocator.free(list); + monitor_list = null; + } +} + pub fn getName(self: *Monitor) []const u8 { return self.device_name; } diff --git a/src/data.zig b/src/data.zig index 38524ec3..f6e71e14 100644 --- a/src/data.zig +++ b/src/data.zig @@ -627,6 +627,7 @@ pub fn ListAtom(comptime T: type) type { return struct { backing_list: ListType, length: Atom(usize), + // TODO: since RwLock doesn't report deadlocks in Debug mode like Mutex does, do it manually here in ListAtom lock: std.Thread.RwLock = .{}, allocator: std.mem.Allocator, @@ -759,6 +760,12 @@ pub fn ListAtom(comptime T: type) type { }; } + pub fn map(self: *Self, comptime U: type, func: *const fn (T) U) *ListAtom(U) { + _ = self; + _ = func; + return undefined; + } + pub fn deinit(self: *Self) void { self.lock.lock(); defer self.lock.unlock(); @@ -768,8 +775,8 @@ pub fn ListAtom(comptime T: type) type { }; } -test "list atom" { - var list = ListAtom(u32).init(); +test ListAtom { + var list = ListAtom(u32).init(std.testing.allocator); defer list.deinit(); try list.append(1); diff --git a/src/monitor.zig b/src/monitor.zig index 1b68f9a3..77ea0726 100644 --- a/src/monitor.zig +++ b/src/monitor.zig @@ -25,23 +25,32 @@ pub const Monitors = struct { /// This function is called by `capy.deinit()`, so it doesn't need to call it manually. pub fn deinit() void { - var iterator = Monitors.list.iterate(); - defer iterator.deinit(); - while (iterator.next()) |monitor| { - monitor.deinit(); + { + var iterator = Monitors.list.iterate(); + defer iterator.deinit(); + while (iterator.next()) |monitor| { + monitor.deinit(); + } } - Monitors.list.deinit(); + Monitors.list = ListAtom(Monitor).init(internal.lasting_allocator); + backend.Monitor.deinitAllPeers(); } }; test "Monitors" { - var iterator = Monitors.list.iterate(); - defer iterator.deinit(); + // NOTE: You don't need to initialize the API in user code. This is only for the testing environment. + Monitors.init(); + defer Monitors.deinit(); - std.log.info("Monitor(s):", .{}); - while (iterator.next()) |monitor| { - std.log.info(" - Name: {s}", .{monitor.getName()}); + { + var iterator = Monitors.list.iterate(); + defer iterator.deinit(); + + std.log.info("Monitor(s):", .{}); + while (iterator.next()) |monitor| { + std.log.info(" - Name: {s}", .{monitor.getName()}); + } } } @@ -113,6 +122,10 @@ pub const Monitor = struct { } test getSize { + // NOTE: You don't need to initialize the API in user code. This is only for the testing environment. + Monitors.init(); + defer Monitors.deinit(); + const monitor = Monitors.list.get(0); const width, const height = monitor.getSize(); std.log.info("Monitor pixels: {d} px x {d} px", .{ width, height });