SDL: Don't update hidden child windows, their relative position doesn't change

From 66eff69d2b4a50421e731264477b5f1a09be496f Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Thu, 16 Mar 2023 11:23:46 -0700
Subject: [PATCH] Don't update hidden child windows, their relative position
 doesn't change

This improves performance when moving a top level window that has many hidden child windows
---
 src/video/windows/SDL_windowsevents.c | 5 ++++-
 src/video/windows/SDL_windowswindow.c | 5 +++++
 src/video/x11/SDL_x11events.c         | 5 ++++-
 src/video/x11/SDL_x11window.c         | 5 +++++
 4 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c
index a9f85f843adb..484ddf674f33 100644
--- a/src/video/windows/SDL_windowsevents.c
+++ b/src/video/windows/SDL_windowsevents.c
@@ -1310,7 +1310,10 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
 
         /* Update the position of any child windows */
         for (win = data->window->first_child; win != NULL; win = win->next_sibling) {
-            WIN_SetWindowPositionInternal(win, SWP_NOCOPYBITS | SWP_NOACTIVATE);
+            /* Don't update hidden child windows, their relative position doesn't change */
+            if (!(win->flags & SDL_WINDOW_HIDDEN)) {
+                WIN_SetWindowPositionInternal(win, SWP_NOCOPYBITS | SWP_NOACTIVATE);
+            }
         }
     } break;
 
diff --git a/src/video/windows/SDL_windowswindow.c b/src/video/windows/SDL_windowswindow.c
index 5ee59bd300bc..dc44cebeecf6 100644
--- a/src/video/windows/SDL_windowswindow.c
+++ b/src/video/windows/SDL_windowswindow.c
@@ -884,6 +884,11 @@ void WIN_ShowWindow(_THIS, SDL_Window *window)
     HWND hwnd;
     int nCmdShow;
 
+    if (window->parent) {
+        /* Update our position in case our parent moved while we were hidden */
+        WIN_SetWindowPositionInternal(window, SWP_NOCOPYBITS | SWP_NOACTIVATE);
+    }
+
     hwnd = window->driverdata->hwnd;
     nCmdShow = SDL_GetHintBoolean(SDL_HINT_WINDOW_NO_ACTIVATION_WHEN_SHOWN, SDL_FALSE) ? SW_SHOWNA : SW_SHOW;
     style = GetWindowLong(hwnd, GWL_EXSTYLE);
diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c
index c3de0c79801f..bf226b31de29 100644
--- a/src/video/x11/SDL_x11events.c
+++ b/src/video/x11/SDL_x11events.c
@@ -1219,7 +1219,10 @@ static void X11_DispatchEvent(_THIS, XEvent *xevent)
             }
 #endif
             for (w = data->window->first_child; w != NULL; w = w->next_sibling) {
-                X11_UpdateWindowPosition(w);
+                /* Don't update hidden child windows, their relative position doesn't change */
+                if (!(w->flags & SDL_WINDOW_HIDDEN)) {
+                    X11_UpdateWindowPosition(w);
+                }
             }
         }
         if (xevent->xconfigure.width != data->last_xconfigure.width ||
diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c
index 5a4661b8fb16..d5750ce3e292 100644
--- a/src/video/x11/SDL_x11window.c
+++ b/src/video/x11/SDL_x11window.c
@@ -1267,6 +1267,11 @@ void X11_ShowWindow(_THIS, SDL_Window *window)
         return;
     }
 
+    if (window->parent) {
+        /* Update our position in case our parent moved while we were hidden */
+        X11_UpdateWindowPosition(window);
+    }
+
     if (!X11_IsWindowMapped(_this, window)) {
         X11_XMapRaised(display, data->xwindow);
         /* Blocking wait for "MapNotify" event.