diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index d7f77f720..6f21b2343 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -621,29 +621,6 @@ WIN_KeyboardHookProc(int nCode, WPARAM wParam, LPARAM lParam) return 1; } -static void WIN_CheckICMProfileChanged(SDL_Window* window) -{ - SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window); - SDL_DisplayData *data = display ? (SDL_DisplayData*)display->driverdata : NULL; - - if (data) { - HDC hdc = CreateDCW(data->DeviceName, NULL, NULL, NULL); - if (hdc) { - static WCHAR currentIcmFileName[MAX_PATH]; - WCHAR icmFileName[MAX_PATH]; - DWORD fileNameSize = SDL_arraysize(icmFileName); - if (GetICMProfileW(hdc, &fileNameSize, icmFileName)) { - /* fileNameSize includes '\0' on return */ - fileNameSize *= sizeof(icmFileName[0]); - if (SDL_memcmp(currentIcmFileName, icmFileName, fileNameSize) != 0) { - SDL_memcpy(currentIcmFileName, icmFileName, fileNameSize); - SDL_SendWindowEvent(window, SDL_WINDOWEVENT_ICCPROF_CHANGED, 0, 0); - } - } - DeleteDC(hdc); - } - } -} #endif /*!defined(__XBOXONE__) && !defined(__XBOXSERIES__)*/ LRESULT CALLBACK @@ -716,7 +693,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) actually being the foreground window, but this appears to get called in all cases where the global foreground window changes to and from this window. */ WIN_UpdateFocus(data->window, !!wParam); - WIN_CheckICMProfileChanged(data->window); + WIN_UpdateWindowICCProfile(data->window, SDL_TRUE); } break; @@ -1221,7 +1198,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) /* Forces a WM_PAINT event */ InvalidateRect(hwnd, NULL, FALSE); - WIN_CheckICMProfileChanged(data->window); + WIN_UpdateWindowICCProfile(data->window, SDL_TRUE); } break; diff --git a/src/video/windows/SDL_windowsmodes.c b/src/video/windows/SDL_windowsmodes.c index e56581f73..16cba5114 100644 --- a/src/video/windows/SDL_windowsmodes.c +++ b/src/video/windows/SDL_windowsmodes.c @@ -325,12 +325,11 @@ WIN_AddDisplay(_THIS, HMONITOR hMonitor, const MONITORINFOEXW *info, SDL_bool se } } - displaydata = (SDL_DisplayData *) SDL_malloc(sizeof(*displaydata)); + displaydata = (SDL_DisplayData *) SDL_calloc(1, sizeof(*displaydata)); if (!displaydata) { return SDL_FALSE; } - SDL_memcpy(displaydata->DeviceName, info->szDevice, - sizeof(displaydata->DeviceName)); + SDL_memcpy(displaydata->DeviceName, info->szDevice, sizeof(displaydata->DeviceName)); displaydata->MonitorHandle = hMonitor; displaydata->IsValid = SDL_TRUE; diff --git a/src/video/windows/SDL_windowswindow.c b/src/video/windows/SDL_windowswindow.c index f02d42554..58f7b9809 100644 --- a/src/video/windows/SDL_windowswindow.c +++ b/src/video/windows/SDL_windowswindow.c @@ -29,6 +29,7 @@ #include "../SDL_pixels_c.h" #include "../../events/SDL_keyboard_c.h" #include "../../events/SDL_mouse_c.h" +#include "../../events/SDL_windowevents_c.h" #include "../../SDL_hints_c.h" #include "SDL_windowsvideo.h" @@ -390,6 +391,7 @@ SetupWindowData(_THIS, SDL_Window * window, HWND hwnd, HWND parent, SDL_bool cre window->y = y; } } + WIN_UpdateWindowICCProfile(window, SDL_FALSE); #endif { DWORD style = GetWindowLong(hwnd, GWL_STYLE); @@ -461,6 +463,9 @@ static void CleanupWindowData(_THIS, SDL_Window * window) SDL_DelHintCallback(SDL_HINT_MOUSE_RELATIVE_MODE_CENTER, WIN_MouseRelativeModeCenterChanged, data); #if !defined(__XBOXONE__) && !defined(__XBOXSERIES__) + if (data->ICMFileName) { + SDL_free(data->ICMFileName); + } if (data->keyboard_hook) { UnhookWindowsHookEx(data->keyboard_hook); } @@ -1013,29 +1018,53 @@ WIN_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp) return succeeded ? 0 : -1; } -void* +void +WIN_UpdateWindowICCProfile(SDL_Window * window, SDL_bool send_event) +{ + SDL_WindowData *data = (SDL_WindowData *) window->driverdata; + SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window); + SDL_DisplayData *displaydata = display ? (SDL_DisplayData*)display->driverdata : NULL; + + if (displaydata) { + HDC hdc = CreateDCW(displaydata->DeviceName, NULL, NULL, NULL); + if (hdc) { + WCHAR fileName[MAX_PATH]; + DWORD fileNameSize = SDL_arraysize(fileName); + if (GetICMProfileW(hdc, &fileNameSize, fileName)) { + /* fileNameSize includes '\0' on return */ + if (!data->ICMFileName || + SDL_wcscmp(data->ICMFileName, fileName) != 0) { + if (data->ICMFileName) { + SDL_free(data->ICMFileName); + } + data->ICMFileName = SDL_wcsdup(fileName); + if (send_event) { + SDL_SendWindowEvent(window, SDL_WINDOWEVENT_ICCPROF_CHANGED, 0, 0); + } + } + } + DeleteDC(hdc); + } + } +} + +void * WIN_GetWindowICCProfile(_THIS, SDL_Window * window, size_t * size) { - SDL_VideoDisplay* display = SDL_GetDisplayForWindow(window); - SDL_DisplayData* data = (SDL_DisplayData*)display->driverdata; - HDC hdc; - BOOL succeeded = FALSE; - WCHAR filename[MAX_PATH]; - DWORD fileNameSize = MAX_PATH; - void* iccProfileData = NULL; + SDL_WindowData *data = (SDL_WindowData *) window->driverdata; + char *filename_utf8; + void *iccProfileData = NULL; - hdc = CreateDCW(data->DeviceName, NULL, NULL, NULL); - if (hdc) { - succeeded = GetICMProfileW(hdc, &fileNameSize, filename); - DeleteDC(hdc); - } - - if (succeeded) { - iccProfileData = SDL_LoadFile(WIN_StringToUTF8(filename), size); - if (!iccProfileData) + filename_utf8 = WIN_StringToUTF8(data->ICMFileName); + if (filename_utf8) { + iccProfileData = SDL_LoadFile(filename_utf8, size); + if (!iccProfileData) { SDL_SetError("Could not open ICC profile"); + } + SDL_free(filename_utf8); + } else { + SDL_OutOfMemory(); } - return iccProfileData; } diff --git a/src/video/windows/SDL_windowswindow.h b/src/video/windows/SDL_windowswindow.h index 8b3c1ff1d..c72707a98 100644 --- a/src/video/windows/SDL_windowswindow.h +++ b/src/video/windows/SDL_windowswindow.h @@ -62,6 +62,7 @@ typedef struct RECT cursor_clipped_rect; SDL_Point last_raw_mouse_position; SDL_bool mouse_tracked; + WCHAR *ICMFileName; struct SDL_VideoData *videodata; #if SDL_VIDEO_OPENGL_EGL EGLSurface egl_surface; @@ -92,6 +93,7 @@ extern void WIN_SetWindowResizable(_THIS, SDL_Window * window, SDL_bool resizabl extern void WIN_SetWindowAlwaysOnTop(_THIS, SDL_Window * window, SDL_bool on_top); extern void WIN_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen); extern int WIN_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp); +extern void WIN_UpdateWindowICCProfile(SDL_Window * window, SDL_bool send_event); extern void* WIN_GetWindowICCProfile(_THIS, SDL_Window * window, size_t * size); extern int WIN_GetWindowGammaRamp(_THIS, SDL_Window * window, Uint16 * ramp); extern void WIN_SetWindowMouseRect(_THIS, SDL_Window * window);