diff options
Diffstat (limited to 'pugl')
-rw-r--r-- | pugl/detail/implementation.c | 7 | ||||
-rw-r--r-- | pugl/detail/mac.m | 65 | ||||
-rw-r--r-- | pugl/detail/types.h | 4 | ||||
-rw-r--r-- | pugl/detail/win.c | 18 | ||||
-rw-r--r-- | pugl/detail/win.h | 25 | ||||
-rw-r--r-- | pugl/detail/x11.c | 82 | ||||
-rw-r--r-- | pugl/pugl.h | 20 | ||||
-rw-r--r-- | pugl/pugl.hpp | 13 |
8 files changed, 194 insertions, 40 deletions
diff --git a/pugl/detail/implementation.c b/pugl/detail/implementation.c index 45c06c6..1ff1c60 100644 --- a/pugl/detail/implementation.c +++ b/pugl/detail/implementation.c @@ -61,6 +61,7 @@ puglStrerror(const PuglStatus status) case PUGL_FAILURE: return "Non-fatal failure"; case PUGL_UNKNOWN_ERROR: return "Unknown system error"; case PUGL_BAD_BACKEND: return "Invalid or missing backend"; + case PUGL_BAD_CONFIGURATION: return "Invalid view configuration"; case PUGL_BAD_PARAMETER: return "Invalid parameter"; case PUGL_BACKEND_FAILED: return "Backend initialisation failed"; case PUGL_REGISTRATION_FAILED: return "Class registration failed"; @@ -189,9 +190,9 @@ puglNewView(PuglWorld* const world) return NULL; } - view->world = world; - view->frame.width = 640; - view->frame.height = 480; + view->world = world; + view->minWidth = 1; + view->minHeight = 1; puglSetDefaultHints(view->hints); diff --git a/pugl/detail/mac.m b/pugl/detail/mac.m index 52417e6..501f5d9 100644 --- a/pugl/detail/mac.m +++ b/pugl/detail/mac.m @@ -210,6 +210,17 @@ updateViewRect(PuglView* view) puglDispatchEvent(puglview, (const PuglEvent*)&ev); } +- (NSSize) intrinsicContentSize +{ + if (puglview->defaultWidth || puglview->defaultHeight) { + return sizePoints(puglview, + puglview->defaultWidth, + puglview->defaultHeight); + } + + return NSMakeSize(NSViewNoInstrinsicMetric, NSViewNoInstrinsicMetric); +} + - (BOOL) isFlipped { return YES; @@ -805,14 +816,29 @@ puglConstraint(id item, NSLayoutAttribute attribute, float constant) PuglStatus puglRealize(PuglView* view) { - PuglInternals* impl = view->impl; + PuglInternals* impl = view->impl; + const NSScreen* const screen = [NSScreen mainScreen]; + const double scaleFactor = [screen backingScaleFactor]; - const double scaleFactor = [[NSScreen mainScreen] backingScaleFactor]; - const NSRect framePx = rectToNsRect(view->frame); - const NSRect framePt = NSMakeRect(framePx.origin.x / scaleFactor, - framePx.origin.y / scaleFactor, - framePx.size.width / scaleFactor, - framePx.size.height / scaleFactor); + if (view->frame.width == 0.0 && view->frame.height == 0.0) { + if (view->defaultWidth == 0.0 && view->defaultHeight == 0.0) { + return PUGL_BAD_CONFIGURATION; + } + + const int screenWidthPx = [screen frame].size.width * scaleFactor; + const int screenHeightPx = [screen frame].size.height * scaleFactor; + + view->frame.width = view->defaultWidth; + view->frame.height = view->defaultHeight; + view->frame.x = screenWidthPx / 2.0 - view->frame.width / 2.0; + view->frame.y = screenHeightPx / 2.0 - view->frame.height / 2.0; + } + + const NSRect framePx = rectToNsRect(view->frame); + const NSRect framePt = NSMakeRect(framePx.origin.x / scaleFactor, + framePx.origin.y / scaleFactor, + framePx.size.width / scaleFactor, + framePx.size.height / scaleFactor); // Create wrapper view to handle input impl->wrapperView = [PuglWrapperView alloc]; @@ -884,6 +910,8 @@ puglRealize(PuglView* view) view->minAspectY)]; } + puglSetFrame(view, view->frame); + [window setContentView:impl->wrapperView]; [view->world->impl->app activateIgnoringOtherApps:YES]; [window makeFirstResponder:impl->wrapperView]; @@ -1179,6 +1207,14 @@ 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; @@ -1194,6 +1230,21 @@ puglSetMinSize(PuglView* const view, const int width, const int height) } PuglStatus +puglSetMaxSize(PuglView* const view, const int width, const int 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)]; + } + + return PUGL_SUCCESS; +} + +PuglStatus puglSetAspectRatio(PuglView* const view, const int minX, const int minY, diff --git a/pugl/detail/types.h b/pugl/detail/types.h index 7b15053..0b0332c 100644 --- a/pugl/detail/types.h +++ b/pugl/detail/types.h @@ -66,8 +66,12 @@ struct PuglViewImpl { PuglHints hints; PuglRect frame; PuglEventConfigure lastConfigure; + int defaultWidth; + int defaultHeight; int minWidth; int minHeight; + int maxWidth; + int maxHeight; int minAspectX; int minAspectY; int maxAspectX; diff --git a/pugl/detail/win.c b/pugl/detail/win.c index 76df1b4..22bcfbf 100644 --- a/pugl/detail/win.c +++ b/pugl/detail/win.c @@ -592,6 +592,8 @@ handleMessage(PuglView* view, UINT message, WPARAM wParam, LPARAM lParam) mmi = (MINMAXINFO*)lParam; mmi->ptMinTrackSize.x = view->minWidth; mmi->ptMinTrackSize.y = view->minHeight; + mmi->ptMaxTrackSize.x = view->maxWidth; + mmi->ptMaxTrackSize.y = view->maxHeight; break; case WM_PAINT: GetUpdateRect(view->impl->hwnd, &rect, false); @@ -959,6 +961,14 @@ 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; @@ -967,6 +977,14 @@ puglSetMinSize(PuglView* const view, const int width, const int height) } PuglStatus +puglSetMaxSize(PuglView* const view, const int width, const int height) +{ + view->maxWidth = width; + view->maxHeight = height; + return PUGL_SUCCESS; +} + +PuglStatus puglSetAspectRatio(PuglView* const view, const int minX, const int minY, diff --git a/pugl/detail/win.h b/pugl/detail/win.h index 8ebb7bf..087bbce 100644 --- a/pugl/detail/win.h +++ b/pugl/detail/win.h @@ -88,15 +88,32 @@ puglWinGetWindowExFlags(const PuglView* const view) } static inline PuglStatus -puglWinCreateWindow(const PuglView* const view, - const char* const title, - HWND* const hwnd, - HDC* const hdc) +puglWinCreateWindow(PuglView* const view, + const char* const title, + HWND* const hwnd, + HDC* const hdc) { const char* className = (const char*)view->world->className; const unsigned winFlags = puglWinGetWindowFlags(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) { + return PUGL_BAD_CONFIGURATION; + } + + RECT desktopRect; + GetClientRect(GetDesktopWindow(), &desktopRect); + + 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; + } + // The meaning of "parent" depends on the window type (WS_CHILD) PuglNativeView parent = view->parent ? view->parent : view->transientParent; diff --git a/pugl/detail/x11.c b/pugl/detail/x11.c index 9998a7a..6a580ce 100644 --- a/pugl/detail/x11.c +++ b/pugl/detail/x11.c @@ -193,23 +193,40 @@ puglFindView(PuglWorld* world, const Window window) return NULL; } -static XSizeHints -getSizeHints(const PuglView* view) +static PuglStatus +updateSizeHints(const PuglView* view) { + if (!view->impl->win) { + return PUGL_SUCCESS; + } + + Display* display = view->world->impl->display; XSizeHints sizeHints = {0}; if (!view->hints[PUGL_RESIZABLE]) { - sizeHints.flags = PMinSize|PMaxSize; - sizeHints.min_width = (int)view->frame.width; - sizeHints.min_height = (int)view->frame.height; - sizeHints.max_width = (int)view->frame.width; - sizeHints.max_height = (int)view->frame.height; + sizeHints.flags = PBaseSize | PMinSize | PMaxSize; + sizeHints.base_width = (int)view->frame.width; + sizeHints.base_height = (int)view->frame.height; + sizeHints.min_width = (int)view->frame.width; + sizeHints.min_height = (int)view->frame.height; + sizeHints.max_width = (int)view->frame.width; + sizeHints.max_height = (int)view->frame.height; } else { + if (view->defaultWidth || view->defaultHeight) { + sizeHints.flags = PBaseSize; + sizeHints.base_width = view->defaultWidth; + sizeHints.base_height = view->defaultHeight; + } if (view->minWidth || view->minHeight) { sizeHints.flags = PMinSize; sizeHints.min_width = view->minWidth; sizeHints.min_height = view->minHeight; } + if (view->maxWidth || view->maxHeight) { + sizeHints.flags = PMaxSize; + sizeHints.max_width = view->maxWidth; + sizeHints.max_height = view->maxHeight; + } if (view->minAspectX) { sizeHints.flags |= PAspect; sizeHints.min_aspect.x = view->minAspectX; @@ -219,7 +236,8 @@ getSizeHints(const PuglView* view) } } - return sizeHints; + XSetNormalHints(display, view->impl->win, &sizeHints); + return PUGL_SUCCESS; } PuglStatus @@ -235,6 +253,18 @@ puglRealize(PuglView* view) if (!view->backend || !view->backend->configure) { return PUGL_BAD_BACKEND; + } else if (view->frame.width == 0.0 && view->frame.height == 0.0) { + if (view->defaultWidth == 0.0 && view->defaultHeight == 0.0) { + return PUGL_BAD_CONFIGURATION; + } + + const int screenWidth = DisplayWidth(display, impl->screen); + const int screenHeight = DisplayHeight(display, impl->screen); + + 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; } PuglStatus st = view->backend->configure(view); @@ -264,8 +294,7 @@ puglRealize(PuglView* view) return st; } - XSizeHints sizeHints = getSizeHints(view); - XSetNormalHints(display, win, &sizeHints); + updateSizeHints(view); XClassHint classHint = { world->className, world->className }; XSetClassHint(display, win, &classHint); @@ -1103,19 +1132,27 @@ puglSetFrame(PuglView* view, const PuglRect frame) } PuglStatus -puglSetMinSize(PuglView* const view, const int width, const int height) +puglSetDefaultSize(PuglView* const view, const int width, const int height) { - Display* display = view->world->impl->display; + view->defaultWidth = width; + view->defaultHeight = height; + return updateSizeHints(view); +} +PuglStatus +puglSetMinSize(PuglView* const view, const int width, const int height) +{ view->minWidth = width; view->minHeight = height; + return updateSizeHints(view); +} - if (view->impl->win) { - XSizeHints sizeHints = getSizeHints(view); - XSetNormalHints(display, view->impl->win, &sizeHints); - } - - return PUGL_SUCCESS; +PuglStatus +puglSetMaxSize(PuglView* const view, const int width, const int height) +{ + view->minWidth = width; + view->minHeight = height; + return updateSizeHints(view); } PuglStatus @@ -1125,19 +1162,12 @@ puglSetAspectRatio(PuglView* const view, const int maxX, const int maxY) { - Display* display = view->world->impl->display; - view->minAspectX = minX; view->minAspectY = minY; view->maxAspectX = maxX; view->maxAspectY = maxY; - if (view->impl->win) { - XSizeHints sizeHints = getSizeHints(view); - XSetNormalHints(display, view->impl->win, &sizeHints); - } - - return PUGL_SUCCESS; + return updateSizeHints(view); } PuglStatus diff --git a/pugl/pugl.h b/pugl/pugl.h index fe8b585..b489407 100644 --- a/pugl/pugl.h +++ b/pugl/pugl.h @@ -559,6 +559,7 @@ typedef enum { PUGL_FAILURE, ///< Non-fatal failure PUGL_UNKNOWN_ERROR, ///< Unknown system error PUGL_BAD_BACKEND, ///< Invalid or missing backend + PUGL_BAD_CONFIGURATION, ///< Invalid view configuration PUGL_BAD_PARAMETER, ///< Invalid parameter PUGL_BACKEND_FAILED, ///< Backend initialisation failed PUGL_REGISTRATION_FAILED, ///< Class registration failed @@ -947,6 +948,16 @@ PUGL_API PuglStatus puglSetFrame(PuglView* view, PuglRect frame); /** + Set the default size of the view. + + This should be called before puglResize() to set the default size of the + view, which will be the initial size of the window if this is a top level + view. +*/ +PUGL_API PuglStatus +puglSetDefaultSize(PuglView* view, int width, int height); + +/** Set the minimum size of the view. If an initial minimum size is known, this should be called before @@ -956,6 +967,15 @@ PUGL_API PuglStatus puglSetMinSize(PuglView* view, int width, int height); /** + Set the maximum size of the view. + + If an initial maximum size is known, this should be called before + puglRealize() to avoid stutter, though it can be called afterwards as well. +*/ +PUGL_API PuglStatus +puglSetMaxSize(PuglView* view, int width, int height); + +/** Set the view aspect ratio range. The x and y values here represent a ratio of width to height. To set a diff --git a/pugl/pugl.hpp b/pugl/pugl.hpp index 52ac52c..2e18306 100644 --- a/pugl/pugl.hpp +++ b/pugl/pugl.hpp @@ -186,6 +186,7 @@ enum class Status { failure, ///< @copydoc PUGL_FAILURE unknownError, ///< @copydoc PUGL_UNKNOWN_ERROR badBackend, ///< @copydoc PUGL_BAD_BACKEND + badConfiguration, ///< @copydoc PUGL_BAD_CONFIGURATION badParameter, ///< @copydoc PUGL_BAD_PARAMETER backendFailed, ///< @copydoc PUGL_BACKEND_FAILED registrationFailed, ///< @copydoc PUGL_REGISTRATION_FAILED @@ -406,12 +407,24 @@ public: return static_cast<Status>(puglSetFrame(cobj(), frame)); } + /// @copydoc puglSetDefaultSize + Status setDefaultSize(int width, int height) + { + return static_cast<Status>(puglSetDefaultSize(cobj(), width, height)); + } + /// @copydoc puglSetMinSize Status setMinSize(int width, int height) { return static_cast<Status>(puglSetMinSize(cobj(), width, height)); } + /// @copydoc puglSetMaxSize + Status setMaxSize(int width, int height) + { + return static_cast<Status>(puglSetMaxSize(cobj(), width, height)); + } + /// @copydoc puglSetAspectRatio Status setAspectRatio(int minX, int minY, int maxX, int maxY) { |