From f1053d1b673c343a7c3514f6f70e2b4310bdadf5 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Wed, 18 May 2022 13:43:46 +0100 Subject: [PATCH] Merge pull request #8154 from AvaloniaUI/fixes/osx-nswindow-refactor-fix-issues --- .../src/OSX/AutoFitContentView.mm | 2 +- native/Avalonia.Native/src/OSX/AvnWindow.mm | 23 +++++++++--- native/Avalonia.Native/src/OSX/PopupImpl.mm | 6 ++++ .../Avalonia.Native/src/OSX/WindowBaseImpl.h | 2 ++ .../Avalonia.Native/src/OSX/WindowBaseImpl.mm | 36 +++++++++++++------ native/Avalonia.Native/src/OSX/WindowImpl.mm | 6 ++-- src/Avalonia.Native/WindowImplBase.cs | 8 +++-- src/Avalonia.Native/avn.idl | 2 +- 8 files changed, 63 insertions(+), 22 deletions(-) diff --git a/native/Avalonia.Native/src/OSX/AutoFitContentView.mm b/native/Avalonia.Native/src/OSX/AutoFitContentView.mm index 314c579b76..0fa4540726 100644 --- a/native/Avalonia.Native/src/OSX/AutoFitContentView.mm +++ b/native/Avalonia.Native/src/OSX/AutoFitContentView.mm @@ -85,7 +85,7 @@ _settingSize = true; [super setFrameSize:newSize]; - auto window = static_cast>([self window]); + auto window = (id ) [self window]; // TODO get actual titlebar size diff --git a/native/Avalonia.Native/src/OSX/AvnWindow.mm b/native/Avalonia.Native/src/OSX/AvnWindow.mm index 27b6fca83d..03f18a9c71 100644 --- a/native/Avalonia.Native/src/OSX/AvnWindow.mm +++ b/native/Avalonia.Native/src/OSX/AvnWindow.mm @@ -173,6 +173,11 @@ [self setBackgroundColor: [NSColor clearColor]]; _isExtended = false; + +#ifdef IS_NSPANEL + [self setCollectionBehavior:NSWindowCollectionBehaviorCanJoinAllSpaces|NSWindowCollectionBehaviorFullScreenAuxiliary]; +#endif + return self; } @@ -193,6 +198,8 @@ [self backingScaleFactor]; } + + - (void)windowWillClose:(NSNotification *)notification { _closed = true; @@ -211,11 +218,14 @@ // If the window has a child window being shown as a dialog then don't allow it to become the key window. for(NSWindow* uch in [self childWindows]) { - auto ch = static_cast>(uch); - if(ch == nil) + if (![uch conformsToProtocol:@protocol(AvnWindowProtocol)]) + { continue; - if (ch.isDialog) - return false; + } + + id ch = (id ) uch; + + return !ch.isDialog; } return true; @@ -371,6 +381,11 @@ if(cparent != nullptr) { + if(!cparent->IsShown()) + { + return; + } + if(cparent->WindowState() == Maximized) { cparent->SetWindowState(Normal); diff --git a/native/Avalonia.Native/src/OSX/PopupImpl.mm b/native/Avalonia.Native/src/OSX/PopupImpl.mm index 80a64dc310..ff244b4402 100644 --- a/native/Avalonia.Native/src/OSX/PopupImpl.mm +++ b/native/Avalonia.Native/src/OSX/PopupImpl.mm @@ -49,11 +49,17 @@ protected: return S_OK; } } + public: virtual bool ShouldTakeFocusOnShow() override { return false; } + + virtual HRESULT Show(bool activate, bool isDialog) override + { + return WindowBaseImpl::Show(activate, true); + } }; diff --git a/native/Avalonia.Native/src/OSX/WindowBaseImpl.h b/native/Avalonia.Native/src/OSX/WindowBaseImpl.h index eff13bcb23..0e482f9f30 100644 --- a/native/Avalonia.Native/src/OSX/WindowBaseImpl.h +++ b/native/Avalonia.Native/src/OSX/WindowBaseImpl.h @@ -60,6 +60,8 @@ BEGIN_INTERFACE_MAP() virtual HRESULT Show(bool activate, bool isDialog) override; + virtual bool IsShown (); + virtual bool ShouldTakeFocusOnShow(); virtual HRESULT Hide() override; diff --git a/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm b/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm index 2601705f25..840c8baddf 100644 --- a/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm +++ b/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm @@ -29,8 +29,8 @@ WindowBaseImpl::WindowBaseImpl(IAvnWindowBaseEvents *events, IAvnGlContext *gl) View = [[AvnView alloc] initWithParent:this]; StandardContainer = [[AutoFitContentView new] initWithContent:View]; - lastPositionSet.X = 100; - lastPositionSet.Y = 100; + lastPositionSet.X = -1; + lastPositionSet.Y = -1; lastSize = NSSize { 100, 100 }; lastMaxSize = NSSize { CGFLOAT_MAX, CGFLOAT_MAX}; lastMinSize = NSSize { 0, 0 }; @@ -91,7 +91,11 @@ HRESULT WindowBaseImpl::Show(bool activate, bool isDialog) { CreateNSWindow(isDialog); InitialiseNSWindow(); - SetPosition(lastPositionSet); + if(lastPositionSet.X >= 0 && lastPositionSet.Y >= 0) + { + SetPosition(lastPositionSet); + } + UpdateStyle(); [Window setTitle:_lastTitle]; @@ -111,6 +115,11 @@ HRESULT WindowBaseImpl::Show(bool activate, bool isDialog) { } } +bool WindowBaseImpl::IsShown () +{ + return _shown; +} + bool WindowBaseImpl::ShouldTakeFocusOnShow() { return true; } @@ -190,9 +199,8 @@ HRESULT WindowBaseImpl::GetClientSize(AvnSize *ret) { if (ret == nullptr) return E_POINTER; - auto frame = [View frame]; - ret->Width = frame.size.width; - ret->Height = frame.size.height; + ret->Width = lastSize.width; + ret->Height = lastSize.height; return S_OK; } @@ -205,9 +213,11 @@ HRESULT WindowBaseImpl::GetFrameSize(AvnSize *ret) { if (ret == nullptr) return E_POINTER; - auto frame = [Window frame]; - ret->Width = frame.size.width; - ret->Height = frame.size.height; + if(Window != nullptr){ + auto frame = [Window frame]; + ret->Width = frame.size.width; + ret->Height = frame.size.height; + } return S_OK; } @@ -369,7 +379,10 @@ HRESULT WindowBaseImpl::SetPosition(AvnPoint point) { @autoreleasepool { lastPositionSet = point; - [Window setFrameTopLeftPoint:ToNSPoint(ConvertPointY(point))]; + + if(Window != nullptr) { + [Window setFrameTopLeftPoint:ToNSPoint(ConvertPointY(point))]; + } return S_OK; } @@ -558,6 +571,7 @@ void WindowBaseImpl::InitialiseNSWindow() { [Window setContentMaxSize:lastMaxSize]; [Window setOpaque:false]; + [Window center]; if (lastMenu != nullptr) { [GetWindowProtocol() applyMenu:lastMenu]; @@ -575,7 +589,7 @@ id WindowBaseImpl::GetWindowProtocol() { return nullptr; } - return static_cast>(Window); + return (id ) Window; } extern IAvnWindow* CreateAvnWindow(IAvnWindowEvents*events, IAvnGlContext* gl) diff --git a/native/Avalonia.Native/src/OSX/WindowImpl.mm b/native/Avalonia.Native/src/OSX/WindowImpl.mm index d38253ec61..7ec5f2d929 100644 --- a/native/Avalonia.Native/src/OSX/WindowImpl.mm +++ b/native/Avalonia.Native/src/OSX/WindowImpl.mm @@ -429,6 +429,9 @@ HRESULT WindowImpl::SetWindowState(AvnWindowState state) { START_COM_CALL; @autoreleasepool { + auto currentState = _actualWindowState; + _lastWindowState = state; + if (Window == nullptr) { return S_OK; } @@ -439,9 +442,6 @@ HRESULT WindowImpl::SetWindowState(AvnWindowState state) { _inSetWindowState = true; - auto currentState = _actualWindowState; - _lastWindowState = state; - if (currentState == Normal) { _preZoomSize = [Window frame]; } diff --git a/src/Avalonia.Native/WindowImplBase.cs b/src/Avalonia.Native/WindowImplBase.cs index b83176e7e7..700f1f2c20 100644 --- a/src/Avalonia.Native/WindowImplBase.cs +++ b/src/Avalonia.Native/WindowImplBase.cs @@ -117,8 +117,12 @@ namespace Avalonia.Native { if (_native != null) { - var s = _native.FrameSize; - return new Size(s.Width, s.Height); + unsafe + { + var s = new AvnSize { Width = -1, Height = -1 }; + _native.GetFrameSize(&s); + return s.Width < 0 && s.Height < 0 ? null : new Size(s.Width, s.Height); + } } return default; diff --git a/src/Avalonia.Native/avn.idl b/src/Avalonia.Native/avn.idl index a508ff687e..e02b244db6 100644 --- a/src/Avalonia.Native/avn.idl +++ b/src/Avalonia.Native/avn.idl @@ -448,7 +448,7 @@ interface IAvnWindowBase : IUnknown HRESULT Close(); HRESULT Activate(); HRESULT GetClientSize(AvnSize*ret); - HRESULT GetFrameSize(AvnSize*ret); + HRESULT GetFrameSize(AvnSize*result); HRESULT GetScaling(double*ret); HRESULT SetMinMaxSize(AvnSize minSize, AvnSize maxSize); HRESULT Resize(double width, double height, AvnPlatformResizeReason reason);