mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-09-29 22:48:30 +00:00
SDL_EVENT_QUIT when no window nor tray
SDL_HINT_QUIT_ON_LAST_WINDOW_CLOSE will not fire if there are active tray icons. This impacts only applications that create tray icons, and that at least one icon outlives the last visible top-level window. SDL_EVENT_QUIT will fire when the last active tray is destroyed if there are no active windows.
This commit is contained in:
@@ -79,6 +79,7 @@ LOCAL_SRC_FILES := \
|
||||
$(wildcard $(LOCAL_PATH)/src/timer/*.c) \
|
||||
$(wildcard $(LOCAL_PATH)/src/timer/unix/*.c) \
|
||||
$(wildcard $(LOCAL_PATH)/src/tray/dummy/*.c) \
|
||||
$(wildcard $(LOCAL_PATH)/src/tray/*.c) \
|
||||
$(wildcard $(LOCAL_PATH)/src/video/*.c) \
|
||||
$(wildcard $(LOCAL_PATH)/src/video/android/*.c) \
|
||||
$(wildcard $(LOCAL_PATH)/src/video/yuv2rgb/*.c))
|
||||
|
@@ -838,6 +838,7 @@
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Gaming.Xbox.XboxOne.x64'">true</ExcludedFromBuild>
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Gaming.Xbox.XboxOne.x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\tray\SDL_tray_utils.c" />
|
||||
<ClCompile Include="..\..\src\video\dummy\SDL_nullevents.c" />
|
||||
<ClCompile Include="..\..\src\video\dummy\SDL_nullframebuffer.c" />
|
||||
<ClCompile Include="..\..\src\video\dummy\SDL_nullvideo.c" />
|
||||
|
@@ -220,6 +220,7 @@
|
||||
<ClCompile Include="..\..\src\time\windows\SDL_systime.c" />
|
||||
<ClCompile Include="..\..\src\tray\dummy\SDL_tray.c" />
|
||||
<ClCompile Include="..\..\src\tray\windows\SDL_tray.c" />
|
||||
<ClCompile Include="..\..\src\tray\SDL_tray_utils.c" />
|
||||
<ClCompile Include="..\..\src\video\yuv2rgb\yuv_rgb_lsx.c" />
|
||||
<ClCompile Include="..\..\src\video\yuv2rgb\yuv_rgb_sse.c" />
|
||||
<ClCompile Include="..\..\src\video\yuv2rgb\yuv_rgb_std.c" />
|
||||
|
@@ -673,6 +673,7 @@
|
||||
<ClCompile Include="..\..\src\time\SDL_time.c" />
|
||||
<ClCompile Include="..\..\src\time\windows\SDL_systime.c" />
|
||||
<ClCompile Include="..\..\src\tray\windows\SDL_tray.c" />
|
||||
<ClCompile Include="..\..\src\tray\SDL_tray_utils.c" />
|
||||
<ClCompile Include="..\..\src\video\dummy\SDL_nullevents.c" />
|
||||
<ClCompile Include="..\..\src\video\dummy\SDL_nullframebuffer.c" />
|
||||
<ClCompile Include="..\..\src\video\dummy\SDL_nullvideo.c" />
|
||||
|
@@ -1235,6 +1235,9 @@
|
||||
<ClCompile Include="..\..\src\tray\windows\SDL_tray.c">
|
||||
<Filter>video</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\tray\SDL_tray_utils.c">
|
||||
<Filter>video</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\video\SDL_RLEaccel.c">
|
||||
<Filter>video</Filter>
|
||||
</ClCompile>
|
||||
|
@@ -2775,6 +2775,10 @@ extern "C" {
|
||||
* - "1": SDL will send a quit event when the last window is requesting to
|
||||
* close. (default)
|
||||
*
|
||||
* If there is at least one active system tray icon, SDL_EVENT_QUIT will instead
|
||||
* be sent when both the last window will be closed and the last tray icon will
|
||||
* be destroyed.
|
||||
*
|
||||
* This hint can be set anytime.
|
||||
*
|
||||
* \since This hint is available since SDL 3.1.3.
|
||||
|
@@ -24,7 +24,7 @@
|
||||
|
||||
#include "SDL_events_c.h"
|
||||
#include "SDL_mouse_c.h"
|
||||
|
||||
#include "../tray/SDL_tray_utils.h"
|
||||
|
||||
static bool SDLCALL RemoveSupercededWindowEvents(void *userdata, SDL_Event *event)
|
||||
{
|
||||
@@ -247,7 +247,7 @@ bool SDL_SendWindowEvent(SDL_Window *window, SDL_EventType windowevent, int data
|
||||
break;
|
||||
}
|
||||
|
||||
if (windowevent == SDL_EVENT_WINDOW_CLOSE_REQUESTED && !window->parent) {
|
||||
if (windowevent == SDL_EVENT_WINDOW_CLOSE_REQUESTED && !window->parent && SDL_HasNoActiveTrays()) {
|
||||
int toplevel_count = 0;
|
||||
SDL_Window *n;
|
||||
for (n = SDL_GetVideoDevice()->windows; n; n = n->next) {
|
||||
|
62
src/tray/SDL_tray_utils.c
Normal file
62
src/tray/SDL_tray_utils.c
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#include "../video/SDL_sysvideo.h"
|
||||
#include "../events/SDL_events_c.h"
|
||||
|
||||
static int active_trays = 0;
|
||||
|
||||
extern void SDL_IncrementTrayCount(void)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
extern void SDL_DecrementTrayCount(void)
|
||||
{
|
||||
int toplevel_count = 0;
|
||||
SDL_Window *n;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if (toplevel_count < 1) {
|
||||
SDL_SendQuit();
|
||||
}
|
||||
}
|
||||
|
||||
extern bool SDL_HasNoActiveTrays(void)
|
||||
{
|
||||
return active_trays < 1;
|
||||
}
|
25
src/tray/SDL_tray_utils.h
Normal file
25
src/tray/SDL_tray_utils.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
extern void SDL_IncrementTrayCount(void);
|
||||
extern void SDL_DecrementTrayCount(void);
|
||||
extern bool SDL_HasNoActiveTrays(void);
|
@@ -25,6 +25,7 @@
|
||||
|
||||
#include <Cocoa/Cocoa.h>
|
||||
|
||||
#include "../SDL_tray_utils.h"
|
||||
#include "../../video/SDL_surface_c.h"
|
||||
|
||||
/* applicationDockMenu */
|
||||
@@ -158,6 +159,8 @@ SDL_Tray *SDL_CreateTray(SDL_Surface *icon, const char *tooltip)
|
||||
}
|
||||
|
||||
skip_putting_an_icon:
|
||||
SDL_IncrementTrayCount();
|
||||
|
||||
return tray;
|
||||
}
|
||||
|
||||
@@ -445,6 +448,8 @@ void SDL_DestroyTray(SDL_Tray *tray)
|
||||
}
|
||||
|
||||
SDL_free(tray);
|
||||
|
||||
SDL_DecrementTrayCount();
|
||||
}
|
||||
|
||||
#endif // SDL_PLATFORM_MACOS
|
||||
|
@@ -23,6 +23,8 @@
|
||||
|
||||
#ifndef SDL_PLATFORM_MACOS
|
||||
|
||||
#include "../SDL_tray_utils.h"
|
||||
|
||||
SDL_Tray *SDL_CreateTray(SDL_Surface *icon, const char *tooltip)
|
||||
{
|
||||
SDL_Unsupported();
|
||||
|
@@ -21,6 +21,8 @@
|
||||
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#include "../SDL_tray_utils.h"
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
/* getpid() */
|
||||
@@ -52,6 +54,7 @@ typedef enum
|
||||
G_CONNECT_SWAPPED = 1 << 1
|
||||
} GConnectFlags;
|
||||
gulong (*g_signal_connect_data)(gpointer instance, const gchar *detailed_signal, GCallback c_handler, gpointer data, GClosureNotify destroy_data, GConnectFlags connect_flags);
|
||||
void (*g_object_unref)(gpointer object);
|
||||
|
||||
#define g_signal_connect(instance, detailed_signal, c_handler, data) \
|
||||
g_signal_connect_data ((instance), (detailed_signal), (c_handler), (data), NULL, (GConnectFlags) 0)
|
||||
@@ -237,6 +240,7 @@ static bool init_gtk(void)
|
||||
gtk_widget_get_sensitive = dlsym(libgtk, "gtk_widget_get_sensitive");
|
||||
|
||||
g_signal_connect_data = dlsym(libgdk, "g_signal_connect_data");
|
||||
g_object_unref = dlsym(libgdk, "g_object_unref");
|
||||
|
||||
app_indicator_new = dlsym(libappindicator, "app_indicator_new");
|
||||
app_indicator_set_status = dlsym(libappindicator, "app_indicator_set_status");
|
||||
@@ -257,6 +261,7 @@ static bool init_gtk(void)
|
||||
!gtk_menu_shell_insert ||
|
||||
!gtk_widget_destroy ||
|
||||
!g_signal_connect_data ||
|
||||
!g_object_unref ||
|
||||
!app_indicator_new ||
|
||||
!app_indicator_set_status ||
|
||||
!app_indicator_set_icon ||
|
||||
@@ -394,6 +399,8 @@ SDL_Tray *SDL_CreateTray(SDL_Surface *icon, const char *tooltip)
|
||||
|
||||
app_indicator_set_status(tray->indicator, APP_INDICATOR_STATUS_ACTIVE);
|
||||
|
||||
SDL_IncrementTrayCount();
|
||||
|
||||
return tray;
|
||||
}
|
||||
|
||||
@@ -660,5 +667,9 @@ void SDL_DestroyTray(SDL_Tray *tray)
|
||||
SDL_RemovePath(tray->icon_path);
|
||||
}
|
||||
|
||||
g_object_unref(tray->indicator);
|
||||
|
||||
SDL_free(tray);
|
||||
|
||||
SDL_DecrementTrayCount();
|
||||
}
|
||||
|
@@ -21,7 +21,9 @@
|
||||
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#include "../SDL_tray_utils.h"
|
||||
#include "../../core/windows/SDL_windows.h"
|
||||
|
||||
#include <windowsx.h>
|
||||
#include <shellapi.h>
|
||||
#include <stdlib.h> /* FIXME: for mbstowcs_s, wcslen */
|
||||
@@ -228,6 +230,8 @@ SDL_Tray *SDL_CreateTray(SDL_Surface *icon, const char *tooltip)
|
||||
|
||||
SetWindowLongPtr(tray->hwnd, GWLP_USERDATA, (LONG_PTR) tray);
|
||||
|
||||
SDL_IncrementTrayCount();
|
||||
|
||||
return tray;
|
||||
}
|
||||
|
||||
@@ -568,4 +572,6 @@ void SDL_DestroyTray(SDL_Tray *tray)
|
||||
}
|
||||
|
||||
SDL_free(tray);
|
||||
|
||||
SDL_DecrementTrayCount();
|
||||
}
|
||||
|
@@ -9,6 +9,20 @@ static void SDLCALL tray_quit(void *ptr, SDL_TrayEntry *entry)
|
||||
SDL_PushEvent(&e);
|
||||
}
|
||||
|
||||
static bool trays_destroyed = false;
|
||||
|
||||
static void SDLCALL tray_close(void *ptr, SDL_TrayEntry *entry)
|
||||
{
|
||||
SDL_Tray **trays = (SDL_Tray **) ptr;
|
||||
|
||||
trays_destroyed = true;
|
||||
|
||||
SDL_DestroyTray(trays[0]);
|
||||
SDL_DestroyTray(trays[1]);
|
||||
|
||||
SDL_free(trays);
|
||||
}
|
||||
|
||||
static void SDLCALL apply_icon(void *ptr, const char * const *filelist, int filter)
|
||||
{
|
||||
if (!*filelist) {
|
||||
@@ -500,6 +514,13 @@ int main(int argc, char **argv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
SDL_Window *w = SDL_CreateWindow("", 640, 480, 0);
|
||||
|
||||
if (!w) {
|
||||
SDL_Log("Couldn't create window: %s", SDL_GetError());
|
||||
goto quit;
|
||||
}
|
||||
|
||||
/* TODO: Resource paths? */
|
||||
SDL_Surface *icon = SDL_LoadBMP("../test/sdl-test_round.bmp");
|
||||
|
||||
@@ -517,7 +538,7 @@ int main(int argc, char **argv)
|
||||
|
||||
if (!tray) {
|
||||
SDL_Log("Couldn't create control tray: %s", SDL_GetError());
|
||||
goto quit;
|
||||
goto clean_window;
|
||||
}
|
||||
|
||||
SDL_Tray *tray2 = SDL_CreateTray(icon2, "SDL Tray example");
|
||||
@@ -545,7 +566,20 @@ int main(int argc, char **argv)
|
||||
SDL_TrayEntry *entry_quit = SDL_InsertTrayEntryAt(menu, -1, "Quit", SDL_TRAYENTRY_BUTTON);
|
||||
CHECK(entry_quit);
|
||||
|
||||
SDL_TrayEntry *entry_close = SDL_InsertTrayEntryAt(menu, -1, "Close", SDL_TRAYENTRY_BUTTON);
|
||||
CHECK(entry_close);
|
||||
|
||||
/* TODO: Track memory! */
|
||||
SDL_Tray **trays = SDL_malloc(sizeof(SDL_Tray *) * 2);
|
||||
if (!trays) {
|
||||
goto clean_all;
|
||||
}
|
||||
|
||||
trays[0] = tray;
|
||||
trays[1] = tray2;
|
||||
|
||||
SDL_SetTrayEntryCallback(entry_quit, tray_quit, NULL);
|
||||
SDL_SetTrayEntryCallback(entry_close, tray_close, trays);
|
||||
|
||||
SDL_InsertTrayEntryAt(menu, -1, NULL, 0);
|
||||
|
||||
@@ -582,14 +616,26 @@ int main(int argc, char **argv)
|
||||
while (SDL_WaitEvent(&e)) {
|
||||
if (e.type == SDL_EVENT_QUIT) {
|
||||
break;
|
||||
} else if (e.type == SDL_EVENT_WINDOW_CLOSE_REQUESTED) {
|
||||
SDL_DestroyWindow(w);
|
||||
w = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
clean_all:
|
||||
SDL_DestroyTray(tray2);
|
||||
if (!trays_destroyed) {
|
||||
SDL_DestroyTray(tray2);
|
||||
}
|
||||
|
||||
clean_tray1:
|
||||
SDL_DestroyTray(tray);
|
||||
if (!trays_destroyed) {
|
||||
SDL_DestroyTray(tray);
|
||||
}
|
||||
|
||||
clean_window:
|
||||
if (w) {
|
||||
SDL_DestroyWindow(w);
|
||||
}
|
||||
|
||||
quit:
|
||||
SDL_Quit();
|
||||
|
Reference in New Issue
Block a user