Made the window ICMProfile filename per-window The event no longer spams each time a window gets focus if there are windows on monitors with different color profiles. This also has the side effect that you no longer get a color profile event at window creation, which is consistent with other events that communicate state changes.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c
index d7f77f7..6f21b23 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 e56581f..16cba51 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 f02d425..58f7b98 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*
-WIN_GetWindowICCProfile(_THIS, SDL_Window * window, size_t * size)
+void
+WIN_UpdateWindowICCProfile(SDL_Window * window, SDL_bool send_event)
{
- 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;
+ SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
+ SDL_DisplayData *displaydata = display ? (SDL_DisplayData*)display->driverdata : NULL;
- hdc = CreateDCW(data->DeviceName, NULL, NULL, NULL);
- if (hdc) {
- succeeded = GetICMProfileW(hdc, &fileNameSize, filename);
- DeleteDC(hdc);
+ 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_WindowData *data = (SDL_WindowData *) window->driverdata;
+ char *filename_utf8;
+ void *iccProfileData = NULL;
- 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 8b3c1ff..c72707a 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);