add reference counting to download window default tip

Fri, 15 Nov 2024 21:50:20 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Fri, 15 Nov 2024 21:50:20 +0100
changeset 86
8e7c57c23133
parent 85
44ebbb4c8a13

add reference counting to download window

application/davcontroller.c file | annotate | diff | comparison | revisions
ui/common/object.c file | annotate | diff | comparison | revisions
ui/common/object.h file | annotate | diff | comparison | revisions
ui/gtk/toolkit.c file | annotate | diff | comparison | revisions
ui/gtk/window.c file | annotate | diff | comparison | revisions
ui/ui/toolkit.h file | annotate | diff | comparison | revisions
--- a/application/davcontroller.c	Thu Nov 14 23:22:35 2024 +0100
+++ b/application/davcontroller.c	Fri Nov 15 21:50:20 2024 +0100
@@ -935,7 +935,7 @@
 
     free(sz_total);
     free(label1.ptr);
-
+    
 
     return 1;
 }
@@ -998,6 +998,16 @@
     return 0;
 }
 
+static int qthr_download_finished(void *data) {
+    return 0;
+}
+
+static void uithr_download_finished(UiEvent *event, void *data) {
+    DavFileDownload *download = data;
+    printf("download finished\n");
+    ui_object_unref(download->dialog);
+}
+
 
 typedef struct DlStackElm {
     DavResource *resource;
@@ -1083,6 +1093,8 @@
             ui_threadpool_job(download->queue, download->ui, qthr_download_resource, file, NULL, NULL);
         } 
     }
+    
+    ui_threadpool_job(download->queue, download->ui, qthr_download_finished, download, uithr_download_finished, download);
 
     cxListDestroy(stack);
 
@@ -1145,6 +1157,8 @@
     ui_set(download->progress, 0);
 
     ui_show(dialog);
+    
+    ui_object_ref(dialog);
 
     // start upload and stat threads
     ui_job(ui, jobthr_download_scan, download, uithr_download_scan_finished, download);
--- a/ui/common/object.c	Thu Nov 14 23:22:35 2024 +0100
+++ b/ui/common/object.c	Fri Nov 15 21:50:20 2024 +0100
@@ -49,6 +49,34 @@
     }
 }
 
+void ui_object_ref(UiObject *obj) {
+    obj->ref++;
+}
+
+void ui_object_unref(UiObject *obj) {
+    // it is possible to have 0 references, in case
+    // a window was created but ui_show was never called
+    if(obj->ref == 0 || --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);
--- a/ui/common/object.h	Thu Nov 14 23:22:35 2024 +0100
+++ b/ui/common/object.h	Fri Nov 15 21:50:20 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);
--- a/ui/gtk/toolkit.c	Thu Nov 14 23:22:35 2024 +0100
+++ b/ui/gtk/toolkit.c	Fri Nov 15 21:50:20 2024 +0100
@@ -163,6 +163,7 @@
 #elif GTK_MAJOR_VERSION <= 3
     gtk_widget_show_all(obj->widget);
 #endif
+    obj->ref++;
 }
 
 void ui_close(UiObject *obj) {
--- a/ui/gtk/window.c	Thu Nov 14 23:22:35 2024 +0100
+++ b/ui/gtk/window.c	Fri Nov 15 21:50:20 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,48 @@
     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) {
+#if GTK_CHECK_VERSION(2, 18, 0)
+        gtk_widget_set_visible(obj->widget, FALSE);
+#else
+        gtk_widget_hide(obj->widget);
+#endif
+        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 = 0;
    
 #ifdef UI_LIBADWAITA
     obj->widget = adw_application_window_new(ui_get_application());
@@ -130,6 +140,7 @@
                 window_default_height);
     }
     
+    obj->destroy = ui_window_widget_destroy;
     g_signal_connect(
             obj->widget,
             "destroy",
@@ -140,13 +151,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);
@@ -683,6 +694,8 @@
     UiObject *obj = cxCalloc(mp->allocator, 1, sizeof(UiObject)); 
     obj->ctx = uic_context(obj, mp);
     obj->widget = dialog;
+    obj->ref = 0;
+    obj->destroy = ui_window_widget_destroy;
     nwindows++;
     
     if(args.title != NULL) {
@@ -710,6 +723,19 @@
             "destroy",
             G_CALLBACK(ui_exit_event),
             obj);
+#if GTK_MAJOR_VERSION >= 4
+    g_signal_connect(
+            obj->widget,
+            "close-request",
+            G_CALLBACK(close_request),
+            obj);
+#else
+    g_signal_connect(
+            obj->widget,
+            "delete-event",
+            G_CALLBACK(close_request),
+            obj);
+#endif
     
 #if GTK_MAJOR_VERSION < 4
     GtkWidget *c = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
--- a/ui/ui/toolkit.h	Thu Nov 14 23:22:35 2024 +0100
+++ b/ui/ui/toolkit.h	Fri Nov 15 21:50:20 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);

mercurial