aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/pugl_cairo_demo.c5
-rw-r--r--examples/pugl_cxx_demo.cpp2
-rw-r--r--examples/pugl_embed_demo.c2
-rw-r--r--examples/pugl_shader_demo.c8
-rw-r--r--examples/pugl_window_demo.c1
-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
-rw-r--r--test/test_redisplay.c1
-rw-r--r--test/test_show_hide.c1
-rw-r--r--test/test_timer.c1
-rw-r--r--test/test_update.c1
17 files changed, 206 insertions, 50 deletions
diff --git a/examples/pugl_cairo_demo.c b/examples/pugl_cairo_demo.c
index 51039a2..2e0b9c7 100644
--- a/examples/pugl_cairo_demo.c
+++ b/examples/pugl_cairo_demo.c
@@ -236,11 +236,10 @@ main(int argc, char** argv)
app.world = puglNewWorld(PUGL_PROGRAM, 0);
puglSetClassName(app.world, "PuglCairoTest");
- PuglRect frame = { 0, 0, 512, 512 };
- PuglView* view = puglNewView(app.world);
+ PuglView* view = puglNewView(app.world);
puglSetWindowTitle(view, "Pugl Cairo Demo");
- puglSetFrame(view, frame);
+ puglSetDefaultSize(view, 512, 512);
puglSetMinSize(view, 256, 256);
puglSetViewHint(view, PUGL_RESIZABLE, app.opts.resizable);
puglSetHandle(view, &app);
diff --git a/examples/pugl_cxx_demo.cpp b/examples/pugl_cxx_demo.cpp
index 9522534..4addee2 100644
--- a/examples/pugl_cxx_demo.cpp
+++ b/examples/pugl_cxx_demo.cpp
@@ -122,7 +122,7 @@ main(int argc, char** argv)
world.setClassName("PuglCppTest");
view.setWindowTitle("Pugl C++ Test");
- view.setFrame({0, 0, 512, 512});
+ view.setDefaultSize(512, 512);
view.setMinSize(64, 64);
view.setAspectRatio(1, 1, 16, 9);
view.setBackend(pugl::glBackend());
diff --git a/examples/pugl_embed_demo.c b/examples/pugl_embed_demo.c
index de7b240..bf7f19c 100644
--- a/examples/pugl_embed_demo.c
+++ b/examples/pugl_embed_demo.c
@@ -293,7 +293,7 @@ main(int argc, char** argv)
puglSetClassName(app.world, "Pugl Test");
const PuglRect parentFrame = { 0, 0, 512, 512 };
- puglSetFrame(app.parent, parentFrame);
+ puglSetDefaultSize(app.parent, 512, 512);
puglSetMinSize(app.parent, borderWidth * 3, borderWidth * 3);
puglSetAspectRatio(app.parent, 1, 1, 16, 9);
puglSetBackend(app.parent, puglGlBackend());
diff --git a/examples/pugl_shader_demo.c b/examples/pugl_shader_demo.c
index 86d01a9..7c0df6a 100644
--- a/examples/pugl_shader_demo.c
+++ b/examples/pugl_shader_demo.c
@@ -243,7 +243,7 @@ parseOptions(PuglTestApp* app, int argc, char** argv)
}
static void
-setupPugl(PuglTestApp* app, const PuglRect frame)
+setupPugl(PuglTestApp* app)
{
// Create world, view, and rect data
app->world = puglNewWorld(PUGL_PROGRAM, 0);
@@ -253,7 +253,7 @@ setupPugl(PuglTestApp* app, const PuglRect frame)
// Set up world and view
puglSetClassName(app->world, "PuglGL3Demo");
puglSetWindowTitle(app->view, "Pugl OpenGL 3");
- puglSetFrame(app->view, frame);
+ puglSetDefaultSize(app->view, defaultWidth, defaultHeight);
puglSetMinSize(app->view, defaultWidth / 4, defaultHeight / 4);
puglSetAspectRatio(app->view, 1, 1, 16, 9);
puglSetBackend(app->view, puglGlBackend());
@@ -389,8 +389,6 @@ main(int argc, char** argv)
app.glMajorVersion = 3;
app.glMinorVersion = 3;
- const PuglRect frame = {0, 0, defaultWidth, defaultHeight};
-
// Parse command line options
if (parseOptions(&app, argc, argv)) {
puglPrintTestUsage("pugl_shader_demo", "[NUM_RECTS] [GL_MAJOR]");
@@ -398,7 +396,7 @@ main(int argc, char** argv)
}
// Create and configure world and view
- setupPugl(&app, frame);
+ setupPugl(&app);
// Create window (which will send a PUGL_CREATE event)
const PuglStatus st = puglRealize(app.view);
diff --git a/examples/pugl_window_demo.c b/examples/pugl_window_demo.c
index 3b167af..b406416 100644
--- a/examples/pugl_window_demo.c
+++ b/examples/pugl_window_demo.c
@@ -213,6 +213,7 @@ main(int argc, char** argv)
puglSetWindowTitle(view, "Pugl Window Demo");
puglSetFrame(view, frame);
+ puglSetDefaultSize(view, 512, 512);
puglSetMinSize(view, 128, 128);
puglSetBackend(view, puglGlBackend());
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)
{
diff --git a/test/test_redisplay.c b/test/test_redisplay.c
index 13f0c81..0e14cf6 100644
--- a/test/test_redisplay.c
+++ b/test/test_redisplay.c
@@ -111,6 +111,7 @@ main(int argc, char** argv)
puglSetBackend(app.view, puglStubBackend());
puglSetHandle(app.view, &app);
puglSetEventFunc(app.view, onEvent);
+ puglSetDefaultSize(app.view, 512, 512);
// Create and show window
assert(!puglRealize(app.view));
diff --git a/test/test_show_hide.c b/test/test_show_hide.c
index 43af7f4..7b6d4f4 100644
--- a/test/test_show_hide.c
+++ b/test/test_show_hide.c
@@ -115,6 +115,7 @@ main(int argc, char** argv)
puglSetBackend(test.view, puglStubBackend());
puglSetHandle(test.view, &test);
puglSetEventFunc(test.view, onEvent);
+ puglSetDefaultSize(test.view, 512, 512);
// Create initially invisible window
assert(!puglRealize(test.view));
diff --git a/test/test_timer.c b/test/test_timer.c
index f26928d..2a0b67f 100644
--- a/test/test_timer.c
+++ b/test/test_timer.c
@@ -109,6 +109,7 @@ main(int argc, char** argv)
puglSetBackend(app.view, puglStubBackend());
puglSetHandle(app.view, &app);
puglSetEventFunc(app.view, onEvent);
+ puglSetDefaultSize(app.view, 512, 512);
// Create and show window
assert(!puglRealize(app.view));
diff --git a/test/test_update.c b/test/test_update.c
index 6dccf00..65d74d6 100644
--- a/test/test_update.c
+++ b/test/test_update.c
@@ -101,6 +101,7 @@ main(int argc, char** argv)
puglSetBackend(app.view, puglStubBackend());
puglSetHandle(app.view, &app);
puglSetEventFunc(app.view, onEvent);
+ puglSetDefaultSize(app.view, 512, 512);
// Create and show window
assert(!puglRealize(app.view));