tray: improved error checking
Also clean up any existing trays when the program quits Fixes https://github.com/libsdl-org/SDL/issues/11893
This commit is contained in:
@@ -51,6 +51,7 @@
|
|||||||
#include "sensor/SDL_sensor_c.h"
|
#include "sensor/SDL_sensor_c.h"
|
||||||
#include "stdlib/SDL_getenv_c.h"
|
#include "stdlib/SDL_getenv_c.h"
|
||||||
#include "thread/SDL_thread_c.h"
|
#include "thread/SDL_thread_c.h"
|
||||||
|
#include "tray/SDL_tray_utils.h"
|
||||||
#include "video/SDL_pixels_c.h"
|
#include "video/SDL_pixels_c.h"
|
||||||
#include "video/SDL_surface_c.h"
|
#include "video/SDL_surface_c.h"
|
||||||
#include "video/SDL_video_c.h"
|
#include "video/SDL_video_c.h"
|
||||||
@@ -642,6 +643,7 @@ void SDL_Quit(void)
|
|||||||
SDL_HelperWindowDestroy();
|
SDL_HelperWindowDestroy();
|
||||||
#endif
|
#endif
|
||||||
SDL_QuitSubSystem(SDL_INIT_EVERYTHING);
|
SDL_QuitSubSystem(SDL_INIT_EVERYTHING);
|
||||||
|
SDL_CleanupTrays();
|
||||||
|
|
||||||
#ifdef SDL_USE_LIBDBUS
|
#ifdef SDL_USE_LIBDBUS
|
||||||
SDL_DBus_Quit();
|
SDL_DBus_Quit();
|
||||||
|
|||||||
@@ -178,6 +178,22 @@ bool SDL_ObjectValid(void *object, SDL_ObjectType type)
|
|||||||
return (((SDL_ObjectType)(uintptr_t)object_type) == 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)
|
void SDL_SetObjectsInvalid(void)
|
||||||
{
|
{
|
||||||
if (SDL_ShouldQuit(&SDL_objects_init)) {
|
if (SDL_ShouldQuit(&SDL_objects_init)) {
|
||||||
@@ -217,6 +233,9 @@ void SDL_SetObjectsInvalid(void)
|
|||||||
case SDL_OBJECT_TYPE_THREAD:
|
case SDL_OBJECT_TYPE_THREAD:
|
||||||
type = "thread";
|
type = "thread";
|
||||||
break;
|
break;
|
||||||
|
case SDL_OBJECT_TYPE_TRAY:
|
||||||
|
type = "SDL_Tray";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
type = "unknown object";
|
type = "unknown object";
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -61,12 +61,14 @@ typedef enum
|
|||||||
SDL_OBJECT_TYPE_HIDAPI_DEVICE,
|
SDL_OBJECT_TYPE_HIDAPI_DEVICE,
|
||||||
SDL_OBJECT_TYPE_HIDAPI_JOYSTICK,
|
SDL_OBJECT_TYPE_HIDAPI_JOYSTICK,
|
||||||
SDL_OBJECT_TYPE_THREAD,
|
SDL_OBJECT_TYPE_THREAD,
|
||||||
|
SDL_OBJECT_TYPE_TRAY,
|
||||||
|
|
||||||
} SDL_ObjectType;
|
} SDL_ObjectType;
|
||||||
|
|
||||||
extern Uint32 SDL_GetNextObjectID(void);
|
extern Uint32 SDL_GetNextObjectID(void);
|
||||||
extern void SDL_SetObjectValid(void *object, SDL_ObjectType type, bool valid);
|
extern void SDL_SetObjectValid(void *object, SDL_ObjectType type, bool valid);
|
||||||
extern bool SDL_ObjectValid(void *object, SDL_ObjectType type);
|
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 void SDL_SetObjectsInvalid(void);
|
||||||
|
|
||||||
extern const char *SDL_GetPersistentString(const char *string);
|
extern const char *SDL_GetPersistentString(const char *string);
|
||||||
|
|||||||
@@ -27,38 +27,65 @@
|
|||||||
|
|
||||||
static int active_trays = 0;
|
static int active_trays = 0;
|
||||||
|
|
||||||
extern void SDL_IncrementTrayCount(void)
|
void SDL_RegisterTray(SDL_Tray *tray)
|
||||||
{
|
{
|
||||||
if (++active_trays < 1) {
|
SDL_SetObjectValid(tray, SDL_OBJECT_TYPE_TRAY, true);
|
||||||
SDL_Log("Active tray count corrupted (%d < 1), this is a bug. The app may close or fail to close unexpectedly.", active_trays);
|
|
||||||
}
|
++active_trays;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void SDL_DecrementTrayCount(void)
|
void SDL_UnregisterTray(SDL_Tray *tray)
|
||||||
{
|
{
|
||||||
int toplevel_count = 0;
|
SDL_assert(SDL_ObjectValid(tray, SDL_OBJECT_TYPE_TRAY));
|
||||||
SDL_Window *n;
|
|
||||||
|
|
||||||
if (--active_trays < 0) {
|
SDL_SetObjectValid(tray, SDL_OBJECT_TYPE_TRAY, false);
|
||||||
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)) {
|
if (!SDL_GetHintBoolean(SDL_HINT_QUIT_ON_LAST_WINDOW_CLOSE, true)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (n = SDL_GetVideoDevice()->windows; n; n = n->next) {
|
int toplevel_count = 0;
|
||||||
if (!n->parent && !(n->flags & SDL_WINDOW_HIDDEN)) {
|
SDL_Window **windows = SDL_GetWindows(NULL);
|
||||||
++toplevel_count;
|
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();
|
SDL_SendQuit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern bool SDL_HasNoActiveTrays(void)
|
void SDL_CleanupTrays(void)
|
||||||
{
|
{
|
||||||
return active_trays < 1;
|
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 == 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
*/
|
*/
|
||||||
#include "SDL_internal.h"
|
#include "SDL_internal.h"
|
||||||
|
|
||||||
extern void SDL_IncrementTrayCount(void);
|
extern void SDL_RegisterTray(SDL_Tray *tray);
|
||||||
extern void SDL_DecrementTrayCount(void);
|
extern void SDL_UnregisterTray(SDL_Tray *tray);
|
||||||
|
extern void SDL_CleanupTrays(void);
|
||||||
extern bool SDL_HasNoActiveTrays(void);
|
extern bool SDL_HasNoActiveTrays(void);
|
||||||
|
|||||||
@@ -80,8 +80,16 @@ static void DestroySDLMenu(SDL_TrayMenu *menu)
|
|||||||
|
|
||||||
SDL_Tray *SDL_CreateTray(SDL_Surface *icon, const char *tooltip)
|
SDL_Tray *SDL_CreateTray(SDL_Surface *icon, const char *tooltip)
|
||||||
{
|
{
|
||||||
|
if (icon) {
|
||||||
|
icon = SDL_ConvertSurface(icon, SDL_PIXELFORMAT_RGBA32);
|
||||||
|
if (!icon) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SDL_Tray *tray = (SDL_Tray *)SDL_calloc(1, sizeof(*tray));
|
SDL_Tray *tray = (SDL_Tray *)SDL_calloc(1, sizeof(*tray));
|
||||||
if (!tray) {
|
if (!tray) {
|
||||||
|
SDL_DestroySurface(icon);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,22 +105,17 @@ SDL_Tray *SDL_CreateTray(SDL_Surface *icon, const char *tooltip)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (icon) {
|
if (icon) {
|
||||||
SDL_Surface *iconfmt = SDL_ConvertSurface(icon, SDL_PIXELFORMAT_RGBA32);
|
NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:(unsigned char **)&icon->pixels
|
||||||
if (!iconfmt) {
|
pixelsWide:icon->w
|
||||||
goto skip_putting_an_icon;
|
pixelsHigh:icon->h
|
||||||
}
|
|
||||||
|
|
||||||
NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:(unsigned char **)&iconfmt->pixels
|
|
||||||
pixelsWide:iconfmt->w
|
|
||||||
pixelsHigh:iconfmt->h
|
|
||||||
bitsPerSample:8
|
bitsPerSample:8
|
||||||
samplesPerPixel:4
|
samplesPerPixel:4
|
||||||
hasAlpha:YES
|
hasAlpha:YES
|
||||||
isPlanar:NO
|
isPlanar:NO
|
||||||
colorSpaceName:NSCalibratedRGBColorSpace
|
colorSpaceName:NSCalibratedRGBColorSpace
|
||||||
bytesPerRow:iconfmt->pitch
|
bytesPerRow:icon->pitch
|
||||||
bitsPerPixel:32];
|
bitsPerPixel:32];
|
||||||
NSImage *iconimg = [[NSImage alloc] initWithSize:NSMakeSize(iconfmt->w, iconfmt->h)];
|
NSImage *iconimg = [[NSImage alloc] initWithSize:NSMakeSize(icon->w, icon->h)];
|
||||||
[iconimg addRepresentation:bitmap];
|
[iconimg addRepresentation:bitmap];
|
||||||
|
|
||||||
/* A typical icon size is 22x22 on macOS. Failing to resize the icon
|
/* A typical icon size is 22x22 on macOS. Failing to resize the icon
|
||||||
@@ -125,39 +128,42 @@ SDL_Tray *SDL_CreateTray(SDL_Surface *icon, const char *tooltip)
|
|||||||
|
|
||||||
tray->statusItem.button.image = iconimg22;
|
tray->statusItem.button.image = iconimg22;
|
||||||
|
|
||||||
SDL_DestroySurface(iconfmt);
|
SDL_DestroySurface(icon);
|
||||||
}
|
}
|
||||||
|
|
||||||
skip_putting_an_icon:
|
SDL_RegisterTray(tray);
|
||||||
SDL_IncrementTrayCount();
|
|
||||||
|
|
||||||
return tray;
|
return tray;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDL_SetTrayIcon(SDL_Tray *tray, SDL_Surface *icon)
|
void SDL_SetTrayIcon(SDL_Tray *tray, SDL_Surface *icon)
|
||||||
{
|
{
|
||||||
|
if (!SDL_ObjectValid(tray, SDL_OBJECT_TYPE_TRAY)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!icon) {
|
if (!icon) {
|
||||||
tray->statusItem.button.image = nil;
|
tray->statusItem.button.image = nil;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_Surface *iconfmt = SDL_ConvertSurface(icon, SDL_PIXELFORMAT_RGBA32);
|
icon = SDL_ConvertSurface(icon, SDL_PIXELFORMAT_RGBA32);
|
||||||
if (!iconfmt) {
|
if (!icon) {
|
||||||
tray->statusItem.button.image = nil;
|
tray->statusItem.button.image = nil;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:(unsigned char **)&iconfmt->pixels
|
NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:(unsigned char **)&icon->pixels
|
||||||
pixelsWide:iconfmt->w
|
pixelsWide:icon->w
|
||||||
pixelsHigh:iconfmt->h
|
pixelsHigh:icon->h
|
||||||
bitsPerSample:8
|
bitsPerSample:8
|
||||||
samplesPerPixel:4
|
samplesPerPixel:4
|
||||||
hasAlpha:YES
|
hasAlpha:YES
|
||||||
isPlanar:NO
|
isPlanar:NO
|
||||||
colorSpaceName:NSCalibratedRGBColorSpace
|
colorSpaceName:NSCalibratedRGBColorSpace
|
||||||
bytesPerRow:iconfmt->pitch
|
bytesPerRow:icon->pitch
|
||||||
bitsPerPixel:32];
|
bitsPerPixel:32];
|
||||||
NSImage *iconimg = [[NSImage alloc] initWithSize:NSMakeSize(iconfmt->w, iconfmt->h)];
|
NSImage *iconimg = [[NSImage alloc] initWithSize:NSMakeSize(icon->w, icon->h)];
|
||||||
[iconimg addRepresentation:bitmap];
|
[iconimg addRepresentation:bitmap];
|
||||||
|
|
||||||
/* A typical icon size is 22x22 on macOS. Failing to resize the icon
|
/* A typical icon size is 22x22 on macOS. Failing to resize the icon
|
||||||
@@ -170,11 +176,15 @@ void SDL_SetTrayIcon(SDL_Tray *tray, SDL_Surface *icon)
|
|||||||
|
|
||||||
tray->statusItem.button.image = iconimg22;
|
tray->statusItem.button.image = iconimg22;
|
||||||
|
|
||||||
SDL_DestroySurface(iconfmt);
|
SDL_DestroySurface(icon);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDL_SetTrayTooltip(SDL_Tray *tray, const char *tooltip)
|
void SDL_SetTrayTooltip(SDL_Tray *tray, const char *tooltip)
|
||||||
{
|
{
|
||||||
|
if (!SDL_ObjectValid(tray, SDL_OBJECT_TYPE_TRAY)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (tooltip) {
|
if (tooltip) {
|
||||||
tray->statusItem.button.toolTip = [NSString stringWithUTF8String:tooltip];
|
tray->statusItem.button.toolTip = [NSString stringWithUTF8String:tooltip];
|
||||||
} else {
|
} else {
|
||||||
@@ -184,6 +194,11 @@ void SDL_SetTrayTooltip(SDL_Tray *tray, const char *tooltip)
|
|||||||
|
|
||||||
SDL_TrayMenu *SDL_CreateTrayMenu(SDL_Tray *tray)
|
SDL_TrayMenu *SDL_CreateTrayMenu(SDL_Tray *tray)
|
||||||
{
|
{
|
||||||
|
if (!SDL_ObjectValid(tray, SDL_OBJECT_TYPE_TRAY)) {
|
||||||
|
SDL_InvalidParamError("tray");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
SDL_TrayMenu *menu = (SDL_TrayMenu *)SDL_calloc(1, sizeof(*menu));
|
SDL_TrayMenu *menu = (SDL_TrayMenu *)SDL_calloc(1, sizeof(*menu));
|
||||||
if (!menu) {
|
if (!menu) {
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -206,11 +221,21 @@ SDL_TrayMenu *SDL_CreateTrayMenu(SDL_Tray *tray)
|
|||||||
|
|
||||||
SDL_TrayMenu *SDL_GetTrayMenu(SDL_Tray *tray)
|
SDL_TrayMenu *SDL_GetTrayMenu(SDL_Tray *tray)
|
||||||
{
|
{
|
||||||
|
if (!SDL_ObjectValid(tray, SDL_OBJECT_TYPE_TRAY)) {
|
||||||
|
SDL_InvalidParamError("tray");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return tray->menu;
|
return tray->menu;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_TrayMenu *SDL_CreateTraySubmenu(SDL_TrayEntry *entry)
|
SDL_TrayMenu *SDL_CreateTraySubmenu(SDL_TrayEntry *entry)
|
||||||
{
|
{
|
||||||
|
if (!entry) {
|
||||||
|
SDL_InvalidParamError("entry");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (entry->submenu) {
|
if (entry->submenu) {
|
||||||
SDL_SetError("Tray entry submenu already exists");
|
SDL_SetError("Tray entry submenu already exists");
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -243,11 +268,21 @@ SDL_TrayMenu *SDL_CreateTraySubmenu(SDL_TrayEntry *entry)
|
|||||||
|
|
||||||
SDL_TrayMenu *SDL_GetTraySubmenu(SDL_TrayEntry *entry)
|
SDL_TrayMenu *SDL_GetTraySubmenu(SDL_TrayEntry *entry)
|
||||||
{
|
{
|
||||||
|
if (!entry) {
|
||||||
|
SDL_InvalidParamError("entry");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return entry->submenu;
|
return entry->submenu;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SDL_TrayEntry **SDL_GetTrayEntries(SDL_TrayMenu *menu, int *size)
|
const SDL_TrayEntry **SDL_GetTrayEntries(SDL_TrayMenu *menu, int *size)
|
||||||
{
|
{
|
||||||
|
if (!menu) {
|
||||||
|
SDL_InvalidParamError("menu");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (size) {
|
if (size) {
|
||||||
*size = menu->nEntries;
|
*size = menu->nEntries;
|
||||||
}
|
}
|
||||||
@@ -293,6 +328,11 @@ void SDL_RemoveTrayEntry(SDL_TrayEntry *entry)
|
|||||||
|
|
||||||
SDL_TrayEntry *SDL_InsertTrayEntryAt(SDL_TrayMenu *menu, int pos, const char *label, SDL_TrayEntryFlags flags)
|
SDL_TrayEntry *SDL_InsertTrayEntryAt(SDL_TrayMenu *menu, int pos, const char *label, SDL_TrayEntryFlags flags)
|
||||||
{
|
{
|
||||||
|
if (!menu) {
|
||||||
|
SDL_InvalidParamError("menu");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (pos < -1 || pos > menu->nEntries) {
|
if (pos < -1 || pos > menu->nEntries) {
|
||||||
SDL_InvalidParamError("pos");
|
SDL_InvalidParamError("pos");
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -347,28 +387,44 @@ SDL_TrayEntry *SDL_InsertTrayEntryAt(SDL_TrayMenu *menu, int pos, const char *la
|
|||||||
|
|
||||||
void SDL_SetTrayEntryLabel(SDL_TrayEntry *entry, const char *label)
|
void SDL_SetTrayEntryLabel(SDL_TrayEntry *entry, const char *label)
|
||||||
{
|
{
|
||||||
|
if (!entry) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
[entry->nsitem setTitle:[NSString stringWithUTF8String:label]];
|
[entry->nsitem setTitle:[NSString stringWithUTF8String:label]];
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *SDL_GetTrayEntryLabel(SDL_TrayEntry *entry)
|
const char *SDL_GetTrayEntryLabel(SDL_TrayEntry *entry)
|
||||||
{
|
{
|
||||||
|
if (!entry) {
|
||||||
|
SDL_InvalidParamError("entry");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return [[entry->nsitem title] UTF8String];
|
return [[entry->nsitem title] UTF8String];
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDL_SetTrayEntryChecked(SDL_TrayEntry *entry, bool checked)
|
void SDL_SetTrayEntryChecked(SDL_TrayEntry *entry, bool checked)
|
||||||
{
|
{
|
||||||
|
if (!entry) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
[entry->nsitem setState:(checked ? NSControlStateValueOn : NSControlStateValueOff)];
|
[entry->nsitem setState:(checked ? NSControlStateValueOn : NSControlStateValueOff)];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SDL_GetTrayEntryChecked(SDL_TrayEntry *entry)
|
bool SDL_GetTrayEntryChecked(SDL_TrayEntry *entry)
|
||||||
{
|
{
|
||||||
|
if (!entry) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return entry->nsitem.state == NSControlStateValueOn;
|
return entry->nsitem.state == NSControlStateValueOn;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDL_SetTrayEntryEnabled(SDL_TrayEntry *entry, bool enabled)
|
void SDL_SetTrayEntryEnabled(SDL_TrayEntry *entry, bool enabled)
|
||||||
{
|
{
|
||||||
if (!(entry->flags & SDL_TRAYENTRY_CHECKBOX)) {
|
if (!entry || !(entry->flags & SDL_TRAYENTRY_CHECKBOX)) {
|
||||||
SDL_SetError("Cannot update check for entry not created with SDL_TRAYENTRY_CHECKBOX");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -377,8 +433,7 @@ void SDL_SetTrayEntryEnabled(SDL_TrayEntry *entry, bool enabled)
|
|||||||
|
|
||||||
bool SDL_GetTrayEntryEnabled(SDL_TrayEntry *entry)
|
bool SDL_GetTrayEntryEnabled(SDL_TrayEntry *entry)
|
||||||
{
|
{
|
||||||
if (!(entry->flags & SDL_TRAYENTRY_CHECKBOX)) {
|
if (!entry || !(entry->flags & SDL_TRAYENTRY_CHECKBOX)) {
|
||||||
SDL_SetError("Cannot fetch check for entry not created with SDL_TRAYENTRY_CHECKBOX");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -387,6 +442,10 @@ bool SDL_GetTrayEntryEnabled(SDL_TrayEntry *entry)
|
|||||||
|
|
||||||
void SDL_SetTrayEntryCallback(SDL_TrayEntry *entry, SDL_TrayCallback callback, void *userdata)
|
void SDL_SetTrayEntryCallback(SDL_TrayEntry *entry, SDL_TrayCallback callback, void *userdata)
|
||||||
{
|
{
|
||||||
|
if (!entry) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
entry->callback = callback;
|
entry->callback = callback;
|
||||||
entry->userdata = userdata;
|
entry->userdata = userdata;
|
||||||
}
|
}
|
||||||
@@ -408,25 +467,42 @@ void SDL_ClickTrayEntry(SDL_TrayEntry *entry)
|
|||||||
|
|
||||||
SDL_TrayMenu *SDL_GetTrayEntryParent(SDL_TrayEntry *entry)
|
SDL_TrayMenu *SDL_GetTrayEntryParent(SDL_TrayEntry *entry)
|
||||||
{
|
{
|
||||||
|
if (!entry) {
|
||||||
|
SDL_InvalidParamError("entry");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return entry->parent;
|
return entry->parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_TrayEntry *SDL_GetTrayMenuParentEntry(SDL_TrayMenu *menu)
|
SDL_TrayEntry *SDL_GetTrayMenuParentEntry(SDL_TrayMenu *menu)
|
||||||
{
|
{
|
||||||
|
if (!menu) {
|
||||||
|
SDL_InvalidParamError("menu");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return menu->parent_entry;
|
return menu->parent_entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_Tray *SDL_GetTrayMenuParentTray(SDL_TrayMenu *menu)
|
SDL_Tray *SDL_GetTrayMenuParentTray(SDL_TrayMenu *menu)
|
||||||
{
|
{
|
||||||
|
if (!menu) {
|
||||||
|
SDL_InvalidParamError("menu");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return menu->parent_tray;
|
return menu->parent_tray;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDL_DestroyTray(SDL_Tray *tray)
|
void SDL_DestroyTray(SDL_Tray *tray)
|
||||||
{
|
{
|
||||||
if (!tray) {
|
if (!SDL_ObjectValid(tray, SDL_OBJECT_TYPE_TRAY)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SDL_UnregisterTray(tray);
|
||||||
|
|
||||||
[[NSStatusBar systemStatusBar] removeStatusItem:tray->statusItem];
|
[[NSStatusBar systemStatusBar] removeStatusItem:tray->statusItem];
|
||||||
|
|
||||||
if (tray->menu) {
|
if (tray->menu) {
|
||||||
@@ -434,8 +510,6 @@ void SDL_DestroyTray(SDL_Tray *tray)
|
|||||||
}
|
}
|
||||||
|
|
||||||
SDL_free(tray);
|
SDL_free(tray);
|
||||||
|
|
||||||
SDL_DecrementTrayCount();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // SDL_PLATFORM_MACOS
|
#endif // SDL_PLATFORM_MACOS
|
||||||
|
|||||||
@@ -33,29 +33,27 @@ SDL_Tray *SDL_CreateTray(SDL_Surface *icon, const char *tooltip)
|
|||||||
|
|
||||||
void SDL_SetTrayIcon(SDL_Tray *tray, SDL_Surface *icon)
|
void SDL_SetTrayIcon(SDL_Tray *tray, SDL_Surface *icon)
|
||||||
{
|
{
|
||||||
SDL_Unsupported();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDL_SetTrayTooltip(SDL_Tray *tray, const char *tooltip)
|
void SDL_SetTrayTooltip(SDL_Tray *tray, const char *tooltip)
|
||||||
{
|
{
|
||||||
SDL_Unsupported();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_TrayMenu *SDL_CreateTrayMenu(SDL_Tray *tray)
|
SDL_TrayMenu *SDL_CreateTrayMenu(SDL_Tray *tray)
|
||||||
{
|
{
|
||||||
SDL_Unsupported();
|
SDL_InvalidParamError("tray");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_TrayMenu *SDL_GetTrayMenu(SDL_Tray *tray)
|
SDL_TrayMenu *SDL_GetTrayMenu(SDL_Tray *tray)
|
||||||
{
|
{
|
||||||
SDL_Unsupported();
|
SDL_InvalidParamError("tray");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_TrayMenu *SDL_CreateTraySubmenu(SDL_TrayEntry *entry)
|
SDL_TrayMenu *SDL_CreateTraySubmenu(SDL_TrayEntry *entry)
|
||||||
{
|
{
|
||||||
SDL_Unsupported();
|
SDL_InvalidParamError("entry");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,57 +64,50 @@ SDL_TrayMenu *SDL_GetTraySubmenu(SDL_TrayEntry *entry)
|
|||||||
|
|
||||||
const SDL_TrayEntry **SDL_GetTrayEntries(SDL_TrayMenu *menu, int *size)
|
const SDL_TrayEntry **SDL_GetTrayEntries(SDL_TrayMenu *menu, int *size)
|
||||||
{
|
{
|
||||||
SDL_Unsupported();
|
SDL_InvalidParamError("menu");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDL_RemoveTrayEntry(SDL_TrayEntry *entry)
|
void SDL_RemoveTrayEntry(SDL_TrayEntry *entry)
|
||||||
{
|
{
|
||||||
SDL_Unsupported();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_TrayEntry *SDL_InsertTrayEntryAt(SDL_TrayMenu *menu, int pos, const char *label, SDL_TrayEntryFlags flags)
|
SDL_TrayEntry *SDL_InsertTrayEntryAt(SDL_TrayMenu *menu, int pos, const char *label, SDL_TrayEntryFlags flags)
|
||||||
{
|
{
|
||||||
SDL_Unsupported();
|
SDL_InvalidParamError("menu");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDL_SetTrayEntryLabel(SDL_TrayEntry *entry, const char *label)
|
void SDL_SetTrayEntryLabel(SDL_TrayEntry *entry, const char *label)
|
||||||
{
|
{
|
||||||
SDL_Unsupported();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *SDL_GetTrayEntryLabel(SDL_TrayEntry *entry)
|
const char *SDL_GetTrayEntryLabel(SDL_TrayEntry *entry)
|
||||||
{
|
{
|
||||||
SDL_Unsupported();
|
SDL_InvalidParamError("entry");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDL_SetTrayEntryChecked(SDL_TrayEntry *entry, bool checked)
|
void SDL_SetTrayEntryChecked(SDL_TrayEntry *entry, bool checked)
|
||||||
{
|
{
|
||||||
SDL_Unsupported();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SDL_GetTrayEntryChecked(SDL_TrayEntry *entry)
|
bool SDL_GetTrayEntryChecked(SDL_TrayEntry *entry)
|
||||||
{
|
{
|
||||||
SDL_Unsupported();
|
return SDL_InvalidParamError("entry");
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDL_SetTrayEntryEnabled(SDL_TrayEntry *entry, bool enabled)
|
void SDL_SetTrayEntryEnabled(SDL_TrayEntry *entry, bool enabled)
|
||||||
{
|
{
|
||||||
SDL_Unsupported();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SDL_GetTrayEntryEnabled(SDL_TrayEntry *entry)
|
bool SDL_GetTrayEntryEnabled(SDL_TrayEntry *entry)
|
||||||
{
|
{
|
||||||
SDL_Unsupported();
|
return SDL_InvalidParamError("entry");
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDL_SetTrayEntryCallback(SDL_TrayEntry *entry, SDL_TrayCallback callback, void *userdata)
|
void SDL_SetTrayEntryCallback(SDL_TrayEntry *entry, SDL_TrayCallback callback, void *userdata)
|
||||||
{
|
{
|
||||||
SDL_Unsupported();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDL_ClickTrayEntry(SDL_TrayEntry *entry)
|
void SDL_ClickTrayEntry(SDL_TrayEntry *entry)
|
||||||
@@ -125,25 +116,24 @@ void SDL_ClickTrayEntry(SDL_TrayEntry *entry)
|
|||||||
|
|
||||||
SDL_TrayMenu *SDL_GetTrayEntryParent(SDL_TrayEntry *entry)
|
SDL_TrayMenu *SDL_GetTrayEntryParent(SDL_TrayEntry *entry)
|
||||||
{
|
{
|
||||||
SDL_Unsupported();
|
SDL_InvalidParamError("entry");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_TrayEntry *SDL_GetTrayMenuParentEntry(SDL_TrayMenu *menu)
|
SDL_TrayEntry *SDL_GetTrayMenuParentEntry(SDL_TrayMenu *menu)
|
||||||
{
|
{
|
||||||
SDL_Unsupported();
|
SDL_InvalidParamError("menu");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_Tray *SDL_GetTrayMenuParentTray(SDL_TrayMenu *menu)
|
SDL_Tray *SDL_GetTrayMenuParentTray(SDL_TrayMenu *menu)
|
||||||
{
|
{
|
||||||
SDL_Unsupported();
|
SDL_InvalidParamError("menu");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDL_DestroyTray(SDL_Tray *tray)
|
void SDL_DestroyTray(SDL_Tray *tray)
|
||||||
{
|
{
|
||||||
SDL_Unsupported();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // !SDL_PLATFORM_MACOS
|
#endif // !SDL_PLATFORM_MACOS
|
||||||
|
|||||||
@@ -144,7 +144,7 @@ static void quit_gtk(void)
|
|||||||
|
|
||||||
static bool init_gtk(void)
|
static bool init_gtk(void)
|
||||||
{
|
{
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
@@ -434,13 +434,17 @@ SDL_Tray *SDL_CreateTray(SDL_Surface *icon, const char *tooltip)
|
|||||||
|
|
||||||
app_indicator_set_status(tray->indicator, APP_INDICATOR_STATUS_ACTIVE);
|
app_indicator_set_status(tray->indicator, APP_INDICATOR_STATUS_ACTIVE);
|
||||||
|
|
||||||
SDL_IncrementTrayCount();
|
SDL_RegisterTray(tray);
|
||||||
|
|
||||||
return tray;
|
return tray;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDL_SetTrayIcon(SDL_Tray *tray, SDL_Surface *icon)
|
void SDL_SetTrayIcon(SDL_Tray *tray, SDL_Surface *icon)
|
||||||
{
|
{
|
||||||
|
if (!SDL_ObjectValid(tray, SDL_OBJECT_TYPE_TRAY)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (*tray->icon_path) {
|
if (*tray->icon_path) {
|
||||||
SDL_RemovePath(tray->icon_path);
|
SDL_RemovePath(tray->icon_path);
|
||||||
}
|
}
|
||||||
@@ -463,6 +467,11 @@ void SDL_SetTrayTooltip(SDL_Tray *tray, const char *tooltip)
|
|||||||
|
|
||||||
SDL_TrayMenu *SDL_CreateTrayMenu(SDL_Tray *tray)
|
SDL_TrayMenu *SDL_CreateTrayMenu(SDL_Tray *tray)
|
||||||
{
|
{
|
||||||
|
if (!SDL_ObjectValid(tray, SDL_OBJECT_TYPE_TRAY)) {
|
||||||
|
SDL_InvalidParamError("tray");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
tray->menu = (SDL_TrayMenu *)SDL_calloc(1, sizeof(*tray->menu));
|
tray->menu = (SDL_TrayMenu *)SDL_calloc(1, sizeof(*tray->menu));
|
||||||
if (!tray->menu) {
|
if (!tray->menu) {
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -481,11 +490,21 @@ SDL_TrayMenu *SDL_CreateTrayMenu(SDL_Tray *tray)
|
|||||||
|
|
||||||
SDL_TrayMenu *SDL_GetTrayMenu(SDL_Tray *tray)
|
SDL_TrayMenu *SDL_GetTrayMenu(SDL_Tray *tray)
|
||||||
{
|
{
|
||||||
|
if (!SDL_ObjectValid(tray, SDL_OBJECT_TYPE_TRAY)) {
|
||||||
|
SDL_InvalidParamError("tray");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return tray->menu;
|
return tray->menu;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_TrayMenu *SDL_CreateTraySubmenu(SDL_TrayEntry *entry)
|
SDL_TrayMenu *SDL_CreateTraySubmenu(SDL_TrayEntry *entry)
|
||||||
{
|
{
|
||||||
|
if (!entry) {
|
||||||
|
SDL_InvalidParamError("entry");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (entry->submenu) {
|
if (entry->submenu) {
|
||||||
SDL_SetError("Tray entry submenu already exists");
|
SDL_SetError("Tray entry submenu already exists");
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -514,11 +533,21 @@ SDL_TrayMenu *SDL_CreateTraySubmenu(SDL_TrayEntry *entry)
|
|||||||
|
|
||||||
SDL_TrayMenu *SDL_GetTraySubmenu(SDL_TrayEntry *entry)
|
SDL_TrayMenu *SDL_GetTraySubmenu(SDL_TrayEntry *entry)
|
||||||
{
|
{
|
||||||
|
if (!entry) {
|
||||||
|
SDL_InvalidParamError("entry");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return entry->submenu;
|
return entry->submenu;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SDL_TrayEntry **SDL_GetTrayEntries(SDL_TrayMenu *menu, int *size)
|
const SDL_TrayEntry **SDL_GetTrayEntries(SDL_TrayMenu *menu, int *size)
|
||||||
{
|
{
|
||||||
|
if (!menu) {
|
||||||
|
SDL_InvalidParamError("menu");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (size) {
|
if (size) {
|
||||||
*size = menu->nEntries;
|
*size = menu->nEntries;
|
||||||
}
|
}
|
||||||
@@ -563,6 +592,11 @@ void SDL_RemoveTrayEntry(SDL_TrayEntry *entry)
|
|||||||
|
|
||||||
SDL_TrayEntry *SDL_InsertTrayEntryAt(SDL_TrayMenu *menu, int pos, const char *label, SDL_TrayEntryFlags flags)
|
SDL_TrayEntry *SDL_InsertTrayEntryAt(SDL_TrayMenu *menu, int pos, const char *label, SDL_TrayEntryFlags flags)
|
||||||
{
|
{
|
||||||
|
if (!menu) {
|
||||||
|
SDL_InvalidParamError("menu");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (pos < -1 || pos > menu->nEntries) {
|
if (pos < -1 || pos > menu->nEntries) {
|
||||||
SDL_InvalidParamError("pos");
|
SDL_InvalidParamError("pos");
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -625,18 +659,26 @@ SDL_TrayEntry *SDL_InsertTrayEntryAt(SDL_TrayMenu *menu, int pos, const char *la
|
|||||||
|
|
||||||
void SDL_SetTrayEntryLabel(SDL_TrayEntry *entry, const char *label)
|
void SDL_SetTrayEntryLabel(SDL_TrayEntry *entry, const char *label)
|
||||||
{
|
{
|
||||||
|
if (!entry) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
gtk_menu_item_set_label(GTK_MENU_ITEM(entry->item), label);
|
gtk_menu_item_set_label(GTK_MENU_ITEM(entry->item), label);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *SDL_GetTrayEntryLabel(SDL_TrayEntry *entry)
|
const char *SDL_GetTrayEntryLabel(SDL_TrayEntry *entry)
|
||||||
{
|
{
|
||||||
|
if (!entry) {
|
||||||
|
SDL_InvalidParamError("entry");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return gtk_menu_item_get_label(GTK_MENU_ITEM(entry->item));
|
return gtk_menu_item_get_label(GTK_MENU_ITEM(entry->item));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDL_SetTrayEntryChecked(SDL_TrayEntry *entry, bool checked)
|
void SDL_SetTrayEntryChecked(SDL_TrayEntry *entry, bool checked)
|
||||||
{
|
{
|
||||||
if (!(entry->flags & SDL_TRAYENTRY_CHECKBOX)) {
|
if (!entry || !(entry->flags & SDL_TRAYENTRY_CHECKBOX)) {
|
||||||
SDL_SetError("Cannot update check for entry not created with SDL_TRAYENTRY_CHECKBOX");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -647,8 +689,7 @@ void SDL_SetTrayEntryChecked(SDL_TrayEntry *entry, bool checked)
|
|||||||
|
|
||||||
bool SDL_GetTrayEntryChecked(SDL_TrayEntry *entry)
|
bool SDL_GetTrayEntryChecked(SDL_TrayEntry *entry)
|
||||||
{
|
{
|
||||||
if (!(entry->flags & SDL_TRAYENTRY_CHECKBOX)) {
|
if (!entry || !(entry->flags & SDL_TRAYENTRY_CHECKBOX)) {
|
||||||
SDL_SetError("Cannot fetch check for entry not created with SDL_TRAYENTRY_CHECKBOX");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -657,16 +698,28 @@ bool SDL_GetTrayEntryChecked(SDL_TrayEntry *entry)
|
|||||||
|
|
||||||
void SDL_SetTrayEntryEnabled(SDL_TrayEntry *entry, bool enabled)
|
void SDL_SetTrayEntryEnabled(SDL_TrayEntry *entry, bool enabled)
|
||||||
{
|
{
|
||||||
|
if (!entry) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
gtk_widget_set_sensitive(entry->item, enabled);
|
gtk_widget_set_sensitive(entry->item, enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SDL_GetTrayEntryEnabled(SDL_TrayEntry *entry)
|
bool SDL_GetTrayEntryEnabled(SDL_TrayEntry *entry)
|
||||||
{
|
{
|
||||||
|
if (!entry) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return gtk_widget_get_sensitive(entry->item);
|
return gtk_widget_get_sensitive(entry->item);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDL_SetTrayEntryCallback(SDL_TrayEntry *entry, SDL_TrayCallback callback, void *userdata)
|
void SDL_SetTrayEntryCallback(SDL_TrayEntry *entry, SDL_TrayCallback callback, void *userdata)
|
||||||
{
|
{
|
||||||
|
if (!entry) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
entry->callback = callback;
|
entry->callback = callback;
|
||||||
entry->userdata = userdata;
|
entry->userdata = userdata;
|
||||||
}
|
}
|
||||||
@@ -688,6 +741,11 @@ void SDL_ClickTrayEntry(SDL_TrayEntry *entry)
|
|||||||
|
|
||||||
SDL_TrayMenu *SDL_GetTrayEntryParent(SDL_TrayEntry *entry)
|
SDL_TrayMenu *SDL_GetTrayEntryParent(SDL_TrayEntry *entry)
|
||||||
{
|
{
|
||||||
|
if (!entry) {
|
||||||
|
SDL_InvalidParamError("entry");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return entry->parent;
|
return entry->parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -698,15 +756,22 @@ SDL_TrayEntry *SDL_GetTrayMenuParentEntry(SDL_TrayMenu *menu)
|
|||||||
|
|
||||||
SDL_Tray *SDL_GetTrayMenuParentTray(SDL_TrayMenu *menu)
|
SDL_Tray *SDL_GetTrayMenuParentTray(SDL_TrayMenu *menu)
|
||||||
{
|
{
|
||||||
|
if (!menu) {
|
||||||
|
SDL_InvalidParamError("menu");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return menu->parent_tray;
|
return menu->parent_tray;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDL_DestroyTray(SDL_Tray *tray)
|
void SDL_DestroyTray(SDL_Tray *tray)
|
||||||
{
|
{
|
||||||
if (!tray) {
|
if (!SDL_ObjectValid(tray, SDL_OBJECT_TYPE_TRAY)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SDL_UnregisterTray(tray);
|
||||||
|
|
||||||
if (tray->menu) {
|
if (tray->menu) {
|
||||||
DestroySDLMenu(tray->menu);
|
DestroySDLMenu(tray->menu);
|
||||||
}
|
}
|
||||||
@@ -725,8 +790,6 @@ void SDL_DestroyTray(SDL_Tray *tray)
|
|||||||
|
|
||||||
SDL_free(tray);
|
SDL_free(tray);
|
||||||
|
|
||||||
SDL_DecrementTrayCount();
|
|
||||||
|
|
||||||
if (SDL_HasNoActiveTrays()) {
|
if (SDL_HasNoActiveTrays()) {
|
||||||
gtk_main_quit();
|
gtk_main_quit();
|
||||||
gtk_thread_active = false;
|
gtk_thread_active = false;
|
||||||
|
|||||||
@@ -252,13 +252,17 @@ SDL_Tray *SDL_CreateTray(SDL_Surface *icon, const char *tooltip)
|
|||||||
|
|
||||||
SetWindowLongPtr(tray->hwnd, GWLP_USERDATA, (LONG_PTR) tray);
|
SetWindowLongPtr(tray->hwnd, GWLP_USERDATA, (LONG_PTR) tray);
|
||||||
|
|
||||||
SDL_IncrementTrayCount();
|
SDL_RegisterTray(tray);
|
||||||
|
|
||||||
return tray;
|
return tray;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDL_SetTrayIcon(SDL_Tray *tray, SDL_Surface *icon)
|
void SDL_SetTrayIcon(SDL_Tray *tray, SDL_Surface *icon)
|
||||||
{
|
{
|
||||||
|
if (!SDL_ObjectValid(tray, SDL_OBJECT_TYPE_TRAY)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (tray->icon) {
|
if (tray->icon) {
|
||||||
DestroyIcon(tray->icon);
|
DestroyIcon(tray->icon);
|
||||||
}
|
}
|
||||||
@@ -281,6 +285,10 @@ void SDL_SetTrayIcon(SDL_Tray *tray, SDL_Surface *icon)
|
|||||||
|
|
||||||
void SDL_SetTrayTooltip(SDL_Tray *tray, const char *tooltip)
|
void SDL_SetTrayTooltip(SDL_Tray *tray, const char *tooltip)
|
||||||
{
|
{
|
||||||
|
if (!SDL_ObjectValid(tray, SDL_OBJECT_TYPE_TRAY)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (tooltip) {
|
if (tooltip) {
|
||||||
wchar_t *tooltipw = WIN_UTF8ToStringW(tooltip);
|
wchar_t *tooltipw = WIN_UTF8ToStringW(tooltip);
|
||||||
SDL_wcslcpy(tray->nid.szTip, tooltipw, sizeof(tray->nid.szTip) / sizeof(*tray->nid.szTip));
|
SDL_wcslcpy(tray->nid.szTip, tooltipw, sizeof(tray->nid.szTip) / sizeof(*tray->nid.szTip));
|
||||||
@@ -294,6 +302,11 @@ void SDL_SetTrayTooltip(SDL_Tray *tray, const char *tooltip)
|
|||||||
|
|
||||||
SDL_TrayMenu *SDL_CreateTrayMenu(SDL_Tray *tray)
|
SDL_TrayMenu *SDL_CreateTrayMenu(SDL_Tray *tray)
|
||||||
{
|
{
|
||||||
|
if (!SDL_ObjectValid(tray, SDL_OBJECT_TYPE_TRAY)) {
|
||||||
|
SDL_InvalidParamError("tray");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
tray->menu = (SDL_TrayMenu *)SDL_calloc(1, sizeof(*tray->menu));
|
tray->menu = (SDL_TrayMenu *)SDL_calloc(1, sizeof(*tray->menu));
|
||||||
|
|
||||||
if (!tray->menu) {
|
if (!tray->menu) {
|
||||||
@@ -309,13 +322,24 @@ SDL_TrayMenu *SDL_CreateTrayMenu(SDL_Tray *tray)
|
|||||||
|
|
||||||
SDL_TrayMenu *SDL_GetTrayMenu(SDL_Tray *tray)
|
SDL_TrayMenu *SDL_GetTrayMenu(SDL_Tray *tray)
|
||||||
{
|
{
|
||||||
|
if (!SDL_ObjectValid(tray, SDL_OBJECT_TYPE_TRAY)) {
|
||||||
|
SDL_InvalidParamError("tray");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return tray->menu;
|
return tray->menu;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_TrayMenu *SDL_CreateTraySubmenu(SDL_TrayEntry *entry)
|
SDL_TrayMenu *SDL_CreateTraySubmenu(SDL_TrayEntry *entry)
|
||||||
{
|
{
|
||||||
|
if (!entry) {
|
||||||
|
SDL_InvalidParamError("entry");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (!entry->submenu) {
|
if (!entry->submenu) {
|
||||||
SDL_SetError("Cannot create submenu for entry not created with SDL_TRAYENTRY_SUBMENU");
|
SDL_SetError("Cannot create submenu for entry not created with SDL_TRAYENTRY_SUBMENU");
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return entry->submenu;
|
return entry->submenu;
|
||||||
@@ -323,11 +347,21 @@ SDL_TrayMenu *SDL_CreateTraySubmenu(SDL_TrayEntry *entry)
|
|||||||
|
|
||||||
SDL_TrayMenu *SDL_GetTraySubmenu(SDL_TrayEntry *entry)
|
SDL_TrayMenu *SDL_GetTraySubmenu(SDL_TrayEntry *entry)
|
||||||
{
|
{
|
||||||
|
if (!entry) {
|
||||||
|
SDL_InvalidParamError("entry");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return entry->submenu;
|
return entry->submenu;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SDL_TrayEntry **SDL_GetTrayEntries(SDL_TrayMenu *menu, int *size)
|
const SDL_TrayEntry **SDL_GetTrayEntries(SDL_TrayMenu *menu, int *size)
|
||||||
{
|
{
|
||||||
|
if (!menu) {
|
||||||
|
SDL_InvalidParamError("menu");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (size) {
|
if (size) {
|
||||||
*size = menu->nEntries;
|
*size = menu->nEntries;
|
||||||
}
|
}
|
||||||
@@ -376,6 +410,11 @@ void SDL_RemoveTrayEntry(SDL_TrayEntry *entry)
|
|||||||
|
|
||||||
SDL_TrayEntry *SDL_InsertTrayEntryAt(SDL_TrayMenu *menu, int pos, const char *label, SDL_TrayEntryFlags flags)
|
SDL_TrayEntry *SDL_InsertTrayEntryAt(SDL_TrayMenu *menu, int pos, const char *label, SDL_TrayEntryFlags flags)
|
||||||
{
|
{
|
||||||
|
if (!menu) {
|
||||||
|
SDL_InvalidParamError("menu");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (pos < -1 || pos > menu->nEntries) {
|
if (pos < -1 || pos > menu->nEntries) {
|
||||||
SDL_InvalidParamError("pos");
|
SDL_InvalidParamError("pos");
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -474,6 +513,10 @@ SDL_TrayEntry *SDL_InsertTrayEntryAt(SDL_TrayMenu *menu, int pos, const char *la
|
|||||||
|
|
||||||
void SDL_SetTrayEntryLabel(SDL_TrayEntry *entry, const char *label)
|
void SDL_SetTrayEntryLabel(SDL_TrayEntry *entry, const char *label)
|
||||||
{
|
{
|
||||||
|
if (!entry) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
SDL_snprintf(entry->label_cache, sizeof(entry->label_cache), "%s", label);
|
SDL_snprintf(entry->label_cache, sizeof(entry->label_cache), "%s", label);
|
||||||
|
|
||||||
wchar_t *label_w = escape_label(label);
|
wchar_t *label_w = escape_label(label);
|
||||||
@@ -498,13 +541,17 @@ void SDL_SetTrayEntryLabel(SDL_TrayEntry *entry, const char *label)
|
|||||||
|
|
||||||
const char *SDL_GetTrayEntryLabel(SDL_TrayEntry *entry)
|
const char *SDL_GetTrayEntryLabel(SDL_TrayEntry *entry)
|
||||||
{
|
{
|
||||||
|
if (!entry) {
|
||||||
|
SDL_InvalidParamError("entry");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return entry->label_cache;
|
return entry->label_cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDL_SetTrayEntryChecked(SDL_TrayEntry *entry, bool checked)
|
void SDL_SetTrayEntryChecked(SDL_TrayEntry *entry, bool checked)
|
||||||
{
|
{
|
||||||
if (!(entry->flags & SDL_TRAYENTRY_CHECKBOX)) {
|
if (!entry || !(entry->flags & SDL_TRAYENTRY_CHECKBOX)) {
|
||||||
SDL_SetError("Can't check/uncheck tray entry not created with SDL_TRAYENTRY_CHECKBOX");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -513,8 +560,7 @@ void SDL_SetTrayEntryChecked(SDL_TrayEntry *entry, bool checked)
|
|||||||
|
|
||||||
bool SDL_GetTrayEntryChecked(SDL_TrayEntry *entry)
|
bool SDL_GetTrayEntryChecked(SDL_TrayEntry *entry)
|
||||||
{
|
{
|
||||||
if (!(entry->flags & SDL_TRAYENTRY_CHECKBOX)) {
|
if (!entry || !(entry->flags & SDL_TRAYENTRY_CHECKBOX)) {
|
||||||
SDL_SetError("Can't get check status of tray entry not created with SDL_TRAYENTRY_CHECKBOX");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -529,11 +575,19 @@ bool SDL_GetTrayEntryChecked(SDL_TrayEntry *entry)
|
|||||||
|
|
||||||
void SDL_SetTrayEntryEnabled(SDL_TrayEntry *entry, bool enabled)
|
void SDL_SetTrayEntryEnabled(SDL_TrayEntry *entry, bool enabled)
|
||||||
{
|
{
|
||||||
|
if (!entry) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
EnableMenuItem(entry->parent->hMenu, (UINT) entry->id, MF_BYCOMMAND | (enabled ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
|
EnableMenuItem(entry->parent->hMenu, (UINT) entry->id, MF_BYCOMMAND | (enabled ? MF_ENABLED : (MF_DISABLED | MF_GRAYED)));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SDL_GetTrayEntryEnabled(SDL_TrayEntry *entry)
|
bool SDL_GetTrayEntryEnabled(SDL_TrayEntry *entry)
|
||||||
{
|
{
|
||||||
|
if (!entry) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
MENUITEMINFOW mii;
|
MENUITEMINFOW mii;
|
||||||
mii.cbSize = sizeof(MENUITEMINFOW);
|
mii.cbSize = sizeof(MENUITEMINFOW);
|
||||||
mii.fMask = MIIM_STATE;
|
mii.fMask = MIIM_STATE;
|
||||||
@@ -545,6 +599,10 @@ bool SDL_GetTrayEntryEnabled(SDL_TrayEntry *entry)
|
|||||||
|
|
||||||
void SDL_SetTrayEntryCallback(SDL_TrayEntry *entry, SDL_TrayCallback callback, void *userdata)
|
void SDL_SetTrayEntryCallback(SDL_TrayEntry *entry, SDL_TrayCallback callback, void *userdata)
|
||||||
{
|
{
|
||||||
|
if (!entry) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
entry->callback = callback;
|
entry->callback = callback;
|
||||||
entry->userdata = userdata;
|
entry->userdata = userdata;
|
||||||
}
|
}
|
||||||
@@ -566,25 +624,42 @@ void SDL_ClickTrayEntry(SDL_TrayEntry *entry)
|
|||||||
|
|
||||||
SDL_TrayMenu *SDL_GetTrayEntryParent(SDL_TrayEntry *entry)
|
SDL_TrayMenu *SDL_GetTrayEntryParent(SDL_TrayEntry *entry)
|
||||||
{
|
{
|
||||||
|
if (!entry) {
|
||||||
|
SDL_InvalidParamError("entry");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return entry->parent;
|
return entry->parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_TrayEntry *SDL_GetTrayMenuParentEntry(SDL_TrayMenu *menu)
|
SDL_TrayEntry *SDL_GetTrayMenuParentEntry(SDL_TrayMenu *menu)
|
||||||
{
|
{
|
||||||
|
if (!menu) {
|
||||||
|
SDL_InvalidParamError("menu");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return menu->parent_entry;
|
return menu->parent_entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_Tray *SDL_GetTrayMenuParentTray(SDL_TrayMenu *menu)
|
SDL_Tray *SDL_GetTrayMenuParentTray(SDL_TrayMenu *menu)
|
||||||
{
|
{
|
||||||
|
if (!menu) {
|
||||||
|
SDL_InvalidParamError("menu");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return menu->parent_tray;
|
return menu->parent_tray;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDL_DestroyTray(SDL_Tray *tray)
|
void SDL_DestroyTray(SDL_Tray *tray)
|
||||||
{
|
{
|
||||||
if (!tray) {
|
if (!SDL_ObjectValid(tray, SDL_OBJECT_TYPE_TRAY)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SDL_UnregisterTray(tray);
|
||||||
|
|
||||||
Shell_NotifyIconW(NIM_DELETE, &tray->nid);
|
Shell_NotifyIconW(NIM_DELETE, &tray->nid);
|
||||||
|
|
||||||
if (tray->menu) {
|
if (tray->menu) {
|
||||||
@@ -600,6 +675,4 @@ void SDL_DestroyTray(SDL_Tray *tray)
|
|||||||
}
|
}
|
||||||
|
|
||||||
SDL_free(tray);
|
SDL_free(tray);
|
||||||
|
|
||||||
SDL_DecrementTrayCount();
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user