gtk-ng: use WeakRef helper for type safety

This commit is contained in:
Jeffrey C. Ollie
2025-08-09 11:12:06 -05:00
committed by Mitchell Hashimoto
parent 2de0c108ba
commit 5bb88d259c
4 changed files with 11 additions and 17 deletions

View File

@@ -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,

View File

@@ -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.

View File

@@ -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;
};

View File

@@ -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