Added SDL_SetWindowAspectRatio() and SDL_GetWindowAspectRatio()

Fixes https://github.com/libsdl-org/SDL/issues/1573
This commit is contained in:
Sam Lantinga 2024-05-27 15:23:04 -07:00
parent aacafd6233
commit c74886ab00
15 changed files with 364 additions and 36 deletions

View file

@ -76,6 +76,8 @@ typedef struct
int window_minH;
int window_maxW;
int window_maxH;
float window_min_aspect;
float window_max_aspect;
int logical_w;
int logical_h;
SDL_bool auto_scale_content;
@ -84,6 +86,7 @@ typedef struct
float scale;
int depth;
float refresh_rate;
SDL_bool fill_usable_bounds;
SDL_bool fullscreen_exclusive;
SDL_DisplayMode fullscreen_mode;
int num_windows;

View file

@ -1346,9 +1346,6 @@ extern SDL_DECLSPEC int SDLCALL SDL_GetWindowPosition(SDL_Window *window, int *x
/**
* Request that the size of a window's client area be set.
*
* NULL can safely be passed as the `w` or `h` parameter if the width or
* height value is not desired.
*
* If, at the time of this request, the window in a fixed-size state, such as
* maximized or fullscreen, the request will be deferred until the window
* exits this state and becomes resizable again.
@ -1385,9 +1382,6 @@ extern SDL_DECLSPEC int SDLCALL SDL_SetWindowSize(SDL_Window *window, int w, int
/**
* Get the size of a window's client area.
*
* NULL can safely be passed as the `w` or `h` parameter if the width or
* height value is not desired.
*
* The window pixel size may differ from its window coordinate size if the
* window is on a high pixel density display. Use SDL_GetWindowSizeInPixels()
* or SDL_GetRenderOutputSize() to get the real client area size in pixels.
@ -1406,6 +1400,55 @@ extern SDL_DECLSPEC int SDLCALL SDL_SetWindowSize(SDL_Window *window, int w, int
*/
extern SDL_DECLSPEC int SDLCALL SDL_GetWindowSize(SDL_Window *window, int *w, int *h);
/**
* Request that the aspect ratio of a window's client area be set.
*
* The aspect ratio is the ratio of width divided by height, e.g. 2560x1600 would be 1.6. Larger aspect ratios are wider and smaller aspect ratios are narrower.
*
* If, at the time of this request, the window in a fixed-size state, such as
* maximized or fullscreen, the request will be deferred until the window
* exits this state and becomes resizable again.
*
* On some windowing systems, this request is asynchronous and the new window
* aspect ratio may not have have been applied immediately upon the return of this
* function. If an immediate change is required, call SDL_SyncWindow() to
* block until the changes have taken effect.
*
* When the window size changes, an SDL_EVENT_WINDOW_RESIZED event will be
* emitted with the new window dimensions. Note that the new dimensions may
* not match the exact aspect ratio requested, as some windowing systems can restrict
* the window size in certain scenarios (e.g. constraining the size of the
* content area to remain within the usable desktop bounds). Additionally, as
* this is just a request, it can be denied by the windowing system.
*
* \param window the window to change
* \param min_aspect the minimum aspect ratio of the window, or 0.0f for no limit
* \param max_aspect the maximum aspect ratio of the window, or 0.0f for no limit
* \returns 0 on success or a negative error code on failure; call
* SDL_GetError() for more information.
*
* \since This function is available since SDL 3.0.0.
*
* \sa SDL_GetWindowAspectRatio
* \sa SDL_SyncWindow
*/
extern SDL_DECLSPEC int SDLCALL SDL_SetWindowAspectRatio(SDL_Window *window, float min_aspect, float max_aspect);
/**
* Get the size of a window's client area.
*
* \param window the window to query the width and height from
* \param min_aspect a pointer filled in with the minimum aspect ratio of the window, may be NULL
* \param max_aspect a pointer filled in with the maximum aspect ratio of the window, may be NULL
* \returns 0 on success or a negative error code on failure; call
* SDL_GetError() for more information.
*
* \since This function is available since SDL 3.0.0.
*
* \sa SDL_SetWindowAspectRatio
*/
extern SDL_DECLSPEC int SDLCALL SDL_GetWindowAspectRatio(SDL_Window *window, float *min_aspect, float *max_aspect);
/**
* Get the size of a window's borders (decorations) around the client area.
*

View file

@ -49,6 +49,45 @@ int SDL_powerof2(int x)
return value;
}
// Algorithm adapted with thanks from John Cook's blog post:
// http://www.johndcook.com/blog/2010/10/20/best-rational-approximation
void SDL_CalculateFraction(float x, int *numerator, int *denominator)
{
const int N = 1000;
int a = 0, b = 1;
int c = 1, d = 0;
while (b <= N && d <= N) {
float mediant = (float)(a + c) / (b + d);
if (x == mediant) {
if (b + d <= N) {
*numerator = a + c;
*denominator = b + d;
} else if (d > b) {
*numerator = c;
*denominator = d;
} else {
*numerator = a;
*denominator = b;
}
return;
} else if (x > mediant) {
a = a + c;
b = b + d;
} else {
c = a + c;
d = b + d;
}
}
if (b > N) {
*numerator = c;
*denominator = d;
} else {
*numerator = a;
*denominator = b;
}
}
SDL_bool SDL_endswith(const char *string, const char *suffix)
{
size_t string_length = string ? SDL_strlen(string) : 0;

View file

@ -28,6 +28,8 @@
/* Return the smallest power of 2 greater than or equal to 'x' */
extern int SDL_powerof2(int x);
SDL_bool SDL_endswith(const char *string, const char *suffix);
extern void SDL_CalculateFraction(float x, int *numerator, int *denominator);
extern SDL_bool SDL_endswith(const char *string, const char *suffix);
#endif /* SDL_utils_h_ */

View file

@ -453,6 +453,7 @@ SDL3_0.0.0 {
SDL_GetUserFolder;
SDL_GetVersion;
SDL_GetVideoDriver;
SDL_GetWindowAspectRatio;
SDL_GetWindowBordersSize;
SDL_GetWindowDisplayScale;
SDL_GetWindowFlags;
@ -748,6 +749,7 @@ SDL3_0.0.0 {
SDL_SetTextureScaleMode;
SDL_SetThreadPriority;
SDL_SetWindowAlwaysOnTop;
SDL_SetWindowAspectRatio;
SDL_SetWindowBordered;
SDL_SetWindowFocusable;
SDL_SetWindowFullscreen;

View file

@ -478,6 +478,7 @@
#define SDL_GetUserFolder SDL_GetUserFolder_REAL
#define SDL_GetVersion SDL_GetVersion_REAL
#define SDL_GetVideoDriver SDL_GetVideoDriver_REAL
#define SDL_GetWindowAspectRatio SDL_GetWindowAspectRatio_REAL
#define SDL_GetWindowBordersSize SDL_GetWindowBordersSize_REAL
#define SDL_GetWindowDisplayScale SDL_GetWindowDisplayScale_REAL
#define SDL_GetWindowFlags SDL_GetWindowFlags_REAL
@ -773,6 +774,7 @@
#define SDL_SetTextureScaleMode SDL_SetTextureScaleMode_REAL
#define SDL_SetThreadPriority SDL_SetThreadPriority_REAL
#define SDL_SetWindowAlwaysOnTop SDL_SetWindowAlwaysOnTop_REAL
#define SDL_SetWindowAspectRatio SDL_SetWindowAspectRatio_REAL
#define SDL_SetWindowBordered SDL_SetWindowBordered_REAL
#define SDL_SetWindowFocusable SDL_SetWindowFocusable_REAL
#define SDL_SetWindowFullscreen SDL_SetWindowFullscreen_REAL

View file

@ -498,6 +498,7 @@ SDL_DYNAPI_PROC(SDL_Finger**,SDL_GetTouchFingers,(SDL_TouchID a, int *b),(a,b),r
SDL_DYNAPI_PROC(char*,SDL_GetUserFolder,(SDL_Folder a),(a),return)
SDL_DYNAPI_PROC(int,SDL_GetVersion,(void),(),return)
SDL_DYNAPI_PROC(const char*,SDL_GetVideoDriver,(int a),(a),return)
SDL_DYNAPI_PROC(int,SDL_GetWindowAspectRatio,(SDL_Window *a, float *b, float *c),(a,b,c),return)
SDL_DYNAPI_PROC(int,SDL_GetWindowBordersSize,(SDL_Window *a, int *b, int *c, int *d, int *e),(a,b,c,d,e),return)
SDL_DYNAPI_PROC(float,SDL_GetWindowDisplayScale,(SDL_Window *a),(a),return)
SDL_DYNAPI_PROC(SDL_WindowFlags,SDL_GetWindowFlags,(SDL_Window *a),(a),return)
@ -783,6 +784,7 @@ SDL_DYNAPI_PROC(int,SDL_SetTextureColorModFloat,(SDL_Texture *a, float b, float
SDL_DYNAPI_PROC(int,SDL_SetTextureScaleMode,(SDL_Texture *a, SDL_ScaleMode b),(a,b),return)
SDL_DYNAPI_PROC(int,SDL_SetThreadPriority,(SDL_ThreadPriority a),(a),return)
SDL_DYNAPI_PROC(int,SDL_SetWindowAlwaysOnTop,(SDL_Window *a, SDL_bool b),(a,b),return)
SDL_DYNAPI_PROC(int,SDL_SetWindowAspectRatio,(SDL_Window *a, float b, float c),(a,b,c),return)
SDL_DYNAPI_PROC(int,SDL_SetWindowBordered,(SDL_Window *a, SDL_bool b),(a,b),return)
SDL_DYNAPI_PROC(int,SDL_SetWindowFocusable,(SDL_Window *a, SDL_bool b),(a,b),return)
SDL_DYNAPI_PROC(int,SDL_SetWindowFullscreen,(SDL_Window *a, SDL_bool b),(a,b),return)

View file

@ -35,6 +35,7 @@ static const char *common_usage[] = {
static const char *video_usage[] = {
"[--always-on-top]",
"[--aspect min-max]",
"[--auto-scale-content]",
"[--center | --position X,Y]",
"[--confine-cursor X,Y,W,H]",
@ -373,12 +374,7 @@ int SDLTest_CommonArg(SDLTest_CommonState *state, int index)
return 2;
}
if (SDL_strcasecmp(argv[index], "--usable-bounds") == 0) {
/* !!! FIXME: this is a bit of a hack, but I don't want to add a
!!! FIXME: flag to the public structure in 2.0.x */
state->window_x = -1;
state->window_y = -1;
state->window_w = -1;
state->window_h = -1;
state->fill_usable_bounds = SDL_TRUE;
return 1;
}
if (SDL_strcasecmp(argv[index], "--geometry") == 0) {
@ -438,6 +434,26 @@ int SDLTest_CommonArg(SDLTest_CommonState *state, int index)
state->window_maxH = SDL_atoi(h);
return 2;
}
if (SDL_strcasecmp(argv[index], "--aspect") == 0) {
char *min_aspect, *max_aspect;
++index;
if (!argv[index]) {
return -1;
}
min_aspect = argv[index];
max_aspect = argv[index];
while (*max_aspect && *max_aspect != '-') {
++max_aspect;
}
if (*max_aspect) {
*max_aspect++ = '\0';
} else {
max_aspect = min_aspect;
}
state->window_min_aspect = SDL_atof(min_aspect);
state->window_max_aspect = SDL_atof(max_aspect);
return 2;
}
if (SDL_strcasecmp(argv[index], "--logical") == 0) {
char *w, *h;
++index;
@ -1308,19 +1324,18 @@ SDL_bool SDLTest_CommonInit(SDLTest_CommonState *state)
SDL_Rect r;
SDL_PropertiesID props;
r.x = state->window_x;
r.y = state->window_y;
r.w = state->window_w;
r.h = state->window_h;
if (state->auto_scale_content) {
float scale = SDL_GetDisplayContentScale(state->displayID);
r.w = (int)SDL_ceilf(r.w * scale);
r.h = (int)SDL_ceilf(r.h * scale);
}
/* !!! FIXME: hack to make --usable-bounds work for now. */
if ((r.x == -1) && (r.y == -1) && (r.w == -1) && (r.h == -1)) {
if (state->fill_usable_bounds) {
SDL_GetDisplayUsableBounds(state->displayID, &r);
} else {
r.x = state->window_x;
r.y = state->window_y;
r.w = state->window_w;
r.h = state->window_h;
if (state->auto_scale_content) {
float scale = SDL_GetDisplayContentScale(state->displayID);
r.w = (int)SDL_ceilf(r.w * scale);
r.h = (int)SDL_ceilf(r.h * scale);
}
}
if (state->num_windows > 1) {
@ -1349,6 +1364,9 @@ SDL_bool SDLTest_CommonInit(SDLTest_CommonState *state)
if (state->window_maxW || state->window_maxH) {
SDL_SetWindowMaximumSize(state->windows[i], state->window_maxW, state->window_maxH);
}
if (state->window_min_aspect || state->window_max_aspect) {
SDL_SetWindowAspectRatio(state->windows[i], state->window_min_aspect, state->window_max_aspect);
}
SDL_GetWindowSize(state->windows[i], &w, &h);
if (!(state->window_flags & SDL_WINDOW_RESIZABLE) && (w != r.w || h != r.h)) {
SDL_Log("Window requested size %dx%d, got %dx%d\n", r.w, r.h, w, h);
@ -2376,15 +2394,21 @@ int SDLTest_CommonEventMainCallbacks(SDLTest_CommonState *state, const SDL_Event
break;
case SDLK_a:
if (withControl) {
/* Ctrl-A reports absolute mouse position. */
float x, y;
const SDL_MouseButtonFlags mask = SDL_GetGlobalMouseState(&x, &y);
SDL_Log("ABSOLUTE MOUSE: (%g, %g)%s%s%s%s%s\n", x, y,
(mask & SDL_BUTTON_LMASK) ? " [LBUTTON]" : "",
(mask & SDL_BUTTON_MMASK) ? " [MBUTTON]" : "",
(mask & SDL_BUTTON_RMASK) ? " [RBUTTON]" : "",
(mask & SDL_BUTTON_X1MASK) ? " [X2BUTTON]" : "",
(mask & SDL_BUTTON_X2MASK) ? " [X2BUTTON]" : "");
/* Ctrl-A toggle aspect ratio */
SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
if (window) {
float min_aspect = 0.0f, max_aspect = 0.0f;
SDL_GetWindowAspectRatio(window, &min_aspect, &max_aspect);
if (min_aspect > 0.0f || max_aspect > 0.0f) {
min_aspect = 0.0f;
max_aspect = 0.0f;
} else {
min_aspect = 1.0f;
max_aspect = 1.0f;
}
SDL_SetWindowAspectRatio(window, min_aspect, max_aspect);
}
}
break;
case SDLK_0:

View file

@ -45,6 +45,8 @@ struct SDL_Window
int w, h;
int min_w, min_h;
int max_w, max_h;
float min_aspect;
float max_aspect;
int last_pixel_w, last_pixel_h;
SDL_WindowFlags flags;
SDL_WindowFlags pending_flags;
@ -240,6 +242,7 @@ struct SDL_VideoDevice
void (*SetWindowSize)(SDL_VideoDevice *_this, SDL_Window *window);
void (*SetWindowMinimumSize)(SDL_VideoDevice *_this, SDL_Window *window);
void (*SetWindowMaximumSize)(SDL_VideoDevice *_this, SDL_Window *window);
void (*SetWindowAspectRatio)(SDL_VideoDevice *_this, SDL_Window *window);
int (*GetWindowBordersSize)(SDL_VideoDevice *_this, SDL_Window *window, int *top, int *left, int *bottom, int *right);
void (*GetWindowSizeInPixels)(SDL_VideoDevice *_this, SDL_Window *window, int *w, int *h);
int (*SetWindowOpacity)(SDL_VideoDevice *_this, SDL_Window *window, float opacity);

View file

@ -2504,6 +2504,10 @@ int SDL_RecreateWindow(SDL_Window *window, SDL_WindowFlags flags)
_this->SetWindowMaximumSize(_this, window);
}
if (_this->SetWindowAspectRatio && (window->min_aspect > 0.0f || window->max_aspect > 0.0f)) {
_this->SetWindowAspectRatio(_this, window);
}
if (window->hit_test) {
_this->SetWindowHitTest(window, SDL_TRUE);
}
@ -2776,6 +2780,7 @@ int SDL_SetWindowAlwaysOnTop(SDL_Window *window, SDL_bool on_top)
int SDL_SetWindowSize(SDL_Window *window, int w, int h)
{
CHECK_WINDOW_MAGIC(window, -1);
if (w <= 0) {
return SDL_InvalidParamError("w");
}
@ -2783,6 +2788,16 @@ int SDL_SetWindowSize(SDL_Window *window, int w, int h)
return SDL_InvalidParamError("h");
}
/* It is possible for the aspect ratio contraints to not satisfy the size constraints. */
/* The size constraints will override the aspect ratio contraints so we will apply the */
/* the aspect ratio constraints first */
float new_aspect = w / (float)h;
if (window->max_aspect > 0.0f && new_aspect > window->max_aspect) {
w = (int)SDL_roundf(h * window->max_aspect);
} else if (window->min_aspect > 0.0f && new_aspect < window->min_aspect) {
h = (int)SDL_roundf(w / window->min_aspect);
}
/* Make sure we don't exceed any window size limits */
if (window->min_w && w < window->min_w) {
w = window->min_w;
@ -2821,6 +2836,31 @@ int SDL_GetWindowSize(SDL_Window *window, int *w, int *h)
return 0;
}
int SDL_SetWindowAspectRatio(SDL_Window *window, float min_aspect, float max_aspect)
{
CHECK_WINDOW_MAGIC(window, -1);
window->min_aspect = min_aspect;
window->max_aspect = max_aspect;
if (_this->SetWindowAspectRatio) {
_this->SetWindowAspectRatio(_this, window);
}
return SDL_SetWindowSize(window, window->floating.w, window->floating.h);
}
int SDL_GetWindowAspectRatio(SDL_Window *window, float *min_aspect, float *max_aspect)
{
CHECK_WINDOW_MAGIC(window, -1);
if (min_aspect) {
*min_aspect = window->min_aspect;
}
if (max_aspect) {
*max_aspect = window->max_aspect;
}
return 0;
}
int SDL_GetWindowBordersSize(SDL_Window *window, int *top, int *left, int *bottom, int *right)
{
int dummy = 0;

View file

@ -986,6 +986,27 @@ static NSCursor *Cocoa_GetDesiredCursor(void)
_data.checking_zoom = NO;
}
if (window->min_aspect > 0.0f || window->max_aspect > 0.0f) {
NSWindow *nswindow = _data.nswindow;
NSRect newContentRect = [nswindow contentRectForFrameRect:NSMakeRect(0, 0, frameSize.width, frameSize.height)];
NSSize newSize = newContentRect.size;
CGFloat minAspectRatio = window->min_aspect;
CGFloat maxAspectRatio = window->max_aspect;
CGFloat aspectRatio;
if (newSize.height > 0) {
aspectRatio = newSize.width / newSize.height;
if (maxAspectRatio > 0.0f && aspectRatio > maxAspectRatio) {
newSize.width = (int)SDL_roundf(newSize.height * maxAspectRatio);
} else if (minAspectRatio > 0.0f && aspectRatio < minAspectRatio) {
newSize.height = (int)SDL_roundf(newSize.width / minAspectRatio);
}
NSRect newFrameRect = [nswindow frameRectForContentRect:NSMakeRect(0, 0, newSize.width, newSize.height)];
frameSize = newFrameRect.size;
}
}
return frameSize;
}

View file

@ -1479,6 +1479,134 @@ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara
KillTimer(hwnd, (UINT_PTR)SDL_IterateMainCallbacks);
} break;
case WM_SIZING:
{
Uint32 edge = wParam;
RECT* dragRect = (RECT*)lParam;
RECT clientDragRect = *dragRect;
SDL_bool lock_aspect_ratio = (data->window->max_aspect == data->window->min_aspect) ? SDL_TRUE : SDL_FALSE;
RECT rc;
LONG w, h;
float new_aspect;
/* if aspect ratio constraints are not enabled then skip this message */
if (data->window->min_aspect <= 0 && data->window->max_aspect <= 0) {
break;
}
/* unadjust the dragRect from the window rect to the client rect */
SetRectEmpty(&rc);
if (!AdjustWindowRectEx(&rc, GetWindowStyle(hwnd), GetMenu(hwnd) != NULL, GetWindowExStyle(hwnd))) {
break;
}
clientDragRect.left -= rc.left;
clientDragRect.top -= rc.top;
clientDragRect.right -= rc.right;
clientDragRect.bottom -= rc.bottom;
w = clientDragRect.right - clientDragRect.left;
h = clientDragRect.bottom - clientDragRect.top;
new_aspect = w / (float)h;
/* handle the special case in which the min ar and max ar are the same so the window can size symmetrically */
if (lock_aspect_ratio) {
switch (edge) {
case WMSZ_LEFT:
case WMSZ_RIGHT:
h = (int)(w / data->window->max_aspect);
break;
default:
/* resizing via corners or top or bottom */
w = (int)(h*data->window->max_aspect);
break;
}
} else {
switch (edge) {
case WMSZ_LEFT:
case WMSZ_RIGHT:
if (data->window->max_aspect > 0.0f && new_aspect > data->window->max_aspect) {
w = (int)SDL_roundf(h * data->window->max_aspect);
} else if (data->window->min_aspect > 0.0f && new_aspect < data->window->min_aspect) {
w = (int)SDL_roundf(h * data->window->min_aspect);
}
break;
case WMSZ_TOP:
case WMSZ_BOTTOM:
if (data->window->min_aspect > 0.0f && new_aspect < data->window->min_aspect) {
h = (int)SDL_roundf(w / data->window->min_aspect);
} else if (data->window->max_aspect > 0.0f && new_aspect > data->window->max_aspect) {
h = (int)SDL_roundf(w / data->window->max_aspect);
}
break;
default:
/* resizing via corners */
if (data->window->max_aspect > 0.0f && new_aspect > data->window->max_aspect) {
w = (int)SDL_roundf(h * data->window->max_aspect);
} else if (data->window->min_aspect > 0.0f && new_aspect < data->window->min_aspect) {
h = (int)SDL_roundf(w / data->window->min_aspect);
}
break;
}
}
switch (edge) {
case WMSZ_LEFT:
clientDragRect.left = clientDragRect.right - w;
if (lock_aspect_ratio) {
clientDragRect.top = (clientDragRect.bottom + clientDragRect.top - h) / 2;
}
clientDragRect.bottom = h + clientDragRect.top;
break;
case WMSZ_BOTTOMLEFT:
clientDragRect.left = clientDragRect.right - w;
clientDragRect.bottom = h + clientDragRect.top;
break;
case WMSZ_RIGHT:
clientDragRect.right = w + clientDragRect.left;
if (lock_aspect_ratio) {
clientDragRect.top = (clientDragRect.bottom + clientDragRect.top - h) / 2;
}
clientDragRect.bottom = h + clientDragRect.top;
break;
case WMSZ_TOPRIGHT:
clientDragRect.right = w + clientDragRect.left;
clientDragRect.top = clientDragRect.bottom - h;
break;
case WMSZ_TOP:
if (lock_aspect_ratio) {
clientDragRect.left = (clientDragRect.right + clientDragRect.left - w) / 2;
}
clientDragRect.right = w + clientDragRect.left;
clientDragRect.top = clientDragRect.bottom - h;
break;
case WMSZ_TOPLEFT:
clientDragRect.left = clientDragRect.right - w;
clientDragRect.top = clientDragRect.bottom - h;
break;
case WMSZ_BOTTOM:
if (lock_aspect_ratio) {
clientDragRect.left = (clientDragRect.right + clientDragRect.left - w) / 2;
}
clientDragRect.right = w + clientDragRect.left;
clientDragRect.bottom = h + clientDragRect.top;
break;
case WMSZ_BOTTOMRIGHT:
clientDragRect.right = w + clientDragRect.left;
clientDragRect.bottom = h + clientDragRect.top;
break;
}
/* convert the client rect to a window rect */
if (!AdjustWindowRectEx(&clientDragRect, GetWindowStyle(hwnd), GetMenu(hwnd) != NULL, GetWindowExStyle(hwnd))) {
break;
}
*dragRect = clientDragRect;
}
break;
case WM_SETCURSOR:
{
Uint16 hittest;

View file

@ -194,6 +194,7 @@ static SDL_VideoDevice *X11_CreateDevice(void)
device->SetWindowSize = X11_SetWindowSize;
device->SetWindowMinimumSize = X11_SetWindowMinimumSize;
device->SetWindowMaximumSize = X11_SetWindowMaximumSize;
device->SetWindowAspectRatio = X11_SetWindowAspectRatio;
device->GetWindowBordersSize = X11_GetWindowBordersSize;
device->SetWindowOpacity = X11_SetWindowOpacity;
device->SetWindowModalFor = X11_SetWindowModalFor;

View file

@ -28,6 +28,7 @@
#include "../../events/SDL_mouse_c.h"
#include "../../events/SDL_events_c.h"
#include "../../core/unix/SDL_appid.h"
#include "../../SDL_utils_c.h"
#include "SDL_x11video.h"
#include "SDL_x11mouse.h"
@ -1086,7 +1087,7 @@ void X11_SetWindowMinMax(SDL_Window *window, SDL_bool use_current)
long hint_flags = 0;
X11_XGetWMNormalHints(display, data->xwindow, sizehints, &hint_flags);
sizehints->flags &= ~(PMinSize | PMaxSize);
sizehints->flags &= ~(PMinSize | PMaxSize | PAspect);
if (data->window->flags & SDL_WINDOW_RESIZABLE) {
if (data->window->min_w || data->window->min_h) {
@ -1099,6 +1100,11 @@ void X11_SetWindowMinMax(SDL_Window *window, SDL_bool use_current)
sizehints->max_width = data->window->max_w;
sizehints->max_height = data->window->max_h;
}
if (data->window->min_aspect > 0.0f || data->window->max_aspect > 0.0f) {
sizehints->flags |= PAspect;
SDL_CalculateFraction(data->window->min_aspect, &sizehints->min_aspect.x, &sizehints->min_aspect.y);
SDL_CalculateFraction(data->window->max_aspect, &sizehints->max_aspect.x, &sizehints->max_aspect.y);
}
} else {
/* Set the min/max to the same values to make the window non-resizable */
sizehints->flags |= PMinSize | PMaxSize;
@ -1132,6 +1138,17 @@ void X11_SetWindowMaximumSize(SDL_VideoDevice *_this, SDL_Window *window)
}
}
void X11_SetWindowAspectRatio(SDL_VideoDevice *_this, SDL_Window *window)
{
if (window->driverdata->pending_operation & X11_PENDING_OP_FULLSCREEN) {
X11_SyncWindow(_this, window);
}
if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
X11_SetWindowMinMax(window, SDL_TRUE);
}
}
void X11_SetWindowSize(SDL_VideoDevice *_this, SDL_Window *window)
{
SDL_WindowData *data = window->driverdata;
@ -1645,7 +1662,7 @@ static int X11_SetWindowFullscreenViaWM(SDL_VideoDevice *_this, SDL_Window *wind
long flags = 0;
X11_XGetWMNormalHints(display, data->xwindow, sizehints, &flags);
/* we are going fullscreen so turn the flags off */
sizehints->flags &= ~(PMinSize | PMaxSize);
sizehints->flags &= ~(PMinSize | PMaxSize | PAspect);
X11_XSetWMNormalHints(display, data->xwindow, sizehints);
X11_XFree(sizehints);
}

View file

@ -114,6 +114,7 @@ extern int X11_SetWindowIcon(SDL_VideoDevice *_this, SDL_Window *window, SDL_Sur
extern int X11_SetWindowPosition(SDL_VideoDevice *_this, SDL_Window *window);
extern void X11_SetWindowMinimumSize(SDL_VideoDevice *_this, SDL_Window *window);
extern void X11_SetWindowMaximumSize(SDL_VideoDevice *_this, SDL_Window *window);
extern void X11_SetWindowAspectRatio(SDL_VideoDevice *_this, SDL_Window *window);
extern int X11_GetWindowBordersSize(SDL_VideoDevice *_this, SDL_Window *window, int *top, int *left, int *bottom, int *right);
extern int X11_SetWindowOpacity(SDL_VideoDevice *_this, SDL_Window *window, float opacity);
extern int X11_SetWindowModalFor(SDL_VideoDevice *_this, SDL_Window *modal_window, SDL_Window *parent_window);