From bf61f29f570208cf6e70e665e4334547c4b18f09 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sun, 27 Jul 2025 15:07:12 -0700 Subject: [PATCH] apprt/gtk-ng: create the privateObjFieldAccessor helper to unref --- src/apprt/gtk-ng/class.zig | 78 +++++++++++++++++++ .../class/clipboard_confirmation_dialog.zig | 14 +--- src/apprt/gtk-ng/class/surface.zig | 14 +--- .../gtk-ng/class/surface_child_exited.zig | 7 +- src/apprt/gtk-ng/class/window.zig | 7 +- 5 files changed, 84 insertions(+), 36 deletions(-) diff --git a/src/apprt/gtk-ng/class.zig b/src/apprt/gtk-ng/class.zig index 427789560..dc024c5cf 100644 --- a/src/apprt/gtk-ng/class.zig +++ b/src/apprt/gtk-ng/class.zig @@ -46,6 +46,84 @@ pub fn Common( } }).private else {}; + /// A helper that can be used to create a property that reads and + /// writes a private boxed gobject field type. + /// + /// Reading the property will result in allocating a pointer and + /// setting it will free the previous pointer. + /// + /// The object class (Self) must still free the private field + /// in finalize! + pub fn privateBoxedFieldAccessor( + comptime name: []const u8, + ) gobject.ext.Accessor( + Self, + @FieldType(Private.?, name), + ) { + return .{ + .getter = &struct { + fn get(self: *Self, value: *gobject.Value) void { + gobject.ext.Value.set( + value, + @field(private(self), name), + ); + } + }.get, + .setter = &struct { + fn set(self: *Self, value: *const gobject.Value) void { + const priv = private(self); + if (@field(priv, name)) |v| { + glib.ext.destroy(v); + } + + const T = @TypeOf(@field(priv, name)); + @field( + priv, + name, + ) = gobject.ext.Value.dup(value, T); + } + }.set, + }; + } + + /// A helper that can be used to create a property that reads and + /// writes a private field gobject field type (reference counted). + /// + /// Reading the property will result in taking a reference to the + /// value and writing the property will unref the previous value. + /// + /// The object class (Self) must still free the private field + /// in finalize! + pub fn privateObjFieldAccessor( + comptime name: []const u8, + ) gobject.ext.Accessor( + Self, + @FieldType(Private.?, name), + ) { + return .{ + .getter = &struct { + fn get(self: *Self, value: *gobject.Value) void { + gobject.ext.Value.set( + value, + @field(private(self), name), + ); + } + }.get, + .setter = &struct { + fn set(self: *Self, value: *const gobject.Value) void { + const priv = private(self); + if (@field(priv, name)) |v| v.unref(); + + const T = @TypeOf(@field(priv, name)); + @field( + priv, + name, + ) = gobject.ext.Value.dup(value, T); + } + }.set, + }; + } + /// A helper that can be used to create a property that reads and /// writes a private `?[:0]const u8` field type. /// diff --git a/src/apprt/gtk-ng/class/clipboard_confirmation_dialog.zig b/src/apprt/gtk-ng/class/clipboard_confirmation_dialog.zig index 7769d8935..cb9a27444 100644 --- a/src/apprt/gtk-ng/class/clipboard_confirmation_dialog.zig +++ b/src/apprt/gtk-ng/class/clipboard_confirmation_dialog.zig @@ -59,12 +59,7 @@ pub const ClipboardConfirmationDialog = extern struct { .{ .nick = "Request", .blurb = "The clipboard request.", - .accessor = gobject.ext.privateFieldAccessor( - Self, - Private, - &Private.offset, - "request", - ), + .accessor = C.privateBoxedFieldAccessor("request"), }, ); }; @@ -78,12 +73,7 @@ pub const ClipboardConfirmationDialog = extern struct { .{ .nick = "Clipboard Contents", .blurb = "The clipboard contents being read/written.", - .accessor = gobject.ext.privateFieldAccessor( - Self, - Private, - &Private.offset, - "clipboard_contents", - ), + .accessor = C.privateObjFieldAccessor("clipboard_contents"), }, ); }; diff --git a/src/apprt/gtk-ng/class/surface.zig b/src/apprt/gtk-ng/class/surface.zig index 98c470764..bb432cf6f 100644 --- a/src/apprt/gtk-ng/class/surface.zig +++ b/src/apprt/gtk-ng/class/surface.zig @@ -50,12 +50,7 @@ pub const Surface = extern struct { .{ .nick = "Config", .blurb = "The configuration that this surface is using.", - .accessor = gobject.ext.privateFieldAccessor( - Self, - Private, - &Private.offset, - "config", - ), + .accessor = C.privateObjFieldAccessor("config"), }, ); }; @@ -89,12 +84,7 @@ pub const Surface = extern struct { .{ .nick = "Desired Font Size", .blurb = "The desired font size, only affects initialization.", - .accessor = gobject.ext.privateFieldAccessor( - Self, - Private, - &Private.offset, - "font_size_request", - ), + .accessor = C.privateBoxedFieldAccessor("font_size_request"), }, ); }; diff --git a/src/apprt/gtk-ng/class/surface_child_exited.zig b/src/apprt/gtk-ng/class/surface_child_exited.zig index 693425c09..3bf29285f 100644 --- a/src/apprt/gtk-ng/class/surface_child_exited.zig +++ b/src/apprt/gtk-ng/class/surface_child_exited.zig @@ -42,12 +42,7 @@ const SurfaceChildExitedBanner = extern struct { .{ .nick = "Data", .blurb = "The child exit data.", - .accessor = gobject.ext.privateFieldAccessor( - Self, - Private, - &Private.offset, - "data", - ), + .accessor = C.privateBoxedFieldAccessor("data"), }, ); }; diff --git a/src/apprt/gtk-ng/class/window.zig b/src/apprt/gtk-ng/class/window.zig index ac5555391..d822bfd49 100644 --- a/src/apprt/gtk-ng/class/window.zig +++ b/src/apprt/gtk-ng/class/window.zig @@ -69,12 +69,7 @@ pub const Window = extern struct { .{ .nick = "Config", .blurb = "The configuration that this surface is using.", - .accessor = gobject.ext.privateFieldAccessor( - Self, - Private, - &Private.offset, - "config", - ), + .accessor = C.privateObjFieldAccessor("config"), }, ); };