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 /src | |
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.
Diffstat (limited to 'src')
-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, |