mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-05-25 05:59:11 +00:00
Added SDL_SetWindowAspectRatio() and SDL_GetWindowAspectRatio()
Fixes https://github.com/libsdl-org/SDL/issues/1573
This commit is contained in:
parent
aacafd6233
commit
c74886ab00
15 changed files with 364 additions and 36 deletions
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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_ */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue