From 1cd37cad0a06fbb15c44fd59dd6b2c12a0812a76 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Fri, 20 May 2022 14:23:41 -0400 Subject: Add a uniform API for setting size hints This collapses many functions into one, which makes the API more easily extensible and reduces code size. --- src/implementation.c | 6 +-- src/mac.m | 140 ++++++++++++++++++++++++--------------------------- src/types.h | 17 +++---- src/win.c | 72 ++++++++++---------------- src/x11.c | 91 ++++++++++++++++----------------- 5 files changed, 145 insertions(+), 181 deletions(-) (limited to 'src') diff --git a/src/implementation.c b/src/implementation.c index 166aebd..c3394ce 100644 --- a/src/implementation.c +++ b/src/implementation.c @@ -139,9 +139,9 @@ puglNewView(PuglWorld* const world) return NULL; } - view->world = world; - view->minWidth = 1; - view->minHeight = 1; + view->world = world; + view->sizeHints[PUGL_MIN_SIZE].width = 1; + view->sizeHints[PUGL_MIN_SIZE].height = 1; puglSetDefaultHints(view->hints); diff --git a/src/mac.m b/src/mac.m index 1040aa7..5f60339 100644 --- a/src/mac.m +++ b/src/mac.m @@ -220,12 +220,11 @@ updateViewRect(PuglView* view) - (NSSize)intrinsicContentSize { - if (puglview->defaultWidth || puglview->defaultHeight) { - return sizePoints( - puglview, puglview->defaultWidth, puglview->defaultHeight); - } + const PuglViewSize defaultSize = puglview->sizeHints[PUGL_DEFAULT_SIZE]; - return NSMakeSize(NSViewNoInstrinsicMetric, NSViewNoInstrinsicMetric); + return (defaultSize.width && defaultSize.height) + ? sizePoints(puglview, defaultSize.width, defaultSize.height) + : NSMakeSize(NSViewNoInstrinsicMetric, NSViewNoInstrinsicMetric); } - (BOOL)isFlipped @@ -889,6 +888,47 @@ puglConstraint(const id item, constant:(CGFloat)constant]; } +static PuglStatus +updateSizeHint(PuglView* const view, const PuglSizeHint hint) +{ + const PuglSpan width = view->sizeHints[hint].width; + const PuglSpan height = view->sizeHints[hint].height; + if (!width || !height) { + return PUGL_FAILURE; + } + + switch (hint) { + case PUGL_DEFAULT_SIZE: + break; + + case PUGL_MIN_SIZE: + [view->impl->window setContentMinSize:sizePoints(view, width, height)]; + break; + + case PUGL_MAX_SIZE: + [view->impl->window setContentMaxSize:sizePoints(view, width, height)]; + break; + + case PUGL_FIXED_ASPECT: + [view->impl->window setContentAspectRatio:sizePoints(view, width, height)]; + break; + + case PUGL_MIN_ASPECT: + case PUGL_MAX_ASPECT: + break; + } + + return PUGL_SUCCESS; +} + +static void +updateSizeHints(PuglView* const view) +{ + for (unsigned i = 0u; i <= PUGL_MAX_ASPECT; ++i) { + updateSizeHint(view, (PuglSizeHint)i); + } +} + PuglStatus puglRealize(PuglView* view) { @@ -935,15 +975,16 @@ puglRealize(PuglView* view) } if (view->frame.width == 0.0 && view->frame.height == 0.0) { - if (view->defaultWidth == 0.0 && view->defaultHeight == 0.0) { + const PuglViewSize defaultSize = view->sizeHints[PUGL_DEFAULT_SIZE]; + if (!defaultSize.width || !defaultSize.height) { return PUGL_BAD_CONFIGURATION; } const double screenWidthPx = [screen frame].size.width * scaleFactor; const double screenHeightPx = [screen frame].size.height * scaleFactor; - view->frame.width = view->defaultWidth; - view->frame.height = view->defaultHeight; + view->frame.width = defaultSize.width; + view->frame.height = defaultSize.height; view->frame.x = screenWidthPx / 2.0 - view->frame.width / 2.0; view->frame.y = screenHeightPx / 2.0 - view->frame.height / 2.0; } @@ -966,26 +1007,27 @@ puglRealize(PuglView* view) addConstraint:puglConstraint(impl->wrapperView, NSLayoutAttributeWidth, NSLayoutRelationGreaterThanOrEqual, - view->minWidth)]; + view->sizeHints[PUGL_MIN_SIZE].width)]; [impl->wrapperView addConstraint:puglConstraint(impl->wrapperView, NSLayoutAttributeHeight, NSLayoutRelationGreaterThanOrEqual, - view->minHeight)]; + view->sizeHints[PUGL_MIN_SIZE].height)]; - if (view->maxWidth && view->maxHeight) { + if (view->sizeHints[PUGL_MAX_SIZE].width && + view->sizeHints[PUGL_MAX_SIZE].height) { [impl->wrapperView addConstraint:puglConstraint(impl->wrapperView, NSLayoutAttributeWidth, NSLayoutRelationLessThanOrEqual, - view->maxWidth)]; + view->sizeHints[PUGL_MAX_SIZE].width)]; [impl->wrapperView addConstraint:puglConstraint(impl->wrapperView, NSLayoutAttributeHeight, NSLayoutRelationLessThanOrEqual, - view->maxHeight)]; + view->sizeHints[PUGL_MAX_SIZE].height)]; } // Create draw view to be rendered to @@ -1028,21 +1070,12 @@ puglRealize(PuglView* view) [window setTitle:titleString]; } - if (view->minWidth || view->minHeight) { - [window - setContentMinSize:sizePoints(view, view->minWidth, view->minHeight)]; - } - impl->window = window; - ((NSWindow*)window).delegate = [[PuglWindowDelegate alloc] initWithPuglWindow:window]; - if (view->minAspectX && view->minAspectY) { - [window setContentAspectRatio:sizePoints(view, - view->minAspectX, - view->minAspectY)]; - } + impl->window = window; + updateSizeHints(view); puglSetFrame(view, view->frame); [window setContentView:impl->wrapperView]; @@ -1358,60 +1391,19 @@ puglSetFrame(PuglView* view, const PuglRect frame) } PuglStatus -puglSetDefaultSize(PuglView* const view, const int width, const int height) -{ - view->defaultWidth = width; - view->defaultHeight = height; - return PUGL_SUCCESS; -} - -PuglStatus -puglSetMinSize(PuglView* const view, const int width, const int height) -{ - view->minWidth = width; - view->minHeight = height; - - if (view->impl->window && (view->minWidth || view->minHeight)) { - [view->impl->window - setContentMinSize:sizePoints(view, view->minWidth, view->minHeight)]; - } - - return PUGL_SUCCESS; -} - -PuglStatus -puglSetMaxSize(PuglView* const view, const int width, const int height) +puglSetSizeHint(PuglView* const view, + const PuglSizeHint hint, + const PuglSpan width, + const PuglSpan height) { - view->maxWidth = width; - view->maxHeight = height; - - if (view->impl->window && (view->maxWidth || view->maxHeight)) { - [view->impl->window - setContentMaxSize:sizePoints(view, view->maxWidth, view->maxHeight)]; + if ((unsigned)hint > (unsigned)PUGL_MAX_ASPECT) { + return PUGL_BAD_PARAMETER; } - return PUGL_SUCCESS; -} + view->sizeHints[hint].width = width; + view->sizeHints[hint].height = height; -PuglStatus -puglSetAspectRatio(PuglView* const view, - const int minX, - const int minY, - const int maxX, - const int maxY) -{ - view->minAspectX = minX; - view->minAspectY = minY; - view->maxAspectX = maxX; - view->maxAspectY = maxY; - - if (view->impl->window && view->minAspectX && view->minAspectY) { - [view->impl->window setContentAspectRatio:sizePoints(view, - view->minAspectX, - view->minAspectY)]; - } - - return PUGL_SUCCESS; + return view->impl->window ? updateSizeHint(view, hint) : PUGL_SUCCESS; } PuglStatus diff --git a/src/types.h b/src/types.h index 67e9eef..0187dad 100644 --- a/src/types.h +++ b/src/types.h @@ -21,6 +21,12 @@ typedef struct PuglInternalsImpl PuglInternals; /// View hints typedef int PuglHints[PUGL_NUM_VIEW_HINTS]; +/// View size (both X and Y coordinates) +typedef struct { + PuglSpan width; + PuglSpan height; +} PuglViewSize; + /// Blob of arbitrary data typedef struct { void* data; ///< Dynamically allocated data @@ -41,16 +47,7 @@ struct PuglViewImpl { PuglRect frame; PuglConfigureEvent lastConfigure; PuglHints hints; - int defaultWidth; - int defaultHeight; - int minWidth; - int minHeight; - int maxWidth; - int maxHeight; - int minAspectX; - int minAspectY; - int maxAspectX; - int maxAspectY; + PuglViewSize sizeHints[(unsigned)PUGL_MAX_ASPECT + 1u]; bool visible; }; diff --git a/src/win.c b/src/win.c index 40a5cb7..4c36afe 100644 --- a/src/win.c +++ b/src/win.c @@ -522,8 +522,11 @@ constrainAspect(const PuglView* const view, RECT* const size, const WPARAM wParam) { - const float minA = (float)view->minAspectX / (float)view->minAspectY; - const float maxA = (float)view->maxAspectX / (float)view->maxAspectY; + const PuglViewSize minAspect = view->sizeHints[PUGL_MIN_ASPECT]; + const PuglViewSize maxAspect = view->sizeHints[PUGL_MAX_ASPECT]; + + const float minA = (float)minAspect.width / (float)minAspect.height; + const float maxA = (float)maxAspect.width / (float)maxAspect.height; const float w = (float)(size->right - size->left); const float h = (float)(size->bottom - size->top); const float a = w / h; @@ -602,7 +605,7 @@ handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam) } break; case WM_SIZING: - if (view->minAspectX) { + if (view->sizeHints[PUGL_MIN_ASPECT].width) { constrainAspect(view, (RECT*)lParam, wParam); return TRUE; } @@ -624,11 +627,12 @@ handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam) break; case WM_GETMINMAXINFO: mmi = (MINMAXINFO*)lParam; - mmi->ptMinTrackSize.x = view->minWidth; - mmi->ptMinTrackSize.y = view->minHeight; - if (view->maxWidth > 0 && view->maxHeight > 0) { - mmi->ptMaxTrackSize.x = view->maxWidth; - mmi->ptMaxTrackSize.y = view->maxHeight; + mmi->ptMinTrackSize.x = view->sizeHints[PUGL_MIN_SIZE].width; + mmi->ptMinTrackSize.y = view->sizeHints[PUGL_MIN_SIZE].height; + if (view->sizeHints[PUGL_MAX_SIZE].width && + view->sizeHints[PUGL_MAX_SIZE].height) { + mmi->ptMaxTrackSize.x = view->sizeHints[PUGL_MAX_SIZE].width; + mmi->ptMaxTrackSize.y = view->sizeHints[PUGL_MAX_SIZE].height; } break; case WM_PAINT: @@ -1008,40 +1012,17 @@ puglSetFrame(PuglView* view, const PuglRect frame) } PuglStatus -puglSetDefaultSize(PuglView* const view, const int width, const int height) +puglSetSizeHint(PuglView* const view, + const PuglSizeHint hint, + const PuglSpan width, + const PuglSpan height) { - view->defaultWidth = width; - view->defaultHeight = height; - return PUGL_SUCCESS; -} - -PuglStatus -puglSetMinSize(PuglView* const view, const int width, const int height) -{ - view->minWidth = width; - view->minHeight = height; - return PUGL_SUCCESS; -} - -PuglStatus -puglSetMaxSize(PuglView* const view, const int width, const int height) -{ - view->maxWidth = width; - view->maxHeight = height; - return PUGL_SUCCESS; -} + if ((unsigned)hint > (unsigned)PUGL_MAX_ASPECT || width < 0 || height < 0) { + return PUGL_BAD_PARAMETER; + } -PuglStatus -puglSetAspectRatio(PuglView* const view, - const int minX, - const int minY, - const int maxX, - const int maxY) -{ - view->minAspectX = minX; - view->minAspectY = minY; - view->maxAspectX = maxX; - view->maxAspectY = maxY; + view->sizeHints[hint].width = width; + view->sizeHints[hint].height = height; return PUGL_SUCCESS; } @@ -1206,7 +1187,8 @@ puglWinCreateWindow(PuglView* const view, const unsigned winExFlags = puglWinGetWindowExFlags(view); if (view->frame.width <= 0.0 && view->frame.height <= 0.0) { - if (view->defaultWidth <= 0.0 && view->defaultHeight <= 0.0) { + const PuglViewSize defaultSize = view->sizeHints[PUGL_DEFAULT_SIZE]; + if (!defaultSize.width || !defaultSize.height) { return PUGL_BAD_CONFIGURATION; } @@ -1216,10 +1198,10 @@ puglWinCreateWindow(PuglView* const view, const int screenWidth = desktopRect.right - desktopRect.left; const int screenHeight = desktopRect.bottom - desktopRect.top; - view->frame.width = view->defaultWidth; - view->frame.height = view->defaultHeight; - view->frame.x = screenWidth / 2.0 - view->frame.width / 2.0; - view->frame.y = screenHeight / 2.0 - view->frame.height / 2.0; + view->frame.width = defaultSize.width; + view->frame.height = defaultSize.height; + view->frame.x = (screenWidth - view->frame.width) / 2.0; + view->frame.y = (screenHeight - view->frame.height) / 2.0; } // The meaning of "parent" depends on the window type (WS_CHILD) diff --git a/src/x11.c b/src/x11.c index 64397bd..76a23de 100644 --- a/src/x11.c +++ b/src/x11.c @@ -224,30 +224,45 @@ updateSizeHints(const PuglView* const view) sizeHints.max_width = (int)view->frame.width; sizeHints.max_height = (int)view->frame.height; } else { - if (view->defaultWidth || view->defaultHeight) { + const PuglViewSize defaultSize = view->sizeHints[PUGL_DEFAULT_SIZE]; + if (defaultSize.width && defaultSize.height) { sizeHints.flags |= PBaseSize; - sizeHints.base_width = view->defaultWidth; - sizeHints.base_height = view->defaultHeight; + sizeHints.base_width = defaultSize.width; + sizeHints.base_height = defaultSize.height; } - if (view->minWidth || view->minHeight) { + const PuglViewSize minSize = view->sizeHints[PUGL_MIN_SIZE]; + if (minSize.width && minSize.height) { sizeHints.flags |= PMinSize; - sizeHints.min_width = view->minWidth; - sizeHints.min_height = view->minHeight; + sizeHints.min_width = minSize.width; + sizeHints.min_height = minSize.height; } - if (view->maxWidth || view->maxHeight) { + const PuglViewSize maxSize = view->sizeHints[PUGL_MAX_SIZE]; + if (maxSize.width && maxSize.height) { sizeHints.flags |= PMaxSize; - sizeHints.max_width = view->maxWidth; - sizeHints.max_height = view->maxHeight; + sizeHints.max_width = maxSize.width; + sizeHints.max_height = maxSize.height; } - if (view->minAspectX) { + const PuglViewSize minAspect = view->sizeHints[PUGL_MIN_ASPECT]; + const PuglViewSize maxAspect = view->sizeHints[PUGL_MAX_ASPECT]; + if (minAspect.width && minAspect.height && maxAspect.width && + maxAspect.height) { sizeHints.flags |= PAspect; - sizeHints.min_aspect.x = view->minAspectX; - sizeHints.min_aspect.y = view->minAspectY; - sizeHints.max_aspect.x = view->maxAspectX; - sizeHints.max_aspect.y = view->maxAspectY; + sizeHints.min_aspect.x = minAspect.width; + sizeHints.min_aspect.y = minAspect.height; + sizeHints.max_aspect.x = maxAspect.width; + sizeHints.max_aspect.y = maxAspect.height; + } + + const PuglViewSize fixedAspect = view->sizeHints[PUGL_FIXED_ASPECT]; + if (fixedAspect.width && fixedAspect.height) { + sizeHints.flags |= PAspect; + sizeHints.min_aspect.x = fixedAspect.width; + sizeHints.min_aspect.y = fixedAspect.height; + sizeHints.max_aspect.x = fixedAspect.width; + sizeHints.max_aspect.y = fixedAspect.height; } } @@ -314,12 +329,13 @@ puglRealize(PuglView* const view) // Set the size to the default if it has not already been set if (view->frame.width <= 0.0 && view->frame.height <= 0.0) { - if (view->defaultWidth <= 0.0 || view->defaultHeight <= 0.0) { + const PuglViewSize defaultSize = view->sizeHints[PUGL_DEFAULT_SIZE]; + if (!defaultSize.width || !defaultSize.height) { return PUGL_BAD_CONFIGURATION; } - view->frame.width = view->defaultWidth; - view->frame.height = view->defaultHeight; + view->frame.width = defaultSize.width; + view->frame.height = defaultSize.height; } // Center top-level windows if a position has not been set @@ -1366,40 +1382,17 @@ puglSetFrame(PuglView* const view, const PuglRect frame) } PuglStatus -puglSetDefaultSize(PuglView* const view, const int width, const int height) -{ - view->defaultWidth = width; - view->defaultHeight = height; - return updateSizeHints(view); -} - -PuglStatus -puglSetMinSize(PuglView* const view, const int width, const int height) +puglSetSizeHint(PuglView* const view, + const PuglSizeHint hint, + const PuglSpan width, + const PuglSpan height) { - view->minWidth = width; - view->minHeight = height; - return updateSizeHints(view); -} - -PuglStatus -puglSetMaxSize(PuglView* const view, const int width, const int height) -{ - view->maxWidth = width; - view->maxHeight = height; - return updateSizeHints(view); -} + if ((unsigned)hint > (unsigned)PUGL_MAX_ASPECT) { + return PUGL_BAD_PARAMETER; + } -PuglStatus -puglSetAspectRatio(PuglView* const view, - const int minX, - const int minY, - const int maxX, - const int maxY) -{ - view->minAspectX = minX; - view->minAspectY = minY; - view->maxAspectX = maxX; - view->maxAspectY = maxY; + view->sizeHints[hint].width = width; + view->sizeHints[hint].height = height; return updateSizeHints(view); } -- cgit v1.2.1