From 82405e8c177de446d03c340b4b6876370d79883a Mon Sep 17 00:00:00 2001 From: David Robillard Date: Fri, 20 May 2022 19:44:23 -0400 Subject: 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). --- src/mac.m | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--------- src/win.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++------- src/x11.c | 53 +++++++++++++++++++++++++++++++++++++---- 3 files changed, 193 insertions(+), 24 deletions(-) (limited to 'src') 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, @@ -1011,13 +1021,69 @@ puglSetFrame(PuglView* view, const PuglRect frame) 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; + } + + 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); } @@ -1381,6 +1385,45 @@ puglSetFrame(PuglView* const view, const PuglRect frame) return PUGL_SUCCESS; } +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, -- cgit v1.2.1