Skip to content

Commit 7570ab1

Browse files
committed
tray: improved error checking
Also clean up any existing trays when the program quits Fixes #11893
1 parent b716eee commit 7570ab1

File tree

9 files changed

+334
-83
lines changed

9 files changed

+334
-83
lines changed

src/SDL.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
#include "sensor/SDL_sensor_c.h"
5252
#include "stdlib/SDL_getenv_c.h"
5353
#include "thread/SDL_thread_c.h"
54+
#include "tray/SDL_tray_utils.h"
5455
#include "video/SDL_pixels_c.h"
5556
#include "video/SDL_surface_c.h"
5657
#include "video/SDL_video_c.h"
@@ -642,6 +643,7 @@ void SDL_Quit(void)
642643
SDL_HelperWindowDestroy();
643644
#endif
644645
SDL_QuitSubSystem(SDL_INIT_EVERYTHING);
646+
SDL_CleanupTrays();
645647

646648
#ifdef SDL_USE_LIBDBUS
647649
SDL_DBus_Quit();

src/SDL_utils.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,22 @@ bool SDL_ObjectValid(void *object, SDL_ObjectType type)
178178
return (((SDL_ObjectType)(uintptr_t)object_type) == type);
179179
}
180180

181+
int SDL_GetObjects(SDL_ObjectType type, void **objects, int count)
182+
{
183+
const void *object, *object_type;
184+
void *iter = NULL;
185+
int num_objects = 0;
186+
while (SDL_IterateHashTable(SDL_objects, &object, &object_type, &iter)) {
187+
if ((SDL_ObjectType)(uintptr_t)object_type == type) {
188+
if (num_objects < count) {
189+
objects[num_objects] = (void *)object;
190+
}
191+
++num_objects;
192+
}
193+
}
194+
return num_objects;
195+
}
196+
181197
void SDL_SetObjectsInvalid(void)
182198
{
183199
if (SDL_ShouldQuit(&SDL_objects_init)) {
@@ -217,6 +233,9 @@ void SDL_SetObjectsInvalid(void)
217233
case SDL_OBJECT_TYPE_THREAD:
218234
type = "thread";
219235
break;
236+
case SDL_OBJECT_TYPE_TRAY:
237+
type = "SDL_Tray";
238+
break;
220239
default:
221240
type = "unknown object";
222241
break;

src/SDL_utils_c.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,14 @@ typedef enum
6161
SDL_OBJECT_TYPE_HIDAPI_DEVICE,
6262
SDL_OBJECT_TYPE_HIDAPI_JOYSTICK,
6363
SDL_OBJECT_TYPE_THREAD,
64+
SDL_OBJECT_TYPE_TRAY,
6465

6566
} SDL_ObjectType;
6667

6768
extern Uint32 SDL_GetNextObjectID(void);
6869
extern void SDL_SetObjectValid(void *object, SDL_ObjectType type, bool valid);
6970
extern bool SDL_ObjectValid(void *object, SDL_ObjectType type);
71+
extern int SDL_GetObjects(SDL_ObjectType type, void **objects, int count);
7072
extern void SDL_SetObjectsInvalid(void);
7173

7274
extern const char *SDL_GetPersistentString(const char *string);

src/tray/SDL_tray_utils.c

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -27,38 +27,65 @@
2727

2828
static int active_trays = 0;
2929

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

37-
extern void SDL_DecrementTrayCount(void)
37+
void SDL_UnregisterTray(SDL_Tray *tray)
3838
{
39-
int toplevel_count = 0;
40-
SDL_Window *n;
39+
SDL_assert(SDL_ObjectValid(tray, SDL_OBJECT_TYPE_TRAY));
40+
41+
SDL_SetObjectValid(tray, SDL_OBJECT_TYPE_TRAY, false);
4142

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

4648
if (!SDL_GetHintBoolean(SDL_HINT_QUIT_ON_LAST_WINDOW_CLOSE, true)) {
4749
return;
4850
}
4951

50-
for (n = SDL_GetVideoDevice()->windows; n; n = n->next) {
51-
if (!n->parent && !(n->flags & SDL_WINDOW_HIDDEN)) {
52-
++toplevel_count;
52+
int toplevel_count = 0;
53+
SDL_Window **windows = SDL_GetWindows(NULL);
54+
if (windows) {
55+
for (int i = 0; windows[i]; ++i) {
56+
SDL_Window *window = windows[i];
57+
if (!window->parent && !(window->flags & SDL_WINDOW_HIDDEN)) {
58+
++toplevel_count;
59+
}
5360
}
61+
SDL_free(windows);
5462
}
5563

56-
if (toplevel_count < 1) {
64+
if (toplevel_count == 0) {
5765
SDL_SendQuit();
5866
}
5967
}
6068

61-
extern bool SDL_HasNoActiveTrays(void)
69+
void SDL_CleanupTrays(void)
70+
{
71+
if (active_trays == 0) {
72+
return;
73+
}
74+
75+
void **trays = (void **)SDL_malloc(active_trays * sizeof(*trays));
76+
if (!trays) {
77+
return;
78+
}
79+
80+
int count = SDL_GetObjects(SDL_OBJECT_TYPE_TRAY, trays, active_trays);
81+
SDL_assert(count == active_trays);
82+
for (int i = 0; i < count; ++i) {
83+
SDL_DestroyTray((SDL_Tray *)trays[i]);
84+
}
85+
SDL_free(trays);
86+
}
87+
88+
bool SDL_HasNoActiveTrays(void)
6289
{
63-
return active_trays < 1;
90+
return active_trays == 0;
6491
}

src/tray/SDL_tray_utils.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
*/
2121
#include "SDL_internal.h"
2222

23-
extern void SDL_IncrementTrayCount(void);
24-
extern void SDL_DecrementTrayCount(void);
23+
extern void SDL_RegisterTray(SDL_Tray *tray);
24+
extern void SDL_UnregisterTray(SDL_Tray *tray);
25+
extern void SDL_CleanupTrays(void);
2526
extern bool SDL_HasNoActiveTrays(void);

0 commit comments

Comments
 (0)