aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2019-07-26 00:57:49 +0200
committerDavid Robillard <d@drobilla.net>2019-07-26 01:05:37 +0200
commiteada1042452e8708ca6c65f7c23ac3c59e4c53f0 (patch)
tree2155469130ef05d42f49a02c0af3abedf66fe9f1
parent55199fe97d7866a0c8998455e43bb5b1f2989eb7 (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.h4
-rw-r--r--pugl/pugl_win.c45
-rw-r--r--test/pugl_test.c2
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);