Cleaned up the lifetime code in unix/newcontrol.c a fair bit.

This commit is contained in:
Pietro Gagliardi 2015-04-18 17:36:12 -04:00
parent ae94993730
commit 48c609b5c3
1 changed files with 8 additions and 13 deletions

View File

@ -12,7 +12,7 @@ struct singleWidget {
gboolean containerHid; gboolean containerHid;
gboolean userDisabled; gboolean userDisabled;
gboolean containerDisabled; gboolean containerDisabled;
gboolean canDestroy; gulong destroyBlocker;
void (*onDestroy)(void *); void (*onDestroy)(void *);
void *onDestroyData; void *onDestroyData;
}; };
@ -24,7 +24,7 @@ static void singleDestroy(uiControl *c)
// first call the widget's own destruction code // first call the widget's own destruction code
(*(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
s->canDestroy = TRUE; g_signal_handler_disconnect(s->immediate, s->destroyBlocker);
// then actually destroy // then actually destroy
gtk_widget_destroy(s->immediate); gtk_widget_destroy(s->immediate);
} }
@ -165,16 +165,12 @@ static void singleContainerDisable(uiControl *c)
gtk_widget_set_sensitive(s->immediate, FALSE); gtk_widget_set_sensitive(s->immediate, FALSE);
} }
static void onDestroy(GtkWidget *widget, gpointer data) static void destroyBlocker(GtkWidget *widget, gpointer data)
{ {
singleWidget *s = (singleWidget *) data; complain("trying to destroy control at %p before uiControlDestroy()", data);
if (!s->canDestroy)
complain("trying to destroy control with singleWidget at %p before uiControlDestroy()", s);
uiFree(s);
} }
void uiUnixNewControl(uiControl *c, GType type, gboolean inScrolledWindow, gboolean scrolledWindowHasBorder, void (*destroy)(void *), void *onDestroyData, const char *firstProperty, ...) void uiUnixNewControl(uiControl *c, GType type, gboolean inScrolledWindow, gboolean scrolledWindowHasBorder, void (*onDestroy)(void *), void *onDestroyData, const char *firstProperty, ...)
{ {
singleWidget *s; singleWidget *s;
va_list ap; va_list ap;
@ -209,7 +205,7 @@ void uiUnixNewControl(uiControl *c, GType type, gboolean inScrolledWindow, gbool
// TODO double-check this for new parenting rules // TODO double-check this for new parenting rules
g_object_ref_sink(s->immediate); g_object_ref_sink(s->immediate);
s->onDestroy = destroy; s->onDestroy = onDestroy;
s->onDestroyData = onDestroyData; s->onDestroyData = onDestroyData;
// assign s later; we still need it for one more thing // assign s later; we still need it for one more thing
@ -228,9 +224,8 @@ void uiUnixNewControl(uiControl *c, GType type, gboolean inScrolledWindow, gbool
c->ContainerEnable = singleContainerEnable; c->ContainerEnable = singleContainerEnable;
c->ContainerDisable = singleContainerDisable; c->ContainerDisable = singleContainerDisable;
// and let's free everything with the immediate widget // let's stop premature destruction
// we send s as data instead of c just in case c is gone by then s->destroyBlocker = g_signal_connect(s->immediate, "destroy", G_CALLBACK(destroyBlocker), c);
g_signal_connect(s->immediate, "destroy", G_CALLBACK(onDestroy), s);
// finally, call gtk_widget_show_all() here to set the initial visibility of the widget // finally, call gtk_widget_show_all() here to set the initial visibility of the widget
gtk_widget_show_all(s->immediate); gtk_widget_show_all(s->immediate);