diff --git a/src/tray/SDL_tray_utils.c b/src/tray/SDL_tray_utils.c index 35cf5593b0be6..943db38c79cc4 100644 --- a/src/tray/SDL_tray_utils.c +++ b/src/tray/SDL_tray_utils.c @@ -83,6 +83,11 @@ void SDL_CleanupTrays(void) SDL_DestroyTray((SDL_Tray *)trays[i]); } SDL_free(trays); + + SDL_PropertiesID g = SDL_GetGlobalProperties(); + if (g) { + SDL_ClearProperty(g, SDL_PROP_TRAY_CLEANUP); + } } bool SDL_HasActiveTrays(void) diff --git a/src/tray/SDL_tray_utils.h b/src/tray/SDL_tray_utils.h index e9e64fc6862fc..6a612bfd0b504 100644 --- a/src/tray/SDL_tray_utils.h +++ b/src/tray/SDL_tray_utils.h @@ -20,6 +20,8 @@ */ #include "SDL_internal.h" +#define SDL_PROP_TRAY_CLEANUP "SDL.PROP.Tray.Cleanup" + extern void SDL_RegisterTray(SDL_Tray *tray); extern void SDL_UnregisterTray(SDL_Tray *tray); extern void SDL_CleanupTrays(void); diff --git a/src/tray/windows/SDL_tray.c b/src/tray/windows/SDL_tray.c index 15021ac79845c..d333fedf56d3e 100644 --- a/src/tray/windows/SDL_tray.c +++ b/src/tray/windows/SDL_tray.c @@ -111,11 +111,20 @@ LRESULT CALLBACK TrayWindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lPar return DefWindowProc(hwnd, uMsg, wParam, lParam); } + static UINT s_taskbarRestart = 0; + if (s_taskbarRestart == 0) { + s_taskbarRestart = RegisterWindowMessage(TEXT("TaskbarCreated")); + } + if(uMsg == s_taskbarRestart) { + Shell_NotifyIconW(NIM_ADD, &tray->nid); + Shell_NotifyIconW(NIM_SETVERSION, &tray->nid); + } + switch (uMsg) { case WM_TRAYICON: if (LOWORD(lParam) == WM_CONTEXTMENU || LOWORD(lParam) == WM_LBUTTONUP) { SetForegroundWindow(hwnd); - + if (tray->menu) { TrackPopupMenu(tray->menu->hMenu, TPM_BOTTOMALIGN | TPM_RIGHTALIGN, GET_X_LPARAM(wParam), GET_Y_LPARAM(wParam), 0, hwnd, NULL); } @@ -216,6 +225,51 @@ void SDL_UpdateTrays(void) { } +static void SDL_PropTrayCleanupCb(void* userdata, void* cls) { + WNDCLASSEX wcex; + + wcex.hIcon = NULL; + wcex.hIconSm = NULL; + HINSTANCE h = GetModuleHandle(NULL); + if (GetClassInfoEx(h, cls, &wcex)) { + UnregisterClass(cls, h); + } +} + +static bool SDL_RegisterTrayClass(LPCWSTR className) +{ + SDL_PropertiesID g = SDL_GetGlobalProperties(); + if (!g) { + return false; + } + void* p = SDL_GetPointerProperty(g, SDL_PROP_TRAY_CLEANUP, NULL); + if (p) { + return true; + } + + WNDCLASSEX wcex; + + wcex.cbSize = sizeof(WNDCLASSEX); + wcex.hCursor = NULL; + wcex.hIcon = NULL; + wcex.hIconSm = NULL; + wcex.lpszMenuName = NULL; + wcex.lpszClassName = className; + wcex.style = 0; + wcex.hbrBackground = NULL; + wcex.lpfnWndProc = TrayWindowProc; + wcex.hInstance = NULL; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 0; + + if (!RegisterClassEx(&wcex)) { + return SDL_SetError("Couldn't register tray class"); + } + + SDL_SetPointerPropertyWithCleanup(g, SDL_PROP_TRAY_CLEANUP, (void*)wcex.lpszClassName, SDL_PropTrayCleanupCb, NULL); + return true; +} + SDL_Tray *SDL_CreateTray(SDL_Surface *icon, const char *tooltip) { if (!SDL_IsMainThread()) { @@ -230,8 +284,12 @@ SDL_Tray *SDL_CreateTray(SDL_Surface *icon, const char *tooltip) } tray->menu = NULL; - tray->hwnd = CreateWindowEx(0, TEXT("Message"), NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL); - SetWindowLongPtr(tray->hwnd, GWLP_WNDPROC, (LONG_PTR) TrayWindowProc); + if (!SDL_RegisterTrayClass(TEXT("SDL_TRAY"))) { + SDL_SetError("Failed to register SDL_TRAY window class"); + return NULL; + } + tray->hwnd = CreateWindowEx(0, TEXT("SDL_TRAY"), NULL, WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, NULL, NULL); WIN_UpdateDarkModeForHWND(tray->hwnd);