aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/internal.c47
-rw-r--r--src/internal.h12
-rw-r--r--src/mac.m51
-rw-r--r--src/win.c61
-rw-r--r--src/x11.c84
5 files changed, 121 insertions, 134 deletions
diff --git a/src/internal.c b/src/internal.c
index 31345f3..38a595a 100644
--- a/src/internal.c
+++ b/src/internal.c
@@ -9,9 +9,17 @@
#include <assert.h>
#include <stdbool.h>
+#include <stdint.h>
#include <stdlib.h>
#include <string.h>
+static PuglPoint
+make_point(const PuglCoord x, const PuglCoord y)
+{
+ const PuglPoint point = {x, y};
+ return point;
+}
+
bool
puglIsValidPosition(const int x, const int y)
{
@@ -30,6 +38,45 @@ puglIsValidArea(const PuglArea size)
return size.width && size.height;
}
+PuglArea
+puglGetInitialSize(const PuglView* const view)
+{
+ if (view->lastConfigure.type == PUGL_CONFIGURE) {
+ // Use the last configured size
+ const PuglConfigureEvent config = view->lastConfigure;
+ const PuglArea size = {config.width, config.height};
+ return size;
+ }
+
+ // Use the default size hint set by the application
+ return view->sizeHints[PUGL_DEFAULT_SIZE];
+}
+
+PuglPoint
+puglGetInitialPosition(const PuglView* const view, const PuglArea size)
+{
+ if (view->lastConfigure.type == PUGL_CONFIGURE) {
+ // Use the last configured frame
+ return make_point(view->lastConfigure.x, view->lastConfigure.y);
+ }
+
+ if (puglIsValidPosition(view->defaultX, view->defaultY)) {
+ // Use the default position hint set by the application
+ return make_point((PuglCoord)view->defaultX, (PuglCoord)view->defaultY);
+ }
+
+ if (view->parent) {
+ // Default to the top/left origin of the parent
+ return make_point(0, 0);
+ }
+
+ // Center frame on a transient ancestor, or failing that, the screen
+ const PuglPoint center = puglGetAncestorCenter(view);
+ const PuglPoint pos = {(PuglCoord)(center.x - (size.width / 2)),
+ (PuglCoord)(center.y - (size.height / 2))};
+ return pos;
+}
+
void
puglEnsureHint(PuglView* const view, const PuglViewHint hint, const int value)
{
diff --git a/src/internal.h b/src/internal.h
index 8497c50..7387494 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -30,6 +30,18 @@ puglIsValidSize(unsigned x, unsigned y);
bool
puglIsValidArea(PuglArea size);
+/// Return the center point of some "soft" ancestor (parent window or screen)
+PuglPoint
+puglGetAncestorCenter(const PuglView* view);
+
+/// Return the initial size of a view
+PuglArea
+puglGetInitialSize(const PuglView* view);
+
+/// Return the initial position of a view if known, or an invalid position
+PuglPoint
+puglGetInitialPosition(const PuglView* view, PuglArea size);
+
/// Set hint to a default value if it is unset (PUGL_DONT_CARE)
void
puglEnsureHint(PuglView* view, PuglViewHint hint, int value);
diff --git a/src/mac.m b/src/mac.m
index b5b617b..2f43ace 100644
--- a/src/mac.m
+++ b/src/mac.m
@@ -121,7 +121,7 @@ viewScreen(const PuglView* view)
}
static NSRect
-nsRectToPoints(PuglView* view, const NSRect rect)
+nsRectToPoints(const PuglView* view, const NSRect rect)
{
const double scaleFactor = [viewScreen(view) backingScaleFactor];
@@ -132,7 +132,7 @@ nsRectToPoints(PuglView* view, const NSRect rect)
}
static NSRect
-nsRectFromPoints(PuglView* view, const NSRect rect)
+nsRectFromPoints(const PuglView* view, const NSRect rect)
{
const double scaleFactor = [viewScreen(view) backingScaleFactor];
@@ -143,7 +143,7 @@ nsRectFromPoints(PuglView* view, const NSRect rect)
}
static NSPoint
-nsPointFromPoints(PuglView* view, const NSPoint point)
+nsPointFromPoints(const PuglView* view, const NSPoint point)
{
const double scaleFactor = [viewScreen(view) backingScaleFactor];
@@ -1153,30 +1153,9 @@ updateSizeHints(PuglView* const view)
}
}
-static PuglRect
-getInitialFrame(PuglView* const view)
+PuglPoint
+puglGetAncestorCenter(const 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 (puglIsValidPosition(x, y)) {
- // 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 =
rectFromScreen(screen,
@@ -1184,17 +1163,11 @@ getInitialFrame(PuglView* const view)
? [[(const NSView*)view->transientParent window] frame]
: [screen frame]);
- // Center the frame around the center of the bounding rectangle
- const PuglArea 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;
+ const NSRect boundsPx = nsRectFromPoints(view, boundsPt);
+ const PuglPoint center = {
+ (PuglCoord)(boundsPx.origin.x + boundsPx.size.width / 2.0),
+ (PuglCoord)(boundsPx.origin.y + boundsPx.size.height / 2.0)};
+ return center;
}
PuglStatus
@@ -1243,7 +1216,9 @@ puglRealize(PuglView* view)
}
// Get the initial frame to use from the defaults or last configuration
- const PuglRect initialFrame = getInitialFrame(view);
+ const PuglArea size = puglGetInitialSize(view);
+ const PuglPoint pos = puglGetInitialPosition(view, size);
+ const PuglRect initialFrame = {pos.x, pos.y, size.width, size.height};
// Convert frame to points
const NSRect framePx = rectToNsRect(initialFrame);
diff --git a/src/win.c b/src/win.c
index 1efc9a2..d9f1b75 100644
--- a/src/win.c
+++ b/src/win.c
@@ -1576,42 +1576,18 @@ puglWinGetPixelFormatDescriptor(const PuglHints hints)
return pfd;
}
-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 (puglIsValidPosition(x, y)) {
- // 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);
+PuglPoint
+puglGetAncestorCenter(const PuglView* const view)
+{
+ RECT rect = {0, 0, 0, 0};
+ GetWindowRect(view->transientParent ? (HWND)view->transientParent
+ : 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;
- const PuglRect frame = {(PuglCoord)(centerX - (defaultWidth / 2)),
- (PuglCoord)(centerY - (defaultHeight / 2)),
- defaultWidth,
- defaultHeight};
- return frame;
+ const PuglPoint center = {
+ (PuglCoord)(rect.left + (rect.right - rect.left) / 2),
+ (PuglCoord)(rect.top + (rect.bottom - rect.top) / 2)};
+ return center;
}
PuglStatus
@@ -1626,13 +1602,14 @@ puglWinCreateWindow(PuglView* const view,
PuglNativeView parent = view->parent ? view->parent : view->transientParent;
// Calculate initial window rectangle
- const unsigned winFlags = puglWinGetWindowFlags(view);
- const unsigned winExFlags = puglWinGetWindowExFlags(view);
- const PuglRect frame = getInitialFrame(view);
- RECT wr = {(long)frame.x,
- (long)frame.y,
- (long)frame.x + frame.width,
- (long)frame.y + frame.height};
+ const unsigned winFlags = puglWinGetWindowFlags(view);
+ const unsigned winExFlags = puglWinGetWindowExFlags(view);
+ const PuglArea size = puglGetInitialSize(view);
+ const PuglPoint pos = puglGetInitialPosition(view, size);
+ RECT wr = {(long)pos.x,
+ (long)pos.y,
+ (long)pos.x + size.width,
+ (long)pos.y + size.height};
AdjustWindowRectEx(&wr, winFlags, FALSE, winExFlags);
ArgStringChar* const classNameArg = puglArgStringNew(className);
diff --git a/src/x11.c b/src/x11.c
index 6e9d6c0..8c388a7 100644
--- a/src/x11.c
+++ b/src/x11.c
@@ -510,48 +510,21 @@ 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 (puglIsValidPosition(x, y)) {
- // 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);
+PuglPoint
+puglGetAncestorCenter(const PuglView* const view)
+{
+ Display* const display = view->world->impl->display;
+ const int screen = view->impl->screen;
+ XWindowAttributes ancestorAttrs = PUGL_INIT_STRUCT;
+ XGetWindowAttributes(display,
+ view->transientParent ? (Window)view->transientParent
+ : RootWindow(display, screen),
+ &ancestorAttrs);
- // 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 / 2)),
- (PuglCoord)(centerY - (defaultHeight / 2)),
- defaultWidth,
- defaultHeight};
- return frame;
+ const PuglPoint center = {
+ (PuglCoord)(ancestorAttrs.x + ancestorAttrs.width / 2),
+ (PuglCoord)(ancestorAttrs.y + ancestorAttrs.height / 2)};
+ return center;
}
PuglStatus
@@ -606,16 +579,17 @@ puglRealize(PuglView* const view)
attr.event_mask |= StructureNotifyMask;
attr.event_mask |= VisibilityChangeMask;
- // Calculate the initial window rectangle
- const PuglRect initialFrame = getInitialFrame(view);
+ // Calculate the initial window frame
+ const PuglArea initialSize = puglGetInitialSize(view);
+ const PuglPoint initialPos = puglGetInitialPosition(view, initialSize);
// Create the window
impl->win = XCreateWindow(display,
parent,
- initialFrame.x,
- initialFrame.y,
- initialFrame.width,
- initialFrame.height,
+ initialPos.x,
+ initialPos.y,
+ initialSize.width,
+ initialSize.height,
0,
impl->vi->depth,
InputOutput,
@@ -1099,17 +1073,19 @@ getCurrentConfiguration(PuglView* const view)
XWindowAttributes attrs;
XGetWindowAttributes(display, view->impl->win, &attrs);
- // Get window position relative to the root window
+ // Get window position (relative to the root window if not a child)
Window ignoredChild = 0;
- int rootX = 0;
- int rootY = 0;
- XTranslateCoordinates(
- display, view->impl->win, attrs.root, 0, 0, &rootX, &rootY, &ignoredChild);
+ int x = attrs.x;
+ int y = attrs.y;
+ if (!view->parent) {
+ XTranslateCoordinates(
+ display, view->impl->win, attrs.root, 0, 0, &x, &y, &ignoredChild);
+ }
// Build a configure event based on the current window configuration
PuglEvent configureEvent = {{PUGL_CONFIGURE, 0}};
- configureEvent.configure.x = (PuglCoord)rootX;
- configureEvent.configure.y = (PuglCoord)rootY;
+ configureEvent.configure.x = (PuglCoord)x;
+ configureEvent.configure.y = (PuglCoord)y;
configureEvent.configure.width = (PuglSpan)attrs.width;
configureEvent.configure.height = (PuglSpan)attrs.height;
configureEvent.configure.style = getCurrentViewStyleFlags(view);