From 5613ce13cd62eb6a765fb8c6192d125fe8f83192 Mon Sep 17 00:00:00 2001 From: david-swift Date: Thu, 23 Jan 2025 13:02:11 +0100 Subject: [PATCH] Fix memory leaks --- Sources/CAdw/shim.h | 10 +++++++--- Sources/Core/Model/Extensions/Bool.swift | 7 ------- Sources/Core/View/Dialogs/AboutDialog.swift | 2 +- Sources/Core/View/Dialogs/AlertDialog.swift | 7 ++++++- Sources/Core/View/Dialogs/Dialog.swift | 1 + Sources/Core/View/Dialogs/FileDialog.swift | 21 +++++++++++++++------ Sources/Core/View/Forms/ComboRow+.swift | 1 + Sources/Core/View/Picture+.swift | 1 + Sources/Demo/AlertDialogDemo.swift | 4 +++- 9 files changed, 35 insertions(+), 19 deletions(-) diff --git a/Sources/CAdw/shim.h b/Sources/CAdw/shim.h index debf3aa..8f356b2 100644 --- a/Sources/CAdw/shim.h +++ b/Sources/CAdw/shim.h @@ -28,9 +28,13 @@ static void gtui_filedialog_open_finish (uint64_t dialog, uint64_t result, uint64_t data) { GFile *file = gtk_file_dialog_open_finish (dialog, result, NULL); - const char *path = g_file_peek_path (file); - g_object_unref (file); - filedialog_on_open_cb (dialog, path, data); + if (file != NULL) { + const char *path = g_file_peek_path (file); + g_object_unref (file); + filedialog_on_open_cb (dialog, path, data); + } else { + filedialog_on_open_cb (dialog, NULL, data); + } } static void diff --git a/Sources/Core/Model/Extensions/Bool.swift b/Sources/Core/Model/Extensions/Bool.swift index 3c0a73b..2052360 100644 --- a/Sources/Core/Model/Extensions/Bool.swift +++ b/Sources/Core/Model/Extensions/Bool.swift @@ -14,11 +14,4 @@ extension Bool { self ? 1 : 0 } - /// The gboolean as a GValue. - public var gValue: UnsafePointer { - let pointer = UnsafeMutablePointer.allocate(capacity: 1) - pointer.initialize(to: gtui_initialize_boolean(cBool)) - return .init(pointer) - } - } diff --git a/Sources/Core/View/Dialogs/AboutDialog.swift b/Sources/Core/View/Dialogs/AboutDialog.swift index a6dd4fc..1a97db7 100644 --- a/Sources/Core/View/Dialogs/AboutDialog.swift +++ b/Sources/Core/View/Dialogs/AboutDialog.swift @@ -121,7 +121,7 @@ public struct AboutDialog: AdwaitaWidget { if storage.content[dialogID]?.first != nil { let dialog = storage.content[dialogID]?.first?.opaquePointer adw_dialog_close(dialog?.cast()) - g_object_unref(dialog?.cast()) + storage.content[dialogID] = [] } } } diff --git a/Sources/Core/View/Dialogs/AlertDialog.swift b/Sources/Core/View/Dialogs/AlertDialog.swift index 0a3e95d..e5530a9 100644 --- a/Sources/Core/View/Dialogs/AlertDialog.swift +++ b/Sources/Core/View/Dialogs/AlertDialog.swift @@ -125,6 +125,9 @@ public struct AlertDialog: AdwaitaWidget { ) where Data: ViewRenderData { storage.fields[Self.visibleID + id] = _visible child.updateStorage(storage, data: data, updateProperties: updateProperties, type: type) + if let storage = storage.content["extra-child"]?.first { + extraChild?.updateStorage(storage, data: data, updateProperties: updateProperties, type: type) + } guard updateProperties else { return } @@ -164,7 +167,8 @@ public struct AlertDialog: AdwaitaWidget { if storage.content[Self.dialogID + id]?.first != nil { let dialog = storage.content[Self.dialogID + id]?.first?.opaquePointer adw_dialog_close(dialog?.cast()) - g_object_unref(dialog?.cast()) + storage.content[Self.dialogID] = [] + storage.content["extra-child"] = nil } } } @@ -213,6 +217,7 @@ public struct AlertDialog: AdwaitaWidget { if let extraChild { let child = extraChild.storage(data: data, type: AdwaitaMainView.self) let childPointer = child.pointer as? OpaquePointer + storage.content["extra-child"] = [child] adw_alert_dialog_set_extra_child(pointer?.cast(), childPointer?.cast()) } } diff --git a/Sources/Core/View/Dialogs/Dialog.swift b/Sources/Core/View/Dialogs/Dialog.swift index 8cac314..612cb42 100644 --- a/Sources/Core/View/Dialogs/Dialog.swift +++ b/Sources/Core/View/Dialogs/Dialog.swift @@ -113,6 +113,7 @@ public struct Dialog: AdwaitaWidget { if storage.content[dialogID + id]?.first != nil { let dialog = storage.content[dialogID + id]?.first?.opaquePointer adw_dialog_close(dialog?.cast()) + storage.content[dialogID + id] = [] } } } diff --git a/Sources/Core/View/Dialogs/FileDialog.swift b/Sources/Core/View/Dialogs/FileDialog.swift index d654dc4..566f343 100644 --- a/Sources/Core/View/Dialogs/FileDialog.swift +++ b/Sources/Core/View/Dialogs/FileDialog.swift @@ -91,7 +91,9 @@ public struct FileDialog: AdwaitaWidget { } child.updateStorage(storage, data: data, updateProperties: updateProperties, type: type) if open.update, storage.fields["callbacks"] == nil { + var unref: [OpaquePointer?] = [] let pointer = gtk_file_dialog_new() + unref.append(pointer) if let initialName { gtk_file_dialog_set_initial_name(pointer, initialName) } @@ -101,18 +103,24 @@ public struct FileDialog: AdwaitaWidget { gtk_file_filter_add_suffix(filter, name) } gtk_file_dialog_set_default_filter(pointer, filter) - g_object_unref(filter?.cast()) + unref.append(filter) } else { gtk_file_dialog_set_default_filter(pointer, nil) } if let initialFolder { let file = g_file_new_for_path(initialFolder.absoluteString) gtk_file_dialog_set_initial_folder(pointer, file) - g_object_unref(file?.cast()) + unref.append(file) } let callbacks = AdwaitaFileDialog() - callbacks.onResult = { (storage.fields["result"] as? (URL) -> Void)?($0); g_object_unref(pointer?.cast()) } - callbacks.onCancel = { (storage.fields["cancel"] as? () -> Void)?() } + let unrefClosure = { + for ref in unref { + g_object_unref(ref?.cast()) + } + storage.fields["callbacks"] = nil + } + callbacks.onResult = { (storage.fields["result"] as? (URL) -> Void)?($0); unrefClosure() } + callbacks.onCancel = { (storage.fields["cancel"] as? () -> Void)?(); unrefClosure() } callbacks.reset = { storage.fields["callbacks"] = nil } storage.fields["callbacks"] = callbacks let ptr = UInt64(Int(bitPattern: pointer)) @@ -138,8 +146,9 @@ class AdwaitaFileDialog { var reset: () -> Void = { } /// Initialize the window callback. - init() { - } + init() { } + + deinit { print("DEINIT fd") } /// Run this when a file gets opened. /// - Parameter path: The file path. diff --git a/Sources/Core/View/Forms/ComboRow+.swift b/Sources/Core/View/Forms/ComboRow+.swift index 882a9ee..0483f5f 100644 --- a/Sources/Core/View/Forms/ComboRow+.swift +++ b/Sources/Core/View/Forms/ComboRow+.swift @@ -38,6 +38,7 @@ extension ComboRow { let list = gtk_string_list_new(nil) storage.fields[Self.stringList] = list adw_combo_row_set_model(storage.opaquePointer?.cast(), list) + g_object_unref(list?.cast()) Self.updateContent(storage: storage, values: values, element: Element.self) } updateFunctions.append { storage, _, _ in diff --git a/Sources/Core/View/Picture+.swift b/Sources/Core/View/Picture+.swift index edc929f..2388200 100644 --- a/Sources/Core/View/Picture+.swift +++ b/Sources/Core/View/Picture+.swift @@ -20,6 +20,7 @@ extension Picture { let pointer = storage.opaquePointer guard let data else { if storage.fields[oldData] != nil { + g_object_unref(gtk_picture_get_paintable(pointer)?.cast()) gtk_picture_set_paintable(pointer, gdk_paintable_new_empty(0, 0)) storage.fields[oldData] = nil } diff --git a/Sources/Demo/AlertDialogDemo.swift b/Sources/Demo/AlertDialogDemo.swift index 072420c..7757490 100644 --- a/Sources/Demo/AlertDialogDemo.swift +++ b/Sources/Demo/AlertDialogDemo.swift @@ -24,7 +24,9 @@ struct AlertDialogDemo: View { .frame(maxWidth: 100) .padding() } - .alertDialog(visible: $dialog, heading: "Alert Dialog", body: "This is an alert dialog") + .alertDialog(visible: $dialog, heading: "Alert Dialog", body: "This is an alert dialog") { + CounterDemo() + } .response("Cancel", role: .close) { print("Cancel") }