From 5bb88d259c11160973e1bd7dd0643c13e6c0ec47 Mon Sep 17 00:00:00 2001 From: "Jeffrey C. Ollie" Date: Sat, 9 Aug 2025 11:12:06 -0500 Subject: [PATCH] gtk-ng: use WeakRef helper for type safety --- src/apprt/gtk-ng/class/application.zig | 2 +- src/apprt/gtk-ng/class/split_tree.zig | 2 +- src/apprt/gtk-ng/class/window.zig | 13 +++++-------- src/apprt/gtk-ng/weak_ref.zig | 11 ++++------- 4 files changed, 11 insertions(+), 17 deletions(-) diff --git a/src/apprt/gtk-ng/class/application.zig b/src/apprt/gtk-ng/class/application.zig index eda2a49eb..4a14434fa 100644 --- a/src/apprt/gtk-ng/class/application.zig +++ b/src/apprt/gtk-ng/class/application.zig @@ -133,7 +133,7 @@ pub const Application = extern struct { /// If non-null, we're currently showing a config errors dialog. /// This is a WeakRef because the dialog can close on its own /// outside of our own lifecycle and that's okay. - config_errors_dialog: WeakRef(ConfigErrorsDialog) = .{}, + config_errors_dialog: WeakRef(ConfigErrorsDialog) = .empty, /// glib source for our signal handler. signal_source: ?c_uint = null, diff --git a/src/apprt/gtk-ng/class/split_tree.zig b/src/apprt/gtk-ng/class/split_tree.zig index 3018afdb4..5eb0a5472 100644 --- a/src/apprt/gtk-ng/class/split_tree.zig +++ b/src/apprt/gtk-ng/class/split_tree.zig @@ -119,7 +119,7 @@ pub const SplitTree = extern struct { /// Last focused surface in the tree. We need this to handle various /// tree change states. - last_focused: WeakRef(Surface) = .{}, + last_focused: WeakRef(Surface) = .empty, /// The source that we use to rebuild the tree. This is also /// used to debounce updates. diff --git a/src/apprt/gtk-ng/class/window.zig b/src/apprt/gtk-ng/class/window.zig index 47f95aece..eb41b61d0 100644 --- a/src/apprt/gtk-ng/class/window.zig +++ b/src/apprt/gtk-ng/class/window.zig @@ -28,6 +28,7 @@ const Surface = @import("surface.zig").Surface; const Tab = @import("tab.zig").Tab; const DebugWarning = @import("debug_warning.zig").DebugWarning; const CommandPalette = @import("command_palette.zig").CommandPalette; +const WeakRef = @import("../weak_ref.zig").WeakRef; const log = std.log.scoped(.gtk_ghostty_window); @@ -249,7 +250,7 @@ pub const Window = extern struct { tab_overview_focus_timer: ?c_uint = null, /// A weak reference to a command palette. - command_palette: gobject.WeakRef = std.mem.zeroes(gobject.WeakRef), + command_palette: WeakRef(CommandPalette) = .empty, // Template bindings tab_overview: *adw.TabOverview, @@ -1065,7 +1066,7 @@ pub const Window = extern struct { fn dispose(self: *Self) callconv(.c) void { const priv = self.private(); - if (priv.command_palette.get()) |object| object.unref(); + priv.command_palette.set(null); if (priv.config) |v| { v.unref(); @@ -1716,11 +1717,7 @@ pub const Window = extern struct { // Get a reference to a command palette. First check the weak reference // that we save to see if we already have one stored. If we don't then // create a new one. - const command_palette = command_palette: { - if (priv.command_palette.get()) |object| not_command_palette: { - break :command_palette gobject.ext.cast(CommandPalette, object) orelse break :not_command_palette; - } - + const command_palette = priv.command_palette.get() orelse command_palette: { // Create a fresh command palette. const command_palette = CommandPalette.new(); @@ -1745,7 +1742,7 @@ pub const Window = extern struct { // Save a weak reference to the command palette. We use a weak reference to avoid // reference counting cycles that might cause problems later. - priv.command_palette.set(command_palette.as(gobject.Object)); + priv.command_palette.set(command_palette); break :command_palette command_palette; }; diff --git a/src/apprt/gtk-ng/weak_ref.zig b/src/apprt/gtk-ng/weak_ref.zig index 7ee5cf730..f689e45fa 100644 --- a/src/apprt/gtk-ng/weak_ref.zig +++ b/src/apprt/gtk-ng/weak_ref.zig @@ -10,6 +10,8 @@ pub fn WeakRef(comptime T: type) type { ref: gobject.WeakRef = std.mem.zeroes(gobject.WeakRef), + pub const empty: Self = .{}; + /// Set the weak reference to the given object. This will not /// increase the reference count of the object. pub fn set(self: *Self, v_: ?*T) void { @@ -23,14 +25,9 @@ pub fn WeakRef(comptime T: type) type { /// Get a strong reference to the object, or null if the object /// has been finalized. This increases the reference count by one. pub fn get(self: *Self) ?*T { - // The GIR of g_weak_ref_get has a bug where the optional - // is not encoded. Or, it may be a bug in zig-gobject. - const obj_: ?*gobject.Object = @ptrCast(self.ref.get()); - const obj = obj_ orelse return null; - // We can't use `as` because `as` guarantees conversion and // that can't be statically guaranteed. - return gobject.ext.cast(T, obj); + return gobject.ext.cast(T, self.ref.get() orelse return null); } }; } @@ -38,7 +35,7 @@ pub fn WeakRef(comptime T: type) type { test WeakRef { const testing = std.testing; - var ref: WeakRef(gtk.TextBuffer) = .{}; + var ref: WeakRef(gtk.TextBuffer) = .empty; const obj: *gtk.TextBuffer = .new(null); ref.set(obj); ref.get().?.unref(); // The "?" asserts non-null