Browse Source

win32: Don't overwrite a programmatically set window size with old data

While in a modal loop, the size in WM_WINDOWPOSCHANGING/WM_WINDOWPOSCHANGED may only be updated if the window is being resized interactively. Set the SWP_NOSIZE flag if the size hasn't changed from the last move/size event, or a size set programmatically may end up being overwritten by old size data.
Frank Praznik 5 days ago
parent
commit
ce1175724a
2 changed files with 23 additions and 0 deletions
  1. 21 0
      src/video/windows/SDL_windowsevents.c
  2. 2 0
      src/video/windows/SDL_windowswindow.h

+ 21 - 0
src/video/windows/SDL_windowsevents.c

@@ -1708,6 +1708,21 @@ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara
     case WM_WINDOWPOSCHANGING:
 
         if (data->expected_resize) {
+            returnCode = 0;
+        } else if (data->in_modal_loop) {
+            WINDOWPOS *windowpos = (WINDOWPOS *)lParam;
+
+            /* While in a modal loop, the size may only be updated if the window is being resized interactively.
+             * Set the SWP_NOSIZE flag if the reported size hasn't changed from the last WM_WINDOWPOSCHANGING
+             * event, or a size set programmatically may end up being overwritten by old size data.
+             */
+            if (data->last_modal_width == windowpos->cx && data->last_modal_height == windowpos->cy) {
+                windowpos->flags |= SWP_NOSIZE;
+            }
+
+            data->last_modal_width = windowpos->cx;
+            data->last_modal_height = windowpos->cy;
+
             returnCode = 0;
         }
         break;
@@ -1819,6 +1834,12 @@ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara
 
         ++data->in_modal_loop;
         if (data->in_modal_loop == 1) {
+            RECT rect;
+            SDL_zero(rect);
+            GetWindowRect(data->hwnd, &rect);
+            data->last_modal_width = rect.right - rect.left;
+            data->last_modal_height = rect.bottom - rect.top;
+
             data->initial_size_rect.left = data->window->x;
             data->initial_size_rect.right = data->window->x + data->window->w;
             data->initial_size_rect.top = data->window->y;

+ 2 - 0
src/video/windows/SDL_windowswindow.h

@@ -86,6 +86,8 @@ struct SDL_WindowData
     bool disable_move_size_events;
     bool showing_window;
     int in_modal_loop;
+    int last_modal_width;
+    int last_modal_height;
     RECT initial_size_rect;
     RECT cursor_clipped_rect; // last successfully committed clipping rect for this window
     RECT cursor_ctrlock_rect; // this is Windows-specific, but probably does not need to be per-window