# HG changeset patch # User Olaf Wintermann # Date 1731701778 -3600 # Node ID 03599608d55566db5d96cb384d8e85dc0284a5a7 # Parent de653b07050b5980c24c91d9bfa5527a2c6e3063 add UiObject reference counting (GTK) diff -r de653b07050b -r 03599608d555 application/main.c --- a/application/main.c Thu Nov 14 17:26:16 2024 +0100 +++ b/application/main.c Fri Nov 15 21:16:18 2024 +0100 @@ -216,6 +216,29 @@ } } +static UiObject *ref_window; + +void action_button_ref(UiEvent *event, void *userdata) { + UiObject *obj = event->obj; + printf("action_button_ref: %u\n", obj->ref); + ui_object_ref(obj); + ref_window = obj; +} + +void action_button_unref(UiEvent *event, void *userdata) { + UiObject *obj = userdata; + printf("action_button_unref: %u\n", obj->ref); + ui_object_unref(obj); +} + +void action_toolbar_unrefwindow(UiEvent *event, void *userdata) { + UiObject *obj = ui_simple_window("Unref", NULL); + ui_grid(obj, .margin = 20) { + ui_button(obj, .label = "Unref", .onclick = action_button_unref, .onclickdata = ref_window); + } + ui_show(obj); +} + void application_startup(UiEvent *event, void *data) { // global list UiContext *global = ui_global_context(); @@ -283,8 +306,8 @@ ui_tab(obj, "Tab 2") { ui_button(obj, .label = "Button 1 Start Thread", .onclick=action_start_thread); ui_button(obj, .label = "Button 2 Notify Thread", .onclick=action_notify_thread); - ui_button(obj, .label = "Button 3", .onclick=action_tab2_button); - ui_button(obj, .label = "Button 4", .onclick=action_tab2_button); + ui_button(obj, .label = "Obj Ref", .onclick=action_button_ref); + ui_button(obj, .label = "Obj Unref", .onclick=action_button_unref, .onclickdata = obj); ui_button(obj, .label = "Button 5", .onclick=action_tab2_button); ui_button(obj, .label = "Button 6", .onclick=action_tab2_button); } @@ -349,7 +372,7 @@ ui_toolbar_item("Test", .label = "Test", .onclick = action_toolbar_button); ui_toolbar_item("Test2", .label = "New Window", .onclick = action_toolbar_newwindow); ui_toolbar_item("Test3", .label = "Dialog", .onclick = action_toolbar_dialog); - ui_toolbar_item("Test4", .label = "Test 4", .onclick = action_toolbar_button); + ui_toolbar_item("Test4", .label = "Unref Window", .onclick = action_toolbar_unrefwindow); ui_toolbar_item("Test5", .label = "Test 5", .onclick = action_toolbar_button); ui_toolbar_item("Test6", .label = "Test 6", .onclick = action_toolbar_button); ui_toolbar_toggleitem("Toggle", .label = "Toggle", .onchange = action_toolbar_button); diff -r de653b07050b -r 03599608d555 ui/common/object.c --- a/ui/common/object.c Thu Nov 14 17:26:16 2024 +0100 +++ b/ui/common/object.c Fri Nov 15 21:16:18 2024 +0100 @@ -49,6 +49,32 @@ } } +void ui_object_ref(UiObject *obj) { + obj->ref++; +} + +void ui_object_unref(UiObject *obj) { + if(--obj->ref == 0) { + if(obj->destroy) { + obj->destroy(obj); + } else { + uic_object_destroy(obj); + } + } +} + +void uic_object_destroy(UiObject *obj) { + if(obj->ctx->close_callback) { + UiEvent ev; + ev.window = obj->window; + ev.document = obj->ctx->document; + ev.obj = obj; + ev.eventdata = NULL; + ev.intval = 0; + obj->ctx->close_callback(&ev, obj->ctx->close_data); + } + cxMempoolDestroy(obj->ctx->mp); +} UiObject* uic_object_new(UiObject *toplevel, UIWIDGET widget) { return uic_ctx_object_new(toplevel->ctx, widget); diff -r de653b07050b -r 03599608d555 ui/common/object.h --- a/ui/common/object.h Thu Nov 14 17:26:16 2024 +0100 +++ b/ui/common/object.h Fri Nov 15 21:16:18 2024 +0100 @@ -35,6 +35,8 @@ extern "C" { #endif +void uic_object_destroy(UiObject *obj); + UiObject* uic_object_new(UiObject *toplevel, UIWIDGET widget); UiObject* uic_ctx_object_new(UiContext *ctx, UIWIDGET widget); void uic_obj_add(UiObject *toplevel, UiObject *ctobj); diff -r de653b07050b -r 03599608d555 ui/gtk/window.c --- a/ui/gtk/window.c Thu Nov 14 17:26:16 2024 +0100 +++ b/ui/gtk/window.c Fri Nov 15 21:16:18 2024 +0100 @@ -51,18 +51,7 @@ static gboolean ui_window_destroy(void *data) { UiObject *obj = data; - UiEvent ev; - ev.window = obj->window; - ev.document = obj->ctx->document; - ev.obj = obj; - ev.eventdata = NULL; - ev.intval = 0; - - if(obj->ctx->close_callback) { - obj->ctx->close_callback(&ev, obj->ctx->close_data); - } - - cxMempoolDestroy(obj->ctx->mp); + uic_object_destroy(obj); nwindows--; #ifdef UI_GTK2 @@ -74,27 +63,44 @@ return FALSE; } +void ui_window_widget_destroy(UiObject *obj) { +#if GTK_MAJOR_VERSION >= 4 + gtk_window_destroy(GTK_WINDOW(obj->widget)); +#else + gtk_widget_destroy(obj->widget); +#endif +} + void ui_exit_event(GtkWidget *widget, gpointer data) { // delay exit handler - UiObject *obj = data; g_idle_add(ui_window_destroy, data); } +static gboolean ui_window_close_request(UiObject *obj) { + uic_context_prepare_close(obj->ctx); + obj->ref--; + if(obj->ref > 0) { + gtk_widget_hide(obj->widget); + return TRUE; + } else { + return FALSE; + } +} + #if GTK_MAJOR_VERSION >= 4 -static gboolean close_request(GtkWindow* self, UiContext *ctx) { - uic_context_prepare_close(ctx); - return FALSE; +static gboolean close_request(GtkWindow* self, UiObject *obj) { + return ui_window_close_request(obj); } #else -static gboolean close_request(GtkWidget* self, GdkEvent* event, UiContext *ctx) { - uic_context_prepare_close(ctx); - return FALSE; +static gboolean close_request(GtkWidget* self, GdkEvent* event, UiObject *obj) { + return ui_window_close_request(obj); } #endif static UiObject* create_window(const char *title, void *window_data, UiBool simple) { CxMempool *mp = cxBasicMempoolCreate(256); - UiObject *obj = cxCalloc(mp->allocator, 1, sizeof(UiObject)); + UiObject *obj = cxCalloc(mp->allocator, 1, sizeof(UiObject)); + obj->ref = 1; #ifdef UI_LIBADWAITA obj->widget = adw_application_window_new(ui_get_application()); @@ -130,6 +136,7 @@ window_default_height); } + obj->destroy = ui_window_widget_destroy; g_signal_connect( obj->widget, "destroy", @@ -140,13 +147,13 @@ obj->widget, "close-request", G_CALLBACK(close_request), - obj->ctx); + obj); #else g_signal_connect( obj->widget, "delete-event", G_CALLBACK(close_request), - obj->ctx); + obj); #endif GtkWidget *vbox = ui_gtk_vbox_new(0); diff -r de653b07050b -r 03599608d555 ui/ui/toolkit.h --- a/ui/ui/toolkit.h Thu Nov 14 17:26:16 2024 +0100 +++ b/ui/ui/toolkit.h Fri Nov 15 21:16:18 2024 +0100 @@ -238,6 +238,16 @@ * next container object */ UiObject *next; + + /* + * obj destroy func + */ + void (*destroy)(UiObject *obj); + + /* + * reference counter + */ + unsigned int ref; }; struct UiTabbedPane { @@ -420,6 +430,9 @@ UIEXPORT void ui_context_destroy(UiContext *ctx); +UIEXPORT void ui_object_ref(UiObject *obj); +UIEXPORT void ui_object_unref(UiObject *obj); + UIEXPORT void ui_onstartup(ui_callback f, void *userdata); UIEXPORT void ui_onopen(ui_callback f, void *userdata); UIEXPORT void ui_onexit(ui_callback f, void *userdata);