rework window closing behavior and reference counting (GTK)

Tue, 19 May 2026 18:10:13 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Tue, 19 May 2026 18:10:13 +0200
changeset 1129
a4affe75198c
parent 1128
0a150985d6b6
child 1130
f0def0c24ae6

rework window closing behavior and reference counting (GTK)

application/main.c file | annotate | diff | comparison | revisions
ui/common/object.c file | annotate | diff | comparison | revisions
ui/gtk/toolkit.c file | annotate | diff | comparison | revisions
ui/gtk/window.c file | annotate | diff | comparison | revisions
ui/qt/window.cpp file | annotate | diff | comparison | revisions
ui/ui/toolkit.h file | annotate | diff | comparison | revisions
--- a/application/main.c	Mon May 18 21:29:56 2026 +0200
+++ b/application/main.c	Tue May 19 18:10:13 2026 +0200
@@ -643,6 +643,10 @@
 }
 
 void application_startup(UiEvent *event, void *data) {
+    // test window destruction
+    UiObject *testobj = ui_window("testwindow");
+    ui_object_unref(testobj);
+    
     // global list
     UiContext *global = ui_global_context();
     ui_add_action(global, "save", global_action_save, NULL);
--- a/ui/common/object.c	Mon May 18 21:29:56 2026 +0200
+++ b/ui/common/object.c	Tue May 19 18:10:13 2026 +0200
@@ -114,6 +114,7 @@
 }
 
 void uic_object_destroy(UiObject *obj) {
+    uic_context_prepare_close(obj->ctx);
     uic_object_destroyed(obj);
     uic_context_destroy(obj->ctx, obj->ctx->document);
 }
--- a/ui/gtk/toolkit.c	Mon May 18 21:29:56 2026 +0200
+++ b/ui/gtk/toolkit.c	Tue May 19 18:10:13 2026 +0200
@@ -165,7 +165,6 @@
 
 void ui_show(UiObject *obj) {
     gboolean visible = FALSE;
-    uic_check_state_widgets(obj->ctx);
     if(obj->widget) {
         visible = gtk_widget_is_visible(obj->widget);
 #if GTK_MAJOR_VERSION >= 4
@@ -174,6 +173,7 @@
         gtk_widget_show_all(obj->widget);
 #endif
     }
+    uic_check_state_widgets(obj->ctx);
       
     if(!visible) {
         obj->ref++;
@@ -181,18 +181,6 @@
 }
 
 void ui_close(UiObject *obj) {
-    uic_context_prepare_close(obj->ctx); // TODO: should this be moved to the close event handler? Yes!
-    /*
-    if(obj->widget) {
-#if GTK_CHECK_VERSION(4, 0, 0)
-        gtk_window_close(GTK_WINDOW(obj->widget));
-#else
-        gtk_widget_destroy(obj->widget);
-#endif
-    } else {
-        ui_window_close_request(obj);
-    }
-    */
     ui_window_close_request(obj);
 }
 
--- a/ui/gtk/window.c	Mon May 18 21:29:56 2026 +0200
+++ b/ui/gtk/window.c	Tue May 19 18:10:13 2026 +0200
@@ -112,7 +112,12 @@
         }
     }
     
-    obj->ref--;
+    if(obj->ref > 0) {
+        obj->ref--;
+    } else {
+        // warn about invalid reference counting
+        fprintf(stderr, "Error: UiObject %p ref == 0\n", obj);
+    }
     if(obj->ref > 0) {
 #if GTK_CHECK_VERSION(2, 18, 0)
         gtk_widget_set_visible(obj->widget, FALSE);
@@ -138,12 +143,25 @@
     }
 }
 
+static void window_onclose_callback(UiObject *obj) {
+    if(obj->onclose) {
+        UiEvent event;
+        memset(&event, 0, sizeof(UiEvent));
+        event.obj = obj;
+        event.window = obj->window;
+        event.document = obj->ctx->document;
+        obj->onclose(&event, obj->onclosedata);
+    }
+}
+
 #if GTK_MAJOR_VERSION >= 4
 static gboolean close_request(GtkWindow* self, UiObject *obj) {
+    window_onclose_callback(obj);
     return ui_window_close_request(obj);
 }
 #else
 static gboolean close_request(GtkWidget* self, GdkEvent* event, UiObject *obj) {
+    window_onclose_callback(obj);
     return ui_window_close_request(obj);
 }
 #endif
@@ -305,17 +323,23 @@
             adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_sidebar), FALSE);
         } else if(!strcmp(show_title, "sidebar")) {
             adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_main), FALSE);
-            adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_sidebar), TRUE);
+            if(headerbar_sidebar) {
+                adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_sidebar), TRUE);
+            }
         } else if(!strcmp(show_title, "false")) {
-            adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_sidebar), FALSE);
+            if(headerbar_sidebar) {
+                adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_sidebar), FALSE);
+            }
             adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_main), FALSE);
         } else {
             fprintf(stderr, "Unknown value '%s' for property ui.gtk.window.showtitle\n", show_title);
-            adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_sidebar), FALSE);
+            if(headerbar_sidebar) {
+                adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_sidebar), FALSE);
+            }
         }
     } else {
         adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_main), FALSE);
-        if(sidebar) {
+        if(headerbar_sidebar) {
             adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_sidebar), TRUE);
         }
     }
--- a/ui/qt/window.cpp	Mon May 18 21:29:56 2026 +0200
+++ b/ui/qt/window.cpp	Tue May 19 18:10:13 2026 +0200
@@ -43,7 +43,6 @@
 
 static UiObject* create_window(const char *title, bool simple, bool sidebar = false) {
     UiObject *obj = uic_object_new_toplevel();
-    obj->next = NULL;
     
     QMainWindow *window = new QMainWindow();
     window->setWindowTitle(title);
--- a/ui/ui/toolkit.h	Mon May 18 21:29:56 2026 +0200
+++ b/ui/ui/toolkit.h	Tue May 19 18:10:13 2026 +0200
@@ -295,9 +295,10 @@
     UiContainer *container_end;
     
     /*
-     * next container object
+     * called when someone requests to close the window
      */
-    UiObject    *next;
+    void (*onclose)(UiEvent *event, void *userdata);
+    void *onclosedata;
     
     /*
      * obj destroy func

mercurial