aboutsummaryrefslogtreecommitdiffstats
path: root/pugl
diff options
context:
space:
mode:
Diffstat (limited to 'pugl')
-rw-r--r--pugl/detail/implementation.c7
-rw-r--r--pugl/detail/mac.m65
-rw-r--r--pugl/detail/types.h4
-rw-r--r--pugl/detail/win.c18
-rw-r--r--pugl/detail/win.h25
-rw-r--r--pugl/detail/x11.c82
-rw-r--r--pugl/pugl.h20
-rw-r--r--pugl/pugl.hpp13
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)
{