aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common.c28
-rw-r--r--src/internal.c19
-rw-r--r--src/mac.h3
-rw-r--r--src/mac.m229
-rw-r--r--src/mac_cairo.m4
-rw-r--r--src/mac_stub.m7
-rw-r--r--src/types.h3
-rw-r--r--src/win.c149
-rw-r--r--src/win_cairo.c6
-rw-r--r--src/x11.c130
10 files changed, 364 insertions, 214 deletions
diff --git a/src/common.c b/src/common.c
index 5c39b39..20e844a 100644
--- a/src/common.c
+++ b/src/common.c
@@ -10,7 +10,9 @@
#include "pugl/pugl.h"
+#include <limits.h>
#include <stdbool.h>
+#include <stdint.h>
#include <stdlib.h>
#include <string.h>
@@ -124,6 +126,8 @@ puglNewView(PuglWorld* const world)
view->world = world;
view->sizeHints[PUGL_MIN_SIZE].width = 1;
view->sizeHints[PUGL_MIN_SIZE].height = 1;
+ view->defaultX = INT_MIN;
+ view->defaultY = INT_MIN;
puglSetDefaultHints(view->hints);
@@ -237,7 +241,29 @@ puglGetViewHint(const PuglView* view, PuglViewHint hint)
PuglRect
puglGetFrame(const PuglView* view)
{
- return view->frame;
+ if (view->lastConfigure.type == PUGL_CONFIGURE) {
+ // Return the last configured frame
+ const PuglRect frame = {view->lastConfigure.x,
+ view->lastConfigure.y,
+ view->lastConfigure.width,
+ view->lastConfigure.height};
+ return frame;
+ }
+
+ // Get the default position if set, or fallback to (0, 0)
+ int x = view->defaultX;
+ int y = view->defaultY;
+ if (x < INT16_MIN || x > INT16_MAX || y < INT16_MIN || y > INT16_MAX) {
+ x = 0;
+ y = 0;
+ }
+
+ // Return the default frame, sanitized if necessary
+ const PuglRect frame = {(PuglCoord)x,
+ (PuglCoord)y,
+ view->sizeHints[PUGL_DEFAULT_SIZE].width,
+ view->sizeHints[PUGL_DEFAULT_SIZE].height};
+ return frame;
}
const char*
diff --git a/src/internal.c b/src/internal.c
index cfb444e..2da5e9e 100644
--- a/src/internal.c
+++ b/src/internal.c
@@ -122,15 +122,10 @@ puglPreRealize(PuglView* const view)
return PUGL_BAD_CONFIGURATION;
}
- // Set the size to the default if it hasn't already been set
- if (!isValidSize(view->frame.width, view->frame.height)) {
- const PuglViewSize defaultSize = view->sizeHints[PUGL_DEFAULT_SIZE];
- if (!isValidSize(defaultSize.width, defaultSize.height)) {
- return PUGL_BAD_CONFIGURATION;
- }
-
- view->frame.width = defaultSize.width;
- view->frame.height = defaultSize.height;
+ // Ensure that the default size is set to a valid size
+ const PuglViewSize defaultSize = view->sizeHints[PUGL_DEFAULT_SIZE];
+ if (!isValidSize(defaultSize.width, defaultSize.height)) {
+ return PUGL_BAD_CONFIGURATION;
}
return PUGL_SUCCESS;
@@ -159,12 +154,6 @@ puglConfigure(PuglView* view, const PuglEvent* event)
PuglStatus st = PUGL_SUCCESS;
assert(event->type == PUGL_CONFIGURE);
-
- view->frame.x = event->configure.x;
- view->frame.y = event->configure.y;
- view->frame.width = event->configure.width;
- view->frame.height = event->configure.height;
-
if (puglMustConfigure(view, &event->configure)) {
st = view->eventFunc(view, event);
view->lastConfigure = event->configure;
diff --git a/src/mac.h b/src/mac.h
index 7473231..119e7c8 100644
--- a/src/mac.h
+++ b/src/mac.h
@@ -21,9 +21,6 @@
@end
@interface PuglWindow : NSWindow
-
-- (void)setPuglview:(PuglView*)view;
-
@end
struct PuglWorldInternalsImpl {
diff --git a/src/mac.m b/src/mac.m
index 7b4e3a2..ca1ec4d 100644
--- a/src/mac.m
+++ b/src/mac.m
@@ -163,27 +163,6 @@ sizePoints(PuglView* view, const double width, const double height)
return NSMakeSize(width / scaleFactor, height / scaleFactor);
}
-static void
-updateViewRect(PuglView* view)
-{
- NSWindow* const window = view->impl->window;
- if (window) {
- const NSRect screenFramePt = [[NSScreen mainScreen] frame];
- const NSRect screenFramePx = nsRectFromPoints(view, screenFramePt);
- const NSRect framePt = [window frame];
- const NSRect contentPt = [window contentRectForFrameRect:framePt];
- const NSRect contentPx = nsRectFromPoints(view, contentPt);
- const double screenHeight = screenFramePx.size.height;
-
- view->frame.x = (PuglCoord)contentPx.origin.x;
- view->frame.y =
- (PuglCoord)(screenHeight - contentPx.origin.y - contentPx.size.height);
-
- view->frame.width = (PuglSpan)contentPx.size.width;
- view->frame.height = (PuglSpan)contentPx.size.height;
- }
-}
-
static PuglViewStyleFlags
getCurrentViewStyleFlags(PuglView* const view)
{
@@ -207,6 +186,32 @@ getCurrentViewStyleFlags(PuglView* const view)
(isResizing ? PUGL_VIEW_STYLE_RESIZING : 0U);
}
+PuglStatus
+dispatchCurrentChildViewConfiguration(PuglView* const view)
+{
+ const NSRect framePt = [view->impl->wrapperView frame];
+ const NSRect framePx = nsRectFromPoints(view, framePt);
+
+ if (view->stage < PUGL_VIEW_STAGE_REALIZED) {
+ return PUGL_SUCCESS;
+ }
+
+ const PuglConfigureEvent ev = {
+ PUGL_CONFIGURE,
+ 0,
+ (PuglCoord)framePx.origin.x,
+ (PuglCoord)framePx.origin.y,
+ (PuglSpan)framePx.size.width,
+ (PuglSpan)framePx.size.height,
+ getCurrentViewStyleFlags(view),
+ };
+
+ PuglEvent configureEvent;
+ configureEvent.configure = ev;
+
+ return puglDispatchEvent(view, &configureEvent);
+}
+
@implementation PuglWindow {
@public
PuglView* puglview;
@@ -228,22 +233,26 @@ getCurrentViewStyleFlags(PuglView* const view)
return (PuglWindow*)result;
}
-- (void)setPuglview:(PuglView*)view
+- (PuglStatus)dispatchCurrentConfiguration
{
- puglview = view;
+ if (puglview->stage < PUGL_VIEW_STAGE_REALIZED) {
+ return PUGL_SUCCESS;
+ }
- [self setContentSize:sizePoints(view, view->frame.width, view->frame.height)];
-}
+ const NSRect screenFramePt = [[NSScreen mainScreen] frame];
+ const NSRect screenFramePx = nsRectFromPoints(puglview, screenFramePt);
+ const NSRect framePt = [self frame];
+ const NSRect contentPt = [self contentRectForFrameRect:framePt];
+ const NSRect contentPx = nsRectFromPoints(puglview, contentPt);
+ const double screenHeight = screenFramePx.size.height;
-- (PuglStatus)dispatchCurrentConfiguration
-{
const PuglConfigureEvent ev = {
PUGL_CONFIGURE,
0,
- puglview->frame.x,
- puglview->frame.y,
- puglview->frame.width,
- puglview->frame.height,
+ (PuglCoord)contentPx.origin.x,
+ (PuglCoord)(screenHeight - contentPx.origin.y - contentPx.size.height),
+ (PuglSpan)contentPx.size.width,
+ (PuglSpan)contentPx.size.height,
getCurrentViewStyleFlags(puglview),
};
@@ -304,21 +313,11 @@ getCurrentViewStyleFlags(PuglView* const view)
const double scaleFactor = [[NSScreen mainScreen] backingScaleFactor];
if (reshaped) {
- updateViewRect(puglview);
-
- const PuglConfigureEvent ev = {
- PUGL_CONFIGURE,
- 0,
- puglview->frame.x,
- puglview->frame.y,
- puglview->frame.width,
- puglview->frame.height,
- getCurrentViewStyleFlags(puglview),
- };
-
- PuglEvent configureEvent;
- configureEvent.configure = ev;
- puglDispatchEvent(puglview, &configureEvent);
+ if (puglview->impl->window) {
+ [puglview->impl->window dispatchCurrentConfiguration];
+ } else {
+ dispatchCurrentChildViewConfiguration(puglview);
+ }
reshaped = false;
}
@@ -944,7 +943,7 @@ handleCrossing(PuglWrapperView* view, NSEvent* event, const PuglEventType type)
{
(void)notification;
- updateViewRect(window->puglview);
+ [window dispatchCurrentConfiguration];
}
- (void)windowDidBecomeKey:(NSNotification*)notification
@@ -1120,9 +1119,29 @@ updateSizeHints(PuglView* const view)
}
}
-static void
-puglMacSetDefaultPosition(PuglView* const view)
+static PuglRect
+getInitialFrame(PuglView* const view)
{
+ if (view->lastConfigure.type == PUGL_CONFIGURE) {
+ // Use the last configured frame
+ const PuglRect frame = {view->lastConfigure.x,
+ view->lastConfigure.y,
+ view->lastConfigure.width,
+ view->lastConfigure.height};
+ return frame;
+ }
+
+ const int x = view->defaultX;
+ const int y = view->defaultY;
+ if (x >= INT16_MIN && x <= INT16_MAX && y >= INT16_MIN && y <= INT16_MAX) {
+ // Use the default position set with puglSetPosition while unrealized
+ const PuglRect frame = {(PuglCoord)x,
+ (PuglCoord)y,
+ view->sizeHints[PUGL_DEFAULT_SIZE].width,
+ view->sizeHints[PUGL_DEFAULT_SIZE].height};
+ return frame;
+ }
+
// Get a bounding rect from the transient parent or the screen
const NSScreen* const screen = viewScreen(view);
const NSRect boundsPt =
@@ -1132,11 +1151,16 @@ puglMacSetDefaultPosition(PuglView* const view)
: [screen frame]);
// Center the frame around the center of the bounding rectangle
- const NSRect boundsPx = nsRectFromPoints(view, boundsPt);
- const double centerX = boundsPx.origin.x + boundsPx.size.width / 2;
- const double centerY = boundsPx.origin.y + boundsPx.size.height / 2;
- view->frame.x = (PuglCoord)(centerX - (view->frame.width / 2U));
- view->frame.y = (PuglCoord)(centerY - (view->frame.height / 2U));
+ const PuglViewSize defaultSize = view->sizeHints[PUGL_DEFAULT_SIZE];
+ const NSRect boundsPx = nsRectFromPoints(view, boundsPt);
+ const double centerX = boundsPx.origin.x + boundsPx.size.width / 2;
+ const double centerY = boundsPx.origin.y + boundsPx.size.height / 2;
+
+ const PuglRect frame = {(PuglCoord)(centerX - (defaultSize.width / 2U)),
+ (PuglCoord)(centerY - (defaultSize.height / 2U)),
+ view->sizeHints[PUGL_DEFAULT_SIZE].width,
+ view->sizeHints[PUGL_DEFAULT_SIZE].height};
+ return frame;
}
PuglStatus
@@ -1184,12 +1208,11 @@ puglRealize(PuglView* view)
CVDisplayLinkRelease(link);
}
- // Center top-level windows if a position has not been set
- if (!view->parent && !view->frame.x && !view->frame.y) {
- puglMacSetDefaultPosition(view);
- }
+ // Get the initial frame to use from the defaults or last configuration
+ const PuglRect initialFrame = getInitialFrame(view);
- const NSRect framePx = rectToNsRect(view->frame);
+ // Convert frame to points
+ const NSRect framePx = rectToNsRect(initialFrame);
const NSRect framePt = NSMakeRect(framePx.origin.x / scaleFactor,
framePx.origin.y / scaleFactor,
framePx.size.width / scaleFactor,
@@ -1258,7 +1281,10 @@ puglRealize(PuglView* view)
styleMask:style
backing:NSBackingStoreBuffered
defer:NO] retain];
- [window setPuglview:view];
+
+ window->puglview = view;
+ impl->window = window;
+ [window setContentSize:framePt.size];
if (view->title) {
NSString* titleString =
@@ -1272,10 +1298,9 @@ puglRealize(PuglView* view)
((NSWindow*)window).delegate =
[[PuglWindowDelegate alloc] initWithPuglWindow:window];
- impl->window = window;
-
updateSizeHints(view);
- puglSetFrame(view, view->frame);
+
+ puglSetFrame(view, initialFrame);
if (view->transientParent) {
puglSetTransientParent(view, view->transientParent);
}
@@ -1342,7 +1367,6 @@ puglShow(PuglView* view, const PuglShowCommand command)
if (![window isVisible]) {
[window setIsVisible:YES];
[view->impl->drawView setNeedsDisplay:YES];
- updateViewRect(view);
}
switch (command) {
@@ -1688,8 +1712,14 @@ puglSetFrame(PuglView* view, const PuglRect frame)
const NSRect framePx = rectToNsRect(frame);
const NSRect framePt = nsRectToPoints(view, framePx);
- // Update view frame to exactly the requested frame
- view->frame = frame;
+ if (!impl->wrapperView) {
+ // Set defaults to be used when realized
+ view->defaultX = frame.x;
+ view->defaultY = frame.y;
+ view->sizeHints[PUGL_DEFAULT_SIZE].width = (PuglSpan)frame.width;
+ view->sizeHints[PUGL_DEFAULT_SIZE].height = (PuglSpan)frame.height;
+ return PUGL_SUCCESS;
+ }
if (impl->window) {
const NSRect screenPt = rectToScreen(viewScreen(view), framePt);
@@ -1703,16 +1733,17 @@ puglSetFrame(PuglView* view, const PuglRect frame)
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];
+ [impl->window dispatchCurrentConfiguration];
+ return PUGL_SUCCESS;
}
- return PUGL_SUCCESS;
+ // 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 dispatchCurrentChildViewConfiguration(view);
}
PuglStatus
@@ -1722,24 +1753,36 @@ puglSetPosition(PuglView* const view, const int x, const int y)
return PUGL_BAD_PARAMETER;
}
- const PuglRect frame = {
- (PuglCoord)x, (PuglCoord)y, view->frame.height, view->frame.height};
-
PuglInternals* const impl = view->impl;
+ if (!impl->wrapperView) {
+ // Set defaults to be used when realized
+ view->defaultX = x;
+ view->defaultY = y;
+ return PUGL_SUCCESS;
+ }
+
+ const PuglRect frame = {(PuglCoord)x,
+ (PuglCoord)y,
+ view->lastConfigure.width,
+ view->lastConfigure.height};
+
if (impl->window) {
+ // Adjust top-level window frame
return puglSetFrame(view, frame);
}
+ // Set wrapper view origin
const NSRect framePx = rectToNsRect(frame);
const NSRect framePt = nsRectToPoints(view, framePx);
[impl->wrapperView setFrameOrigin:framePt.origin];
+ // Set draw view origin
const NSRect drawPx = NSMakeRect(0, 0, frame.width, frame.height);
const NSRect drawPt = [impl->drawView convertRectFromBacking:drawPx];
[impl->drawView setFrameOrigin:drawPt.origin];
- view->frame = frame;
- return PUGL_SUCCESS;
+ // Dispatch new configuration
+ return dispatchCurrentChildViewConfiguration(view);
}
PuglStatus
@@ -1749,24 +1792,34 @@ puglSetSize(PuglView* const view, const unsigned width, const unsigned height)
return PUGL_BAD_PARAMETER;
}
- const PuglRect frame = {
- view->frame.x, view->frame.y, (PuglSpan)width, (PuglSpan)height};
-
PuglInternals* const impl = view->impl;
+ if (!impl->wrapperView) {
+ // Set defaults to be used when realized
+ view->sizeHints[PUGL_DEFAULT_SIZE].width = (PuglSpan)width;
+ view->sizeHints[PUGL_DEFAULT_SIZE].height = (PuglSpan)height;
+ return PUGL_SUCCESS;
+ }
+
if (impl->window) {
+ // Adjust top-level window frame
+ PuglRect frame = puglGetFrame(view);
+ frame.width = (PuglSpan)width;
+ frame.height = (PuglSpan)height;
return puglSetFrame(view, frame);
}
- const NSRect framePx = rectToNsRect(frame);
- const NSRect framePt = nsRectToPoints(view, framePx);
- [impl->wrapperView setFrameSize:framePt.size];
+ // Set wrapper view size
+ const double scaleFactor = [viewScreen(view) backingScaleFactor];
+ const CGSize frameSizePt = {width / scaleFactor, height / scaleFactor};
+ [impl->wrapperView setFrameSize:frameSizePt];
- const NSRect drawPx = NSMakeRect(0, 0, frame.width, frame.height);
+ // Set draw view size
+ const NSRect drawPx = NSMakeRect(0, 0, width, height);
const NSRect drawPt = [impl->drawView convertRectFromBacking:drawPx];
[impl->drawView setFrameSize:drawPt.size];
- view->frame = frame;
- return PUGL_SUCCESS;
+ // Dispatch new configuration
+ return dispatchCurrentChildViewConfiguration(view);
}
PuglStatus
diff --git a/src/mac_cairo.m b/src/mac_cairo.m
index 66af5ba..8e28985 100644
--- a/src/mac_cairo.m
+++ b/src/mac_cairo.m
@@ -90,8 +90,8 @@ puglMacCairoEnter(PuglView* view, const PuglExposeEvent* expose)
CGContextRef context =
(CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
- const CGSize sizePx = {(CGFloat)view->frame.width,
- (CGFloat)view->frame.height};
+ const CGSize sizePx = {(CGFloat)view->lastConfigure.width,
+ (CGFloat)view->lastConfigure.height};
const CGSize sizePt = CGContextConvertSizeToUserSpace(context, sizePx);
diff --git a/src/mac_stub.m b/src/mac_stub.m
index ceffa6e..9ebedca 100644
--- a/src/mac_stub.m
+++ b/src/mac_stub.m
@@ -41,8 +41,11 @@ puglMacStubCreate(PuglView* view)
PuglStubView* drawView = [PuglStubView alloc];
drawView->puglview = view;
- [drawView
- initWithFrame:NSMakeRect(0, 0, view->frame.width, view->frame.height)];
+ [drawView initWithFrame:NSMakeRect(0,
+ 0,
+ view->lastConfigure.width,
+ view->lastConfigure.height)];
+
if (view->hints[PUGL_RESIZABLE]) {
[drawView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
} else {
diff --git a/src/types.h b/src/types.h
index da0a295..35f29c5 100644
--- a/src/types.h
+++ b/src/types.h
@@ -56,10 +56,11 @@ struct PuglViewImpl {
char* title;
PuglNativeView parent;
uintptr_t transientParent;
- PuglRect frame;
PuglConfigureEvent lastConfigure;
PuglHints hints;
PuglViewSize sizeHints[PUGL_NUM_SIZE_HINTS];
+ int defaultX;
+ int defaultY;
PuglViewStage stage;
bool resizing;
};
diff --git a/src/win.c b/src/win.c
index d8c574b..13184aa 100644
--- a/src/win.c
+++ b/src/win.c
@@ -153,7 +153,8 @@ puglWinGetMonitor(const PuglView* const view)
return MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY);
}
- const POINT point = {(long)view->frame.x, (long)view->frame.y};
+ const POINT point = {(long)view->lastConfigure.x,
+ (long)view->lastConfigure.y};
return MonitorFromPoint(point, MONITOR_DEFAULTTOPRIMARY);
}
@@ -289,7 +290,6 @@ puglRealize(PuglView* view)
view->impl->scaleFactor = puglWinGetViewScaleFactor(view);
view->impl->cursor = LoadCursor(NULL, IDC_ARROW);
- puglSetFrame(view, view->frame);
SetWindowLongPtr(impl->hwnd, GWLP_USERDATA, (LONG_PTR)view);
return puglDispatchSimpleEvent(view, PUGL_REALIZE);
@@ -589,12 +589,9 @@ handleConfigure(PuglView* view, PuglEvent* event)
const LONG width = rect.right - rect.left;
const LONG height = rect.bottom - rect.top;
- view->frame.x = (PuglCoord)rect.left;
- view->frame.y = (PuglCoord)rect.top;
-
event->configure.type = PUGL_CONFIGURE;
- event->configure.x = (PuglCoord)view->frame.x;
- event->configure.y = (PuglCoord)view->frame.y;
+ event->configure.x = (PuglCoord)rect.left;
+ event->configure.y = (PuglCoord)rect.top;
event->configure.width = (PuglSpan)width;
event->configure.height = (PuglSpan)height;
@@ -1200,23 +1197,27 @@ puglGetScaleFactor(const PuglView* const view)
PuglStatus
puglSetFrame(PuglView* view, const PuglRect frame)
{
- if (view->impl->hwnd) {
- const RECT rect =
- adjustedWindowRect(view, frame.x, frame.y, frame.width, frame.height);
+ if (!view->impl->hwnd) {
+ // Set defaults to be used when realized
+ view->defaultX = frame.x;
+ view->defaultY = frame.y;
+ view->sizeHints[PUGL_DEFAULT_SIZE].width = (PuglSpan)frame.width;
+ view->sizeHints[PUGL_DEFAULT_SIZE].height = (PuglSpan)frame.height;
+ return PUGL_SUCCESS;
+ }
+
+ const RECT rect =
+ adjustedWindowRect(view, frame.x, frame.y, frame.width, frame.height);
- if (!SetWindowPos(view->impl->hwnd,
+ return SetWindowPos(view->impl->hwnd,
HWND_TOP,
rect.left,
rect.top,
rect.right - rect.left,
rect.bottom - rect.top,
- SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER)) {
- return PUGL_UNKNOWN_ERROR;
- }
- }
-
- view->frame = frame;
- return PUGL_SUCCESS;
+ SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER)
+ ? PUGL_SUCCESS
+ : PUGL_UNKNOWN_ERROR;
}
PuglStatus
@@ -1226,25 +1227,26 @@ puglSetPosition(PuglView* const view, const int x, const int y)
return PUGL_BAD_PARAMETER;
}
- if (view->impl->hwnd) {
- const RECT rect =
- adjustedWindowRect(view, x, y, view->frame.width, view->frame.height);
+ if (!view->impl->hwnd) {
+ // Set defaults to be used when realized
+ view->defaultX = x;
+ view->defaultY = y;
+ return PUGL_SUCCESS;
+ }
+
+ const RECT rect = adjustedWindowRect(
+ view, x, y, view->lastConfigure.width, view->lastConfigure.height);
- if (!SetWindowPos(view->impl->hwnd,
+ return 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;
+ SWP_NOSIZE)
+ ? PUGL_SUCCESS
+ : PUGL_UNKNOWN_ERROR;
}
PuglStatus
@@ -1254,25 +1256,29 @@ puglSetSize(PuglView* const view, const unsigned width, const unsigned height)
return PUGL_BAD_PARAMETER;
}
- if (view->impl->hwnd) {
- const RECT rect = adjustedWindowRect(
- view, view->frame.x, view->frame.y, (long)width, (long)height);
+ if (!view->impl->hwnd) {
+ // Set defaults to be used when realized
+ view->sizeHints[PUGL_DEFAULT_SIZE].width = (PuglSpan)width;
+ view->sizeHints[PUGL_DEFAULT_SIZE].height = (PuglSpan)height;
+ return PUGL_SUCCESS;
+ }
+
+ const RECT rect = adjustedWindowRect(view,
+ view->lastConfigure.x,
+ view->lastConfigure.y,
+ (long)width,
+ (long)height);
- if (!SetWindowPos(view->impl->hwnd,
+ return 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;
+ SWP_NOMOVE)
+ ? PUGL_SUCCESS
+ : PUGL_UNKNOWN_ERROR;
}
PuglStatus
@@ -1502,19 +1508,42 @@ puglWinGetPixelFormatDescriptor(const PuglHints hints)
return pfd;
}
-static void
-puglWinSetDefaultPosition(PuglView* const view)
+static PuglRect
+getInitialFrame(PuglView* const view)
{
+ if (view->lastConfigure.type == PUGL_CONFIGURE) {
+ // Use the last configured frame
+ const PuglRect frame = {view->lastConfigure.x,
+ view->lastConfigure.y,
+ view->lastConfigure.width,
+ view->lastConfigure.height};
+ return frame;
+ }
+
+ const PuglSpan defaultWidth = view->sizeHints[PUGL_DEFAULT_SIZE].width;
+ const PuglSpan defaultHeight = view->sizeHints[PUGL_DEFAULT_SIZE].height;
+ const int x = view->defaultX;
+ const int y = view->defaultY;
+ if (x >= INT16_MIN && x <= INT16_MAX && y >= INT16_MIN && y <= INT16_MAX) {
+ // Use the default position set with puglSetPosition while unrealized
+ const PuglRect frame = {
+ (PuglCoord)x, (PuglCoord)y, defaultWidth, defaultHeight};
+ return frame;
+ }
+
// Get a bounding rect from the "nearest" parent or parent-like window
const HWND hwnd = puglWinGetWindow(view);
RECT rect = {0, 0, 0, 0};
GetWindowRect(hwnd ? hwnd : GetDesktopWindow(), &rect);
// Center the frame around the center of the bounding rectangle
- const LONG centerX = rect.left + (rect.right - rect.left) / 2;
- const LONG centerY = rect.top + (rect.bottom - rect.top) / 2;
- view->frame.x = (PuglCoord)(centerX - (view->frame.width / 2U));
- view->frame.y = (PuglCoord)(centerY - (view->frame.height / 2U));
+ const LONG centerX = rect.left + (rect.right - rect.left) / 2;
+ const LONG centerY = rect.top + (rect.bottom - rect.top) / 2;
+ const PuglRect frame = {(PuglCoord)(centerX - (defaultWidth / 2U)),
+ (PuglCoord)(centerY - (defaultHeight / 2U)),
+ defaultWidth,
+ defaultHeight};
+ return frame;
}
PuglStatus
@@ -1526,20 +1555,16 @@ puglWinCreateWindow(PuglView* const view,
const char* className = (const char*)view->world->className;
const unsigned winFlags = puglWinGetWindowFlags(view);
const unsigned winExFlags = puglWinGetWindowExFlags(view);
-
- // Center top-level windows if a position has not been set
- if (!view->parent && !view->frame.x && !view->frame.y) {
- puglWinSetDefaultPosition(view);
- }
+ const PuglRect frame = getInitialFrame(view);
// The meaning of "parent" depends on the window type (WS_CHILD)
PuglNativeView parent = view->parent ? view->parent : view->transientParent;
- // Calculate total window size to accommodate requested view size
- RECT wr = {(long)view->frame.x,
- (long)view->frame.y,
- (long)view->frame.width,
- (long)view->frame.height};
+ // Calculate initial window rectangle
+ RECT wr = {(long)frame.x,
+ (long)frame.y,
+ (long)frame.x + frame.width,
+ (long)frame.y + frame.height};
AdjustWindowRectEx(&wr, winFlags, FALSE, winExFlags);
// Create window and get drawing context
@@ -1558,6 +1583,14 @@ puglWinCreateWindow(PuglView* const view,
return PUGL_REALIZE_FAILED;
}
+ SetWindowPos(view->impl->hwnd,
+ HWND_TOP,
+ wr.left,
+ wr.top,
+ wr.right - wr.left,
+ wr.bottom - wr.top,
+ SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER);
+
if (!(*hdc = GetDC(*hwnd))) {
DestroyWindow(*hwnd);
*hwnd = NULL;
diff --git a/src/win_cairo.c b/src/win_cairo.c
index ddc9554..75c61db 100644
--- a/src/win_cairo.c
+++ b/src/win_cairo.c
@@ -27,7 +27,7 @@ puglWinCairoCreateDrawContext(PuglView* view)
surface->drawDc = CreateCompatibleDC(impl->hdc);
surface->drawBitmap = CreateCompatibleBitmap(
- impl->hdc, (int)view->frame.width, (int)view->frame.height);
+ impl->hdc, (int)view->lastConfigure.width, (int)view->lastConfigure.height);
DeleteObject(SelectObject(surface->drawDc, surface->drawBitmap));
@@ -126,8 +126,8 @@ puglWinCairoLeave(PuglView* view, const PuglExposeEvent* expose)
BitBlt(impl->hdc,
0,
0,
- (int)view->frame.width,
- (int)view->frame.height,
+ (int)view->lastConfigure.width,
+ (int)view->lastConfigure.height,
surface->drawDc,
0,
0,
diff --git a/src/x11.c b/src/x11.c
index f1a077b..2b9b0f6 100644
--- a/src/x11.c
+++ b/src/x11.c
@@ -374,13 +374,14 @@ updateSizeHints(const PuglView* const view)
XSizeHints sizeHints = PUGL_INIT_STRUCT;
if (!view->hints[PUGL_RESIZABLE]) {
+ const PuglRect frame = puglGetFrame(view);
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;
+ sizeHints.base_width = (int)frame.width;
+ sizeHints.base_height = (int)frame.height;
+ sizeHints.min_width = (int)frame.width;
+ sizeHints.min_height = (int)frame.height;
+ sizeHints.max_width = (int)frame.width;
+ sizeHints.max_height = (int)frame.height;
} else {
const PuglViewSize defaultSize = view->sizeHints[PUGL_DEFAULT_SIZE];
if (defaultSize.width && defaultSize.height) {
@@ -478,6 +479,50 @@ clearX11Clipboard(PuglX11Clipboard* const board)
board->data.len = 0;
}
+static PuglRect
+getInitialFrame(PuglView* const view)
+{
+ if (view->lastConfigure.type == PUGL_CONFIGURE) {
+ // Use the last configured frame
+ const PuglRect frame = {view->lastConfigure.x,
+ view->lastConfigure.y,
+ view->lastConfigure.width,
+ view->lastConfigure.height};
+ return frame;
+ }
+
+ const PuglSpan defaultWidth = view->sizeHints[PUGL_DEFAULT_SIZE].width;
+ const PuglSpan defaultHeight = view->sizeHints[PUGL_DEFAULT_SIZE].height;
+ const int x = view->defaultX;
+ const int y = view->defaultY;
+ if (x >= INT16_MIN && x <= INT16_MAX && y >= INT16_MIN && y <= INT16_MAX) {
+ // Use the default position set with puglSetPosition while unrealized
+ const PuglRect frame = {
+ (PuglCoord)x, (PuglCoord)y, defaultWidth, defaultHeight};
+ return frame;
+ }
+
+ // Get the best "parentish" window to position the window in
+ Display* const display = view->world->impl->display;
+ const Window parent =
+ (view->parent ? (Window)view->parent
+ : view->transientParent ? (Window)view->transientParent
+ : RootWindow(display, view->impl->screen));
+
+ // Get the position/size of the parent as bounds for the new window
+ XWindowAttributes parentAttrs = PUGL_INIT_STRUCT;
+ XGetWindowAttributes(display, parent, &parentAttrs);
+
+ // Center the frame within the parent bounds
+ const int centerX = parentAttrs.x + parentAttrs.width / 2;
+ const int centerY = parentAttrs.y + parentAttrs.height / 2;
+ const PuglRect frame = {(PuglCoord)(centerX - (defaultWidth / 2U)),
+ (PuglCoord)(centerY - (defaultHeight / 2U)),
+ defaultWidth,
+ defaultHeight};
+ return frame;
+}
+
PuglStatus
puglRealize(PuglView* const view)
{
@@ -501,15 +546,6 @@ puglRealize(PuglView* const view)
return st;
}
- // Center top-level windows if a position has not been set
- if (!view->parent && !view->frame.x && !view->frame.y) {
- const int screenWidth = DisplayWidth(display, screen);
- const int screenHeight = DisplayHeight(display, screen);
-
- view->frame.x = (PuglCoord)((screenWidth - view->frame.width) / 2);
- view->frame.y = (PuglCoord)((screenHeight - view->frame.height) / 2);
- }
-
// Configure the backend to get the visual info
impl->screen = screen;
if ((st = view->backend->configure(view)) || !impl->vi) {
@@ -534,13 +570,16 @@ puglRealize(PuglView* const view)
attr.event_mask |= StructureNotifyMask;
attr.event_mask |= VisibilityChangeMask;
+ // Calculate the initial window rectangle
+ const PuglRect initialFrame = getInitialFrame(view);
+
// Create the window
impl->win = XCreateWindow(display,
parent,
- view->frame.x,
- view->frame.y,
- view->frame.width,
- view->frame.height,
+ initialFrame.x,
+ initialFrame.y,
+ initialFrame.width,
+ initialFrame.height,
0,
impl->vi->depth,
InputOutput,
@@ -1762,7 +1801,9 @@ puglGetTime(const PuglWorld* const world)
PuglStatus
puglPostRedisplay(PuglView* const view)
{
- const PuglRect rect = {0, 0, view->frame.width, view->frame.height};
+ PuglRect rect = puglGetFrame(view);
+ rect.x = 0;
+ rect.y = 0;
return puglPostRedisplayRect(view, rect);
}
@@ -1824,57 +1865,64 @@ puglGetScaleFactor(const PuglView* const view)
PuglStatus
puglSetFrame(PuglView* const view, const PuglRect frame)
{
- if (view->impl->win) {
- if (!XMoveResizeWindow(view->world->impl->display,
+ if (!view->impl->win) {
+ // Set defaults to be used when realized
+ view->defaultX = frame.x;
+ view->defaultY = frame.y;
+ view->sizeHints[PUGL_DEFAULT_SIZE].width = frame.width;
+ view->sizeHints[PUGL_DEFAULT_SIZE].height = frame.height;
+ return PUGL_SUCCESS;
+ }
+
+ return XMoveResizeWindow(view->world->impl->display,
view->impl->win,
frame.x,
frame.y,
frame.width,
- frame.height)) {
- return PUGL_UNKNOWN_ERROR;
- }
- }
-
- view->frame = frame;
- return PUGL_SUCCESS;
+ frame.height)
+ ? PUGL_SUCCESS
+ : PUGL_UNKNOWN_ERROR;
}
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_MIN || x > INT16_MAX || y < INT16_MIN || y > INT16_MAX) {
return PUGL_BAD_PARAMETER;
}
- if (win && !XMoveWindow(display, win, x, y)) {
- return PUGL_UNKNOWN_ERROR;
+ if (!view->impl->win) {
+ // Set defaults to be used when realized
+ view->defaultX = x;
+ view->defaultY = y;
+ return PUGL_SUCCESS;
}
- view->frame.x = (PuglCoord)x;
- view->frame.y = (PuglCoord)y;
- return PUGL_SUCCESS;
+ return XMoveWindow(display, view->impl->win, x, y) ? PUGL_SUCCESS
+ : PUGL_UNKNOWN_ERROR;
}
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 && !XResizeWindow(display, win, width, height)) {
- return PUGL_UNKNOWN_ERROR;
+ if (!view->impl->win) {
+ // Set defaults to be used when realized
+ view->sizeHints[PUGL_DEFAULT_SIZE].width = (PuglSpan)width;
+ view->sizeHints[PUGL_DEFAULT_SIZE].height = (PuglSpan)height;
+ return PUGL_SUCCESS;
}
- view->frame.width = (PuglSpan)width;
- view->frame.height = (PuglSpan)height;
- return PUGL_SUCCESS;
+ return XResizeWindow(display, view->impl->win, width, height)
+ ? PUGL_SUCCESS
+ : PUGL_UNKNOWN_ERROR;
}
PuglStatus