diff options
author | David Robillard <d@drobilla.net> | 2023-01-10 15:26:44 -0500 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2023-01-11 03:28:10 -0500 |
commit | 16739fe3b2cf0fe8c2ffcb3e983ef09aa04517dc (patch) | |
tree | cc807d652bbb565d7d9beac108108374e9ca64f5 | |
parent | 569ad0408d5db4911b20138a46cde8f6912d8291 (diff) | |
download | pugl-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.m | 38 | ||||
-rw-r--r-- | src/types.h | 6 | ||||
-rw-r--r-- | src/win.c | 28 |
3 files changed, 56 insertions, 16 deletions
@@ -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; @@ -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, |