Skip to content

Commit

Permalink
tray: improved error checking
Browse files Browse the repository at this point in the history
Also clean up any existing trays when the program quits

Fixes libsdl-org#11893
  • Loading branch information
slouken committed Jan 19, 2025
1 parent 20ad2f3 commit 10eacc2
Show file tree
Hide file tree
Showing 9 changed files with 331 additions and 75 deletions.
2 changes: 2 additions & 0 deletions src/SDL.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
#include "sensor/SDL_sensor_c.h"
#include "stdlib/SDL_getenv_c.h"
#include "thread/SDL_thread_c.h"
#include "tray/SDL_tray_utils.h"
#include "video/SDL_pixels_c.h"
#include "video/SDL_surface_c.h"
#include "video/SDL_video_c.h"
Expand Down Expand Up @@ -642,6 +643,7 @@ void SDL_Quit(void)
SDL_HelperWindowDestroy();
#endif
SDL_QuitSubSystem(SDL_INIT_EVERYTHING);
SDL_CleanupTrays();

#ifdef SDL_USE_LIBDBUS
SDL_DBus_Quit();
Expand Down
19 changes: 19 additions & 0 deletions src/SDL_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,22 @@ bool SDL_ObjectValid(void *object, SDL_ObjectType type)
return (((SDL_ObjectType)(uintptr_t)object_type) == type);
}

int SDL_GetObjects(SDL_ObjectType type, void **objects, int count)
{
const void *object, *object_type;
void *iter = NULL;
int num_objects = 0;
while (SDL_IterateHashTable(SDL_objects, &object, &object_type, &iter)) {
if ((SDL_ObjectType)(uintptr_t)object_type == type) {
if (num_objects < count) {
objects[num_objects] = (void *)object;
}
++num_objects;
}
}
return num_objects;
}

void SDL_SetObjectsInvalid(void)
{
if (SDL_ShouldQuit(&SDL_objects_init)) {
Expand Down Expand Up @@ -217,6 +233,9 @@ void SDL_SetObjectsInvalid(void)
case SDL_OBJECT_TYPE_THREAD:
type = "thread";
break;
case SDL_OBJECT_TYPE_TRAY:
type = "SDL_Tray";
break;
default:
type = "unknown object";
break;
Expand Down
2 changes: 2 additions & 0 deletions src/SDL_utils_c.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,14 @@ typedef enum
SDL_OBJECT_TYPE_HIDAPI_DEVICE,
SDL_OBJECT_TYPE_HIDAPI_JOYSTICK,
SDL_OBJECT_TYPE_THREAD,
SDL_OBJECT_TYPE_TRAY,

} SDL_ObjectType;

extern Uint32 SDL_GetNextObjectID(void);
extern void SDL_SetObjectValid(void *object, SDL_ObjectType type, bool valid);
extern bool SDL_ObjectValid(void *object, SDL_ObjectType type);
extern int SDL_GetObjects(SDL_ObjectType type, void **objects, int count);
extern void SDL_SetObjectsInvalid(void);

extern const char *SDL_GetPersistentString(const char *string);
Expand Down
57 changes: 42 additions & 15 deletions src/tray/SDL_tray_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,38 +27,65 @@

static int active_trays = 0;

extern void SDL_IncrementTrayCount(void)
void SDL_RegisterTray(SDL_Tray *tray)
{
if (++active_trays < 1) {
SDL_Log("Active tray count corrupted (%d < 1), this is a bug. The app may close or fail to close unexpectedly.", active_trays);
}
SDL_SetObjectValid(tray, SDL_OBJECT_TYPE_TRAY, true);

++active_trays;
}

extern void SDL_DecrementTrayCount(void)
void SDL_UnregisterTray(SDL_Tray *tray)
{
int toplevel_count = 0;
SDL_Window *n;
SDL_assert(SDL_ObjectValid(tray, SDL_OBJECT_TYPE_TRAY));

SDL_SetObjectValid(tray, SDL_OBJECT_TYPE_TRAY, false);

if (--active_trays < 0) {
SDL_Log("Active tray count corrupted (%d < 0), this is a bug. The app may close or fail to close unexpectedly.", active_trays);
--active_trays;
if (active_trays > 0) {
return;
}

if (!SDL_GetHintBoolean(SDL_HINT_QUIT_ON_LAST_WINDOW_CLOSE, true)) {
return;
}

for (n = SDL_GetVideoDevice()->windows; n; n = n->next) {
if (!n->parent && !(n->flags & SDL_WINDOW_HIDDEN)) {
++toplevel_count;
int toplevel_count = 0;
SDL_Window **windows = SDL_GetWindows(NULL);
if (windows) {
for (int i = 0; windows[i]; ++i) {
SDL_Window *window = windows[i];
if (!window->parent && !(window->flags & SDL_WINDOW_HIDDEN)) {
++toplevel_count;
}
}
SDL_free(windows);
}

if (toplevel_count < 1) {
if (toplevel_count == 0) {
SDL_SendQuit();
}
}

extern bool SDL_HasNoActiveTrays(void)
void SDL_CleanupTrays(void)
{
if (active_trays == 0) {
return;
}

void **trays = (void **)SDL_malloc(active_trays * sizeof(*trays));
if (!trays) {
return;
}

int count = SDL_GetObjects(SDL_OBJECT_TYPE_TRAY, trays, active_trays);
SDL_assert(count == active_trays);
for (int i = 0; i < count; ++i) {
SDL_DestroyTray((SDL_Tray *)trays[i]);
}
SDL_free(trays);
}

bool SDL_HasNoActiveTrays(void)
{
return active_trays < 1;
return active_trays == 0;
}
5 changes: 3 additions & 2 deletions src/tray/SDL_tray_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
*/
#include "SDL_internal.h"

extern void SDL_IncrementTrayCount(void);
extern void SDL_DecrementTrayCount(void);
extern void SDL_RegisterTray(SDL_Tray *tray);
extern void SDL_UnregisterTray(SDL_Tray *tray);
extern void SDL_CleanupTrays(void);
extern bool SDL_HasNoActiveTrays(void);
Loading

0 comments on commit 10eacc2

Please sign in to comment.