diff --git a/src/tray/unix/SDL_tray.c b/src/tray/unix/SDL_tray.c index 02b59436bc..dc2d0ca639 100644 --- a/src/tray/unix/SDL_tray.c +++ b/src/tray/unix/SDL_tray.c @@ -58,6 +58,13 @@ typedef enum static gulong (*g_signal_connect_data)(gpointer instance, const gchar *detailed_signal, GCallback c_handler, gpointer data, GClosureNotify destroy_data, GConnectFlags connect_flags); static void (*g_object_unref)(gpointer object); static gchar *(*g_mkdtemp)(gchar *template); +gpointer (*g_object_ref_sink)(gpointer object); +gpointer (*g_object_ref)(gpointer object); + +// glib_typeof requires compiler-specific code and includes that are too complex +// to be worth copy-pasting here +//#define g_object_ref(Obj) ((glib_typeof (Obj)) (g_object_ref) (Obj)) +//#define g_object_ref_sink(Obj) ((glib_typeof (Obj)) (g_object_ref_sink) (Obj)) #define g_signal_connect(instance, detailed_signal, c_handler, data) \ g_signal_connect_data ((instance), (detailed_signal), (c_handler), (data), NULL, (GConnectFlags) 0) @@ -248,6 +255,8 @@ static bool init_gtk(void) g_mkdtemp = dlsym(libgdk, "g_mkdtemp"); g_signal_connect_data = dlsym(libgdk, "g_signal_connect_data"); g_object_unref = dlsym(libgdk, "g_object_unref"); + g_object_ref_sink = dlsym(libgdk, "g_object_ref_sink"); + g_object_ref = dlsym(libgdk, "g_object_ref"); app_indicator_new = dlsym(libappindicator, "app_indicator_new"); app_indicator_set_status = dlsym(libappindicator, "app_indicator_set_status"); @@ -268,6 +277,8 @@ static bool init_gtk(void) !gtk_menu_shell_insert || !gtk_widget_destroy || !g_mkdtemp || + !g_object_ref_sink || + !g_object_ref || !g_signal_connect_data || !g_object_unref || !app_indicator_new || @@ -326,6 +337,8 @@ struct SDL_Tray { SDL_TrayMenu *menu; char icon_dir[sizeof(ICON_DIR_TEMPLATE)]; char icon_path[256]; + + GtkMenuShell *menu_cached; }; static void call_callback(GtkMenuItem *item, gpointer ptr) @@ -384,6 +397,11 @@ static void DestroySDLMenu(SDL_TrayMenu *menu) } SDL_free(menu->entries[i]); } + + if (menu->menu) { + g_object_unref(menu->menu); + } + SDL_free(menu->entries); SDL_free(menu); } @@ -435,6 +453,10 @@ SDL_Tray *SDL_CreateTray(SDL_Surface *icon, const char *tooltip) app_indicator_set_status(tray->indicator, APP_INDICATOR_STATUS_ACTIVE); + // The tray icon isn't shown before a menu is created; create one early. + tray->menu_cached = (GtkMenuShell *) g_object_ref_sink(gtk_menu_new()); + app_indicator_set_menu(tray->indicator, GTK_MENU(tray->menu_cached)); + SDL_RegisterTray(tray); return tray; @@ -478,14 +500,12 @@ SDL_TrayMenu *SDL_CreateTrayMenu(SDL_Tray *tray) return NULL; } - tray->menu->menu = (GtkMenuShell *)gtk_menu_new(); + tray->menu->menu = g_object_ref(tray->menu_cached); tray->menu->parent_tray = tray; tray->menu->parent_entry = NULL; tray->menu->nEntries = 0; tray->menu->entries = NULL; - app_indicator_set_menu(tray->indicator, GTK_MENU(tray->menu->menu)); - return tray->menu; } @@ -785,6 +805,10 @@ void SDL_DestroyTray(SDL_Tray *tray) SDL_RemovePath(tray->icon_dir); } + if (tray->menu_cached) { + g_object_unref(tray->menu_cached); + } + if (tray->indicator) { g_object_unref(tray->indicator); }