From 0ae57f1d90d770a5d294e544815e4498f6f47109 Mon Sep 17 00:00:00 2001 From: David Gow Date: Sun, 5 Jan 2025 17:54:55 +0800 Subject: [PATCH] tray: unix: Shutdown the GTK thread when not in use When using the libappindicator/gtk/unix Tray backend, the background thread which calls gtk_main() is never destroyed. This means that we detect a leaked thread as SDL_Quit(). Instead, tell gtk to shut down its main loop when no tray icons are active. This fixes the issue here: SDL notices no leak, and repeatedly creating / destroying tray icons seems to work fine. Signed-off-by: David Gow --- src/tray/unix/SDL_tray.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/tray/unix/SDL_tray.c b/src/tray/unix/SDL_tray.c index 994fb5de95..e4f0208f4a 100644 --- a/src/tray/unix/SDL_tray.c +++ b/src/tray/unix/SDL_tray.c @@ -78,7 +78,7 @@ typedef struct _GtkCheckMenuItem GtkCheckMenuItem; gboolean (*gtk_init_check)(int *argc, char ***argv); void (*gtk_main)(void); - +void (*gtk_main_quit)(void); GtkWidget* (*gtk_menu_new)(void); GtkWidget* (*gtk_separator_menu_item_new)(void); GtkWidget* (*gtk_menu_item_new_with_label)(const gchar *label); @@ -132,6 +132,8 @@ static int main_gtk_thread(void *data) return 0; } +static bool gtk_thread_active = false; + #ifdef APPINDICATOR_HEADER static void quit_gtk(void) @@ -140,7 +142,7 @@ static void quit_gtk(void) static bool init_gtk(void) { - SDL_DetachThread(SDL_CreateThread(main_gtk_thread, "tray gtk", NULL)); + } #else @@ -223,6 +225,7 @@ static bool init_gtk(void) gtk_init_check = dlsym(libgtk, "gtk_init_check"); gtk_main = dlsym(libgtk, "gtk_main"); + gtk_main_quit = dlsym(libgtk, "gtk_main_quit"); gtk_menu_new = dlsym(libgtk, "gtk_menu_new"); gtk_separator_menu_item_new = dlsym(libgtk, "gtk_separator_menu_item_new"); gtk_menu_item_new_with_label = dlsym(libgtk, "gtk_menu_item_new_with_label"); @@ -249,6 +252,7 @@ static bool init_gtk(void) if (!gtk_init_check || !gtk_main || + !gtk_main_quit || !gtk_menu_new || !gtk_separator_menu_item_new || !gtk_menu_item_new_with_label || @@ -281,8 +285,6 @@ static bool init_gtk(void) gtk_is_init = true; - SDL_DetachThread(SDL_CreateThread(main_gtk_thread, "tray gtk", NULL)); - return true; } #endif @@ -383,6 +385,11 @@ SDL_Tray *SDL_CreateTray(SDL_Surface *icon, const char *tooltip) return NULL; } + if (!gtk_thread_active) { + SDL_DetachThread(SDL_CreateThread(main_gtk_thread, "tray gtk", NULL)); + gtk_thread_active = true; + } + SDL_Tray *tray = (SDL_Tray *) SDL_malloc(sizeof(SDL_Tray)); if (!tray) { @@ -674,4 +681,9 @@ void SDL_DestroyTray(SDL_Tray *tray) SDL_free(tray); SDL_DecrementTrayCount(); + + if (SDL_HasNoActiveTrays()) { + gtk_main_quit(); + gtk_thread_active = false; + } }