From 042898995c8fcc88ad821c177b4c4e6566755bb5 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 10 Jan 2025 12:20:37 -0800 Subject: [PATCH] Added SDL_ClickTrayEntry() Also removed the app delegate from the tray code on Cocoa and folded that into SDL3AppDelegate. Fixes https://github.com/libsdl-org/SDL/issues/11906 --- include/SDL3/SDL_tray.h | 9 ++++++ src/dynapi/SDL_dynapi.sym | 1 + src/dynapi/SDL_dynapi_overrides.h | 1 + src/dynapi/SDL_dynapi_procs.h | 1 + src/tray/cocoa/SDL_tray.m | 47 +++++++++++-------------------- src/tray/dummy/SDL_tray.c | 4 +++ src/tray/unix/SDL_tray.c | 15 ++++++++++ src/tray/windows/SDL_tray.c | 15 ++++++++++ src/video/cocoa/SDL_cocoaevents.m | 8 ++++++ 9 files changed, 70 insertions(+), 31 deletions(-) diff --git a/include/SDL3/SDL_tray.h b/include/SDL3/SDL_tray.h index d6d6042658992..a3448cd2f9729 100644 --- a/include/SDL3/SDL_tray.h +++ b/include/SDL3/SDL_tray.h @@ -388,6 +388,15 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetTrayEntryEnabled(SDL_TrayEntry *entry); */ extern SDL_DECLSPEC void SDLCALL SDL_SetTrayEntryCallback(SDL_TrayEntry *entry, SDL_TrayCallback callback, void *userdata); +/** + * Simulate a click on a tray entry. + * + * \param entry The entry to activate. + * + * \since This function is available since SDL 3.1.9. + */ +extern SDL_DECLSPEC void SDLCALL SDL_ClickTrayEntry(SDL_TrayEntry *entry); + /** * Destroys a tray object. * diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index db3718e694b33..f0e66fc8348d8 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -1231,6 +1231,7 @@ SDL3_0.0.0 { SDL_GetTrayMenuParentTray; SDL_GetThreadState; SDL_AudioStreamDevicePaused; + SDL_ClickTrayEntry; # extra symbols go here (don't modify this line) local: *; }; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index bf42c0f7b2f90..e23fe2ed2841b 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -1256,3 +1256,4 @@ #define SDL_GetTrayMenuParentTray SDL_GetTrayMenuParentTray_REAL #define SDL_GetThreadState SDL_GetThreadState_REAL #define SDL_AudioStreamDevicePaused SDL_AudioStreamDevicePaused_REAL +#define SDL_ClickTrayEntry SDL_ClickTrayEntry_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 74da2a73c289d..d74f9597c694a 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -1264,3 +1264,4 @@ SDL_DYNAPI_PROC(SDL_TrayEntry*,SDL_GetTrayMenuParentEntry,(SDL_TrayMenu *a),(a), SDL_DYNAPI_PROC(SDL_Tray*,SDL_GetTrayMenuParentTray,(SDL_TrayMenu *a),(a),return) SDL_DYNAPI_PROC(SDL_ThreadState,SDL_GetThreadState,(SDL_Thread *a),(a),return) SDL_DYNAPI_PROC(bool,SDL_AudioStreamDevicePaused,(SDL_AudioStream *a),(a),return) +SDL_DYNAPI_PROC(void,SDL_ClickTrayEntry,(SDL_TrayEntry *a),(a),) diff --git a/src/tray/cocoa/SDL_tray.m b/src/tray/cocoa/SDL_tray.m index 0bb6fe80df9b5..66f99a2b28a5a 100644 --- a/src/tray/cocoa/SDL_tray.m +++ b/src/tray/cocoa/SDL_tray.m @@ -58,31 +58,6 @@ SDL_TrayMenu *menu; }; -static NSApplication *app = NULL; - -@interface AppDelegate: NSObject - - (IBAction)menu:(id)sender; -@end - -@implementation AppDelegate{} - - (IBAction)menu:(id)sender - { - SDL_TrayEntry *entry = [[sender representedObject] pointerValue]; - - if (!entry) { - return; - } - - if (entry->flags & SDL_TRAYENTRY_CHECKBOX) { - SDL_SetTrayEntryChecked(entry, !SDL_GetTrayEntryChecked(entry)); - } - - if (entry->callback) { - entry->callback(entry->userdata, entry); - } - } -@end - static void DestroySDLMenu(SDL_TrayMenu *menu) { for (int i = 0; i < menu->nEntries; i++) { @@ -106,11 +81,6 @@ static void DestroySDLMenu(SDL_TrayMenu *menu) SDL_Tray *SDL_CreateTray(SDL_Surface *icon, const char *tooltip) { SDL_Tray *tray = (SDL_Tray *)SDL_calloc(1, sizeof(*tray)); - - AppDelegate *delegate = [[AppDelegate alloc] init]; - app = [NSApplication sharedApplication]; - [app setDelegate:delegate]; - if (!tray) { return NULL; } @@ -118,7 +88,7 @@ static void DestroySDLMenu(SDL_TrayMenu *menu) tray->statusItem = nil; tray->statusBar = [NSStatusBar systemStatusBar]; tray->statusItem = [tray->statusBar statusItemWithLength:NSVariableStatusItemLength]; - [app activateIgnoringOtherApps:TRUE]; + [[NSApplication sharedApplication] activateIgnoringOtherApps:TRUE]; if (tooltip) { tray->statusItem.button.toolTip = [NSString stringWithUTF8String:tooltip]; @@ -421,6 +391,21 @@ void SDL_SetTrayEntryCallback(SDL_TrayEntry *entry, SDL_TrayCallback callback, v entry->userdata = userdata; } +void SDL_ClickTrayEntry(SDL_TrayEntry *entry) +{ + if (!entry) { + return; + } + + if (entry->flags & SDL_TRAYENTRY_CHECKBOX) { + SDL_SetTrayEntryChecked(entry, !SDL_GetTrayEntryChecked(entry)); + } + + if (entry->callback) { + entry->callback(entry->userdata, entry); + } +} + SDL_TrayMenu *SDL_GetTrayEntryParent(SDL_TrayEntry *entry) { return entry->parent; diff --git a/src/tray/dummy/SDL_tray.c b/src/tray/dummy/SDL_tray.c index 00d73960f4bfc..59d7e8a7bb0cf 100644 --- a/src/tray/dummy/SDL_tray.c +++ b/src/tray/dummy/SDL_tray.c @@ -119,6 +119,10 @@ void SDL_SetTrayEntryCallback(SDL_TrayEntry *entry, SDL_TrayCallback callback, v SDL_Unsupported(); } +void SDL_ClickTrayEntry(SDL_TrayEntry *entry) +{ +} + SDL_TrayMenu *SDL_GetTrayEntryParent(SDL_TrayEntry *entry) { SDL_Unsupported(); diff --git a/src/tray/unix/SDL_tray.c b/src/tray/unix/SDL_tray.c index 74a72ffddce40..cc57fd78114d2 100644 --- a/src/tray/unix/SDL_tray.c +++ b/src/tray/unix/SDL_tray.c @@ -671,6 +671,21 @@ void SDL_SetTrayEntryCallback(SDL_TrayEntry *entry, SDL_TrayCallback callback, v entry->userdata = userdata; } +void SDL_ClickTrayEntry(SDL_TrayEntry *entry) +{ + if (!entry) { + return; + } + + if (entry->flags & SDL_TRAYENTRY_CHECKBOX) { + SDL_SetTrayEntryChecked(entry, !SDL_GetTrayEntryChecked(entry)); + } + + if (entry->callback) { + entry->callback(entry->userdata, entry); + } +} + SDL_TrayMenu *SDL_GetTrayEntryParent(SDL_TrayEntry *entry) { return entry->parent; diff --git a/src/tray/windows/SDL_tray.c b/src/tray/windows/SDL_tray.c index 11273d4490353..c73a1d5510fd1 100644 --- a/src/tray/windows/SDL_tray.c +++ b/src/tray/windows/SDL_tray.c @@ -536,6 +536,21 @@ void SDL_SetTrayEntryCallback(SDL_TrayEntry *entry, SDL_TrayCallback callback, v entry->userdata = userdata; } +void SDL_ClickTrayEntry(SDL_TrayEntry *entry) +{ + if (!entry) { + return; + } + + if (entry->flags & SDL_TRAYENTRY_CHECKBOX) { + SDL_SetTrayEntryChecked(entry, !SDL_GetTrayEntryChecked(entry)); + } + + if (entry->callback) { + entry->callback(entry->userdata, entry); + } +} + SDL_TrayMenu *SDL_GetTrayEntryParent(SDL_TrayEntry *entry) { return entry->parent; diff --git a/src/video/cocoa/SDL_cocoaevents.m b/src/video/cocoa/SDL_cocoaevents.m index b377237b0a0ba..89f72b2bd20d1 100644 --- a/src/video/cocoa/SDL_cocoaevents.m +++ b/src/video/cocoa/SDL_cocoaevents.m @@ -136,6 +136,7 @@ - (void)observeValueForKeyPath:(NSString *)keyPath change:(NSDictionary *)change context:(void *)context; - (BOOL)applicationSupportsSecureRestorableState:(NSApplication *)app; +- (IBAction)menu:(id)sender; @end @implementation SDL3AppDelegate : NSObject @@ -358,6 +359,13 @@ - (BOOL)applicationSupportsSecureRestorableState:(NSApplication *)app return YES; } +- (IBAction)menu:(id)sender +{ + SDL_TrayEntry *entry = [[sender representedObject] pointerValue]; + + SDL_ClickTrayEntry(entry); +} + @end static SDL3AppDelegate *appDelegate = nil;