Skip to content

Commit

Permalink
tray: fixed multi-threading issues with GTk implementation
Browse files Browse the repository at this point in the history
GTK+ documentation states that all GDK and GTK+ calls should be made from the main thread.

Fixes libsdl-org#11984
  • Loading branch information
slouken committed Jan 20, 2025
1 parent 6612c95 commit d0529d6
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 40 deletions.
3 changes: 3 additions & 0 deletions src/events/SDL_events.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "../audio/SDL_audio_c.h"
#include "../camera/SDL_camera_c.h"
#include "../timer/SDL_timer_c.h"
#include "../tray/SDL_tray_utils.h"
#ifndef SDL_JOYSTICK_DISABLED
#include "../joystick/SDL_joystick_c.h"
#endif
Expand Down Expand Up @@ -1399,6 +1400,8 @@ static void SDL_PumpEventsInternal(bool push_sentinel)
}
#endif

SDL_UpdateTrays();

SDL_SendPendingSignalEvents(); // in case we had a signal handler fire, etc.

if (push_sentinel && SDL_EventEnabled(SDL_EVENT_POLL_SENTINEL)) {
Expand Down
1 change: 1 addition & 0 deletions src/tray/SDL_tray_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,6 @@

extern void SDL_RegisterTray(SDL_Tray *tray);
extern void SDL_UnregisterTray(SDL_Tray *tray);
extern void SDL_UpdateTrays(void);
extern void SDL_CleanupTrays(void);
extern bool SDL_HasActiveTrays(void);
4 changes: 4 additions & 0 deletions src/tray/cocoa/SDL_tray.m
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@ static void DestroySDLMenu(SDL_TrayMenu *menu)
SDL_free(menu);
}

void SDL_UpdateTrays(void)
{
}

SDL_Tray *SDL_CreateTray(SDL_Surface *icon, const char *tooltip)
{
if (!SDL_IsMainThread()) {
Expand Down
4 changes: 4 additions & 0 deletions src/tray/dummy/SDL_tray.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@

#include "../SDL_tray_utils.h"

void SDL_UpdateTrays(void)
{
}

SDL_Tray *SDL_CreateTray(SDL_Surface *icon, const char *tooltip)
{
SDL_Unsupported();
Expand Down
66 changes: 26 additions & 40 deletions src/tray/unix/SDL_tray.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,24 +78,23 @@ typedef struct _GtkMenuShell GtkMenuShell;
typedef struct _GtkWidget GtkWidget;
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);
void (*gtk_menu_item_set_submenu)(GtkMenuItem *menu_item, GtkWidget *submenu);
GtkWidget* (*gtk_check_menu_item_new_with_label)(const gchar *label);
void (*gtk_check_menu_item_set_active)(GtkCheckMenuItem *check_menu_item, gboolean is_active);
void (*gtk_widget_set_sensitive)(GtkWidget *widget, gboolean sensitive);
void (*gtk_widget_show)(GtkWidget *widget);
void (*gtk_menu_shell_append)(GtkMenuShell *menu_shell, GtkWidget *child);
void (*gtk_menu_shell_insert)(GtkMenuShell *menu_shell, GtkWidget *child, gint position);
void (*gtk_widget_destroy)(GtkWidget *widget);
const gchar *(*gtk_menu_item_get_label)(GtkMenuItem *menu_item);
void (*gtk_menu_item_set_label)(GtkMenuItem *menu_item, const gchar *label);
gboolean (*gtk_check_menu_item_get_active)(GtkCheckMenuItem *check_menu_item);
gboolean (*gtk_widget_get_sensitive)(GtkWidget *widget);
static gboolean (*gtk_init_check)(int *argc, char ***argv);
static gboolean (*gtk_main_iteration_do)(gboolean blocking);
static GtkWidget* (*gtk_menu_new)(void);
static GtkWidget* (*gtk_separator_menu_item_new)(void);
static GtkWidget* (*gtk_menu_item_new_with_label)(const gchar *label);
static void (*gtk_menu_item_set_submenu)(GtkMenuItem *menu_item, GtkWidget *submenu);
static GtkWidget* (*gtk_check_menu_item_new_with_label)(const gchar *label);
static void (*gtk_check_menu_item_set_active)(GtkCheckMenuItem *check_menu_item, gboolean is_active);
static void (*gtk_widget_set_sensitive)(GtkWidget *widget, gboolean sensitive);
static void (*gtk_widget_show)(GtkWidget *widget);
static void (*gtk_menu_shell_append)(GtkMenuShell *menu_shell, GtkWidget *child);
static void (*gtk_menu_shell_insert)(GtkMenuShell *menu_shell, GtkWidget *child, gint position);
static void (*gtk_widget_destroy)(GtkWidget *widget);
static const gchar *(*gtk_menu_item_get_label)(GtkMenuItem *menu_item);
static void (*gtk_menu_item_set_label)(GtkMenuItem *menu_item, const gchar *label);
static gboolean (*gtk_check_menu_item_get_active)(GtkCheckMenuItem *check_menu_item);
static gboolean (*gtk_widget_get_sensitive)(GtkWidget *widget);

#define GTK_MENU_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_MENU_ITEM, GtkMenuItem))
#define GTK_WIDGET(widget) (G_TYPE_CHECK_INSTANCE_CAST ((widget), GTK_TYPE_WIDGET, GtkWidget))
Expand Down Expand Up @@ -128,14 +127,6 @@ void (*app_indicator_set_menu)(AppIndicator *self, GtkMenu *menu);
/* ------------------------------------------------------------------------- */
#endif

static int main_gtk_thread(void *data)
{
gtk_main();
return 0;
}

static bool gtk_thread_active = false;

#ifdef APPINDICATOR_HEADER

static void quit_gtk(void)
Expand Down Expand Up @@ -232,8 +223,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_main_iteration_do = dlsym(libgtk, "gtk_main_iteration_do");
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");
Expand Down Expand Up @@ -262,8 +252,7 @@ static bool init_gtk(void)
app_indicator_set_menu = dlsym(libappindicator, "app_indicator_set_menu");

if (!gtk_init_check ||
!gtk_main ||
!gtk_main_quit ||
!gtk_main_iteration_do ||
!gtk_menu_new ||
!gtk_separator_menu_item_new ||
!gtk_menu_item_new_with_label ||
Expand Down Expand Up @@ -396,6 +385,13 @@ static void DestroySDLMenu(SDL_TrayMenu *menu)
SDL_free(menu);
}

void SDL_UpdateTrays(void)
{
if (SDL_HasActiveTrays()) {
gtk_main_iteration_do(FALSE);
}
}

SDL_Tray *SDL_CreateTray(SDL_Surface *icon, const char *tooltip)
{
if (!SDL_IsMainThread()) {
Expand All @@ -407,11 +403,6 @@ 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_calloc(1, sizeof(*tray));
if (!tray) {
return NULL;
Expand Down Expand Up @@ -799,9 +790,4 @@ void SDL_DestroyTray(SDL_Tray *tray)
}

SDL_free(tray);

if (!SDL_HasActiveTrays()) {
gtk_main_quit();
gtk_thread_active = false;
}
}
4 changes: 4 additions & 0 deletions src/tray/windows/SDL_tray.c
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,10 @@ static HICON load_default_icon()
return LoadIcon(NULL, IDI_APPLICATION);
}

void SDL_UpdateTrays(void)
{
}

SDL_Tray *SDL_CreateTray(SDL_Surface *icon, const char *tooltip)
{
if (!SDL_IsMainThread()) {
Expand Down

0 comments on commit d0529d6

Please sign in to comment.