From 0ff5c054862caebe26e8a3febc366c4098353267 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Mon, 24 Jun 2024 12:22:12 -0700
Subject: [PATCH] Added SDL_GetWindows()
---
include/SDL3/SDL_video.h | 14 ++++++++++-
src/dynapi/SDL_dynapi.sym | 1 +
src/dynapi/SDL_dynapi_overrides.h | 1 +
src/dynapi/SDL_dynapi_procs.h | 1 +
src/video/SDL_video.c | 42 +++++++++++++++++++++++++++++--
test/testautomation_video.c | 8 ++++++
6 files changed, 64 insertions(+), 3 deletions(-)
diff --git a/include/SDL3/SDL_video.h b/include/SDL3/SDL_video.h
index 6ff85cf0936dc..5943d9d2b8c76 100644
--- a/include/SDL3/SDL_video.h
+++ b/include/SDL3/SDL_video.h
@@ -384,7 +384,7 @@ extern SDL_DECLSPEC SDL_SystemTheme SDLCALL SDL_GetSystemTheme(void);
/**
* Get a list of currently connected displays.
*
- * \param count a pointer filled in with the number of displays returned.
+ * \param count a pointer filled in with the number of displays returned, may be NULL.
* \returns a 0 terminated array of display instance IDs which should be freed
* with SDL_free(), or NULL on error; call SDL_GetError() for more
* details.
@@ -783,6 +783,18 @@ extern SDL_DECLSPEC void *SDLCALL SDL_GetWindowICCProfile(SDL_Window *window, si
*/
extern SDL_DECLSPEC Uint32 SDLCALL SDL_GetWindowPixelFormat(SDL_Window *window);
+/**
+ * Get a list of valid windows.
+ *
+ * \param count a pointer filled in with the number of windows returned, may be NULL.
+ * \returns a 0 terminated array of window pointers which should be freed
+ * with SDL_free(), or NULL on error; call SDL_GetError() for more
+ * details.
+ *
+ * \since This function is available since SDL 3.0.0.
+ */
+extern SDL_DECLSPEC SDL_Window **SDLCALL SDL_GetWindows(int *count);
+
/**
* Create a window with the specified dimensions and flags.
*
diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym
index 02fe914686724..e3bcc9d445873 100644
--- a/src/dynapi/SDL_dynapi.sym
+++ b/src/dynapi/SDL_dynapi.sym
@@ -480,6 +480,7 @@ SDL3_0.0.0 {
SDL_GetWindowSurface;
SDL_GetWindowSurfaceVSync;
SDL_GetWindowTitle;
+ SDL_GetWindows;
SDL_GlobDirectory;
SDL_GlobStorageDirectory;
SDL_HapticEffectSupported;
diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h
index ba1777a3731f7..2d71ca64a5b80 100644
--- a/src/dynapi/SDL_dynapi_overrides.h
+++ b/src/dynapi/SDL_dynapi_overrides.h
@@ -505,6 +505,7 @@
#define SDL_GetWindowSurface SDL_GetWindowSurface_REAL
#define SDL_GetWindowSurfaceVSync SDL_GetWindowSurfaceVSync_REAL
#define SDL_GetWindowTitle SDL_GetWindowTitle_REAL
+#define SDL_GetWindows SDL_GetWindows_REAL
#define SDL_GlobDirectory SDL_GlobDirectory_REAL
#define SDL_GlobStorageDirectory SDL_GlobStorageDirectory_REAL
#define SDL_HapticEffectSupported SDL_HapticEffectSupported_REAL
diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h
index 67e62d7b6bf6a..a1528faeba295 100644
--- a/src/dynapi/SDL_dynapi_procs.h
+++ b/src/dynapi/SDL_dynapi_procs.h
@@ -525,6 +525,7 @@ SDL_DYNAPI_PROC(int,SDL_GetWindowSizeInPixels,(SDL_Window *a, int *b, int *c),(a
SDL_DYNAPI_PROC(SDL_Surface*,SDL_GetWindowSurface,(SDL_Window *a),(a),return)
SDL_DYNAPI_PROC(int,SDL_GetWindowSurfaceVSync,(SDL_Window *a, int *b),(a,b),return)
SDL_DYNAPI_PROC(const char*,SDL_GetWindowTitle,(SDL_Window *a),(a),return)
+SDL_DYNAPI_PROC(SDL_Window**,SDL_GetWindows,(int *a),(a),return)
SDL_DYNAPI_PROC(char**,SDL_GlobDirectory,(const char *a, const char *b, SDL_GlobFlags c, int *d),(a,b,c,d),return)
SDL_DYNAPI_PROC(char**,SDL_GlobStorageDirectory,(SDL_Storage *a, const char *b, const char *c, SDL_GlobFlags d, int *e),(a,b,c,d,e),return)
SDL_DYNAPI_PROC(SDL_bool,SDL_HapticEffectSupported,(SDL_Haptic *a, const SDL_HapticEffect *b),(a,b),return)
diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c
index 2ffb28ff4576c..37628f086084b 100644
--- a/src/video/SDL_video.c
+++ b/src/video/SDL_video.c
@@ -1999,6 +1999,44 @@ void SDL_ToggleDragAndDropSupport(void)
}
}
+SDL_Window **SDLCALL SDL_GetWindows(int *count)
+{
+ if (count) {
+ *count = 0;
+ }
+
+ if (!_this) {
+ SDL_UninitializedVideo();
+ return NULL;
+ }
+
+ SDL_Window *window;
+ int num_added = 0;
+ int num_windows = 0;
+ for (window = _this->windows; window; window = window->next) {
+ ++num_windows;
+ }
+
+ SDL_Window **windows = SDL_malloc((num_windows + 1) * sizeof(*windows));
+ if (!windows) {
+ return NULL;
+ }
+
+ for (window = _this->windows; window; window = window->next) {
+ windows[num_added++] = window;
+ if (num_added == num_windows) {
+ // Race condition? Multi-threading not supported, ignore it
+ break;
+ }
+ }
+ windows[num_added] = NULL;
+
+ if (count) {
+ *count = num_added;
+ }
+ return windows;
+}
+
static void ApplyWindowFlags(SDL_Window *window, SDL_WindowFlags flags)
{
if (!SDL_WINDOW_IS_POPUP(window)) {
@@ -3955,7 +3993,7 @@ SDL_bool SDL_ScreenSaverEnabled(void)
int SDL_EnableScreenSaver(void)
{
if (!_this) {
- return 0;
+ return SDL_UninitializedVideo();
}
if (!_this->suspend_screensaver) {
return 0;
@@ -3971,7 +4009,7 @@ int SDL_EnableScreenSaver(void)
int SDL_DisableScreenSaver(void)
{
if (!_this) {
- return 0;
+ return SDL_UninitializedVideo();
}
if (_this->suspend_screensaver) {
return 0;
diff --git a/test/testautomation_video.c b/test/testautomation_video.c
index c98cab7e22616..88ae689f08bcc 100644
--- a/test/testautomation_video.c
+++ b/test/testautomation_video.c
@@ -13,8 +13,10 @@
static SDL_Window *createVideoSuiteTestWindow(const char *title)
{
SDL_Window *window;
+ SDL_Window **windows;
SDL_Event event;
int w, h;
+ int count;
SDL_WindowFlags flags;
SDL_bool needs_renderer = SDL_FALSE;
SDL_bool needs_events_pumped = SDL_FALSE;
@@ -28,6 +30,12 @@ static SDL_Window *createVideoSuiteTestWindow(const char *title)
SDLTest_AssertPass("Call to SDL_CreateWindow('Title',%d,%d,%" SDL_PRIu64 ")", w, h, flags);
SDLTest_AssertCheck(window != NULL, "Validate that returned window struct is not NULL");
+ /* Check the window is available in the window list */
+ windows = SDL_GetWindows(&count);
+ SDLTest_AssertCheck(windows != NULL, "Validate that returned window list is not NULL");
+ SDLTest_AssertCheck(windows[0] == window, "Validate that the window is first in the window list");
+ SDL_free(windows);
+
/* Wayland and XWayland windows require that a frame be presented before they are fully mapped and visible onscreen.
* This is required for the mouse/keyboard grab tests to pass.
*/