diff --git a/include/SDL3/SDL_video.h b/include/SDL3/SDL_video.h index 6ff85cf093..5943d9d2b8 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 02fe914686..e3bcc9d445 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 ba1777a373..2d71ca64a5 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 67e62d7b6b..a1528faeba 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 2ffb28ff45..37628f0860 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 c98cab7e22..88ae689f08 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. */