Mon, 12 Jan 2026 20:54:27 +0100
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);