diff options
author | David Robillard <d@drobilla.net> | 2019-07-26 00:57:49 +0200 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2019-07-26 01:05:37 +0200 |
commit | eada1042452e8708ca6c65f7c23ac3c59e4c53f0 (patch) | |
tree | 2155469130ef05d42f49a02c0af3abedf66fe9f1 | |
parent | 55199fe97d7866a0c8998455e43bb5b1f2989eb7 (diff) |
Windows: Implement size constraints
There are two possible approaches to take here: try to expand dimensions that
are not being explicitly resized (for example expand the bottom when dragging
right), or just stop single-dimension resizes if they would go out of range.
I chose the latter here for two reasons: it's hard to always do something
smooth and unsurprising with the first approach (and it would require more
code), and it can be nice from the user's perspective to easily be able to
resize the window to exactly one of its aspect ratio limits. For example, it
is very easy to drag pugl_test to 1:1 or 16:9.
In other words, simplicity and user power wins.
-rw-r--r-- | pugl/pugl.h | 4 | ||||
-rw-r--r-- | pugl/pugl_win.c | 45 | ||||
-rw-r--r-- | test/pugl_test.c | 2 |
3 files changed, 50 insertions, 1 deletions
diff --git a/pugl/pugl.h b/pugl/pugl.h index 59d26fe..3e0578e 100644 --- a/pugl/pugl.h +++ b/pugl/pugl.h @@ -457,6 +457,10 @@ puglInitWindowMinSize(PuglView* view, int width, int height); The x and y values here represent a ratio of width to height. To set a fixed aspect ratio, set the minimum and maximum values to the same ratio. + + Note that setting different minimum and maximum constraints does not + currenty work on MacOS (the minimum is used), so only setting a fixed aspect + ratio works properly across all platforms. */ PUGL_API void puglInitWindowAspectRatio(PuglView* view, diff --git a/pugl/pugl_win.c b/pugl/pugl_win.c index 1c93ea6..b691295 100644 --- a/pugl/pugl_win.c +++ b/pugl/pugl_win.c @@ -634,6 +634,45 @@ stopFlashing(PuglView* view) } } +static void +constrainAspect(const PuglView* const view, + RECT* const size, + const WPARAM wParam) +{ + const float minAspect = view->min_aspect_x / (float)view->min_aspect_y; + const float maxAspect = view->max_aspect_x / (float)view->max_aspect_y; + const int w = size->right - size->left; + const int h = size->bottom - size->top; + const float a = w / (float)h; + + switch (wParam) { + case WMSZ_TOP: + size->top = (a < minAspect ? (LONG)(size->bottom - w * minAspect) : + a > maxAspect ? (LONG)(size->bottom - w * maxAspect) : + size->top); + break; + case WMSZ_TOPRIGHT: + case WMSZ_RIGHT: + case WMSZ_BOTTOMRIGHT: + size->right = (a < minAspect ? (LONG)(size->left + h * minAspect) : + a > maxAspect ? (LONG)(size->left + h * maxAspect) : + size->right); + break; + case WMSZ_BOTTOM: + size->bottom = (a < minAspect ? (LONG)(size->top + w * minAspect) : + a > maxAspect ? (LONG)(size->top + w * maxAspect) : + size->bottom); + break; + case WMSZ_BOTTOMLEFT: + case WMSZ_LEFT: + case WMSZ_TOPLEFT: + size->left = (a < minAspect ? (LONG)(size->right - h * minAspect) : + a > maxAspect ? (LONG)(size->right - h * maxAspect) : + size->left); + break; + } +} + static LRESULT handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam) { @@ -661,6 +700,12 @@ handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam) RDW_INVALIDATE|RDW_ALLCHILDREN|RDW_INTERNALPAINT| RDW_UPDATENOW); break; + case WM_SIZING: + if (view->min_aspect_x) { + constrainAspect(view, (RECT*)lParam, wParam); + return TRUE; + } + break; case WM_ENTERSIZEMOVE: view->impl->resizing = true; SetTimer(view->impl->hwnd, diff --git a/test/pugl_test.c b/test/pugl_test.c index a609027..f011962 100644 --- a/test/pugl_test.c +++ b/test/pugl_test.c @@ -170,7 +170,7 @@ main(int argc, char** argv) puglInitWindowClass(view, "PuglTest"); puglInitWindowSize(view, 512, 512); puglInitWindowMinSize(view, 256, 256); - puglInitWindowAspectRatio(view, 1, 1, 1, 1); + puglInitWindowAspectRatio(view, 1, 1, 16, 9); puglInitResizable(view, resizable); puglInitWindowHint(view, PUGL_SAMPLES, samples); |