From f9eb709a18cb12daf0bdef5aff7c322eb7cebec3 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 18 Jan 2022 19:10:13 +0100 Subject: [PATCH] Add window resizing and positioning on Mac --- Source/Engine/Platform/Base/WindowBase.h | 1 + Source/Engine/Platform/Mac/MacPlatform.cpp | 9 +++ Source/Engine/Platform/Mac/MacUtils.h | 1 + Source/Engine/Platform/Mac/MacWindow.cpp | 82 +++++++++++++++++++++- Source/Engine/Platform/Mac/MacWindow.h | 7 ++ 5 files changed, 98 insertions(+), 2 deletions(-) diff --git a/Source/Engine/Platform/Base/WindowBase.h b/Source/Engine/Platform/Base/WindowBase.h index 754c79828..d8c014ef4 100644 --- a/Source/Engine/Platform/Base/WindowBase.h +++ b/Source/Engine/Platform/Base/WindowBase.h @@ -521,6 +521,7 @@ public: /// The client area position. API_PROPERTY() virtual void SetClientPosition(const Vector2& position) { + SetClientBounds(Rectangle(position, GetClientSize())); } /// diff --git a/Source/Engine/Platform/Mac/MacPlatform.cpp b/Source/Engine/Platform/Mac/MacPlatform.cpp index 0490520d3..b0d7fb8ac 100644 --- a/Source/Engine/Platform/Mac/MacPlatform.cpp +++ b/Source/Engine/Platform/Mac/MacPlatform.cpp @@ -81,6 +81,15 @@ Vector2 MacUtils::PosToCoca(const Vector2& pos) return result; } +Vector2 MacUtils::CocaToPos(const Vector2& pos) +{ + // MacOS uses y-coordinate starting at the bottom of the screen + Vector2 result = pos; + result -= GetScreensOrigin(); + result.Y *= -1; + return result; +} + Vector2 MacUtils::GetScreensOrigin() { Vector2 result = Vector2::Zero; diff --git a/Source/Engine/Platform/Mac/MacUtils.h b/Source/Engine/Platform/Mac/MacUtils.h index 59acb655b..04caf1fe0 100644 --- a/Source/Engine/Platform/Mac/MacUtils.h +++ b/Source/Engine/Platform/Mac/MacUtils.h @@ -11,5 +11,6 @@ public: static String ToString(CFStringRef str); static CFStringRef ToString(const StringView& str); static Vector2 PosToCoca(const Vector2& pos); + static Vector2 CocaToPos(const Vector2& pos); static Vector2 GetScreensOrigin(); }; diff --git a/Source/Engine/Platform/Mac/MacWindow.cpp b/Source/Engine/Platform/Mac/MacWindow.cpp index 4309a70e5..9fa3fd501 100644 --- a/Source/Engine/Platform/Mac/MacWindow.cpp +++ b/Source/Engine/Platform/Mac/MacWindow.cpp @@ -430,7 +430,7 @@ MacWindow::MacWindow(const CreateWindowSettings& settings) NSUInteger styleMask = NSWindowStyleMaskClosable; if (settings.IsRegularWindow) { - styleMask |= NSWindowStyleMaskTitled | NSWindowStyleMaskFullSizeContentView; + styleMask |= NSWindowStyleMaskTitled; if (settings.AllowMinimize) styleMask |= NSWindowStyleMaskMiniaturizable; if (settings.HasSizingFrame || settings.AllowMaximize) @@ -468,7 +468,6 @@ MacWindow::MacWindow(const CreateWindowSettings& settings) // TODO: impl StartPosition for MacWindow // TODO: impl Fullscreen for MacWindow // TODO: impl ShowInTaskbar for MacWindow - // TODO: impl ActivateWhenFirstShown for MacWindow // TODO: impl AllowInput for MacWindow // TODO: impl AllowDragAndDrop for MacWindow // TODO: impl IsTopmost for MacWindow @@ -558,6 +557,8 @@ void MacWindow::Minimize() if (!_settings.AllowMinimize) return; NSWindow* window = (NSWindow*)_window; + if (!window) + return; if (!window.miniaturized) [window miniaturize:nil]; } @@ -601,15 +602,90 @@ void MacWindow::SetIsFullscreen(bool isFullscreen) // TODO: fullscreen mode on Mac } +void MacWindow::SetClientBounds(const Rectangle& clientArea) +{ + NSWindow* window = (NSWindow*)_window; + if (!window) + return; + NSRect oldRect = [window frame]; + NSRect newRect = NSMakeRect(0, 0, clientArea.Size.X, clientArea.Size.Y); + newRect = [window frameRectForContentRect:newRect]; + + //newRect.origin.x = oldRect.origin.x; + //newRect.origin.y = NSMaxY(oldRect) - newRect.size.height; + + Vector2 pos = MacUtils::PosToCoca(clientArea.Location); + NSRect frameStart = [window frameRectForContentRect:NSMakeRect(0, 0, 0, 0)]; + newRect.origin.x = pos.X; + newRect.origin.y = pos.Y - newRect.size.height + frameStart.size.height; + + [window setFrame:newRect display:YES]; +} + +void MacWindow::SetPosition(const Vector2& position) +{ + NSWindow* window = (NSWindow*)_window; + if (!window) + return; + Vector2 pos = MacUtils::PosToCoca(position); + NSRect rect = [window frame]; + [window setFrameOrigin:NSMakePoint(pos.X, pos.Y - rect.size.height)]; +} + +Vector2 MacWindow::GetPosition() const +{ + NSWindow* window = (NSWindow*)_window; + if (!window) + return Vector2::Zero; + NSRect rect = [window frame]; + return MacUtils::CocaToPos(Vector2(rect.origin.x, rect.origin.y + rect.size.height)); +} + +Vector2 MacWindow::GetSize() const +{ + NSWindow* window = (NSWindow*)_window; + if (!window) + return Vector2::Zero; + NSRect rect = [window frame]; + return Vector2(rect.size.width, rect.size.height); +} + +Vector2 MacWindow::GetClientSize() const +{ + return _clientSize; +} + +Vector2 MacWindow::ScreenToClient(const Vector2& screenPos) const +{ + NSWindow* window = (NSWindow*)_window; + if (!window) + return screenPos; + NSRect frameStart = [window frameRectForContentRect:NSMakeRect(0, 0, 0, 0)]; + return screenPos - GetPosition() - Vector2(0, frameStart.size.height); +} + +Vector2 MacWindow::ClientToScreen(const Vector2& clientPos) const +{ + NSWindow* window = (NSWindow*)_window; + if (!window) + return clientPos; + NSRect frameStart = [window frameRectForContentRect:NSMakeRect(0, 0, 0, 0)]; + return GetPosition() + Vector2(0, frameStart.size.height) + clientPos; +} + void MacWindow::SetOpacity(float opacity) { NSWindow* window = (NSWindow*)_window; + if (!window) + return; [window setAlphaValue:opacity]; } void MacWindow::Focus() { NSWindow* window = (NSWindow*)_window; + if (!window) + return; [window makeKeyAndOrderFront:window]; } @@ -617,6 +693,8 @@ void MacWindow::SetTitle(const StringView& title) { _title = title; NSWindow* window = (NSWindow*)_window; + if (!window) + return; [window setTitle:(__bridge NSString*)MacUtils::ToString(_title)]; } diff --git a/Source/Engine/Platform/Mac/MacWindow.h b/Source/Engine/Platform/Mac/MacWindow.h index c5e98f643..a698af6b5 100644 --- a/Source/Engine/Platform/Mac/MacWindow.h +++ b/Source/Engine/Platform/Mac/MacWindow.h @@ -38,6 +38,13 @@ public: bool IsClosed() const override; bool IsForegroundWindow() const override; void BringToFront(bool force) override; + void SetClientBounds(const Rectangle& clientArea) override; + void SetPosition(const Vector2& position) override; + Vector2 GetPosition() const override; + Vector2 GetSize() const override; + Vector2 GetClientSize() const override; + Vector2 ScreenToClient(const Vector2& screenPos) const override; + Vector2 ClientToScreen(const Vector2& clientPos) const override; void SetIsFullscreen(bool isFullscreen) override; void SetOpacity(float opacity) override; void Focus() override;