aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2022-05-20 19:44:23 -0400
committerDavid Robillard <d@drobilla.net>2022-05-21 17:05:51 -0400
commit82405e8c177de446d03c340b4b6876370d79883a (patch)
tree8b58d94ce03810d95558d725f9a3394d2e7d0fc7
parenta136586a339032126540ceb24f7c3f15eaba68c8 (diff)
downloadpugl-82405e8c177de446d03c340b4b6876370d79883a.tar.gz
pugl-82405e8c177de446d03c340b4b6876370d79883a.tar.bz2
pugl-82405e8c177de446d03c340b4b6876370d79883a.zip
Add puglSetPosition() and puglSetSize()
These are redundant with puglSetFrame in a sense, but allow setting the size of a view without the position, or vice-versa. This API also maps more nicely to Wayland, where applications can not position themselves (but can resize).
-rw-r--r--examples/pugl_embed_demo.c22
-rw-r--r--examples/pugl_window_demo.c35
-rw-r--r--include/pugl/pugl.h28
-rw-r--r--src/mac.m82
-rw-r--r--src/win.c82
-rw-r--r--src/x11.c53
6 files changed, 239 insertions, 63 deletions
diff --git a/examples/pugl_embed_demo.c b/examples/pugl_embed_demo.c
index ae3956a..af48a15 100644
--- a/examples/pugl_embed_demo.c
+++ b/examples/pugl_embed_demo.c
@@ -119,30 +119,24 @@ onKeyPress(PuglView* view, const PuglKeyEvent* event, const char* prefix)
fprintf(stderr, "%sPaste \"%s\"\n", prefix, text);
} else if (event->state & PUGL_MOD_SHIFT) {
if (event->key == PUGL_KEY_UP) {
- frame.height = (PuglSpan)(frame.height + 10u);
+ puglSetSize(view, frame.width, frame.height - 10u);
} else if (event->key == PUGL_KEY_DOWN) {
- frame.height = (PuglSpan)(frame.height - 10u);
+ puglSetSize(view, frame.width, frame.height + 10u);
} else if (event->key == PUGL_KEY_LEFT) {
- frame.width = (PuglSpan)(frame.width - 10u);
+ puglSetSize(view, frame.width - 10u, frame.height);
} else if (event->key == PUGL_KEY_RIGHT) {
- frame.width = (PuglSpan)(frame.width + 10u);
- } else {
- return;
+ puglSetSize(view, frame.width + 10u, frame.height);
}
- puglSetFrame(view, frame);
} else {
if (event->key == PUGL_KEY_UP) {
- frame.y = (PuglCoord)(frame.y - 10);
+ puglSetPosition(view, frame.x, frame.y - 10);
} else if (event->key == PUGL_KEY_DOWN) {
- frame.y = (PuglCoord)(frame.y + 10);
+ puglSetPosition(view, frame.x, frame.y + 10);
} else if (event->key == PUGL_KEY_LEFT) {
- frame.x = (PuglCoord)(frame.x - 10);
+ puglSetPosition(view, frame.x - 10, frame.y);
} else if (event->key == PUGL_KEY_RIGHT) {
- frame.x = (PuglCoord)(frame.x + 10);
- } else {
- return;
+ puglSetPosition(view, frame.x + 10, frame.y);
}
- puglSetFrame(view, frame);
}
}
diff --git a/examples/pugl_window_demo.c b/examples/pugl_window_demo.c
index 8d79f00..3b8da31 100644
--- a/examples/pugl_window_demo.c
+++ b/examples/pugl_window_demo.c
@@ -70,30 +70,24 @@ onKeyPress(PuglView* view, const PuglKeyEvent* event)
app->quit = 1;
} else if (event->state & PUGL_MOD_SHIFT) {
if (event->key == PUGL_KEY_UP) {
- frame.height = (PuglSpan)(frame.height + 10u);
+ puglSetSize(view, frame.width, frame.height - 10u);
} else if (event->key == PUGL_KEY_DOWN) {
- frame.height = (PuglSpan)(frame.height - 10u);
+ puglSetSize(view, frame.width, frame.height + 10u);
} else if (event->key == PUGL_KEY_LEFT) {
- frame.width = (PuglSpan)(frame.width - 10u);
+ puglSetSize(view, frame.width - 10u, frame.height);
} else if (event->key == PUGL_KEY_RIGHT) {
- frame.width = (PuglSpan)(frame.width + 10u);
- } else {
- return;
+ puglSetSize(view, frame.width + 10u, frame.height);
}
- puglSetFrame(view, frame);
} else {
if (event->key == PUGL_KEY_UP) {
- frame.y = (PuglCoord)(frame.y - 10);
+ puglSetPosition(view, frame.x, frame.y - 10);
} else if (event->key == PUGL_KEY_DOWN) {
- frame.y = (PuglCoord)(frame.y + 10);
+ puglSetPosition(view, frame.x, frame.y + 10);
} else if (event->key == PUGL_KEY_LEFT) {
- frame.x = (PuglCoord)(frame.x - 10);
+ puglSetPosition(view, frame.x - 10, frame.y);
} else if (event->key == PUGL_KEY_RIGHT) {
- frame.x = (PuglCoord)(frame.x + 10);
- } else {
- return;
+ puglSetPosition(view, frame.x + 10, frame.y);
}
- puglSetFrame(view, frame);
}
}
@@ -186,17 +180,16 @@ main(int argc, char** argv)
PuglStatus st = PUGL_SUCCESS;
for (unsigned i = 0; i < 2; ++i) {
- CubeView* cube = &app.cubes[i];
- PuglView* view = cube->view;
- const PuglRect frame = {(PuglCoord)(pad + (128.0 + pad) * i),
- (PuglCoord)(pad + (128.0 + pad) * i),
- 512u,
- 512u};
+ CubeView* cube = &app.cubes[i];
+ PuglView* view = cube->view;
cube->dist = 10;
puglSetWindowTitle(view, "Pugl Window Demo");
- puglSetFrame(view, frame);
+ puglSetPosition(view,
+ (PuglCoord)(pad + (128u + pad) * i),
+ (PuglCoord)(pad + (128u + pad) * i));
+
puglSetSizeHint(view, PUGL_DEFAULT_SIZE, 512, 512);
puglSetSizeHint(view, PUGL_MIN_SIZE, 128, 128);
puglSetSizeHint(view, PUGL_MAX_SIZE, 2048, 2048);
diff --git a/include/pugl/pugl.h b/include/pugl/pugl.h
index 3fc124e..a7dd7eb 100644
--- a/include/pugl/pugl.h
+++ b/include/pugl/pugl.h
@@ -1001,13 +1001,33 @@ PuglStatus
puglSetFrame(PuglView* view, PuglRect frame);
/**
+ Set the current position of the view.
+
+ @return #PUGL_UNKNOWN_ERROR on failure, in which case the view frame is
+ unchanged.
+*/
+PUGL_API
+PuglStatus
+puglSetPosition(PuglView* view, int x, int y);
+
+/**
+ Set the current size of the view.
+
+ @return #PUGL_UNKNOWN_ERROR on failure, in which case the view frame is
+ unchanged.
+*/
+PUGL_API
+PuglStatus
+puglSetSize(PuglView* view, unsigned width, unsigned height);
+
+/**
Set a size hint for the view.
- This can be used to set the default, minimum, and maximum size of a view, as
- well as the supported range of aspect ratios.
+ This can be used to set the default, minimum, and maximum size of a view,
+ as well as the supported range of aspect ratios.
- This should be called before puglResize() so the initial window for the view
- can be configured correctly.
+ This should be called before puglResize() so the initial window for the
+ view can be configured correctly.
@return #PUGL_UNKNOWN_ERROR on failure, but always succeeds if the view is
not yet realized.
diff --git a/src/mac.m b/src/mac.m
index 7608ec8..67422a5 100644
--- a/src/mac.m
+++ b/src/mac.m
@@ -1368,28 +1368,88 @@ puglSetWindowTitle(PuglView* view, const char* title)
PuglStatus
puglSetFrame(PuglView* view, const PuglRect frame)
{
- PuglInternals* const impl = view->impl;
+ PuglInternals* const impl = view->impl;
+ const NSRect framePx = rectToNsRect(frame);
+ const NSRect framePt = nsRectToPoints(view, framePx);
- // Update view frame to exactly the requested frame in Pugl coordinates
+ // Update view frame to exactly the requested frame
view->frame = frame;
- const NSRect framePx = rectToNsRect(frame);
- const NSRect framePt = nsRectToPoints(view, framePx);
if (impl->window) {
- // Resize window to fit new content rect
const NSRect screenPt = rectToScreen(viewScreen(view), framePt);
- const NSRect winFrame = [impl->window frameRectForContentRect:screenPt];
+ // Move and resize window to fit new content rect
+ const NSRect winFrame = [impl->window frameRectForContentRect:screenPt];
[impl->window setFrame:winFrame display:NO];
+
+ // Resize views
+ const NSRect sizePx = NSMakeRect(0, 0, frame.width, frame.height);
+ const NSRect sizePt = [impl->drawView convertRectFromBacking:sizePx];
+ [impl->wrapperView setFrame:sizePt];
+ [impl->drawView setFrame:sizePt];
+ } else {
+ // Resize view
+ const NSRect sizePx = NSMakeRect(0, 0, frame.width, frame.height);
+ const NSRect sizePt = [impl->drawView convertRectFromBacking:sizePx];
+
+ [impl->wrapperView setFrame:framePt];
+ [impl->drawView setFrame:sizePt];
+ }
+
+ return PUGL_SUCCESS;
+}
+
+PuglStatus
+puglSetPosition(PuglView* const view, const int x, const int y)
+{
+ if (x > INT16_MAX || y > INT16_MAX) {
+ return PUGL_BAD_PARAMETER;
+ }
+
+ const PuglRect frame = {
+ (PuglCoord)x, (PuglCoord)y, view->frame.height, view->frame.height};
+
+ PuglInternals* const impl = view->impl;
+ if (impl->window) {
+ return puglSetFrame(view, frame);
}
- // Resize views
- const NSRect sizePx = NSMakeRect(0, 0, frame.width, frame.height);
- const NSRect sizePt = [impl->drawView convertRectFromBacking:sizePx];
+ const NSRect framePx = rectToNsRect(frame);
+ const NSRect framePt = nsRectToPoints(view, framePx);
+ [impl->wrapperView setFrameOrigin:framePt.origin];
+
+ const NSRect drawPx = NSMakeRect(0, 0, frame.width, frame.height);
+ const NSRect drawPt = [impl->drawView convertRectFromBacking:drawPx];
+ [impl->drawView setFrameOrigin:drawPt.origin];
- [impl->wrapperView setFrame:(impl->window ? sizePt : framePt)];
- [impl->drawView setFrame:sizePt];
+ view->frame = frame;
+ return PUGL_SUCCESS;
+}
+
+PuglStatus
+puglSetSize(PuglView* const view, const unsigned width, const unsigned height)
+{
+ if (width > INT16_MAX || height > INT16_MAX) {
+ return PUGL_BAD_PARAMETER;
+ }
+ const PuglRect frame = {
+ view->frame.x, view->frame.y, (PuglSpan)width, (PuglSpan)height};
+
+ PuglInternals* const impl = view->impl;
+ if (impl->window) {
+ return puglSetFrame(view, frame);
+ }
+
+ const NSRect framePx = rectToNsRect(frame);
+ const NSRect framePt = nsRectToPoints(view, framePx);
+ [impl->wrapperView setFrameSize:framePt.size];
+
+ const NSRect drawPx = NSMakeRect(0, 0, frame.width, frame.height);
+ const NSRect drawPt = [impl->drawView convertRectFromBacking:drawPx];
+ [impl->drawView setFrameSize:drawPt.size];
+
+ view->frame = frame;
return PUGL_SUCCESS;
}
diff --git a/src/win.c b/src/win.c
index 34f46d9..26dd4c8 100644
--- a/src/win.c
+++ b/src/win.c
@@ -984,17 +984,27 @@ puglSetWindowTitle(PuglView* view, const char* title)
return PUGL_SUCCESS;
}
+static RECT
+adjustedWindowRect(PuglView* const view,
+ const long x,
+ const long y,
+ const long width,
+ const long height)
+{
+ const unsigned flags = puglWinGetWindowFlags(view);
+ const unsigned exFlags = puglWinGetWindowExFlags(view);
+
+ RECT rect = {(long)x, (long)y, (long)x + (long)width, (long)y + (long)height};
+ AdjustWindowRectEx(&rect, flags, FALSE, exFlags);
+ return rect;
+}
+
PuglStatus
puglSetFrame(PuglView* view, const PuglRect frame)
{
if (view->impl->hwnd) {
- RECT rect = {(long)frame.x,
- (long)frame.y,
- (long)frame.x + (long)frame.width,
- (long)frame.y + (long)frame.height};
-
- AdjustWindowRectEx(
- &rect, puglWinGetWindowFlags(view), FALSE, puglWinGetWindowExFlags(view));
+ const RECT rect =
+ adjustedWindowRect(view, frame.x, frame.y, frame.width, frame.height);
if (!SetWindowPos(view->impl->hwnd,
HWND_TOP,
@@ -1012,12 +1022,68 @@ puglSetFrame(PuglView* view, const PuglRect frame)
}
PuglStatus
+puglSetPosition(PuglView* const view, const int x, const int y)
+{
+ if (x > INT16_MAX || y > INT16_MAX) {
+ return PUGL_BAD_PARAMETER;
+ }
+
+ if (view->impl->hwnd) {
+ const RECT rect =
+ adjustedWindowRect(view, x, y, view->frame.width, view->frame.height);
+
+ if (!SetWindowPos(view->impl->hwnd,
+ HWND_TOP,
+ rect.left,
+ rect.top,
+ 0,
+ 0,
+ SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER |
+ SWP_NOSIZE)) {
+ return PUGL_UNKNOWN_ERROR;
+ }
+ }
+
+ view->frame.x = (PuglCoord)x;
+ view->frame.y = (PuglCoord)y;
+ return PUGL_SUCCESS;
+}
+
+PuglStatus
+puglSetSize(PuglView* const view, const unsigned width, const unsigned height)
+{
+ if (width > INT16_MAX || height > INT16_MAX) {
+ return PUGL_BAD_PARAMETER;
+ }
+
+ if (view->impl->hwnd) {
+ const RECT rect = adjustedWindowRect(
+ view, view->frame.x, view->frame.y, (long)width, (long)height);
+
+ if (!SetWindowPos(view->impl->hwnd,
+ HWND_TOP,
+ 0,
+ 0,
+ rect.right - rect.left,
+ rect.bottom - rect.top,
+ SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER |
+ SWP_NOMOVE)) {
+ return PUGL_UNKNOWN_ERROR;
+ }
+ }
+
+ view->frame.width = (PuglSpan)width;
+ view->frame.height = (PuglSpan)height;
+ return PUGL_SUCCESS;
+}
+
+PuglStatus
puglSetSizeHint(PuglView* const view,
const PuglSizeHint hint,
const PuglSpan width,
const PuglSpan height)
{
- if ((unsigned)hint > (unsigned)PUGL_MAX_ASPECT || width < 0 || height < 0) {
+ if ((unsigned)hint > (unsigned)PUGL_MAX_ASPECT) {
return PUGL_BAD_PARAMETER;
}
diff --git a/src/x11.c b/src/x11.c
index f5a5461..5ae6b12 100644
--- a/src/x11.c
+++ b/src/x11.c
@@ -1026,11 +1026,15 @@ mergeExposeEvents(PuglExposeEvent* const dst, const PuglExposeEvent* const src)
if (!dst->type) {
*dst = *src;
} else {
- const double max_x = MAX(dst->x + dst->width, src->x + src->width);
- const double max_y = MAX(dst->y + dst->height, src->y + src->height);
-
- dst->x = MIN(dst->x, src->x);
- dst->y = MIN(dst->y, src->y);
+ const int dst_r = dst->x + dst->width;
+ const int src_r = src->x + src->width;
+ const int max_x = MAX(dst_r, src_r);
+ const int dst_b = dst->y + dst->height;
+ const int src_b = src->y + src->height;
+ const int max_y = MAX(dst_b, src_b);
+
+ dst->x = (PuglCoord)MIN(dst->x, src->x);
+ dst->y = (PuglCoord)MIN(dst->y, src->y);
dst->width = (PuglSpan)(max_x - dst->x);
dst->height = (PuglSpan)(max_y - dst->y);
}
@@ -1382,6 +1386,45 @@ puglSetFrame(PuglView* const view, const PuglRect frame)
}
PuglStatus
+puglSetPosition(PuglView* const view, const int x, const int y)
+{
+ Display* const display = view->world->impl->display;
+ const Window win = view->impl->win;
+
+ if (x > INT16_MAX || y > INT16_MAX) {
+ return PUGL_BAD_PARAMETER;
+ }
+
+ if (win && !XMoveWindow(display, win, x, y)) {
+ return PUGL_UNKNOWN_ERROR;
+ }
+
+ view->frame.x = (PuglCoord)x;
+ view->frame.y = (PuglCoord)y;
+ return PUGL_SUCCESS;
+}
+
+PuglStatus
+puglSetSize(PuglView* const view, const unsigned width, const unsigned height)
+{
+ Display* const display = view->world->impl->display;
+ const Window win = view->impl->win;
+
+ if (width > INT16_MAX || height > INT16_MAX) {
+ return PUGL_BAD_PARAMETER;
+ }
+
+ if (win) {
+ return XResizeWindow(display, win, width, height) ? PUGL_SUCCESS
+ : PUGL_UNKNOWN_ERROR;
+ }
+
+ view->frame.width = (PuglSpan)width;
+ view->frame.height = (PuglSpan)height;
+ return PUGL_SUCCESS;
+}
+
+PuglStatus
puglSetSizeHint(PuglView* const view,
const PuglSizeHint hint,
const PuglSpan width,