diff -urN SDL2-2.0.3/include/SDL_video.h SDL2-2.0.3-aspectratio/include/SDL_video.h --- SDL2-2.0.3/include/SDL_video.h 2014-03-15 19:31:44.000000000 -0700 +++ SDL2-2.0.3-aspectratio/include/SDL_video.h 2014-07-18 00:22:04.000000000 -0700 @@ -603,6 +603,66 @@ int *w, int *h); /** + * \brief Set the minimum aspect ratio of a window's client area. + * + * \param window The window to set a minimum aspect ratio. + * \param min_ar The minimum aspect ratio use to contrain the size of the window + * + * \note Setting a minimum aspect ratio to 0 or a negative number will remove + * the minimum aspect ratio constraint on the window size. + * + * \sa SDL_GetWindowMinimumAspectRatio() + * \sa SDL_SetWindowMaximumAspectRatio() + * \sa SDL_GetWindowMaximumAspectRatio() + */ +extern DECLSPEC void SDLCALL SDL_SetWindowMinimumAspectRatio(SDL_Window * window, float min_ar); + +/** + * \brief Get the minimum aspect ratio of a window's client area. + * + * \param window The window to query. + * \param min_ar Pointer to variable for storing the minimum aspect ratio, may be NULL + * + * \note A minimum aspect ratio of 0 or a negative number means there is no + * minimum aspect ratio constraint on the window size. + * + * \sa SDL_SetWindowMinimumAspectRatio() + * \sa SDL_SetWindowMaximumAspectRatio() + * \sa SDL_GetWindowMaximumAspectRatio() + */ +extern DECLSPEC void SDLCALL SDL_GetWindowMinimumAspectRatio(SDL_Window * window, float * min_ar); + +/** + * \brief Set the maximum aspect ratio of a window's client area. + * + * \param window The window to set a maximum aspect ratio. + * \param max_ar The maximum aspect ratio use to contrain the size of the window + * + * \note Setting a maximum aspect ratio to 0 or a negative number will remove + * the maximum aspect ratio constraint on the window size. + * + * \sa SDL_GetWindowMaximumAspectRatio() + * \sa SDL_SetWindowMinimumAspectRatio() + * \sa SDL_GetWindowMinimumAspectRatio() + */ +extern DECLSPEC void SDLCALL SDL_SetWindowMaximumAspectRatio(SDL_Window * window, float max_ar); + +/** + * \brief Get the maximum aspect ratio of a window's client area. + * + * \param window The window to query. + * \param max_ar Pointer to variable for storing the maximum aspect ratio, may be NULL + * + * \note A maximum aspect ratio of 0 or a negative number means there is no + * maximum aspect ratio constraint on the window size. + * + * \sa SDL_SetWindowMaximumAspectRatio() + * \sa SDL_SetWindowMinimumAspectRatio() + * \sa SDL_GetWindowMinimumAspectRatio() + */ +extern DECLSPEC void SDLCALL SDL_GetWindowMaximumAspectRatio(SDL_Window * window, float * max_ar); + +/** * \brief Set the border state of a window. * * This will add or remove the window's SDL_WINDOW_BORDERLESS flag and diff -urN SDL2-2.0.3/src/dynapi/SDL_dynapi_overrides.h SDL2-2.0.3-aspectratio/src/dynapi/SDL_dynapi_overrides.h --- SDL2-2.0.3/src/dynapi/SDL_dynapi_overrides.h 2014-03-15 19:31:44.000000000 -0700 +++ SDL2-2.0.3-aspectratio/src/dynapi/SDL_dynapi_overrides.h 2014-07-18 00:22:04.000000000 -0700 @@ -575,3 +575,7 @@ #define SDL_GetDefaultAssertionHandler SDL_GetDefaultAssertionHandler_REAL #define SDL_GetAssertionHandler SDL_GetAssertionHandler_REAL #define SDL_DXGIGetOutputInfo SDL_DXGIGetOutputInfo_REAL +#define SDL_SetWindowMinimumAspectRatio SDL_SetWindowMinimumAspectRatio_REAL +#define SDL_GetWindowMinimumAspectRatio SDL_GetWindowMinimumAspectRatio_REAL +#define SDL_SetWindowMaximumAspectRatio SDL_SetWindowMaximumAspectRatio_REAL +#define SDL_GetWindowMaximumAspectRatio SDL_GetWindowMaximumAspectRatio_REAL diff -urN SDL2-2.0.3/src/dynapi/SDL_dynapi_procs.h SDL2-2.0.3-aspectratio/src/dynapi/SDL_dynapi_procs.h --- SDL2-2.0.3/src/dynapi/SDL_dynapi_procs.h 2014-03-15 19:31:44.000000000 -0700 +++ SDL2-2.0.3-aspectratio/src/dynapi/SDL_dynapi_procs.h 2014-07-18 00:22:04.000000000 -0700 @@ -606,3 +606,7 @@ #ifdef __WIN32__ SDL_DYNAPI_PROC(void,SDL_DXGIGetOutputInfo,(int a,int *b, int *c),(a,b,c),) #endif +SDL_DYNAPI_PROC(void,SDL_SetWindowMinimumAspectRatio,(SDL_Window *a, float b),(a,b),) +SDL_DYNAPI_PROC(void,SDL_GetWindowMinimumAspectRatio,(SDL_Window *a, float *b),(a,b),) +SDL_DYNAPI_PROC(void,SDL_SetWindowMaximumAspectRatio,(SDL_Window *a, float b),(a,b),) +SDL_DYNAPI_PROC(void,SDL_GetWindowMaximumAspectRatio,(SDL_Window *a, float *b),(a,b),) diff -urN SDL2-2.0.3/src/video/SDL_sysvideo.h SDL2-2.0.3-aspectratio/src/video/SDL_sysvideo.h --- SDL2-2.0.3/src/video/SDL_sysvideo.h 2014-03-15 19:31:44.000000000 -0700 +++ SDL2-2.0.3-aspectratio/src/video/SDL_sysvideo.h 2014-07-18 00:22:04.000000000 -0700 @@ -78,6 +78,7 @@ int w, h; int min_w, min_h; int max_w, max_h; + float min_ar, max_ar; Uint32 flags; Uint32 last_fullscreen_flags; diff -urN SDL2-2.0.3/src/video/SDL_video.c SDL2-2.0.3-aspectratio/src/video/SDL_video.c --- SDL2-2.0.3/src/video/SDL_video.c 2014-03-15 19:31:44.000000000 -0700 +++ SDL2-2.0.3-aspectratio/src/video/SDL_video.c 2014-07-18 00:26:47.000000000 -0700 @@ -1655,6 +1655,19 @@ return; } + /* 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_ar = w / (float)h; + if (window->max_ar > 0.0f && new_ar > window->max_ar) + { + w = (int)(h*window->max_ar); + } + else if (window->min_ar > 0.0f && new_ar < window->min_ar) + { + h = (int)(w/window->min_ar); + } + /* Make sure we don't exceed any window size limits */ if (window->min_w && w < window->min_w) { @@ -1775,6 +1788,52 @@ } void +SDL_SetWindowMinimumAspectRatio(SDL_Window * window, float min_ar) +{ + CHECK_WINDOW_MAGIC(window, ); + if (min_ar <= 0.0f) { + window->min_ar = 0.0f; + } + else { + window->min_ar = min_ar; + /* apply the aspect ratio constraints */ + SDL_SetWindowSize(window, window->w, window->h); + } +} + +void +SDL_GetWindowMinimumAspectRatio(SDL_Window * window, float * min_ar) +{ + CHECK_WINDOW_MAGIC(window, ); + if (min_ar) { + *min_ar = window->min_ar; + } +} + +void +SDL_SetWindowMaximumAspectRatio(SDL_Window * window, float max_ar) +{ + CHECK_WINDOW_MAGIC(window, ); + if (max_ar <= 0.0f) { + window->max_ar = 0.0f; + } + else { + window->max_ar = max_ar; + /* apply the aspect ratio constraints */ + SDL_SetWindowSize(window, window->w, window->h); + } +} + +void +SDL_GetWindowMaximumAspectRatio(SDL_Window * window, float * max_ar) +{ + CHECK_WINDOW_MAGIC(window, ); + if (max_ar) { + *max_ar = window->max_ar; + } +} + +void SDL_ShowWindow(SDL_Window * window) { CHECK_WINDOW_MAGIC(window, ); diff -urN SDL2-2.0.3/src/video/cocoa/SDL_cocoawindow.m SDL2-2.0.3-aspectratio/src/video/cocoa/SDL_cocoawindow.m --- SDL2-2.0.3/src/video/cocoa/SDL_cocoawindow.m 2014-03-15 19:31:42.000000000 -0700 +++ SDL2-2.0.3-aspectratio/src/video/cocoa/SDL_cocoawindow.m 2014-07-18 00:22:04.000000000 -0700 @@ -435,6 +435,27 @@ SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MOVED, x, y); } +- (NSSize)windowWillResize:(NSWindow *)sender toSize:(NSSize)frameSize +{ + SDL_Window *window = _data->window; + NSWindow *nswindow = _data->nswindow; + NSRect newContentRect = [nswindow contentRectForFrameRect:NSMakeRect(0, 0, frameSize.width, frameSize.height)]; + NSSize newSize = newContentRect.size; + CGFloat minAspectRatio = window->min_ar; + CGFloat maxAspectRatio = window->max_ar; + CGFloat aspectRatio = newSize.width / newSize.height; + + if ( (maxAspectRatio > 0.0f) && (aspectRatio > maxAspectRatio) ) { + newSize.width = (int)(newSize.height * maxAspectRatio); + } + else if ( (minAspectRatio > 0.0f) && (aspectRatio < minAspectRatio) ) { + newSize.height = (int)(newSize.width / minAspectRatio); + } + + NSRect newFrameRect = [nswindow frameRectForContentRect:NSMakeRect(0, 0, newSize.width, newSize.height)]; + return newFrameRect.size; +} + - (void)windowDidResize:(NSNotification *)aNotification { if (inFullscreenTransition) { diff -urN SDL2-2.0.3/src/video/windows/SDL_windowsevents.c SDL2-2.0.3-aspectratio/src/video/windows/SDL_windowsevents.c --- SDL2-2.0.3/src/video/windows/SDL_windowsevents.c 2014-03-15 19:31:44.000000000 -0700 +++ SDL2-2.0.3-aspectratio/src/video/windows/SDL_windowsevents.c 2014-07-18 00:24:07.000000000 -0700 @@ -734,6 +734,134 @@ } break; + case WM_SIZING: + { + Uint32 edge = wParam; + RECT* dragRect = (RECT*)lParam; + RECT clientDragRect = *dragRect; + SDL_bool lock_aspect_ratio = (data->window->max_ar == data->window->min_ar) ? SDL_TRUE : SDL_FALSE; + RECT rc; + LONG w, h; + float new_ar; + + /* if aspect ratio constraints are not enabled then skip this message */ + if (data->window->min_ar <= 0 && data->window->max_ar <= 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_ar = 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_ar); + break; + default: + /* resizing via corners or top or bottom */ + w = (int)(h*data->window->max_ar); + break; + } + } + else { + switch (edge) { + case WMSZ_LEFT: + case WMSZ_RIGHT: + if (data->window->max_ar > 0.0f && new_ar > data->window->max_ar) { + w = (int)(h*data->window->max_ar); + } + else if (data->window->min_ar > 0.0f && new_ar < data->window->min_ar) { + w = (int)(h*data->window->min_ar); + } + break; + case WMSZ_TOP: + case WMSZ_BOTTOM: + if (data->window->min_ar > 0.0f && new_ar < data->window->min_ar) { + h = (int)(w / data->window->min_ar); + } + else if (data->window->max_ar > 0.0f && new_ar > data->window->max_ar) { + h = (int)(w / data->window->max_ar); + } + break; + + default: + /* resizing via corners */ + if (data->window->max_ar > 0.0f && new_ar > data->window->max_ar) { + w = (int)(h*data->window->max_ar); + } + else if (data->window->min_ar > 0.0f && new_ar < data->window->min_ar) { + h = (int)(w / data->window->min_ar); + } + 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; @@ -762,7 +890,7 @@ /* We'll do our own drawing, prevent flicker */ case WM_ERASEBKGND: { - } + } return (1); #if defined(SC_SCREENSAVE) || defined(SC_MONITORPOWER)