fix ui_close could make UiObjects unusable (GTK)

Mon, 12 Jan 2026 20:54:27 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Mon, 12 Jan 2026 20:54:27 +0100
changeset 1046
94df16a7fff2
parent 1045
e855396fd839
child 1047
acb5352a2038

fix ui_close could make UiObjects unusable (GTK)

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/gtk/window.h file | annotate | diff | comparison | revisions
ui/motif/toolkit.c file | annotate | diff | comparison | revisions
ui/ui/toolkit.h file | annotate | diff | comparison | revisions
--- a/ui/common/object.c	Sun Jan 11 15:10:20 2026 +0100
+++ b/ui/common/object.c	Mon Jan 12 20:54:27 2026 +0100
@@ -60,6 +60,10 @@
     cxListAdd(destruction_callbacks, &cb);
 }
 
+UiObject* ui_dummy_object(void) {
+    return uic_object_new_toplevel();
+}
+
 void uic_object_created(UiObject *obj) {
     CxIterator i = cxListIterator(creation_callbacks);
     cx_foreach(objcallback *, cb, i) {
--- a/ui/gtk/toolkit.c	Sun Jan 11 15:10:20 2026 +0100
+++ b/ui/gtk/toolkit.c	Mon Jan 12 20:54:27 2026 +0100
@@ -33,6 +33,7 @@
 
 #include "toolkit.h"
 #include "toolbar.h"
+#include "window.h"
 #include "icon.h"
 #include "../common/document.h"
 #include "../common/properties.h"
@@ -145,27 +146,33 @@
 #endif
 
 void ui_show(UiObject *obj) {
-    gboolean visible = gtk_widget_is_visible(obj->widget);
-    
+    gboolean visible = FALSE;
     uic_check_state_widgets(obj->ctx);
+    if(obj->widget) {
+        visible = gtk_widget_is_visible(obj->widget);
 #if GTK_MAJOR_VERSION >= 4
-    gtk_window_present(GTK_WINDOW(obj->widget));
+        gtk_window_present(GTK_WINDOW(obj->widget));
 #elif GTK_MAJOR_VERSION <= 3
-    gtk_widget_show_all(obj->widget);
+        gtk_widget_show_all(obj->widget);
 #endif
-    
+    }
+      
     if(!visible) {
         obj->ref++;
     }
 }
 
 void ui_close(UiObject *obj) {
-    uic_context_prepare_close(obj->ctx);
+    uic_context_prepare_close(obj->ctx); // TODO: should this be moved to the close event handler?
+    if(obj->widget) {
 #if GTK_CHECK_VERSION(4, 0, 0)
-    gtk_window_close(GTK_WINDOW(obj->widget));
+        gtk_window_close(GTK_WINDOW(obj->widget));
 #else
-    gtk_widget_destroy(obj->widget);
+        gtk_widget_destroy(obj->widget);
 #endif
+    } else {
+        ui_window_close_request(obj);
+    }
 }
 
 
--- a/ui/gtk/window.c	Sun Jan 11 15:10:20 2026 +0100
+++ b/ui/gtk/window.c	Mon Jan 12 20:54:27 2026 +0100
@@ -44,6 +44,7 @@
 #include "container.h"
 #include "headerbar.h"
 #include "button.h"
+#include "window.h"
 
 static int nwindows = 0;
 
@@ -80,7 +81,7 @@
     g_idle_add(ui_window_destroy, data);
 }
 
-static gboolean ui_window_close_request(UiObject *obj) {
+gboolean ui_window_close_request(UiObject *obj) {
     if(obj->widget) {
         void *appwindow = g_object_get_data(G_OBJECT(obj->widget), "ui.appwindow");
         if(appwindow) {
@@ -111,7 +112,6 @@
         }
     }
     
-    uic_context_prepare_close(obj->ctx);
     obj->ref--;
     if(obj->ref > 0) {
 #if GTK_CHECK_VERSION(2, 18, 0)
@@ -121,6 +121,7 @@
 #endif
         return TRUE;
     } else {
+        uic_context_prepare_close(obj->ctx);
         return FALSE;
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ui/gtk/window.h	Mon Jan 12 20:54:27 2026 +0100
@@ -0,0 +1,47 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2026 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef WINDOW_H
+#define WINDOW_H
+
+#include "toolkit.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+gboolean ui_window_close_request(UiObject *obj);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* WINDOW_H */
+
--- a/ui/motif/toolkit.c	Sun Jan 11 15:10:20 2026 +0100
+++ b/ui/motif/toolkit.c	Mon Jan 12 20:54:27 2026 +0100
@@ -156,8 +156,12 @@
 
 void ui_show(UiObject *obj) {
     uic_check_state_widgets(obj->ctx);
-    if(!XtIsRealized(obj->widget)) {
-        XtRealizeWidget(obj->widget);
+    if(obj->widget) {
+        if(!XtIsRealized(obj->widget)) {
+            XtRealizeWidget(obj->widget);
+            obj->ref++;
+        }
+    } else {
         obj->ref++;
     }
 }
--- a/ui/ui/toolkit.h	Sun Jan 11 15:10:20 2026 +0100
+++ b/ui/ui/toolkit.h	Mon Jan 12 20:54:27 2026 +0100
@@ -554,6 +554,8 @@
 UIEXPORT void ui_show(UiObject *obj);
 UIEXPORT void ui_close(UiObject *obj);
 
+UIEXPORT UiObject* ui_dummy_object(void);
+
 UIEXPORT void ui_job(UiObject *obj, ui_threadfunc tf, void *td, ui_callback f, void *fd);
 UIEXPORT void ui_call_mainthread(ui_threadfunc tf, void* td);
 

mercurial