Added SDL_CreateWindowWithPosition()

It turns out there's a race condition on X11 where the window could be placed by the window manager while being placed by the application, so we need to have the initial position available at window creation.
This commit is contained in:
Sam Lantinga 2023-03-31 17:07:38 -07:00
parent b6ae281e97
commit 2aa2fa5449
9 changed files with 88 additions and 20 deletions

View File

@ -2519,16 +2519,21 @@ SDL_Event *e1;
+ e1->gsensor + e1->gsensor
@@ @@
expression e1, e2, e3, e4; expression e1, e2, e3, e4;
constant c1, c2;
@@ @@
- SDL_CreateWindow(e1, c1, c2, e2, e3, e4) - SDL_CreateWindow(e1, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, e2, e3, e4)
+ SDL_CreateWindow(e1, e2, e3, e4) + SDL_CreateWindow(e1, e2, e3, e4)
@@ @@
expression e1, e2, e3, e4, e5, e6;
@@
- SDL_CreateWindow(e1, e2, e3, e4, e5, e6)
+ SDL_CreateWindowWithPosition(e1, e2, e3, e4, e5, e6)
@@
expression e1, e2, e3, e4; expression e1, e2, e3, e4;
constant c1, c2; constant c1, c2;
@@ @@
- SDL_CreateShapedWindow(e1, c1, c2, e2, e3, e4) - SDL_CreateShapedWindow(e1, c1, c2, e2, e3, e4)
+ SDL_CreateShapedWindow(e1, e2, e3, e4) + SDL_CreateShapedWindow(e1, e2, e3, e4)
@@
typedef SDL_atomic_t, SDL_AtomicInt; typedef SDL_atomic_t, SDL_AtomicInt;
@@ @@
- SDL_atomic_t - SDL_atomic_t

View File

@ -1036,14 +1036,7 @@ Rather than iterating over displays using display index, there is a new function
} }
``` ```
SDL_CreateWindow() has been simplified and no longer takes a window position. You can set a position for your window during window creation by creating it hidden and setting the position before showing it: SDL_CreateWindow() has been simplified and no longer takes a window position. You can use SDL_CreateWindowWithPosition() if you need to set the window position when creating it.
```c
{
SDL_Window *window = SDL_CreateWindow("Test", 640, 480, SDL_WINDOW_HIDDEN);
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
SDL_ShowWindow(window);
}
```
The SDL_WINDOWPOS_UNDEFINED_DISPLAY() and SDL_WINDOWPOS_CENTERED_DISPLAY() macros take a display ID instead of display index. The display ID 0 has a special meaning in this case, and is used to indicate the primary display. The SDL_WINDOWPOS_UNDEFINED_DISPLAY() and SDL_WINDOWPOS_CENTERED_DISPLAY() macros take a display ID instead of display index. The display ID 0 has a special meaning in this case, and is used to indicate the primary display.

View File

@ -92,6 +92,7 @@ typedef enum
* *
* \sa SDL_CreateWindow() * \sa SDL_CreateWindow()
* \sa SDL_CreateWindowFrom() * \sa SDL_CreateWindowFrom()
* \sa SDL_CreateWindowWithPosition()
* \sa SDL_DestroyWindow() * \sa SDL_DestroyWindow()
* \sa SDL_FlashWindow() * \sa SDL_FlashWindow()
* \sa SDL_GetWindowData() * \sa SDL_GetWindowData()
@ -602,7 +603,7 @@ extern DECLSPEC void *SDLCALL SDL_GetWindowICCProfile(SDL_Window *window, size_t
extern DECLSPEC Uint32 SDLCALL SDL_GetWindowPixelFormat(SDL_Window *window); extern DECLSPEC Uint32 SDLCALL SDL_GetWindowPixelFormat(SDL_Window *window);
/** /**
* Create a window with the specified position, dimensions, and flags. * Create a window with the specified dimensions and flags.
* *
* `flags` may be any of the following OR'd together: * `flags` may be any of the following OR'd together:
* *
@ -661,10 +662,78 @@ extern DECLSPEC Uint32 SDLCALL SDL_GetWindowPixelFormat(SDL_Window *window);
* *
* \sa SDL_CreatePopupWindow * \sa SDL_CreatePopupWindow
* \sa SDL_CreateWindowFrom * \sa SDL_CreateWindowFrom
* \sa SDL_CreateWindowWithPosition
* \sa SDL_DestroyWindow * \sa SDL_DestroyWindow
*/ */
extern DECLSPEC SDL_Window *SDLCALL SDL_CreateWindow(const char *title, int w, int h, Uint32 flags); extern DECLSPEC SDL_Window *SDLCALL SDL_CreateWindow(const char *title, int w, int h, Uint32 flags);
/**
* Create a window with the specified position, dimensions, and flags.
*
* `flags` may be any of the following OR'd together:
*
* - `SDL_WINDOW_FULLSCREEN`: fullscreen window at desktop resolution
* - `SDL_WINDOW_OPENGL`: window usable with an OpenGL context
* - `SDL_WINDOW_VULKAN`: window usable with a Vulkan instance
* - `SDL_WINDOW_METAL`: window usable with a Metal instance
* - `SDL_WINDOW_HIDDEN`: window is not visible
* - `SDL_WINDOW_BORDERLESS`: no window decoration
* - `SDL_WINDOW_RESIZABLE`: window can be resized
* - `SDL_WINDOW_MINIMIZED`: window is minimized
* - `SDL_WINDOW_MAXIMIZED`: window is maximized
* - `SDL_WINDOW_MOUSE_GRABBED`: window has grabbed mouse focus
*
* The SDL_Window is implicitly shown if SDL_WINDOW_HIDDEN is not set.
*
* On Apple's macOS, you **must** set the NSHighResolutionCapable Info.plist
* property to YES, otherwise you will not receive a High-DPI OpenGL canvas.
*
* The window size in pixels may differ from its size in screen coordinates if
* the window is on a high density display (one with an OS scaling factor).
* Use SDL_GetWindowSize() to query the client area's size in screen
* coordinates, and SDL_GetWindowSizeInPixels() or SDL_GetRenderOutputSize()
* to query the drawable size in pixels. Note that the drawable size can vary
* after the window is created and should be queried again if you get an
* SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED event.
*
* If the window is set fullscreen, the width and height parameters `w` and
* `h` will not be used. However, invalid size parameters (e.g. too large) may
* still fail. Window size is actually limited to 16384 x 16384 for all
* platforms at window creation.
*
* If the window is created with any of the SDL_WINDOW_OPENGL or
* SDL_WINDOW_VULKAN flags, then the corresponding LoadLibrary function
* (SDL_GL_LoadLibrary or SDL_Vulkan_LoadLibrary) is called and the
* corresponding UnloadLibrary function is called by SDL_DestroyWindow().
*
* If SDL_WINDOW_VULKAN is specified and there isn't a working Vulkan driver,
* SDL_CreateWindow() will fail because SDL_Vulkan_LoadLibrary() will fail.
*
* If SDL_WINDOW_METAL is specified on an OS that does not support Metal,
* SDL_CreateWindow() will fail.
*
* On non-Apple devices, SDL requires you to either not link to the Vulkan
* loader or link to a dynamic library version. This limitation may be removed
* in a future version of SDL.
*
* \param title the title of the window, in UTF-8 encoding
* \param x the x position of the window, or `SDL_WINDOWPOS_CENTERED`
* \param y the y position of the window, or `SDL_WINDOWPOS_CENTERED`
* \param w the width of the window, in screen coordinates
* \param h the height of the window, in screen coordinates
* \param flags 0, or one or more SDL_WindowFlags OR'd together
* \returns the window that was created or NULL on failure; call
* SDL_GetError() for more information.
*
* \since This function is available since SDL 3.0.0.
*
* \sa SDL_CreatePopupWindow
* \sa SDL_CreateWindow
* \sa SDL_CreateWindowFrom
* \sa SDL_DestroyWindow
*/
extern DECLSPEC SDL_Window *SDLCALL SDL_CreateWindowWithPosition(const char *title, int x, int y, int w, int h, Uint32 flags);
/** /**
* Create a child popup window of the specified parent window. * Create a child popup window of the specified parent window.
* *

View File

@ -841,6 +841,7 @@ SDL3_0.0.0 {
SDL_GetSystemTheme; SDL_GetSystemTheme;
SDL_CreatePopupWindow; SDL_CreatePopupWindow;
SDL_GetWindowParent; SDL_GetWindowParent;
SDL_CreateWindowWithPosition;
# extra symbols go here (don't modify this line) # extra symbols go here (don't modify this line)
local: *; local: *;
}; };

View File

@ -867,3 +867,4 @@
#define SDL_GetSystemTheme SDL_GetSystemTheme_REAL #define SDL_GetSystemTheme SDL_GetSystemTheme_REAL
#define SDL_CreatePopupWindow SDL_CreatePopupWindow_REAL #define SDL_CreatePopupWindow SDL_CreatePopupWindow_REAL
#define SDL_GetWindowParent SDL_GetWindowParent_REAL #define SDL_GetWindowParent SDL_GetWindowParent_REAL
#define SDL_CreateWindowWithPosition SDL_CreateWindowWithPosition_REAL

View File

@ -912,3 +912,4 @@ SDL_DYNAPI_PROC(int,SDL_GetRenderWindowSize,(SDL_Renderer *a, int *b, int *c),(a
SDL_DYNAPI_PROC(SDL_SystemTheme,SDL_GetSystemTheme,(void),(),return) SDL_DYNAPI_PROC(SDL_SystemTheme,SDL_GetSystemTheme,(void),(),return)
SDL_DYNAPI_PROC(SDL_Window*,SDL_CreatePopupWindow,(SDL_Window *a, int b, int c, int d, int e, Uint32 f),(a,b,c,d,e,f),return) SDL_DYNAPI_PROC(SDL_Window*,SDL_CreatePopupWindow,(SDL_Window *a, int b, int c, int d, int e, Uint32 f),(a,b,c,d,e,f),return)
SDL_DYNAPI_PROC(SDL_Window*,SDL_GetWindowParent,(SDL_Window *a),(a),return) SDL_DYNAPI_PROC(SDL_Window*,SDL_GetWindowParent,(SDL_Window *a),(a),return)
SDL_DYNAPI_PROC(SDL_Window*,SDL_CreateWindowWithPosition,(const char *a, int b, int c, int d, int e, Uint32 f),(a,b,c,d,e,f),return)

View File

@ -1312,15 +1312,12 @@ SDLTest_CommonInit(SDLTest_CommonState *state)
} else { } else {
SDL_strlcpy(title, state->window_title, SDL_arraysize(title)); SDL_strlcpy(title, state->window_title, SDL_arraysize(title));
} }
state->windows[i] = SDL_CreateWindow(title, r.w, r.h, state->window_flags); state->windows[i] = SDL_CreateWindowWithPosition(title, r.x, r.y, r.w, r.h, state->window_flags);
if (!state->windows[i]) { if (!state->windows[i]) {
SDL_Log("Couldn't create window: %s\n", SDL_Log("Couldn't create window: %s\n",
SDL_GetError()); SDL_GetError());
return SDL_FALSE; return SDL_FALSE;
} }
if (r.x != SDL_WINDOWPOS_UNDEFINED || r.y != SDL_WINDOWPOS_UNDEFINED) {
SDL_SetWindowPosition(state->windows[i], r.x, r.y);
}
if (state->window_minW || state->window_minH) { if (state->window_minW || state->window_minH) {
SDL_SetWindowMinimumSize(state->windows[i], state->window_minW, state->window_minH); SDL_SetWindowMinimumSize(state->windows[i], state->window_minW, state->window_minH);
} }

View File

@ -1948,6 +1948,11 @@ SDL_Window *SDL_CreateWindow(const char *title, int w, int h, Uint32 flags)
return SDL_CreateWindowInternal(title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, w , h, NULL, flags); return SDL_CreateWindowInternal(title, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, w , h, NULL, flags);
} }
SDL_Window *SDL_CreateWindowWithPosition(const char *title, int x, int y, int w, int h, Uint32 flags)
{
return SDL_CreateWindowInternal(title, x, y, w , h, NULL, flags);
}
SDL_Window *SDL_CreatePopupWindow(SDL_Window *parent, int offset_x, int offset_y, int w, int h, Uint32 flags) SDL_Window *SDL_CreatePopupWindow(SDL_Window *parent, int offset_x, int offset_y, int w, int h, Uint32 flags)
{ {
if (!(_this->quirk_flags & VIDEO_DEVICE_QUIRK_HAS_POPUP_WINDOW_SUPPORT)) { if (!(_this->quirk_flags & VIDEO_DEVICE_QUIRK_HAS_POPUP_WINDOW_SUPPORT)) {

View File

@ -1672,14 +1672,10 @@ static int video_setWindowCenteredOnDisplay(void *arg)
expectedX = (expectedDisplayRect.x + ((expectedDisplayRect.w - w) / 2)); expectedX = (expectedDisplayRect.x + ((expectedDisplayRect.w - w) / 2));
expectedY = (expectedDisplayRect.y + ((expectedDisplayRect.h - h) / 2)); expectedY = (expectedDisplayRect.y + ((expectedDisplayRect.h - h) / 2));
window = SDL_CreateWindow(title, w, h, SDL_WINDOW_HIDDEN); window = SDL_CreateWindowWithPosition(title, x, y, w, h, 0);
SDLTest_AssertPass("Call to SDL_CreateWindow('Title',%d,%d,%d,%d,SHOWN)", x, y, w, h); SDLTest_AssertPass("Call to SDL_CreateWindow('Title',%d,%d,%d,%d,SHOWN)", x, y, w, h);
SDLTest_AssertCheck(window != NULL, "Validate that returned window struct is not NULL"); SDLTest_AssertCheck(window != NULL, "Validate that returned window struct is not NULL");
/* Set the desired position */
SDL_SetWindowPosition(window, x, y);
SDL_ShowWindow(window);
/* Check the window is centered on the requested display */ /* Check the window is centered on the requested display */
currentDisplay = SDL_GetDisplayForWindow(window); currentDisplay = SDL_GetDisplayForWindow(window);
SDL_GetWindowSize(window, &currentW, &currentH); SDL_GetWindowSize(window, &currentW, &currentH);