From 98be55894eb0db46f9cef689365719ed5f35ab3b Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Fri, 12 Jan 2024 09:38:28 -0800
Subject: [PATCH] Moved window state change handling from WM_WINDOWPOSCHANGING
to WM_WINDOWPOSCHANGED
Applications might override WM_WINDOWPOSCHANGING which would prevent us from getting the correct window state.
This also fixes cases where the window doesn't get WM_SHOWWINDOW, as described in Raymond Chen's blog post:
https://devblogs.microsoft.com/oldnewthing/20080115-00/?p=23813
---
src/video/windows/SDL_windowsevents.c | 119 ++++++++++++++------------
1 file changed, 64 insertions(+), 55 deletions(-)
diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c
index 08b9e9dd6091..bfbf93dc0579 100644
--- a/src/video/windows/SDL_windowsevents.c
+++ b/src/video/windows/SDL_windowsevents.c
@@ -1088,91 +1088,96 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
case WM_WINDOWPOSCHANGING:
{
WINDOWPOS *windowpos = (WINDOWPOS*)lParam;
+ if (!IsIconic(hwnd) &&
+ !IsZoomed(hwnd) &&
+ (data->window->flags & (SDL_WINDOW_MAXIMIZED | SDL_WINDOW_MINIMIZED)) &&
+ !(data->window->flags & SDL_WINDOW_FULLSCREEN)) {
+ /* Use the stored floating size if moving from a fixed-size to floating state. */
+ int fx, fy, fw, fh;
+
+ WIN_AdjustWindowRect(data->window, &fx, &fy, &fw, &fh, SDL_WINDOWRECT_FLOATING);
+ windowpos->x = fx;
+ windowpos->y = fy;
+ windowpos->cx = fw;
+ windowpos->cy = fh;
+ windowpos->flags &= ~(SWP_NOSIZE | SWP_NOMOVE);
+ }
+ } break;
- if (data->expected_resize) {
- returnCode = 0;
+ case WM_WINDOWPOSCHANGED:
+ {
+ SDL_Window *win;
+ const SDL_DisplayID original_displayID = data->last_displayID;
+ const WINDOWPOS *windowpos = (WINDOWPOS *)lParam;
+ const SDL_bool moved = !(windowpos->flags & SWP_NOMOVE);
+ const SDL_bool resized = !(windowpos->flags & SWP_NOSIZE);
+ const SDL_bool iconic = IsIconic(hwnd);
+ const SDL_bool zoomed = IsZoomed(hwnd);
+
+ if (windowpos->flags & SWP_SHOWWINDOW) {
+ SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_SHOWN, 0, 0);
}
- if (IsIconic(hwnd)) {
+ if (iconic) {
SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_MINIMIZED, 0, 0);
- } else if (IsZoomed(hwnd)) {
+ } else if (zoomed) {
if (data->window->flags & SDL_WINDOW_MINIMIZED) {
/* If going from minimized to maximized, send the restored event first. */
SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_RESTORED, 0, 0);
}
SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_MAXIMIZED, 0, 0);
- } else {
- SDL_bool was_fixed_size = !!(data->window->flags & (SDL_WINDOW_MAXIMIZED | SDL_WINDOW_MINIMIZED));
+ } else if (data->window->flags & (SDL_WINDOW_MAXIMIZED | SDL_WINDOW_MINIMIZED)) {
SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_RESTORED, 0, 0);
-
- /* Send the stored floating size if moving from a fixed-size to floating state. */
- if (was_fixed_size && !(data->window->flags & SDL_WINDOW_FULLSCREEN)) {
- int fx, fy, fw, fh;
-
- WIN_AdjustWindowRect(data->window, &fx, &fy, &fw, &fh, SDL_WINDOWRECT_FLOATING);
- windowpos->x = fx;
- windowpos->y = fy;
- windowpos->cx = fw;
- windowpos->cy = fh;
- windowpos->flags &= ~(SWP_NOSIZE | SWP_NOMOVE);
- }
}
- } break;
- case WM_WINDOWPOSCHANGED:
- {
- SDL_Window *win;
- RECT rect;
- int x, y;
- int w, h;
- const SDL_DisplayID original_displayID = data->last_displayID;
+ if (windowpos->flags & SWP_HIDEWINDOW) {
+ SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_HIDDEN, 0, 0);
+ }
- if (data->initializing || data->in_border_change) {
+ if (!moved && !resized) {
+ /* Nothing left to handle */
break;
}
/* When the window is minimized it's resized to the dock icon size, ignore this */
- if (IsIconic(hwnd)) {
+ if (iconic) {
break;
}
- if (!GetClientRect(hwnd, &rect) || WIN_IsRectEmpty(&rect)) {
+ if (data->initializing) {
break;
}
- ClientToScreen(hwnd, (LPPOINT)&rect);
- ClientToScreen(hwnd, (LPPOINT)&rect + 1);
-
- WIN_UpdateClipCursor(data->window);
-
- x = rect.left;
- y = rect.top;
- SDL_GlobalToRelativeForWindow(data->window, x, y, &x, &y);
- SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_MOVED, x, y);
+ if (moved) {
+ RECT rect;
+ int x, y;
- // Moving the window from one display to another can change the size of the window (in the handling of SDL_EVENT_WINDOW_MOVED), so we need to re-query the bounds
- if (GetClientRect(hwnd, &rect)) {
- ClientToScreen(hwnd, (LPPOINT)&rect);
- ClientToScreen(hwnd, (LPPOINT)&rect + 1);
+ if (GetClientRect(hwnd, &rect) && !WIN_IsRectEmpty(&rect)) {
+ ClientToScreen(hwnd, (LPPOINT)&rect);
+ ClientToScreen(hwnd, (LPPOINT)&rect + 1);
- WIN_UpdateClipCursor(data->window);
+ x = rect.left;
+ y = rect.top;
- x = rect.left;
- y = rect.top;
+ SDL_GlobalToRelativeForWindow(data->window, x, y, &x, &y);
+ SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_MOVED, x, y);
+ }
}
- w = rect.right - rect.left;
- h = rect.bottom - rect.top;
- SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_RESIZED, w, h);
+ if (resized) {
+ RECT rect;
+ int w, h;
-#ifdef HIGHDPI_DEBUG
- SDL_Log("WM_WINDOWPOSCHANGED: Windows client rect (pixels): (%d, %d) (%d x %d)\tSDL client rect (points): (%d, %d) (%d x %d) windows reported dpi %d",
- rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
- x, y, w, h, data->videodata->GetDpiForWindow ? data->videodata->GetDpiForWindow(data->hwnd) : 0);
-#endif
+ /* Moving the window from one display to another can change the size of the window (in the handling of SDL_EVENT_WINDOW_MOVED), so we need to re-query the bounds */
+ if (GetClientRect(hwnd, &rect) && !WIN_IsRectEmpty(&rect)) {
+ w = rect.right;
+ h = rect.bottom;
- /* Forces a WM_PAINT event */
- InvalidateRect(hwnd, NULL, FALSE);
+ SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_RESIZED, w, h);
+ }
+ }
+
+ WIN_UpdateClipCursor(data->window);
/* Update the window display position */
data->last_displayID = SDL_GetDisplayForWindow(data->window);
@@ -1189,6 +1194,10 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
WIN_SetWindowPositionInternal(win, SWP_NOCOPYBITS | SWP_NOACTIVATE, SDL_WINDOWRECT_CURRENT);
}
}
+
+ /* Forces a WM_PAINT event */
+ InvalidateRect(hwnd, NULL, FALSE);
+
} break;
case WM_ENTERSIZEMOVE: