aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2023-01-10 15:26:44 -0500
committerDavid Robillard <d@drobilla.net>2023-01-11 03:28:10 -0500
commit16739fe3b2cf0fe8c2ffcb3e983ef09aa04517dc (patch)
treecc807d652bbb565d7d9beac108108374e9ca64f5
parent569ad0408d5db4911b20138a46cde8f6912d8291 (diff)
downloadpugl-16739fe3b2cf0fe8c2ffcb3e983ef09aa04517dc.tar.gz
pugl-16739fe3b2cf0fe8c2ffcb3e983ef09aa04517dc.tar.bz2
pugl-16739fe3b2cf0fe8c2ffcb3e983ef09aa04517dc.zip
Center windows on their transient parent where possible
This is only really relevant in practice on MacOS and Windows. On X11, the window manager places new windows where it pleases.
-rw-r--r--src/mac.m38
-rw-r--r--src/types.h6
-rw-r--r--src/win.c28
3 files changed, 56 insertions, 16 deletions
diff --git a/src/mac.m b/src/mac.m
index 841a154..77c825f 100644
--- a/src/mac.m
+++ b/src/mac.m
@@ -91,7 +91,7 @@ utiForMimeType(const NSString* const mimeType)
}
static NSRect
-rectToScreen(NSScreen* screen, NSRect rect)
+rectToScreen(const NSScreen* screen, NSRect rect)
{
const double screenHeight = [screen frame].size.height;
@@ -99,6 +99,17 @@ rectToScreen(NSScreen* screen, NSRect rect)
return rect;
}
+static NSRect
+rectFromScreen(const NSScreen* screen, NSRect rect)
+{
+ /* The math happens to work out to the same expression because this is just
+ an inversion of the Y axis based on the screen height. This function is
+ preserved to make the code clearer and more future-proof since the use
+ cases are distinctly either a "from" or "to" conversion. */
+
+ return rectToScreen(screen, rect);
+}
+
static NSScreen*
viewScreen(const PuglView* view)
{
@@ -1109,6 +1120,25 @@ updateSizeHints(PuglView* const view)
}
}
+static void
+puglMacSetDefaultPosition(PuglView* const view)
+{
+ // Get a bounding rect from the transient parent or the screen
+ const NSScreen* const screen = viewScreen(view);
+ const NSRect boundsPt =
+ rectFromScreen(screen,
+ view->transientParent
+ ? [[(const NSView*)view->transientParent window] frame]
+ : [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));
+}
+
PuglStatus
puglRealize(PuglView* view)
{
@@ -1156,11 +1186,7 @@ puglRealize(PuglView* view)
// Center top-level windows if a position has not been set
if (!view->parent && !view->frame.x && !view->frame.y) {
- const double screenWidthPx = [screen frame].size.width * scaleFactor;
- const double screenHeightPx = [screen frame].size.height * scaleFactor;
-
- view->frame.x = (PuglCoord)((screenWidthPx - view->frame.width) / 2.0);
- view->frame.y = (PuglCoord)((screenHeightPx - view->frame.height) / 2.0);
+ puglMacSetDefaultPosition(view);
}
const NSRect framePx = rectToNsRect(view->frame);
diff --git a/src/types.h b/src/types.h
index 785eae8..da0a295 100644
--- a/src/types.h
+++ b/src/types.h
@@ -21,6 +21,12 @@ typedef struct PuglInternalsImpl PuglInternals;
/// View hints
typedef int PuglHints[PUGL_NUM_VIEW_HINTS];
+/// View position (both X and Y coordinates) or general point
+typedef struct {
+ PuglCoord x;
+ PuglCoord y;
+} PuglPoint;
+
/// View size (both X and Y coordinates)
typedef struct {
PuglSpan width;
diff --git a/src/win.c b/src/win.c
index d3bc4fd..4c4c815 100644
--- a/src/win.c
+++ b/src/win.c
@@ -1502,6 +1502,21 @@ puglWinGetPixelFormatDescriptor(const PuglHints hints)
return pfd;
}
+static void
+puglWinSetDefaultPosition(PuglView* const view)
+{
+ // 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));
+}
+
PuglStatus
puglWinCreateWindow(PuglView* const view,
const char* const title,
@@ -1514,14 +1529,7 @@ puglWinCreateWindow(PuglView* const view,
// Center top-level windows if a position has not been set
if (!view->parent && !view->frame.x && !view->frame.y) {
- RECT desktopRect;
- GetClientRect(GetDesktopWindow(), &desktopRect);
-
- const int screenWidth = desktopRect.right - desktopRect.left;
- const int screenHeight = desktopRect.bottom - desktopRect.top;
-
- view->frame.x = (PuglCoord)((screenWidth - view->frame.width) / 2);
- view->frame.y = (PuglCoord)((screenHeight - view->frame.height) / 2);
+ puglWinSetDefaultPosition(view);
}
// The meaning of "parent" depends on the window type (WS_CHILD)
@@ -1539,8 +1547,8 @@ puglWinCreateWindow(PuglView* const view,
className,
title,
winFlags,
- CW_USEDEFAULT,
- CW_USEDEFAULT,
+ wr.left,
+ wr.right,
wr.right - wr.left,
wr.bottom - wr.top,
(HWND)parent,