diff options
author | StapleButter <thetotalworm@gmail.com> | 2017-12-05 05:21:11 +0100 |
---|---|---|
committer | StapleButter <thetotalworm@gmail.com> | 2017-12-05 05:21:11 +0100 |
commit | 10b797e53d4e6788fa30089de6242780af8c6db1 (patch) | |
tree | a05fb878862de26f925fb936099375fa62840838 /src/libui_sdl | |
parent | 746b4db3829d830813a2f79a958a645935eec51d (diff) |
libui/GTK: properly clean up menus, so it doesn't crash upon exit
Diffstat (limited to 'src/libui_sdl')
-rw-r--r-- | src/libui_sdl/libui/unix/menu.c | 45 |
1 files changed, 31 insertions, 14 deletions
diff --git a/src/libui_sdl/libui/unix/menu.c b/src/libui_sdl/libui/unix/menu.c index c4affd2..d6aa398 100644 --- a/src/libui_sdl/libui/unix/menu.c +++ b/src/libui_sdl/libui/unix/menu.c @@ -2,6 +2,7 @@ #include "uipriv_unix.h" static GArray *menus = NULL; +static guint nmenus = 0; static gboolean menusFinalized = FALSE; static gboolean hasQuit = FALSE; static gboolean hasPreferences = FALSE; @@ -11,6 +12,7 @@ struct uiMenu { char *name; GArray *items; // []*uiMenuItem gboolean ischild; + guint id; }; struct uiMenuItem { @@ -267,6 +269,8 @@ uiMenu *uiNewMenu(const char *name) m = uiNew(uiMenu); g_array_append_val(menus, m); + m->id = nmenus; + nmenus++; m->name = g_strdup(name); m->items = g_array_new(FALSE, TRUE, sizeof (uiMenuItem *)); @@ -345,6 +349,8 @@ struct freeMenuItemData { guint i; }; +static void freeMenu(GtkWidget *widget, gpointer data); + static void freeMenuItem(GtkWidget *widget, gpointer data) { struct freeMenuItemData *fmi = (struct freeMenuItemData *) data; @@ -352,6 +358,8 @@ static void freeMenuItem(GtkWidget *widget, gpointer data) struct menuItemWindow *w; item = g_array_index(fmi->items, uiMenuItem *, fmi->i); + if (item->popupchild != NULL) + freeMenu(widget, &item->popupchild->id); w = (struct menuItemWindow *) g_hash_table_lookup(item->windows, widget); if (g_hash_table_remove(item->windows, widget) == FALSE) implbug("GtkMenuItem %p not in menu item's item/window map", widget); @@ -385,28 +393,37 @@ void freeMenubar(GtkWidget *mb) // no need to worry about destroying any widgets; destruction of the window they're in will do it for us } +void _freeMenu(uiMenu* m) +{ + uiMenuItem *item; + guint j; + + g_free(m->name); + for (j = 0; j < m->items->len; j++) { + item = g_array_index(m->items, uiMenuItem *, j); + if (item->popupchild != NULL) _freeMenu(item->popupchild); + if (g_hash_table_size(item->windows) != 0) + // TODO is this really a userbug()? + implbug("menu item %p (%s) still has uiWindows attached; did you forget to destroy some windows?", item, item->name); + if (item->type != typeSubmenu) g_free(item->name); + g_hash_table_destroy(item->windows); + uiFree(item); + } + g_array_free(m->items, TRUE); + uiFree(m); +} + void uninitMenus(void) { uiMenu *m; - uiMenuItem *item; - guint i, j; + guint i; if (menus == NULL) return; for (i = 0; i < menus->len; i++) { m = g_array_index(menus, uiMenu *, i); - g_free(m->name); - for (j = 0; j < m->items->len; j++) { - item = g_array_index(m->items, uiMenuItem *, j); - if (g_hash_table_size(item->windows) != 0) - // TODO is this really a userbug()? - implbug("menu item %p (%s) still has uiWindows attached; did you forget to destroy some windows?", item, item->name); - g_free(item->name); - g_hash_table_destroy(item->windows); - uiFree(item); - } - g_array_free(m->items, TRUE); - uiFree(m); + if (m->ischild) continue; + _freeMenu(m); } g_array_free(menus, TRUE); } |