Finished cleaning up the GTK+ lifetiming code. Yeah, this will definitely work.

This commit is contained in:
Pietro Gagliardi 2015-04-18 17:46:37 -04:00
parent 48c609b5c3
commit 89d584cdcd
4 changed files with 15 additions and 11 deletions

View File

@ -20,7 +20,7 @@
- verify that uiParentSetMainControl() does indeed not update - verify that uiParentSetMainControl() does indeed not update
- settle differences between intmax_t and uintmax_t - settle differences between intmax_t and uintmax_t
- settle onDestroy/destroy naming - settle onDestroy/destroy naming
- clean up Unix lifetiming code - clean up Windows lifetiming code
ultimately: ultimately:
- make everything vtable-based - make everything vtable-based

View File

@ -25,8 +25,10 @@ static void singleDestroy(uiControl *c)
(*(s->onDestroy))(s->onDestroyData); (*(s->onDestroy))(s->onDestroyData);
// then mark that we are ready to be destroyed // then mark that we are ready to be destroyed
g_signal_handler_disconnect(s->immediate, s->destroyBlocker); g_signal_handler_disconnect(s->immediate, s->destroyBlocker);
// then actually destroy // then actually destroy (TODO sync these comments)
gtk_widget_destroy(s->immediate); gtk_widget_destroy(s->immediate);
// and free ourselves
uiFree(s);
} }
static uintptr_t singleHandle(uiControl *c) static uintptr_t singleHandle(uiControl *c)

View File

@ -46,6 +46,8 @@ static void uipParent_dispose(GObject *obj)
if (!p->canDestroy) if (!p->canDestroy)
complain("attempt to dispose uiParent with uipParent at %p before uiParentDestroy()", p); complain("attempt to dispose uiParent with uipParent at %p before uiParentDestroy()", p);
if (p->children != NULL) { if (p->children != NULL) {
if (p->children->len != 0)
complain("disposing uiParent with uipParent at %p while there are still children", p);
g_ptr_array_unref(p->children); g_ptr_array_unref(p->children);
p->children = NULL; p->children = NULL;
} }
@ -150,6 +152,8 @@ static void parentDestroy(uiParent *pp)
p->canDestroy = TRUE; p->canDestroy = TRUE;
// finally, destroy the parent // finally, destroy the parent
gtk_widget_destroy(GTK_WIDGET(p)); gtk_widget_destroy(GTK_WIDGET(p));
// and free ourselves
uiFree(pp);
} }
static uintptr_t parentHandle(uiParent *p) static uintptr_t parentHandle(uiParent *p)

View File

@ -10,7 +10,7 @@ struct window {
int (*onClosing)(uiWindow *, void *); int (*onClosing)(uiWindow *, void *);
void *onClosingData; void *onClosingData;
int margined; int margined;
gboolean canDestroy; gulong destroyBlocker;
}; };
static gboolean onClosing(GtkWidget *win, GdkEvent *e, gpointer data) static gboolean onClosing(GtkWidget *win, GdkEvent *e, gpointer data)
@ -28,13 +28,9 @@ static int defaultOnClosing(uiWindow *w, void *data)
return 1; return 1;
} }
static void onDestroy(GtkWidget *widget, gpointer data) static void destroyBlocker(GtkWidget *widget, gpointer data)
{ {
struct window *w = (struct window *) data; complain("attempt to dispose uiWindow at %p before uiWindowDestroy()", data);
if (!w->canDestroy)
complain("attempt to dispose uiWindow at %p before uiWindowDestroy()", w);
uiFree(w);
} }
// TODO should we change the GtkWindow's child first? // TODO should we change the GtkWindow's child first?
@ -47,9 +43,11 @@ static void windowDestroy(uiWindow *ww)
// next, destroy the content uiParent // next, destroy the content uiParent
uiParentDestroy(w->content); uiParentDestroy(w->content);
// now that we cleaned up properly, we can mark our window as ready to be destroyed // now that we cleaned up properly, we can mark our window as ready to be destroyed
w->canDestroy = TRUE; g_signal_handler_disconnect(w->widget, w->destroyBlocker);
// finally, destroy the window // finally, destroy the window
gtk_widget_destroy(w->widget); gtk_widget_destroy(w->widget);
// and free ourselves
uiFree(w);
} }
static uintptr_t windowHandle(uiWindow *ww) static uintptr_t windowHandle(uiWindow *ww)
@ -136,7 +134,7 @@ uiWindow *uiNewWindow(const char *title, int width, int height)
gtk_window_resize(w->window, width, height); gtk_window_resize(w->window, width, height);
g_signal_connect(w->widget, "delete-event", G_CALLBACK(onClosing), w); g_signal_connect(w->widget, "delete-event", G_CALLBACK(onClosing), w);
g_signal_connect(w->widget, "destroy", G_CALLBACK(onDestroy), w); w->destroyBlocker = g_signal_connect(w->widget, "destroy", G_CALLBACK(destroyBlocker), w);
w->content = uiNewParent((uintptr_t) (w->container)); w->content = uiNewParent((uintptr_t) (w->container));
w->onClosing = defaultOnClosing; w->onClosing = defaultOnClosing;