Cleaned up memory leaks in the GTK+ backend.

This commit is contained in:
Pietro Gagliardi 2015-04-08 01:16:22 -04:00
parent f5c8bdd4b3
commit d37bc67158
4 changed files with 37 additions and 3 deletions

View File

@ -19,7 +19,13 @@ static void defaultOnClicked(uiControl *c, void *data)
// do nothing // do nothing
} }
// TODO destruction static void onDestroy(GtkWidget *widget, gpointer data)
{
struct button *b = (struct button *) data;
uiFree(b);
}
uiControl *uiNewButton(const char *text) uiControl *uiNewButton(const char *text)
{ {
struct button *b; struct button *b;
@ -33,6 +39,7 @@ uiControl *uiNewButton(const char *text)
NULL); NULL);
widget = GTK_WIDGET(uiControlHandle(b->c)); widget = GTK_WIDGET(uiControlHandle(b->c));
g_signal_connect(widget, "destroy", G_CALLBACK(onDestroy), b);
g_signal_connect(widget, "clicked", G_CALLBACK(onClicked), b); g_signal_connect(widget, "clicked", G_CALLBACK(onClicked), b);
b->onClicked = defaultOnClicked; b->onClicked = defaultOnClicked;

View File

@ -15,6 +15,10 @@ static void uiContainer_init(uiContainer *c)
static void uiContainer_dispose(GObject *obj) static void uiContainer_dispose(GObject *obj)
{ {
g_ptr_array_unref(uiContainer(obj)->children); g_ptr_array_unref(uiContainer(obj)->children);
if (uiContainer(obj)->child != NULL) {
uiControlDestroy(uiContainer(obj)->child);
uiContainer(obj)->child = NULL;
}
G_OBJECT_CLASS(uiContainer_parent_class)->dispose(obj); G_OBJECT_CLASS(uiContainer_parent_class)->dispose(obj);
} }

View File

@ -13,6 +13,11 @@ struct uiSingleWidgetControl {
#define S(c) ((uiSingleWidgetControl *) (c)) #define S(c) ((uiSingleWidgetControl *) (c))
static void singleDestroy(uiControl *c)
{
gtk_widget_destroy(S(c)->immediate);
}
static uintptr_t singleHandle(uiControl *c) static uintptr_t singleHandle(uiControl *c)
{ {
return (uintptr_t) (S(c)->widget); return (uintptr_t) (S(c)->widget);
@ -48,7 +53,12 @@ static void singleResize(uiControl *c, intmax_t x, intmax_t y, intmax_t width, i
gtk_widget_size_allocate(S(c)->immediate, &a); gtk_widget_size_allocate(S(c)->immediate, &a);
} }
// TODO connect free function static void onDestroy(GtkWidget *widget, gpointer data)
{
uiSingleWidgetControl *c = (uiSingleWidgetControl *) data;
uiFree(c);
}
uiControl *uiUnixNewControl(GType type, gboolean inScrolledWindow, gboolean needsViewport, gboolean scrolledWindowHasBorder, void *data, const char *firstProperty, ...) uiControl *uiUnixNewControl(GType type, gboolean inScrolledWindow, gboolean needsViewport, gboolean scrolledWindowHasBorder, void *data, const char *firstProperty, ...)
{ {
@ -75,6 +85,19 @@ uiControl *uiUnixNewControl(GType type, gboolean inScrolledWindow, gboolean need
c->immediate = c->scrolledWindow; c->immediate = c->scrolledWindow;
} }
// we need to keep an extra reference on the immediate widget
// this is so uiControlDestroy() can work regardless of when it is called and who calls it
// without this:
// - end user call works (only one ref)
// - call in uiContainer destructor fails (uiContainer ref freed)
// with this:
// - end user call works (shoudn't be in any container)
// - call in uiContainer works (both refs freed)
g_object_ref_sink(c->immediate);
// and let's free the uiSingleWidgetControl with it
g_signal_connect(c->immediate, "destroy", G_CALLBACK(onDestroy), c);
c->control.destroy = singleDestroy;
c->control.handle = singleHandle; c->control.handle = singleHandle;
c->control.setParent = singleSetParent; c->control.setParent = singleSetParent;
c->control.preferredSize = singlePreferredSize; c->control.preferredSize = singlePreferredSize;

View File

@ -8,7 +8,7 @@ struct uiWindow {
void *onClosingData; void *onClosingData;
}; };
static void onDestroy(GtkWindow *window, gpointer data) static void onDestroy(GtkWidget *widget, gpointer data)
{ {
uiWindow *w = (uiWindow *) data; uiWindow *w = (uiWindow *) data;