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
main
Sam Lantinga 2024-01-12 09:38:28 -08:00
parent 7efeb36131
commit 98be55894e
1 changed files with 74 additions and 65 deletions

View File

@ -1088,92 +1088,97 @@ 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;
if (data->expected_resize) {
returnCode = 0;
}
if (IsIconic(hwnd)) {
SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_MINIMIZED, 0, 0);
} else if (IsZoomed(hwnd)) {
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));
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);
}
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;
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 (data->initializing || data->in_border_change) {
if (windowpos->flags & SWP_SHOWWINDOW) {
SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_SHOWN, 0, 0);
}
if (iconic) {
SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_MINIMIZED, 0, 0);
} 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 if (data->window->flags & (SDL_WINDOW_MAXIMIZED | SDL_WINDOW_MINIMIZED)) {
SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_RESTORED, 0, 0);
}
if (windowpos->flags & SWP_HIDEWINDOW) {
SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_HIDDEN, 0, 0);
}
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);
if (moved) {
RECT rect;
int x, y;
if (GetClientRect(hwnd, &rect) && !WIN_IsRectEmpty(&rect)) {
ClientToScreen(hwnd, (LPPOINT)&rect);
ClientToScreen(hwnd, (LPPOINT)&rect + 1);
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 (resized) {
RECT rect;
int w, h;
/* 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;
SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_RESIZED, w, h);
}
}
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);
// 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);
WIN_UpdateClipCursor(data->window);
x = rect.left;
y = rect.top;
}
w = rect.right - rect.left;
h = rect.bottom - rect.top;
SDL_SendWindowEvent(data->window, SDL_EVENT_WINDOW_RESIZED, 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
/* Forces a WM_PAINT event */
InvalidateRect(hwnd, NULL, FALSE);
/* 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: