From 4cba4519f3e76d368384a40a9e655a76eedcf7f9 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 6 May 2022 11:45:47 +0100 Subject: [PATCH 01/13] only create the NSWindow when show is called. Cache sizes until needed. --- .../Avalonia.Native/src/OSX/WindowBaseImpl.h | 11 ++-- .../Avalonia.Native/src/OSX/WindowBaseImpl.mm | 53 ++++++++++++++----- native/Avalonia.Native/src/OSX/window.h | 2 +- native/Avalonia.Native/src/OSX/window.mm | 6 ++- 4 files changed, 51 insertions(+), 21 deletions(-) diff --git a/native/Avalonia.Native/src/OSX/WindowBaseImpl.h b/native/Avalonia.Native/src/OSX/WindowBaseImpl.h index d2690cee418..19c443806c6 100644 --- a/native/Avalonia.Native/src/OSX/WindowBaseImpl.h +++ b/native/Avalonia.Native/src/OSX/WindowBaseImpl.h @@ -24,10 +24,7 @@ BEGIN_INTERFACE_MAP() INTERFACE_MAP_ENTRY(IAvnWindowBase, IID_IAvnWindowBase) END_INTERFACE_MAP() - virtual ~WindowBaseImpl() { - View = NULL; - Window = NULL; - } + virtual ~WindowBaseImpl(); AutoFitContentView *StandardContainer; AvnView *View; @@ -36,6 +33,9 @@ BEGIN_INTERFACE_MAP() ComPtr _glContext; NSObject *renderTarget; AvnPoint lastPositionSet; + NSSize lastSize; + NSSize lastMinSize; + NSSize lastMaxSize; NSString *_lastTitle; bool _shown; @@ -116,6 +116,9 @@ BEGIN_INTERFACE_MAP() void UpdateStyle(); +private: + void InitialiseNSWindow (); + }; #endif //AVALONIA_NATIVE_OSX_WINDOWBASEIMPL_H diff --git a/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm b/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm index fb67addce1f..fe3a209d3ee 100644 --- a/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm +++ b/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm @@ -12,6 +12,13 @@ #import "cursor.h" #include "ResizeScope.h" #import "AutoFitContentView.h" +#include "WindowBaseImpl.h" + + +WindowBaseImpl::~WindowBaseImpl() { + View = nullptr; + Window = nullptr; +} WindowBaseImpl::WindowBaseImpl(IAvnWindowBaseEvents *events, IAvnGlContext *gl) { _shown = false; @@ -22,17 +29,11 @@ View = [[AvnView alloc] initWithParent:this]; StandardContainer = [[AutoFitContentView new] initWithContent:View]; - Window = [[AvnWindow alloc] initWithParent:this]; - [Window setContentView:StandardContainer]; - lastPositionSet.X = 100; lastPositionSet.Y = 100; _lastTitle = @""; - [Window setStyleMask:NSWindowStyleMaskBorderless]; - [Window setBackingType:NSBackingStoreBuffered]; - - [Window setOpaque:false]; + Window = nullptr; } HRESULT WindowBaseImpl::ObtainNSViewHandle(void **ret) { @@ -83,6 +84,8 @@ START_COM_CALL; @autoreleasepool { + InitialiseNSWindow(); + SetPosition(lastPositionSet); UpdateStyle(); @@ -97,6 +100,10 @@ [Window orderFront:Window]; } + [Window setContentMinSize:lastMinSize]; + [Window setContentMaxSize:lastMaxSize]; + [Window setContentSize: lastSize]; + _shown = true; return S_OK; @@ -225,8 +232,13 @@ START_COM_CALL; @autoreleasepool { - [Window setMinSize:ToNSSize(minSize)]; - [Window setMaxSize:ToNSSize(maxSize)]; + lastMinSize = ToNSSize(minSize); + lastMaxSize = ToNSSize(maxSize); + + if(Window != nullptr) { + [Window setContentMinSize:lastMinSize]; + [Window setContentMaxSize:lastMaxSize]; + } return S_OK; } @@ -243,8 +255,8 @@ auto resizeBlock = ResizeScope(View, reason); @autoreleasepool { - auto maxSize = [Window maxSize]; - auto minSize = [Window minSize]; + auto maxSize = lastMaxSize; + auto minSize = lastMinSize; if (x < minSize.width) { x = minSize.width; @@ -267,8 +279,12 @@ BaseEvents->Resized(AvnSize{x, y}, reason); } - [Window setContentSize:NSSize{x, y}]; - [Window invalidateShadow]; + lastSize = NSSize {x, y}; + + if(Window != nullptr) { + [Window setContentSize:lastSize]; + [Window invalidateShadow]; + } } @finally { _inResize = false; @@ -502,4 +518,13 @@ void WindowBaseImpl::UpdateStyle() { [Window setStyleMask:GetStyle()]; -} \ No newline at end of file +} + +void WindowBaseImpl::InitialiseNSWindow() { + Window = [[AvnWindow alloc] initWithParent:this contentRect:NSRect{ 0, 0, lastSize } styleMask:GetStyle()]; + [Window setContentView:StandardContainer]; + [Window setStyleMask:NSWindowStyleMaskBorderless]; + [Window setBackingType:NSBackingStoreBuffered]; + + [Window setOpaque:false]; +} diff --git a/native/Avalonia.Native/src/OSX/window.h b/native/Avalonia.Native/src/OSX/window.h index e9b98ce9ae7..a8c31e7b600 100644 --- a/native/Avalonia.Native/src/OSX/window.h +++ b/native/Avalonia.Native/src/OSX/window.h @@ -8,7 +8,7 @@ class WindowBaseImpl; @interface AvnWindow : NSWindow --(AvnWindow* _Nonnull) initWithParent: (WindowBaseImpl* _Nonnull) parent; +-(AvnWindow* _Nonnull) initWithParent: (WindowBaseImpl* _Nonnull) parent contentRect: (NSRect)contentRect styleMask: (NSWindowStyleMask)styleMask; -(void) setCanBecomeKeyAndMain; -(void) pollModalSession: (NSModalSession _Nonnull) session; -(void) restoreParentWindow; diff --git a/native/Avalonia.Native/src/OSX/window.mm b/native/Avalonia.Native/src/OSX/window.mm index 68a459d0889..965b4a849bb 100644 --- a/native/Avalonia.Native/src/OSX/window.mm +++ b/native/Avalonia.Native/src/OSX/window.mm @@ -143,9 +143,10 @@ -(void) setCanBecomeKeyAndMain _canBecomeKeyAndMain = true; } --(AvnWindow*) initWithParent: (WindowBaseImpl*) parent +-(AvnWindow*) initWithParent: (WindowBaseImpl*) parent contentRect: (NSRect)contentRect styleMask: (NSWindowStyleMask)styleMask; { - self = [super init]; + self = [super initWithContentRect:contentRect styleMask: styleMask backing:NSBackingStoreBuffered defer:false]; + [self setReleasedWhenClosed:false]; _parent = parent; [self setDelegate:self]; @@ -155,6 +156,7 @@ -(AvnWindow*) initWithParent: (WindowBaseImpl*) parent [self backingScaleFactor]; [self setOpaque:NO]; [self setBackgroundColor: [NSColor clearColor]]; + _isExtended = false; return self; } From 0ee1a7e3910525a069230d713c93ed47d3528b4d Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 6 May 2022 11:50:42 +0100 Subject: [PATCH 02/13] add explanation for init with content size. --- native/Avalonia.Native/src/OSX/window.mm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/native/Avalonia.Native/src/OSX/window.mm b/native/Avalonia.Native/src/OSX/window.mm index 965b4a849bb..68f8f76d755 100644 --- a/native/Avalonia.Native/src/OSX/window.mm +++ b/native/Avalonia.Native/src/OSX/window.mm @@ -145,6 +145,9 @@ -(void) setCanBecomeKeyAndMain -(AvnWindow*) initWithParent: (WindowBaseImpl*) parent contentRect: (NSRect)contentRect styleMask: (NSWindowStyleMask)styleMask; { + // https://jameshfisher.com/2020/07/10/why-is-the-contentrect-of-my-nswindow-ignored/ + // create nswindow with specific contentRect, otherwise we wont be able to resize the window + // until several ms after the window is physically on the screen. self = [super initWithContentRect:contentRect styleMask: styleMask backing:NSBackingStoreBuffered defer:false]; [self setReleasedWhenClosed:false]; From 2372155995ec6680c5ec27570da95a23b9e09cc4 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 6 May 2022 13:05:40 +0100 Subject: [PATCH 03/13] only create the window if reference is null --- native/Avalonia.Native/src/OSX/WindowBaseImpl.mm | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm b/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm index fe3a209d3ee..0c85dcc303b 100644 --- a/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm +++ b/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm @@ -521,10 +521,12 @@ } void WindowBaseImpl::InitialiseNSWindow() { - Window = [[AvnWindow alloc] initWithParent:this contentRect:NSRect{ 0, 0, lastSize } styleMask:GetStyle()]; - [Window setContentView:StandardContainer]; - [Window setStyleMask:NSWindowStyleMaskBorderless]; - [Window setBackingType:NSBackingStoreBuffered]; + if(Window == nullptr) { + Window = [[AvnWindow alloc] initWithParent:this contentRect:NSRect{0, 0, lastSize} styleMask:GetStyle()]; + [Window setContentView:StandardContainer]; + [Window setStyleMask:NSWindowStyleMaskBorderless]; + [Window setBackingType:NSBackingStoreBuffered]; - [Window setOpaque:false]; + [Window setOpaque:false]; + } } From e76887fe25830404a0d6afd97782e0f8629c22b0 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 6 May 2022 14:14:08 +0100 Subject: [PATCH 04/13] INSWindowHolder uses NSView and NSWindow types. --- native/Avalonia.Native/src/OSX/INSWindowHolder.h | 4 ++-- native/Avalonia.Native/src/OSX/WindowBaseImpl.h | 4 ++-- native/Avalonia.Native/src/OSX/WindowBaseImpl.mm | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/native/Avalonia.Native/src/OSX/INSWindowHolder.h b/native/Avalonia.Native/src/OSX/INSWindowHolder.h index adc0dd1990d..ae64a53e7d9 100644 --- a/native/Avalonia.Native/src/OSX/INSWindowHolder.h +++ b/native/Avalonia.Native/src/OSX/INSWindowHolder.h @@ -10,8 +10,8 @@ struct INSWindowHolder { - virtual AvnWindow* _Nonnull GetNSWindow () = 0; - virtual AvnView* _Nonnull GetNSView () = 0; + virtual NSWindow* _Nonnull GetNSWindow () = 0; + virtual NSView* _Nonnull GetNSView () = 0; }; #endif //AVALONIA_NATIVE_OSX_INSWINDOWHOLDER_H diff --git a/native/Avalonia.Native/src/OSX/WindowBaseImpl.h b/native/Avalonia.Native/src/OSX/WindowBaseImpl.h index 19c443806c6..fd079b14273 100644 --- a/native/Avalonia.Native/src/OSX/WindowBaseImpl.h +++ b/native/Avalonia.Native/src/OSX/WindowBaseImpl.h @@ -51,9 +51,9 @@ BEGIN_INTERFACE_MAP() virtual HRESULT ObtainNSViewHandleRetained(void **ret) override; - virtual AvnWindow *GetNSWindow() override; + virtual NSWindow *GetNSWindow() override; - virtual AvnView *GetNSView() override; + virtual NSView *GetNSView() override; virtual HRESULT Show(bool activate, bool isDialog) override; diff --git a/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm b/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm index 0c85dcc303b..6ec026ed10a 100644 --- a/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm +++ b/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm @@ -60,11 +60,11 @@ return S_OK; } -AvnWindow *WindowBaseImpl::GetNSWindow() { +NSWindow *WindowBaseImpl::GetNSWindow() { return Window; } -AvnView *WindowBaseImpl::GetNSView() { +NSView *WindowBaseImpl::GetNSView() { return View; } From 0ac5a1c808f192b17afcbb9acc8a9d387432fab8 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 6 May 2022 14:16:11 +0100 Subject: [PATCH 05/13] set min and max when creating window. --- native/Avalonia.Native/src/OSX/WindowBaseImpl.mm | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm b/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm index 6ec026ed10a..826486ae31d 100644 --- a/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm +++ b/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm @@ -527,6 +527,10 @@ [Window setStyleMask:NSWindowStyleMaskBorderless]; [Window setBackingType:NSBackingStoreBuffered]; + [Window setContentSize: lastSize]; + [Window setContentMinSize:lastMinSize]; + [Window setContentMaxSize:lastMaxSize]; + [Window setOpaque:false]; } } From 8be332ab1d1504ff12950821ce8136e1a8647603 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 6 May 2022 14:20:49 +0100 Subject: [PATCH 06/13] make AvnWindowProtocol --- .../project.pbxproj | 12 ++++++++++ .../Avalonia.Native/src/OSX/AvnPanelWindow.h | 9 ++++++++ .../Avalonia.Native/src/OSX/AvnPanelWindow.mm | 8 +++++++ .../Avalonia.Native/src/OSX/WindowBaseImpl.h | 6 +++-- .../Avalonia.Native/src/OSX/WindowBaseImpl.mm | 18 +++++++++------ native/Avalonia.Native/src/OSX/WindowImpl.mm | 8 +++---- .../Avalonia.Native/src/OSX/WindowProtocol.h | 23 +++++++++++++++++++ native/Avalonia.Native/src/OSX/window.h | 15 ++---------- native/Avalonia.Native/src/OSX/window.mm | 10 ++++---- 9 files changed, 78 insertions(+), 31 deletions(-) create mode 100644 native/Avalonia.Native/src/OSX/AvnPanelWindow.h create mode 100644 native/Avalonia.Native/src/OSX/AvnPanelWindow.mm create mode 100644 native/Avalonia.Native/src/OSX/WindowProtocol.h diff --git a/native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj b/native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj index 88e4c0c6829..8ee2a61741f 100644 --- a/native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj +++ b/native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj @@ -9,9 +9,11 @@ /* Begin PBXBuildFile section */ 18391068E48EF96E3DB5FDAB /* ResizeScope.mm in Sources */ = {isa = PBXBuildFile; fileRef = 18391E45702740FE9DD69695 /* ResizeScope.mm */; }; 1839125F057B0A4EB1760058 /* WindowImpl.mm in Sources */ = {isa = PBXBuildFile; fileRef = 183919BF108EB72A029F7671 /* WindowImpl.mm */; }; + 1839151F32D1BB1AB51A7BB6 /* AvnPanelWindow.mm in Sources */ = {isa = PBXBuildFile; fileRef = 18391884C7476DA4E53A492D /* AvnPanelWindow.mm */; }; 183916173528EC2737DBE5E1 /* WindowBaseImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 183915BFF0E234CD3604A7CD /* WindowBaseImpl.h */; }; 1839171DCC651B0638603AC4 /* INSWindowHolder.h in Headers */ = {isa = PBXBuildFile; fileRef = 18391BBB7782C296D424071F /* INSWindowHolder.h */; }; 1839179A55FC1421BEE83330 /* WindowBaseImpl.mm in Sources */ = {isa = PBXBuildFile; fileRef = 18391676ECF0E983F4964357 /* WindowBaseImpl.mm */; }; + 1839196EC57BBC5C8BE1C735 /* AvnPanelWindow.h in Headers */ = {isa = PBXBuildFile; fileRef = 18391DC046BC700D56DF0B82 /* AvnPanelWindow.h */; }; 183919D91DB9AAB5D700C2EA /* WindowImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 18391CD090AA776E7E841AC9 /* WindowImpl.h */; }; 18391AA7E0BBA74D184C5734 /* AutoFitContentView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1839166350F32661F3ABD70F /* AutoFitContentView.mm */; }; 18391C28BF1823B5464FDD36 /* ResizeScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 1839171D898F9BFC1373631A /* ResizeScope.h */; }; @@ -19,6 +21,7 @@ 18391D4EB311BC7EF8B8C0A6 /* AvnView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1839132D0E2454D911F1D1F9 /* AvnView.mm */; }; 18391E1381E2D5BFD60265A9 /* AutoFitContentView.h in Headers */ = {isa = PBXBuildFile; fileRef = 18391654EF0E7AB3D3AB4071 /* AutoFitContentView.h */; }; 18391ED5F611FF62C45F196D /* AvnView.h in Headers */ = {isa = PBXBuildFile; fileRef = 18391D1669284AD2EC9E866A /* AvnView.h */; }; + 18391F1E2411C79405A9943A /* WindowProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 1839122E037567BDD1D09DEB /* WindowProtocol.h */; }; 1A002B9E232135EE00021753 /* app.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1A002B9D232135EE00021753 /* app.mm */; }; 1A1852DC23E05814008F0DED /* deadlock.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1A1852DB23E05814008F0DED /* deadlock.mm */; }; 1A3E5EA823E9E83B00EDE661 /* rendertarget.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1A3E5EA723E9E83B00EDE661 /* rendertarget.mm */; }; @@ -47,6 +50,7 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 1839122E037567BDD1D09DEB /* WindowProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WindowProtocol.h; sourceTree = ""; }; 1839132D0E2454D911F1D1F9 /* AvnView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AvnView.mm; sourceTree = ""; }; 183913C6BFD6856BD42D19FD /* IWindowStateChanged.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IWindowStateChanged.h; sourceTree = ""; }; 183915BFF0E234CD3604A7CD /* WindowBaseImpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WindowBaseImpl.h; sourceTree = ""; }; @@ -54,10 +58,12 @@ 1839166350F32661F3ABD70F /* AutoFitContentView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AutoFitContentView.mm; sourceTree = ""; }; 18391676ECF0E983F4964357 /* WindowBaseImpl.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WindowBaseImpl.mm; sourceTree = ""; }; 1839171D898F9BFC1373631A /* ResizeScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ResizeScope.h; sourceTree = ""; }; + 18391884C7476DA4E53A492D /* AvnPanelWindow.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AvnPanelWindow.mm; sourceTree = ""; }; 183919BF108EB72A029F7671 /* WindowImpl.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WindowImpl.mm; sourceTree = ""; }; 18391BBB7782C296D424071F /* INSWindowHolder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = INSWindowHolder.h; sourceTree = ""; }; 18391CD090AA776E7E841AC9 /* WindowImpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WindowImpl.h; sourceTree = ""; }; 18391D1669284AD2EC9E866A /* AvnView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AvnView.h; sourceTree = ""; }; + 18391DC046BC700D56DF0B82 /* AvnPanelWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AvnPanelWindow.h; sourceTree = ""; }; 18391E45702740FE9DD69695 /* ResizeScope.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ResizeScope.mm; sourceTree = ""; }; 1A002B9D232135EE00021753 /* app.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = app.mm; sourceTree = ""; }; 1A1852DB23E05814008F0DED /* deadlock.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = deadlock.mm; sourceTree = ""; }; @@ -166,6 +172,9 @@ 18391D1669284AD2EC9E866A /* AvnView.h */, 1839166350F32661F3ABD70F /* AutoFitContentView.mm */, 18391654EF0E7AB3D3AB4071 /* AutoFitContentView.h */, + 18391884C7476DA4E53A492D /* AvnPanelWindow.mm */, + 18391DC046BC700D56DF0B82 /* AvnPanelWindow.h */, + 1839122E037567BDD1D09DEB /* WindowProtocol.h */, ); sourceTree = ""; }; @@ -193,6 +202,8 @@ 18391C28BF1823B5464FDD36 /* ResizeScope.h in Headers */, 18391ED5F611FF62C45F196D /* AvnView.h in Headers */, 18391E1381E2D5BFD60265A9 /* AutoFitContentView.h in Headers */, + 1839196EC57BBC5C8BE1C735 /* AvnPanelWindow.h in Headers */, + 18391F1E2411C79405A9943A /* WindowProtocol.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -277,6 +288,7 @@ 18391068E48EF96E3DB5FDAB /* ResizeScope.mm in Sources */, 18391D4EB311BC7EF8B8C0A6 /* AvnView.mm in Sources */, 18391AA7E0BBA74D184C5734 /* AutoFitContentView.mm in Sources */, + 1839151F32D1BB1AB51A7BB6 /* AvnPanelWindow.mm in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/native/Avalonia.Native/src/OSX/AvnPanelWindow.h b/native/Avalonia.Native/src/OSX/AvnPanelWindow.h new file mode 100644 index 00000000000..0fe95d044d3 --- /dev/null +++ b/native/Avalonia.Native/src/OSX/AvnPanelWindow.h @@ -0,0 +1,9 @@ +// +// Created by Dan Walmsley on 06/05/2022. +// Copyright (c) 2022 Avalonia. All rights reserved. +// + +#define NSWindow NSPanel +#define AvnWindow AvnPanelWindow + +//#include "window.h" \ No newline at end of file diff --git a/native/Avalonia.Native/src/OSX/AvnPanelWindow.mm b/native/Avalonia.Native/src/OSX/AvnPanelWindow.mm new file mode 100644 index 00000000000..8b79e28ca18 --- /dev/null +++ b/native/Avalonia.Native/src/OSX/AvnPanelWindow.mm @@ -0,0 +1,8 @@ +// +// Created by Dan Walmsley on 06/05/2022. +// Copyright (c) 2022 Avalonia. All rights reserved. +// + +#define AvnWindow AvnPanelWindow + +//#include "window.mm" \ No newline at end of file diff --git a/native/Avalonia.Native/src/OSX/WindowBaseImpl.h b/native/Avalonia.Native/src/OSX/WindowBaseImpl.h index fd079b14273..19065097fbd 100644 --- a/native/Avalonia.Native/src/OSX/WindowBaseImpl.h +++ b/native/Avalonia.Native/src/OSX/WindowBaseImpl.h @@ -7,6 +7,7 @@ #define AVALONIA_NATIVE_OSX_WINDOWBASEIMPL_H #import "rendertarget.h" +#import "WindowProtocol.h" #include "INSWindowHolder.h" @class AutoFitContentView; @@ -28,7 +29,7 @@ BEGIN_INTERFACE_MAP() AutoFitContentView *StandardContainer; AvnView *View; - AvnWindow *Window; + NSWindow * Window; ComPtr BaseEvents; ComPtr _glContext; NSObject *renderTarget; @@ -116,9 +117,10 @@ BEGIN_INTERFACE_MAP() void UpdateStyle(); + id GetWindowProtocol (); + private: void InitialiseNSWindow (); - }; #endif //AVALONIA_NATIVE_OSX_WINDOWBASEIMPL_H diff --git a/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm b/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm index 826486ae31d..82c634dc4f0 100644 --- a/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm +++ b/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm @@ -100,10 +100,6 @@ [Window orderFront:Window]; } - [Window setContentMinSize:lastMinSize]; - [Window setContentMaxSize:lastMaxSize]; - [Window setContentSize: lastSize]; - _shown = true; return S_OK; @@ -132,7 +128,8 @@ @autoreleasepool { if (Window != nullptr) { [Window orderOut:Window]; - [Window restoreParentWindow]; + + [GetWindowProtocol() restoreParentWindow]; } return S_OK; @@ -311,10 +308,10 @@ auto nsmenu = nativeMenu->GetNative(); - [Window applyMenu:nsmenu]; + [GetWindowProtocol() applyMenu:nsmenu]; if ([Window isKeyWindow]) { - [Window showWindowMenuWithAppMenu]; + [GetWindowProtocol() showWindowMenuWithAppMenu]; } return S_OK; @@ -532,5 +529,12 @@ [Window setContentMaxSize:lastMaxSize]; [Window setOpaque:false]; + + [Window setContentMinSize: lastMinSize]; + [Window setContentMaxSize: lastMaxSize]; } } + +id WindowBaseImpl::GetWindowProtocol() { + return static_cast>(Window); +} diff --git a/native/Avalonia.Native/src/OSX/WindowImpl.mm b/native/Avalonia.Native/src/OSX/WindowImpl.mm index 0d325c44901..3de4f5d5a8d 100644 --- a/native/Avalonia.Native/src/OSX/WindowImpl.mm +++ b/native/Avalonia.Native/src/OSX/WindowImpl.mm @@ -20,7 +20,7 @@ _lastWindowState = Normal; _actualWindowState = Normal; WindowEvents = events; - [Window setCanBecomeKeyAndMain]; + [GetWindowProtocol() setCanBecomeKeyAndMain]; [Window disableCursorRects]; [Window setTabbingMode:NSWindowTabbingModeDisallowed]; [Window setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary]; @@ -68,7 +68,7 @@ START_COM_CALL; @autoreleasepool { - [Window setEnabled:enable]; + [GetWindowProtocol() setEnabled:enable]; return S_OK; } } @@ -354,7 +354,7 @@ View.layer.zPosition = 0; } - [Window setIsExtended:enable]; + [GetWindowProtocol() setIsExtended:enable]; HideOrShowTrafficLights(); @@ -383,7 +383,7 @@ return E_POINTER; } - *ret = [Window getExtendedTitleBarHeight]; + *ret = [GetWindowProtocol() getExtendedTitleBarHeight]; return S_OK; } diff --git a/native/Avalonia.Native/src/OSX/WindowProtocol.h b/native/Avalonia.Native/src/OSX/WindowProtocol.h new file mode 100644 index 00000000000..ac20fe8eb13 --- /dev/null +++ b/native/Avalonia.Native/src/OSX/WindowProtocol.h @@ -0,0 +1,23 @@ +// +// Created by Dan Walmsley on 06/05/2022. +// Copyright (c) 2022 Avalonia. All rights reserved. +// + +#import + +@class AvnMenu; + +@protocol AvnWindowProtocol +-(void) setCanBecomeKeyAndMain; +-(void) pollModalSession: (NSModalSession _Nonnull) session; +-(void) restoreParentWindow; +-(bool) shouldTryToHandleEvents; +-(void) setEnabled: (bool) enable; +-(void) showAppMenuOnly; +-(void) showWindowMenuWithAppMenu; +-(void) applyMenu:(AvnMenu* _Nullable)menu; + +-(double) getExtendedTitleBarHeight; +-(void) setIsExtended:(bool)value; +-(bool) isDialog; +@end \ No newline at end of file diff --git a/native/Avalonia.Native/src/OSX/window.h b/native/Avalonia.Native/src/OSX/window.h index a8c31e7b600..1a001dd6e4c 100644 --- a/native/Avalonia.Native/src/OSX/window.h +++ b/native/Avalonia.Native/src/OSX/window.h @@ -2,25 +2,14 @@ #define window_h #import "avalonia-native.h" +#import "WindowProtocol.h" @class AvnMenu; class WindowBaseImpl; -@interface AvnWindow : NSWindow +@interface AvnWindow : NSWindow -(AvnWindow* _Nonnull) initWithParent: (WindowBaseImpl* _Nonnull) parent contentRect: (NSRect)contentRect styleMask: (NSWindowStyleMask)styleMask; --(void) setCanBecomeKeyAndMain; --(void) pollModalSession: (NSModalSession _Nonnull) session; --(void) restoreParentWindow; --(bool) shouldTryToHandleEvents; --(void) setEnabled: (bool) enable; --(void) showAppMenuOnly; --(void) showWindowMenuWithAppMenu; --(void) applyMenu:(AvnMenu* _Nullable)menu; - --(double) getExtendedTitleBarHeight; --(void) setIsExtended:(bool)value; --(bool) isDialog; @end #endif /* window_h */ diff --git a/native/Avalonia.Native/src/OSX/window.mm b/native/Avalonia.Native/src/OSX/window.mm index 68f8f76d755..e4bfedaba45 100644 --- a/native/Avalonia.Native/src/OSX/window.mm +++ b/native/Avalonia.Native/src/OSX/window.mm @@ -1,11 +1,11 @@ #import -#include "common.h" +#import "common.h" #import "window.h" -#include "menu.h" -#include "automation.h" +#import "menu.h" +#import "automation.h" #import "WindowBaseImpl.h" -#include "WindowImpl.h" -#include "AvnView.h" +#import "WindowImpl.h" +#import "AvnView.h" @implementation AvnWindow { From cd9be07ced12909309b68a68934ba4371855a3c3 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 6 May 2022 14:30:36 +0100 Subject: [PATCH 07/13] ensure menu gets applied. --- .../Avalonia.Native/src/OSX/WindowBaseImpl.h | 1 + .../Avalonia.Native/src/OSX/WindowBaseImpl.mm | 36 ++++++++++++++----- native/Avalonia.Native/src/OSX/WindowImpl.mm | 1 - 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/native/Avalonia.Native/src/OSX/WindowBaseImpl.h b/native/Avalonia.Native/src/OSX/WindowBaseImpl.h index 19065097fbd..d52518820c5 100644 --- a/native/Avalonia.Native/src/OSX/WindowBaseImpl.h +++ b/native/Avalonia.Native/src/OSX/WindowBaseImpl.h @@ -37,6 +37,7 @@ BEGIN_INTERFACE_MAP() NSSize lastSize; NSSize lastMinSize; NSSize lastMaxSize; + AvnMenu* lastMenu; NSString *_lastTitle; bool _shown; diff --git a/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm b/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm index 82c634dc4f0..bd763ce2fd2 100644 --- a/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm +++ b/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm @@ -34,6 +34,7 @@ _lastTitle = @""; Window = nullptr; + lastMenu = nullptr; } HRESULT WindowBaseImpl::ObtainNSViewHandle(void **ret) { @@ -91,6 +92,10 @@ [Window setTitle:_lastTitle]; + if(!isDialog) { + [GetWindowProtocol() setCanBecomeKeyAndMain]; + } + if (ShouldTakeFocusOnShow() && activate) { [Window orderFront:Window]; [Window makeKeyAndOrderFront:Window]; @@ -306,12 +311,14 @@ auto nativeMenu = dynamic_cast(menu); - auto nsmenu = nativeMenu->GetNative(); + lastMenu = nativeMenu->GetNative(); - [GetWindowProtocol() applyMenu:nsmenu]; + if(Window != nullptr) { + [GetWindowProtocol() applyMenu:lastMenu]; - if ([Window isKeyWindow]) { - [GetWindowProtocol() showWindowMenuWithAppMenu]; + if ([Window isKeyWindow]) { + [GetWindowProtocol() showWindowMenuWithAppMenu]; + } } return S_OK; @@ -524,17 +531,30 @@ [Window setStyleMask:NSWindowStyleMaskBorderless]; [Window setBackingType:NSBackingStoreBuffered]; - [Window setContentSize: lastSize]; + [Window setContentSize:lastSize]; [Window setContentMinSize:lastMinSize]; [Window setContentMaxSize:lastMaxSize]; [Window setOpaque:false]; - [Window setContentMinSize: lastMinSize]; - [Window setContentMaxSize: lastMaxSize]; + [Window setContentMinSize:lastMinSize]; + [Window setContentMaxSize:lastMaxSize]; + + if (lastMenu != nullptr) { + [GetWindowProtocol() applyMenu:lastMenu]; + + if ([Window isKeyWindow]) { + [GetWindowProtocol() showWindowMenuWithAppMenu]; + } + } } } id WindowBaseImpl::GetWindowProtocol() { - return static_cast>(Window); + id instance; + if ([Window conformsToProtocol:@protocol(AvnWindowProtocol)]) { + instance = Window; + } + + return instance; } diff --git a/native/Avalonia.Native/src/OSX/WindowImpl.mm b/native/Avalonia.Native/src/OSX/WindowImpl.mm index 3de4f5d5a8d..2a25cc69dad 100644 --- a/native/Avalonia.Native/src/OSX/WindowImpl.mm +++ b/native/Avalonia.Native/src/OSX/WindowImpl.mm @@ -20,7 +20,6 @@ _lastWindowState = Normal; _actualWindowState = Normal; WindowEvents = events; - [GetWindowProtocol() setCanBecomeKeyAndMain]; [Window disableCursorRects]; [Window setTabbingMode:NSWindowTabbingModeDisallowed]; [Window setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary]; From f008e403cf1e1ef18fa1d6fba631eb3048a18059 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 6 May 2022 16:02:50 +0100 Subject: [PATCH 08/13] make it compile 2 versions is AvnWindow (NSWindow / NSPanel version) fix include mess, and pragma once. --- native/Avalonia.Native/inc/rendertarget.h | 5 + .../src/OSX/AutoFitContentView.h | 4 +- .../src/OSX/AutoFitContentView.mm | 3 +- .../project.pbxproj | 26 ++- .../Avalonia.Native/src/OSX/AvnPanelWindow.h | 9 - .../Avalonia.Native/src/OSX/AvnPanelWindow.mm | 7 +- native/Avalonia.Native/src/OSX/AvnView.h | 10 +- native/Avalonia.Native/src/OSX/AvnView.mm | 3 +- .../src/OSX/{window.mm => AvnWindow.mm} | 189 +++++++----------- native/Avalonia.Native/src/OSX/PopupImpl.h | 9 + native/Avalonia.Native/src/OSX/PopupImpl.mm | 68 +++++++ native/Avalonia.Native/src/OSX/ResizeScope.h | 1 - native/Avalonia.Native/src/OSX/ResizeScope.mm | 2 +- .../Avalonia.Native/src/OSX/SystemDialogs.mm | 1 - .../Avalonia.Native/src/OSX/WindowBaseImpl.h | 5 +- .../Avalonia.Native/src/OSX/WindowBaseImpl.mm | 19 +- native/Avalonia.Native/src/OSX/WindowImpl.h | 1 - native/Avalonia.Native/src/OSX/WindowImpl.mm | 6 +- .../src/OSX/WindowInterfaces.h | 17 ++ .../Avalonia.Native/src/OSX/WindowProtocol.h | 2 + native/Avalonia.Native/src/OSX/automation.h | 3 +- native/Avalonia.Native/src/OSX/automation.mm | 7 +- native/Avalonia.Native/src/OSX/main.mm | 1 - native/Avalonia.Native/src/OSX/menu.mm | 1 - native/Avalonia.Native/src/OSX/window.h | 15 -- src/Avalonia.Native/avn.idl | 1 + 26 files changed, 235 insertions(+), 180 deletions(-) delete mode 100644 native/Avalonia.Native/src/OSX/AvnPanelWindow.h rename native/Avalonia.Native/src/OSX/{window.mm => AvnWindow.mm} (79%) create mode 100644 native/Avalonia.Native/src/OSX/PopupImpl.h create mode 100644 native/Avalonia.Native/src/OSX/PopupImpl.mm create mode 100644 native/Avalonia.Native/src/OSX/WindowInterfaces.h delete mode 100644 native/Avalonia.Native/src/OSX/window.h diff --git a/native/Avalonia.Native/inc/rendertarget.h b/native/Avalonia.Native/inc/rendertarget.h index 2b0338d099f..a59915777f0 100644 --- a/native/Avalonia.Native/inc/rendertarget.h +++ b/native/Avalonia.Native/inc/rendertarget.h @@ -1,3 +1,8 @@ +#pragma once + +#include "com.h" +#include "comimpl.h" +#include "avalonia-native.h" @protocol IRenderTarget -(void) setNewLayer: (CALayer*) layer; diff --git a/native/Avalonia.Native/src/OSX/AutoFitContentView.h b/native/Avalonia.Native/src/OSX/AutoFitContentView.h index 68c9fb8dc83..7f1f7641410 100644 --- a/native/Avalonia.Native/src/OSX/AutoFitContentView.h +++ b/native/Avalonia.Native/src/OSX/AutoFitContentView.h @@ -3,8 +3,10 @@ // Copyright (c) 2022 Avalonia. All rights reserved. // +#pragma once + #import -#import "avalonia-native.h" +#include "avalonia-native.h" @interface AutoFitContentView : NSView -(AutoFitContentView* _Nonnull) initWithContent: (NSView* _Nonnull) content; diff --git a/native/Avalonia.Native/src/OSX/AutoFitContentView.mm b/native/Avalonia.Native/src/OSX/AutoFitContentView.mm index 92d6f67a91d..4eaa08cbe20 100644 --- a/native/Avalonia.Native/src/OSX/AutoFitContentView.mm +++ b/native/Avalonia.Native/src/OSX/AutoFitContentView.mm @@ -4,7 +4,8 @@ // #include "AvnView.h" -#import "AutoFitContentView.h" +#include "AutoFitContentView.h" +#import "WindowInterfaces.h" @implementation AutoFitContentView { diff --git a/native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj b/native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj index 8ee2a61741f..6fc3977d4ef 100644 --- a/native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj +++ b/native/Avalonia.Native/src/OSX/Avalonia.Native.OSX.xcodeproj/project.pbxproj @@ -9,16 +9,19 @@ /* Begin PBXBuildFile section */ 18391068E48EF96E3DB5FDAB /* ResizeScope.mm in Sources */ = {isa = PBXBuildFile; fileRef = 18391E45702740FE9DD69695 /* ResizeScope.mm */; }; 1839125F057B0A4EB1760058 /* WindowImpl.mm in Sources */ = {isa = PBXBuildFile; fileRef = 183919BF108EB72A029F7671 /* WindowImpl.mm */; }; + 183914E50CF6D2EFC1667F7C /* WindowInterfaces.h in Headers */ = {isa = PBXBuildFile; fileRef = 18391DB45C7D892E61BF388C /* WindowInterfaces.h */; }; 1839151F32D1BB1AB51A7BB6 /* AvnPanelWindow.mm in Sources */ = {isa = PBXBuildFile; fileRef = 18391884C7476DA4E53A492D /* AvnPanelWindow.mm */; }; 183916173528EC2737DBE5E1 /* WindowBaseImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 183915BFF0E234CD3604A7CD /* WindowBaseImpl.h */; }; 1839171DCC651B0638603AC4 /* INSWindowHolder.h in Headers */ = {isa = PBXBuildFile; fileRef = 18391BBB7782C296D424071F /* INSWindowHolder.h */; }; 1839179A55FC1421BEE83330 /* WindowBaseImpl.mm in Sources */ = {isa = PBXBuildFile; fileRef = 18391676ECF0E983F4964357 /* WindowBaseImpl.mm */; }; - 1839196EC57BBC5C8BE1C735 /* AvnPanelWindow.h in Headers */ = {isa = PBXBuildFile; fileRef = 18391DC046BC700D56DF0B82 /* AvnPanelWindow.h */; }; 183919D91DB9AAB5D700C2EA /* WindowImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 18391CD090AA776E7E841AC9 /* WindowImpl.h */; }; 18391AA7E0BBA74D184C5734 /* AutoFitContentView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1839166350F32661F3ABD70F /* AutoFitContentView.mm */; }; + 18391AC16726CBC45856233B /* AvnWindow.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1839155B28B20FFB672D29C6 /* AvnWindow.mm */; }; + 18391AC65ADD7DDD33FBE737 /* PopupImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 183910513F396141938832B5 /* PopupImpl.h */; }; 18391C28BF1823B5464FDD36 /* ResizeScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 1839171D898F9BFC1373631A /* ResizeScope.h */; }; 18391CF07316F819E76B617C /* IWindowStateChanged.h in Headers */ = {isa = PBXBuildFile; fileRef = 183913C6BFD6856BD42D19FD /* IWindowStateChanged.h */; }; 18391D4EB311BC7EF8B8C0A6 /* AvnView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1839132D0E2454D911F1D1F9 /* AvnView.mm */; }; + 18391D8CD1756DC858DC1A09 /* PopupImpl.mm in Sources */ = {isa = PBXBuildFile; fileRef = 18391BB698579F40F1783F31 /* PopupImpl.mm */; }; 18391E1381E2D5BFD60265A9 /* AutoFitContentView.h in Headers */ = {isa = PBXBuildFile; fileRef = 18391654EF0E7AB3D3AB4071 /* AutoFitContentView.h */; }; 18391ED5F611FF62C45F196D /* AvnView.h in Headers */ = {isa = PBXBuildFile; fileRef = 18391D1669284AD2EC9E866A /* AvnView.h */; }; 18391F1E2411C79405A9943A /* WindowProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 1839122E037567BDD1D09DEB /* WindowProtocol.h */; }; @@ -43,16 +46,17 @@ AB00E4F72147CA920032A60A /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB00E4F62147CA920032A60A /* main.mm */; }; AB1E522C217613570091CD71 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB1E522B217613570091CD71 /* OpenGL.framework */; }; AB661C1E2148230F00291242 /* AppKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AB661C1D2148230F00291242 /* AppKit.framework */; }; - AB661C202148286E00291242 /* window.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB661C1F2148286E00291242 /* window.mm */; }; AB8F7D6B21482D7F0057DBA5 /* platformthreading.mm in Sources */ = {isa = PBXBuildFile; fileRef = AB8F7D6A21482D7F0057DBA5 /* platformthreading.mm */; }; BC11A5BE2608D58F0017BAD0 /* automation.h in Headers */ = {isa = PBXBuildFile; fileRef = BC11A5BC2608D58F0017BAD0 /* automation.h */; }; BC11A5BF2608D58F0017BAD0 /* automation.mm in Sources */ = {isa = PBXBuildFile; fileRef = BC11A5BD2608D58F0017BAD0 /* automation.mm */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 183910513F396141938832B5 /* PopupImpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PopupImpl.h; sourceTree = ""; }; 1839122E037567BDD1D09DEB /* WindowProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WindowProtocol.h; sourceTree = ""; }; 1839132D0E2454D911F1D1F9 /* AvnView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AvnView.mm; sourceTree = ""; }; 183913C6BFD6856BD42D19FD /* IWindowStateChanged.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IWindowStateChanged.h; sourceTree = ""; }; + 1839155B28B20FFB672D29C6 /* AvnWindow.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AvnWindow.mm; sourceTree = ""; }; 183915BFF0E234CD3604A7CD /* WindowBaseImpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WindowBaseImpl.h; sourceTree = ""; }; 18391654EF0E7AB3D3AB4071 /* AutoFitContentView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AutoFitContentView.h; sourceTree = ""; }; 1839166350F32661F3ABD70F /* AutoFitContentView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AutoFitContentView.mm; sourceTree = ""; }; @@ -60,10 +64,11 @@ 1839171D898F9BFC1373631A /* ResizeScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ResizeScope.h; sourceTree = ""; }; 18391884C7476DA4E53A492D /* AvnPanelWindow.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AvnPanelWindow.mm; sourceTree = ""; }; 183919BF108EB72A029F7671 /* WindowImpl.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WindowImpl.mm; sourceTree = ""; }; + 18391BB698579F40F1783F31 /* PopupImpl.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PopupImpl.mm; sourceTree = ""; }; 18391BBB7782C296D424071F /* INSWindowHolder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = INSWindowHolder.h; sourceTree = ""; }; 18391CD090AA776E7E841AC9 /* WindowImpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WindowImpl.h; sourceTree = ""; }; 18391D1669284AD2EC9E866A /* AvnView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AvnView.h; sourceTree = ""; }; - 18391DC046BC700D56DF0B82 /* AvnPanelWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AvnPanelWindow.h; sourceTree = ""; }; + 18391DB45C7D892E61BF388C /* WindowInterfaces.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WindowInterfaces.h; sourceTree = ""; }; 18391E45702740FE9DD69695 /* ResizeScope.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ResizeScope.mm; sourceTree = ""; }; 1A002B9D232135EE00021753 /* app.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = app.mm; sourceTree = ""; }; 1A1852DB23E05814008F0DED /* deadlock.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = deadlock.mm; sourceTree = ""; }; @@ -78,7 +83,6 @@ 37A4E71A2178846A00EACBCD /* headers */ = {isa = PBXFileReference; lastKnownFileType = folder; name = headers; path = ../../inc; sourceTree = ""; }; 37A517B22159597E00FBA241 /* Screens.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = Screens.mm; sourceTree = ""; }; 37C09D8721580FE4006A6758 /* SystemDialogs.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = SystemDialogs.mm; sourceTree = ""; }; - 37C09D8A21581EF2006A6758 /* window.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = window.h; sourceTree = ""; }; 37DDA9AF219330F8002E132B /* AvnString.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = AvnString.mm; sourceTree = ""; }; 37DDA9B121933371002E132B /* AvnString.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AvnString.h; sourceTree = ""; }; 37E2330E21583241000CB7E2 /* KeyTransform.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = KeyTransform.mm; sourceTree = ""; }; @@ -92,7 +96,6 @@ AB00E4F62147CA920032A60A /* main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = ""; }; AB1E522B217613570091CD71 /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = System/Library/Frameworks/OpenGL.framework; sourceTree = SDKROOT; }; AB661C1D2148230F00291242 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; - AB661C1F2148286E00291242 /* window.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = window.mm; sourceTree = ""; }; AB661C212148288600291242 /* common.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = common.h; sourceTree = ""; }; AB7A61EF2147C815003C5833 /* libAvalonia.Native.OSX.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libAvalonia.Native.OSX.dylib; sourceTree = BUILT_PRODUCTS_DIR; }; AB8F7D6A21482D7F0057DBA5 /* platformthreading.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = platformthreading.mm; sourceTree = ""; }; @@ -148,8 +151,6 @@ AB661C212148288600291242 /* common.h */, 379860FE214DA0C000CD0246 /* KeyTransform.h */, 37E2330E21583241000CB7E2 /* KeyTransform.mm */, - AB661C1F2148286E00291242 /* window.mm */, - 37C09D8A21581EF2006A6758 /* window.h */, AB00E4F62147CA920032A60A /* main.mm */, 37155CE3233C00EB0034DCE9 /* menu.h */, 520624B222973F4100C4DCEF /* menu.mm */, @@ -173,8 +174,11 @@ 1839166350F32661F3ABD70F /* AutoFitContentView.mm */, 18391654EF0E7AB3D3AB4071 /* AutoFitContentView.h */, 18391884C7476DA4E53A492D /* AvnPanelWindow.mm */, - 18391DC046BC700D56DF0B82 /* AvnPanelWindow.h */, 1839122E037567BDD1D09DEB /* WindowProtocol.h */, + 1839155B28B20FFB672D29C6 /* AvnWindow.mm */, + 18391DB45C7D892E61BF388C /* WindowInterfaces.h */, + 18391BB698579F40F1783F31 /* PopupImpl.mm */, + 183910513F396141938832B5 /* PopupImpl.h */, ); sourceTree = ""; }; @@ -202,8 +206,9 @@ 18391C28BF1823B5464FDD36 /* ResizeScope.h in Headers */, 18391ED5F611FF62C45F196D /* AvnView.h in Headers */, 18391E1381E2D5BFD60265A9 /* AutoFitContentView.h in Headers */, - 1839196EC57BBC5C8BE1C735 /* AvnPanelWindow.h in Headers */, 18391F1E2411C79405A9943A /* WindowProtocol.h in Headers */, + 183914E50CF6D2EFC1667F7C /* WindowInterfaces.h in Headers */, + 18391AC65ADD7DDD33FBE737 /* PopupImpl.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -282,13 +287,14 @@ 1A465D10246AB61600C5858B /* dnd.mm in Sources */, AB00E4F72147CA920032A60A /* main.mm in Sources */, 37C09D8821580FE4006A6758 /* SystemDialogs.mm in Sources */, - AB661C202148286E00291242 /* window.mm in Sources */, 1839179A55FC1421BEE83330 /* WindowBaseImpl.mm in Sources */, 1839125F057B0A4EB1760058 /* WindowImpl.mm in Sources */, 18391068E48EF96E3DB5FDAB /* ResizeScope.mm in Sources */, 18391D4EB311BC7EF8B8C0A6 /* AvnView.mm in Sources */, 18391AA7E0BBA74D184C5734 /* AutoFitContentView.mm in Sources */, 1839151F32D1BB1AB51A7BB6 /* AvnPanelWindow.mm in Sources */, + 18391AC16726CBC45856233B /* AvnWindow.mm in Sources */, + 18391D8CD1756DC858DC1A09 /* PopupImpl.mm in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/native/Avalonia.Native/src/OSX/AvnPanelWindow.h b/native/Avalonia.Native/src/OSX/AvnPanelWindow.h deleted file mode 100644 index 0fe95d044d3..00000000000 --- a/native/Avalonia.Native/src/OSX/AvnPanelWindow.h +++ /dev/null @@ -1,9 +0,0 @@ -// -// Created by Dan Walmsley on 06/05/2022. -// Copyright (c) 2022 Avalonia. All rights reserved. -// - -#define NSWindow NSPanel -#define AvnWindow AvnPanelWindow - -//#include "window.h" \ No newline at end of file diff --git a/native/Avalonia.Native/src/OSX/AvnPanelWindow.mm b/native/Avalonia.Native/src/OSX/AvnPanelWindow.mm index 8b79e28ca18..23651890109 100644 --- a/native/Avalonia.Native/src/OSX/AvnPanelWindow.mm +++ b/native/Avalonia.Native/src/OSX/AvnPanelWindow.mm @@ -3,6 +3,9 @@ // Copyright (c) 2022 Avalonia. All rights reserved. // -#define AvnWindow AvnPanelWindow +#pragma once + +#define IS_NSPANEL + +#include "AvnWindow.mm" -//#include "window.mm" \ No newline at end of file diff --git a/native/Avalonia.Native/src/OSX/AvnView.h b/native/Avalonia.Native/src/OSX/AvnView.h index c6dd90150f8..86a68d34c5a 100644 --- a/native/Avalonia.Native/src/OSX/AvnView.h +++ b/native/Avalonia.Native/src/OSX/AvnView.h @@ -2,17 +2,15 @@ // Created by Dan Walmsley on 05/05/2022. // Copyright (c) 2022 Avalonia. All rights reserved. // - +#pragma once #import #import #import -#include "window.h" -#import "comimpl.h" -#import "common.h" -#import "WindowImpl.h" -#import "KeyTransform.h" +#include "common.h" +#include "WindowImpl.h" +#include "KeyTransform.h" @class AvnAccessibilityElement; diff --git a/native/Avalonia.Native/src/OSX/AvnView.mm b/native/Avalonia.Native/src/OSX/AvnView.mm index 24cbc25502b..e6cf73755bb 100644 --- a/native/Avalonia.Native/src/OSX/AvnView.mm +++ b/native/Avalonia.Native/src/OSX/AvnView.mm @@ -4,8 +4,9 @@ // #import -#import "AvnView.h" +#include "AvnView.h" #include "automation.h" +#import "WindowInterfaces.h" @implementation AvnView { diff --git a/native/Avalonia.Native/src/OSX/window.mm b/native/Avalonia.Native/src/OSX/AvnWindow.mm similarity index 79% rename from native/Avalonia.Native/src/OSX/window.mm rename to native/Avalonia.Native/src/OSX/AvnWindow.mm index e4bfedaba45..09534a0a4b1 100644 --- a/native/Avalonia.Native/src/OSX/window.mm +++ b/native/Avalonia.Native/src/OSX/AvnWindow.mm @@ -1,13 +1,32 @@ +// +// Created by Dan Walmsley on 06/05/2022. +// Copyright (c) 2022 Avalonia. All rights reserved. +// + + #import -#import "common.h" -#import "window.h" -#import "menu.h" -#import "automation.h" +#import "WindowProtocol.h" #import "WindowBaseImpl.h" -#import "WindowImpl.h" -#import "AvnView.h" -@implementation AvnWindow +#ifdef IS_NSPANEL +#define BASE_CLASS NSPanel +#define CLASS_NAME AvnPanel +#else +#define BASE_CLASS NSWindow +#define CLASS_NAME AvnWindow +#endif + +#import +#include "common.h" +#include "menu.h" +#include "automation.h" +#include "WindowBaseImpl.h" +#include "WindowImpl.h" +#include "AvnView.h" +#include "WindowInterfaces.h" +#include "PopupImpl.h" + +@implementation CLASS_NAME { ComPtr _parent; bool _canBecomeKeyAndMain; @@ -66,7 +85,7 @@ - (void)performClose:(id)sender - (void)pollModalSession:(nonnull NSModalSession)session { auto response = [NSApp runModalSession:session]; - + if(response == NSModalResponseContinue) { dispatch_async(dispatch_get_main_queue(), ^{ @@ -85,18 +104,18 @@ -(void) showWindowMenuWithAppMenu if(_menu != nullptr) { auto appMenuItem = ::GetAppMenuItem(); - + if(appMenuItem != nullptr) { auto appMenu = [appMenuItem menu]; - + [appMenu removeItem:appMenuItem]; - + [_menu insertItem:appMenuItem atIndex:0]; - + [_menu setHasGlobalMenuItem:true]; } - + [NSApp setMenu:_menu]; } else @@ -108,22 +127,22 @@ -(void) showWindowMenuWithAppMenu -(void) showAppMenuOnly { auto appMenuItem = ::GetAppMenuItem(); - + if(appMenuItem != nullptr) { auto appMenu = ::GetAppMenu(); - + auto nativeAppMenu = dynamic_cast(appMenu); - + [[appMenuItem menu] removeItem:appMenuItem]; - + if(_menu != nullptr) { [_menu setHasGlobalMenuItem:false]; } - + [nativeAppMenu->GetNative() addItem:appMenuItem]; - + [NSApp setMenu:nativeAppMenu->GetNative()]; } } @@ -134,7 +153,7 @@ -(void) applyMenu:(AvnMenu *)menu { menu = [AvnMenu new]; } - + _menu = menu; } @@ -143,19 +162,19 @@ -(void) setCanBecomeKeyAndMain _canBecomeKeyAndMain = true; } --(AvnWindow*) initWithParent: (WindowBaseImpl*) parent contentRect: (NSRect)contentRect styleMask: (NSWindowStyleMask)styleMask; +-(CLASS_NAME*) initWithParent: (WindowBaseImpl*) parent contentRect: (NSRect)contentRect styleMask: (NSWindowStyleMask)styleMask; { // https://jameshfisher.com/2020/07/10/why-is-the-contentrect-of-my-nswindow-ignored/ // create nswindow with specific contentRect, otherwise we wont be able to resize the window // until several ms after the window is physically on the screen. self = [super initWithContentRect:contentRect styleMask: styleMask backing:NSBackingStoreBuffered defer:false]; - + [self setReleasedWhenClosed:false]; _parent = parent; [self setDelegate:self]; _closed = false; _isEnabled = true; - + [self backingScaleFactor]; [self setOpaque:NO]; [self setBackgroundColor: [NSColor clearColor]]; @@ -167,12 +186,12 @@ -(AvnWindow*) initWithParent: (WindowBaseImpl*) parent contentRect: (NSRect)con - (BOOL)windowShouldClose:(NSWindow *)sender { auto window = dynamic_cast(_parent.getRaw()); - + if(window != nullptr) { return !window->WindowEvents->Closing(); } - + return true; } @@ -201,16 +220,17 @@ -(BOOL)canBecomeKeyWindow // 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 = objc_cast(uch); + // TODO protocol + auto ch = objc_cast(uch); if(ch == nil) continue; if (ch.isDialog) return false; } - + return true; } - + return false; } @@ -232,7 +252,7 @@ -(void) setEnabled:(bool)enable -(void)becomeKeyWindow { [self showWindowMenuWithAppMenu]; - + if(_parent != nullptr) { _parent->BaseEvents->Activated(); @@ -243,7 +263,8 @@ -(void)becomeKeyWindow -(void) restoreParentWindow; { - auto parent = objc_cast([self parentWindow]); + // TODO protocol + auto parent = objc_cast([self parentWindow]); if(parent != nil) { [parent removeChildWindow:self]; @@ -253,7 +274,7 @@ -(void) restoreParentWindow; - (void)windowDidMiniaturize:(NSNotification *)notification { auto parent = dynamic_cast(_parent.operator->()); - + if(parent != nullptr) { parent->WindowStateChanged(); @@ -263,7 +284,7 @@ - (void)windowDidMiniaturize:(NSNotification *)notification - (void)windowDidDeminiaturize:(NSNotification *)notification { auto parent = dynamic_cast(_parent.operator->()); - + if(parent != nullptr) { parent->WindowStateChanged(); @@ -273,7 +294,7 @@ - (void)windowDidDeminiaturize:(NSNotification *)notification - (void)windowDidResize:(NSNotification *)notification { auto parent = dynamic_cast(_parent.operator->()); - + if(parent != nullptr) { parent->WindowStateChanged(); @@ -283,7 +304,7 @@ - (void)windowDidResize:(NSNotification *)notification - (void)windowWillExitFullScreen:(NSNotification *)notification { auto parent = dynamic_cast(_parent.operator->()); - + if(parent != nullptr) { parent->StartStateTransition(); @@ -293,22 +314,22 @@ - (void)windowWillExitFullScreen:(NSNotification *)notification - (void)windowDidExitFullScreen:(NSNotification *)notification { auto parent = dynamic_cast(_parent.operator->()); - + if(parent != nullptr) { parent->EndStateTransition(); - + if(parent->Decorations() != SystemDecorationsFull && parent->WindowState() == Maximized) { NSRect screenRect = [[self screen] visibleFrame]; [self setFrame:screenRect display:YES]; } - + if(parent->WindowState() == Minimized) { [self miniaturize:nullptr]; } - + parent->WindowStateChanged(); } } @@ -316,7 +337,7 @@ - (void)windowDidExitFullScreen:(NSNotification *)notification - (void)windowWillEnterFullScreen:(NSNotification *)notification { auto parent = dynamic_cast(_parent.operator->()); - + if(parent != nullptr) { parent->StartStateTransition(); @@ -326,7 +347,7 @@ - (void)windowWillEnterFullScreen:(NSNotification *)notification - (void)windowDidEnterFullScreen:(NSNotification *)notification { auto parent = dynamic_cast(_parent.operator->()); - + if(parent != nullptr) { parent->EndStateTransition(); @@ -343,20 +364,20 @@ -(void)resignKeyWindow { if(_parent) _parent->BaseEvents->Deactivated(); - + [self showAppMenuOnly]; - + [super resignKeyWindow]; } - (void)windowDidMove:(NSNotification *)notification { AvnPoint position; - + if(_parent != nullptr) { auto cparent = dynamic_cast(_parent.getRaw()); - + if(cparent != nullptr) { if(cparent->WindowState() == Maximized) @@ -364,7 +385,7 @@ - (void)windowDidMove:(NSNotification *)notification cparent->SetWindowState(Normal); } } - + _parent->GetPosition(&position); _parent->BaseEvents->PositionChanged(position); } @@ -379,7 +400,7 @@ - (AvnPoint) translateLocalPoint:(AvnPoint)pt - (void)sendEvent:(NSEvent *)event { [super sendEvent:event]; - + /// This is to detect non-client clicks. This can only be done on Windows... not popups, hence the dynamic_cast. if(_parent != nullptr && dynamic_cast(_parent.getRaw()) != nullptr) { @@ -390,30 +411,30 @@ - (void)sendEvent:(NSEvent *)event AvnView* view = _parent->View; NSPoint windowPoint = [event locationInWindow]; NSPoint viewPoint = [view convertPoint:windowPoint fromView:nil]; - + if (!NSPointInRect(viewPoint, view.bounds)) { auto avnPoint = [AvnView toAvnPoint:windowPoint]; auto point = [self translateLocalPoint:avnPoint]; AvnVector delta = { 0, 0 }; - + _parent->BaseEvents->RawMouseEvent(NonClientLeftButtonDown, static_cast([event timestamp] * 1000), AvnInputModifiersNone, point, delta); } } - break; - + break; + case NSEventTypeMouseEntered: { _parent->UpdateCursor(); } - break; - + break; + case NSEventTypeMouseExited: { [[NSCursor arrowCursor] set]; } - break; - + break; + default: break; } @@ -422,63 +443,3 @@ - (void)sendEvent:(NSEvent *)event @end -class PopupImpl : public virtual WindowBaseImpl, public IAvnPopup -{ -private: - BEGIN_INTERFACE_MAP() - INHERIT_INTERFACE_MAP(WindowBaseImpl) - INTERFACE_MAP_ENTRY(IAvnPopup, IID_IAvnPopup) - END_INTERFACE_MAP() - virtual ~PopupImpl(){} - ComPtr WindowEvents; - PopupImpl(IAvnWindowEvents* events, IAvnGlContext* gl) : WindowBaseImpl(events, gl) - { - WindowEvents = events; - [Window setLevel:NSPopUpMenuWindowLevel]; - } -protected: - virtual NSWindowStyleMask GetStyle() override - { - return NSWindowStyleMaskBorderless; - } - - virtual HRESULT Resize(double x, double y, AvnPlatformResizeReason reason) override - { - START_COM_CALL; - - @autoreleasepool - { - if (Window != nullptr) - { - [Window setContentSize:NSSize{x, y}]; - - [Window setFrameTopLeftPoint:ToNSPoint(ConvertPointY(lastPositionSet))]; - } - - return S_OK; - } - } -public: - virtual bool ShouldTakeFocusOnShow() override - { - return false; - } -}; - -extern IAvnPopup* CreateAvnPopup(IAvnWindowEvents*events, IAvnGlContext* gl) -{ - @autoreleasepool - { - IAvnPopup* ptr = dynamic_cast(new PopupImpl(events, gl)); - return ptr; - } -} - -extern IAvnWindow* CreateAvnWindow(IAvnWindowEvents*events, IAvnGlContext* gl) -{ - @autoreleasepool - { - IAvnWindow* ptr = (IAvnWindow*)new WindowImpl(events, gl); - return ptr; - } -} diff --git a/native/Avalonia.Native/src/OSX/PopupImpl.h b/native/Avalonia.Native/src/OSX/PopupImpl.h new file mode 100644 index 00000000000..451019a6a4f --- /dev/null +++ b/native/Avalonia.Native/src/OSX/PopupImpl.h @@ -0,0 +1,9 @@ +// +// Created by Dan Walmsley on 06/05/2022. +// Copyright (c) 2022 Avalonia. All rights reserved. +// + +#ifndef AVALONIA_NATIVE_OSX_POPUPIMPL_H +#define AVALONIA_NATIVE_OSX_POPUPIMPL_H + +#endif //AVALONIA_NATIVE_OSX_POPUPIMPL_H diff --git a/native/Avalonia.Native/src/OSX/PopupImpl.mm b/native/Avalonia.Native/src/OSX/PopupImpl.mm new file mode 100644 index 00000000000..64a8780158c --- /dev/null +++ b/native/Avalonia.Native/src/OSX/PopupImpl.mm @@ -0,0 +1,68 @@ +// +// Created by Dan Walmsley on 06/05/2022. +// Copyright (c) 2022 Avalonia. All rights reserved. +// + +#include "WindowInterfaces.h" +#include "AvnView.h" +#include "WindowImpl.h" +#include "automation.h" +#include "menu.h" +#include "common.h" +#import "WindowBaseImpl.h" +#import "WindowProtocol.h" +#import +#include "PopupImpl.h" + +class PopupImpl : public virtual WindowBaseImpl, public IAvnPopup +{ +private: + BEGIN_INTERFACE_MAP() + INHERIT_INTERFACE_MAP(WindowBaseImpl) + INTERFACE_MAP_ENTRY(IAvnPopup, IID_IAvnPopup) + END_INTERFACE_MAP() + virtual ~PopupImpl(){} + ComPtr WindowEvents; + PopupImpl(IAvnWindowEvents* events, IAvnGlContext* gl) : WindowBaseImpl(events, gl) + { + WindowEvents = events; + [Window setLevel:NSPopUpMenuWindowLevel]; + } +protected: + virtual NSWindowStyleMask GetStyle() override + { + return NSWindowStyleMaskBorderless; + } + + virtual HRESULT Resize(double x, double y, AvnPlatformResizeReason reason) override + { + START_COM_CALL; + + @autoreleasepool + { + if (Window != nullptr) + { + [Window setContentSize:NSSize{x, y}]; + + [Window setFrameTopLeftPoint:ToNSPoint(ConvertPointY(lastPositionSet))]; + } + + return S_OK; + } + } +public: + virtual bool ShouldTakeFocusOnShow() override + { + return false; + } +}; + + +extern IAvnPopup* CreateAvnPopup(IAvnWindowEvents*events, IAvnGlContext* gl) +{ + @autoreleasepool + { + IAvnPopup* ptr = dynamic_cast(new PopupImpl(events, gl)); + return ptr; + } +} \ No newline at end of file diff --git a/native/Avalonia.Native/src/OSX/ResizeScope.h b/native/Avalonia.Native/src/OSX/ResizeScope.h index 7509f93c018..9a43c158feb 100644 --- a/native/Avalonia.Native/src/OSX/ResizeScope.h +++ b/native/Avalonia.Native/src/OSX/ResizeScope.h @@ -6,7 +6,6 @@ #ifndef AVALONIA_NATIVE_OSX_RESIZESCOPE_H #define AVALONIA_NATIVE_OSX_RESIZESCOPE_H -#include "window.h" #include "avalonia-native.h" @class AvnView; diff --git a/native/Avalonia.Native/src/OSX/ResizeScope.mm b/native/Avalonia.Native/src/OSX/ResizeScope.mm index 90e7f5cf151..9f1177af8b0 100644 --- a/native/Avalonia.Native/src/OSX/ResizeScope.mm +++ b/native/Avalonia.Native/src/OSX/ResizeScope.mm @@ -5,7 +5,7 @@ #import #include "ResizeScope.h" -#import "AvnView.h" +#include "AvnView.h" ResizeScope::ResizeScope(AvnView *view, AvnPlatformResizeReason reason) { _view = view; diff --git a/native/Avalonia.Native/src/OSX/SystemDialogs.mm b/native/Avalonia.Native/src/OSX/SystemDialogs.mm index 21ad9cfa7c6..535b6c3b665 100644 --- a/native/Avalonia.Native/src/OSX/SystemDialogs.mm +++ b/native/Avalonia.Native/src/OSX/SystemDialogs.mm @@ -1,5 +1,4 @@ #include "common.h" -#include "window.h" #include "INSWindowHolder.h" class SystemDialogs : public ComSingleObject diff --git a/native/Avalonia.Native/src/OSX/WindowBaseImpl.h b/native/Avalonia.Native/src/OSX/WindowBaseImpl.h index d52518820c5..a8f549b3c68 100644 --- a/native/Avalonia.Native/src/OSX/WindowBaseImpl.h +++ b/native/Avalonia.Native/src/OSX/WindowBaseImpl.h @@ -6,11 +6,12 @@ #ifndef AVALONIA_NATIVE_OSX_WINDOWBASEIMPL_H #define AVALONIA_NATIVE_OSX_WINDOWBASEIMPL_H -#import "rendertarget.h" -#import "WindowProtocol.h" +#include "rendertarget.h" #include "INSWindowHolder.h" @class AutoFitContentView; +@class AvnMenu; +@protocol AvnWindowProtocol; class WindowBaseImpl : public virtual ComObject, public virtual IAvnWindowBase, diff --git a/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm b/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm index bd763ce2fd2..a58d0bb8be7 100644 --- a/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm +++ b/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm @@ -5,14 +5,14 @@ #import #include "common.h" -#import "window.h" -#import "AvnView.h" +#include "AvnView.h" #include "menu.h" #include "automation.h" -#import "cursor.h" +#include "cursor.h" #include "ResizeScope.h" -#import "AutoFitContentView.h" -#include "WindowBaseImpl.h" +#include "AutoFitContentView.h" +#import "WindowProtocol.h" +#import "WindowInterfaces.h" WindowBaseImpl::~WindowBaseImpl() { @@ -558,3 +558,12 @@ return instance; } + +extern IAvnWindow* CreateAvnWindow(IAvnWindowEvents*events, IAvnGlContext* gl) +{ + @autoreleasepool + { + IAvnWindow* ptr = (IAvnWindow*)new WindowImpl(events, gl); + return ptr; + } +} diff --git a/native/Avalonia.Native/src/OSX/WindowImpl.h b/native/Avalonia.Native/src/OSX/WindowImpl.h index b229921baa9..a4ee4f447cf 100644 --- a/native/Avalonia.Native/src/OSX/WindowImpl.h +++ b/native/Avalonia.Native/src/OSX/WindowImpl.h @@ -6,7 +6,6 @@ #ifndef AVALONIA_NATIVE_OSX_WINDOWIMPL_H #define AVALONIA_NATIVE_OSX_WINDOWIMPL_H - #import "WindowBaseImpl.h" #include "IWindowStateChanged.h" diff --git a/native/Avalonia.Native/src/OSX/WindowImpl.mm b/native/Avalonia.Native/src/OSX/WindowImpl.mm index 2a25cc69dad..9992d64b47d 100644 --- a/native/Avalonia.Native/src/OSX/WindowImpl.mm +++ b/native/Avalonia.Native/src/OSX/WindowImpl.mm @@ -4,10 +4,10 @@ // #import -#import "window.h" -#import "AutoFitContentView.h" -#import "AvnView.h" +#include "AutoFitContentView.h" +#include "AvnView.h" #include "automation.h" +#include "WindowProtocol.h" WindowImpl::WindowImpl(IAvnWindowEvents *events, IAvnGlContext *gl) : WindowBaseImpl(events, gl) { _isClientAreaExtended = false; diff --git a/native/Avalonia.Native/src/OSX/WindowInterfaces.h b/native/Avalonia.Native/src/OSX/WindowInterfaces.h new file mode 100644 index 00000000000..6e6d62e85e7 --- /dev/null +++ b/native/Avalonia.Native/src/OSX/WindowInterfaces.h @@ -0,0 +1,17 @@ +// +// Created by Dan Walmsley on 06/05/2022. +// Copyright (c) 2022 Avalonia. All rights reserved. +// + +#import +#import +#include "WindowProtocol.h" +#include "WindowBaseImpl.h" + +@interface AvnWindow : NSWindow +-(AvnWindow* _Nonnull) initWithParent: (WindowBaseImpl* _Nonnull) parent contentRect: (NSRect)contentRect styleMask: (NSWindowStyleMask)styleMask; +@end + +@interface AvnPanel : NSPanel +-(AvnPanel* _Nonnull) initWithParent: (WindowBaseImpl* _Nonnull) parent contentRect: (NSRect)contentRect styleMask: (NSWindowStyleMask)styleMask; +@end \ No newline at end of file diff --git a/native/Avalonia.Native/src/OSX/WindowProtocol.h b/native/Avalonia.Native/src/OSX/WindowProtocol.h index ac20fe8eb13..d81d2f1ed1a 100644 --- a/native/Avalonia.Native/src/OSX/WindowProtocol.h +++ b/native/Avalonia.Native/src/OSX/WindowProtocol.h @@ -3,6 +3,8 @@ // Copyright (c) 2022 Avalonia. All rights reserved. // +#pragma once + #import @class AvnMenu; diff --git a/native/Avalonia.Native/src/OSX/automation.h b/native/Avalonia.Native/src/OSX/automation.h index 1727d21f27f..367df3619d8 100644 --- a/native/Avalonia.Native/src/OSX/automation.h +++ b/native/Avalonia.Native/src/OSX/automation.h @@ -1,5 +1,6 @@ -#import +#pragma once +#import NS_ASSUME_NONNULL_BEGIN class IAvnAutomationPeer; diff --git a/native/Avalonia.Native/src/OSX/automation.mm b/native/Avalonia.Native/src/OSX/automation.mm index 7a0b3b81271..d0c8d7a9dbf 100644 --- a/native/Avalonia.Native/src/OSX/automation.mm +++ b/native/Avalonia.Native/src/OSX/automation.mm @@ -1,9 +1,8 @@ #include "common.h" -#import "automation.h" -#import "window.h" +#include "automation.h" #include "AvnString.h" -#import "INSWindowHolder.h" -#import "AvnView.h" +#include "INSWindowHolder.h" +#include "AvnView.h" @interface AvnAccessibilityElement (Events) - (void) raiseChildrenChanged; diff --git a/native/Avalonia.Native/src/OSX/main.mm b/native/Avalonia.Native/src/OSX/main.mm index 011f881e945..6ee86b21ae5 100644 --- a/native/Avalonia.Native/src/OSX/main.mm +++ b/native/Avalonia.Native/src/OSX/main.mm @@ -1,7 +1,6 @@ //This file will contain actual IID structures #define COM_GUIDS_MATERIALIZE #include "common.h" -#include "window.h" static NSString* s_appTitle = @"Avalonia"; diff --git a/native/Avalonia.Native/src/OSX/menu.mm b/native/Avalonia.Native/src/OSX/menu.mm index fd74edd7729..b05588a441e 100644 --- a/native/Avalonia.Native/src/OSX/menu.mm +++ b/native/Avalonia.Native/src/OSX/menu.mm @@ -1,7 +1,6 @@ #include "common.h" #include "menu.h" -#import "window.h" #include "KeyTransform.h" #include #include /* For kVK_ constants, and TIS functions. */ diff --git a/native/Avalonia.Native/src/OSX/window.h b/native/Avalonia.Native/src/OSX/window.h deleted file mode 100644 index 1a001dd6e4c..00000000000 --- a/native/Avalonia.Native/src/OSX/window.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef window_h -#define window_h - -#import "avalonia-native.h" -#import "WindowProtocol.h" - -@class AvnMenu; - -class WindowBaseImpl; - -@interface AvnWindow : NSWindow --(AvnWindow* _Nonnull) initWithParent: (WindowBaseImpl* _Nonnull) parent contentRect: (NSRect)contentRect styleMask: (NSWindowStyleMask)styleMask; -@end - -#endif /* window_h */ diff --git a/src/Avalonia.Native/avn.idl b/src/Avalonia.Native/avn.idl index 8092004989b..d6ef0f89186 100644 --- a/src/Avalonia.Native/avn.idl +++ b/src/Avalonia.Native/avn.idl @@ -2,6 +2,7 @@ @clr-access internal @clr-map bool int @cpp-preamble @@ +#pragma once #include "com.h" #include "stddef.h" @@ From 1cca34f56ede6b1c4b2169b64a74a9832331e536 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 6 May 2022 17:30:03 +0100 Subject: [PATCH 09/13] actually create nspanels for dialogs. --- native/Avalonia.Native/src/OSX/AvnWindow.mm | 35 ++++++++----------- .../Avalonia.Native/src/OSX/WindowBaseImpl.h | 1 + .../Avalonia.Native/src/OSX/WindowBaseImpl.mm | 28 ++++++++++----- native/Avalonia.Native/src/OSX/WindowImpl.mm | 2 +- .../Avalonia.Native/src/OSX/WindowProtocol.h | 1 - 5 files changed, 35 insertions(+), 32 deletions(-) diff --git a/native/Avalonia.Native/src/OSX/AvnWindow.mm b/native/Avalonia.Native/src/OSX/AvnWindow.mm index 09534a0a4b1..d0b23540f9f 100644 --- a/native/Avalonia.Native/src/OSX/AvnWindow.mm +++ b/native/Avalonia.Native/src/OSX/AvnWindow.mm @@ -29,7 +29,6 @@ @implementation CLASS_NAME { ComPtr _parent; - bool _canBecomeKeyAndMain; bool _closed; bool _isEnabled; bool _isExtended; @@ -157,11 +156,6 @@ -(void) applyMenu:(AvnMenu *)menu _menu = menu; } --(void) setCanBecomeKeyAndMain -{ - _canBecomeKeyAndMain = true; -} - -(CLASS_NAME*) initWithParent: (WindowBaseImpl*) parent contentRect: (NSRect)contentRect styleMask: (NSWindowStyleMask)styleMask; { // https://jameshfisher.com/2020/07/10/why-is-the-contentrect-of-my-nswindow-ignored/ @@ -215,28 +209,27 @@ - (void)windowWillClose:(NSNotification *)notification -(BOOL)canBecomeKeyWindow { - if (_canBecomeKeyAndMain) + // 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]) { - // 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]) - { - // TODO protocol - auto ch = objc_cast(uch); - if(ch == nil) - continue; - if (ch.isDialog) - return false; - } - - return true; + // TODO protocol + auto ch = objc_cast(uch); + if(ch == nil) + continue; + if (ch.isDialog) + return false; } - return false; + return true; } -(BOOL)canBecomeMainWindow { - return _canBecomeKeyAndMain; +#ifdef IS_NSPANEL + return false; +#else + return true; +#endif } -(bool)shouldTryToHandleEvents diff --git a/native/Avalonia.Native/src/OSX/WindowBaseImpl.h b/native/Avalonia.Native/src/OSX/WindowBaseImpl.h index a8f549b3c68..ae1e6a7016b 100644 --- a/native/Avalonia.Native/src/OSX/WindowBaseImpl.h +++ b/native/Avalonia.Native/src/OSX/WindowBaseImpl.h @@ -122,6 +122,7 @@ BEGIN_INTERFACE_MAP() id GetWindowProtocol (); private: + void CreateNSWindow (bool isDialog); void InitialiseNSWindow (); }; diff --git a/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm b/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm index a58d0bb8be7..414632770f5 100644 --- a/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm +++ b/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm @@ -13,6 +13,7 @@ #include "AutoFitContentView.h" #import "WindowProtocol.h" #import "WindowInterfaces.h" +#include "WindowBaseImpl.h" WindowBaseImpl::~WindowBaseImpl() { @@ -31,6 +32,9 @@ lastPositionSet.X = 100; lastPositionSet.Y = 100; + lastSize = NSSize { 100, 100 }; + lastMaxSize = NSSize { CGFLOAT_MAX, CGFLOAT_MAX}; + lastMinSize = NSSize { 0, 0 }; _lastTitle = @""; Window = nullptr; @@ -85,6 +89,7 @@ START_COM_CALL; @autoreleasepool { + CreateNSWindow(isDialog); InitialiseNSWindow(); SetPosition(lastPositionSet); @@ -92,10 +97,6 @@ [Window setTitle:_lastTitle]; - if(!isDialog) { - [GetWindowProtocol() setCanBecomeKeyAndMain]; - } - if (ShouldTakeFocusOnShow() && activate) { [Window orderFront:Window]; [Window makeKeyAndOrderFront:Window]; @@ -524,9 +525,21 @@ [Window setStyleMask:GetStyle()]; } -void WindowBaseImpl::InitialiseNSWindow() { +void WindowBaseImpl::CreateNSWindow(bool isDialog) { if(Window == nullptr) { - Window = [[AvnWindow alloc] initWithParent:this contentRect:NSRect{0, 0, lastSize} styleMask:GetStyle()]; + if(isDialog) + { + Window = [[AvnPanel alloc] initWithParent:this contentRect:NSRect{0, 0, lastSize} styleMask:GetStyle()]; + } + else + { + Window = [[AvnWindow alloc] initWithParent:this contentRect:NSRect{0, 0, lastSize} styleMask:GetStyle()]; + } + } +} + +void WindowBaseImpl::InitialiseNSWindow() { + if(Window != nullptr) { [Window setContentView:StandardContainer]; [Window setStyleMask:NSWindowStyleMaskBorderless]; [Window setBackingType:NSBackingStoreBuffered]; @@ -537,9 +550,6 @@ [Window setOpaque:false]; - [Window setContentMinSize:lastMinSize]; - [Window setContentMaxSize:lastMaxSize]; - if (lastMenu != nullptr) { [GetWindowProtocol() applyMenu:lastMenu]; diff --git a/native/Avalonia.Native/src/OSX/WindowImpl.mm b/native/Avalonia.Native/src/OSX/WindowImpl.mm index 9992d64b47d..63a38f0c22d 100644 --- a/native/Avalonia.Native/src/OSX/WindowImpl.mm +++ b/native/Avalonia.Native/src/OSX/WindowImpl.mm @@ -507,7 +507,7 @@ } NSWindowStyleMask WindowImpl::GetStyle() { - unsigned long s = NSWindowStyleMaskBorderless; + unsigned long s = this->_isDialog ? NSWindowStyleMaskUtilityWindow : NSWindowStyleMaskBorderless; switch (_decorations) { case SystemDecorationsNone: diff --git a/native/Avalonia.Native/src/OSX/WindowProtocol.h b/native/Avalonia.Native/src/OSX/WindowProtocol.h index d81d2f1ed1a..1c97d89f392 100644 --- a/native/Avalonia.Native/src/OSX/WindowProtocol.h +++ b/native/Avalonia.Native/src/OSX/WindowProtocol.h @@ -10,7 +10,6 @@ @class AvnMenu; @protocol AvnWindowProtocol --(void) setCanBecomeKeyAndMain; -(void) pollModalSession: (NSModalSession _Nonnull) session; -(void) restoreParentWindow; -(bool) shouldTryToHandleEvents; From d6a4a6c901fec82f9675c3f70e72a7e01c008fb5 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 6 May 2022 18:04:57 +0100 Subject: [PATCH 10/13] ensure cast to protocol instead of concrete types. --- native/Avalonia.Native/src/OSX/AutoFitContentView.mm | 5 +++-- native/Avalonia.Native/src/OSX/AvnView.mm | 7 ++++++- native/Avalonia.Native/src/OSX/AvnWindow.mm | 6 ++---- native/Avalonia.Native/src/OSX/WindowBaseImpl.h | 4 ++-- native/Avalonia.Native/src/OSX/WindowBaseImpl.mm | 8 ++++---- 5 files changed, 17 insertions(+), 13 deletions(-) diff --git a/native/Avalonia.Native/src/OSX/AutoFitContentView.mm b/native/Avalonia.Native/src/OSX/AutoFitContentView.mm index 4eaa08cbe20..314c579b763 100644 --- a/native/Avalonia.Native/src/OSX/AutoFitContentView.mm +++ b/native/Avalonia.Native/src/OSX/AutoFitContentView.mm @@ -5,7 +5,8 @@ #include "AvnView.h" #include "AutoFitContentView.h" -#import "WindowInterfaces.h" +#include "WindowInterfaces.h" +#include "WindowProtocol.h" @implementation AutoFitContentView { @@ -84,7 +85,7 @@ -(void)setFrameSize:(NSSize)newSize _settingSize = true; [super setFrameSize:newSize]; - auto window = objc_cast([self window]); + auto window = static_cast>([self window]); // TODO get actual titlebar size diff --git a/native/Avalonia.Native/src/OSX/AvnView.mm b/native/Avalonia.Native/src/OSX/AvnView.mm index e6cf73755bb..02526afbcb3 100644 --- a/native/Avalonia.Native/src/OSX/AvnView.mm +++ b/native/Avalonia.Native/src/OSX/AvnView.mm @@ -195,7 +195,12 @@ - (void) viewDidChangeBackingProperties - (bool) ignoreUserInput:(bool)trigerInputWhenDisabled { - auto parentWindow = objc_cast([self window]); + if(_parent == nullptr) + { + return TRUE; + } + + auto parentWindow = _parent->GetWindowProtocol(); if(parentWindow == nil || ![parentWindow shouldTryToHandleEvents]) { diff --git a/native/Avalonia.Native/src/OSX/AvnWindow.mm b/native/Avalonia.Native/src/OSX/AvnWindow.mm index d0b23540f9f..ef4dcc3df43 100644 --- a/native/Avalonia.Native/src/OSX/AvnWindow.mm +++ b/native/Avalonia.Native/src/OSX/AvnWindow.mm @@ -212,8 +212,7 @@ -(BOOL)canBecomeKeyWindow // 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]) { - // TODO protocol - auto ch = objc_cast(uch); + auto ch = static_cast>(uch); if(ch == nil) continue; if (ch.isDialog) @@ -256,8 +255,7 @@ -(void)becomeKeyWindow -(void) restoreParentWindow; { - // TODO protocol - auto parent = objc_cast([self parentWindow]); + auto parent = static_cast>([self parentWindow]); if(parent != nil) { [parent removeChildWindow:self]; diff --git a/native/Avalonia.Native/src/OSX/WindowBaseImpl.h b/native/Avalonia.Native/src/OSX/WindowBaseImpl.h index ae1e6a7016b..8c82bba98cb 100644 --- a/native/Avalonia.Native/src/OSX/WindowBaseImpl.h +++ b/native/Avalonia.Native/src/OSX/WindowBaseImpl.h @@ -114,13 +114,13 @@ BEGIN_INTERFACE_MAP() virtual bool IsDialog(); + id GetWindowProtocol (); + protected: virtual NSWindowStyleMask GetStyle(); void UpdateStyle(); - id GetWindowProtocol (); - private: void CreateNSWindow (bool isDialog); void InitialiseNSWindow (); diff --git a/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm b/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm index 414632770f5..227f3483337 100644 --- a/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm +++ b/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm @@ -561,12 +561,12 @@ } id WindowBaseImpl::GetWindowProtocol() { - id instance; - if ([Window conformsToProtocol:@protocol(AvnWindowProtocol)]) { - instance = Window; + if(Window == nullptr) + { + return nullptr; } - return instance; + return static_cast>(Window); } extern IAvnWindow* CreateAvnWindow(IAvnWindowEvents*events, IAvnGlContext* gl) From 99e07e68d592771273aa4b795682603d2507d973 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 6 May 2022 18:07:01 +0100 Subject: [PATCH 11/13] remove unnecessary cast. --- native/Avalonia.Native/src/OSX/AvnWindow.mm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/native/Avalonia.Native/src/OSX/AvnWindow.mm b/native/Avalonia.Native/src/OSX/AvnWindow.mm index ef4dcc3df43..33f7f75314f 100644 --- a/native/Avalonia.Native/src/OSX/AvnWindow.mm +++ b/native/Avalonia.Native/src/OSX/AvnWindow.mm @@ -255,7 +255,8 @@ -(void)becomeKeyWindow -(void) restoreParentWindow; { - auto parent = static_cast>([self parentWindow]); + auto parent = [self parentWindow]; + if(parent != nil) { [parent removeChildWindow:self]; From 3600639d39482ef60efbb573f4586d8019da745a Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Sun, 8 May 2022 19:17:08 +0100 Subject: [PATCH 12/13] re-create NSWindow if we call show and need to swap out for a dialog. --- native/Avalonia.Native/src/OSX/AvnWindow.mm | 4 ++++ .../Avalonia.Native/src/OSX/WindowBaseImpl.h | 1 + .../Avalonia.Native/src/OSX/WindowBaseImpl.mm | 21 ++++++++++++++----- .../Avalonia.Native/src/OSX/WindowProtocol.h | 1 + 4 files changed, 22 insertions(+), 5 deletions(-) diff --git a/native/Avalonia.Native/src/OSX/AvnWindow.mm b/native/Avalonia.Native/src/OSX/AvnWindow.mm index 33f7f75314f..6ff19ead68a 100644 --- a/native/Avalonia.Native/src/OSX/AvnWindow.mm +++ b/native/Avalonia.Native/src/OSX/AvnWindow.mm @@ -433,5 +433,9 @@ - (void)sendEvent:(NSEvent *)event } } +- (void)disconnectParent { + _parent = nullptr; +} + @end diff --git a/native/Avalonia.Native/src/OSX/WindowBaseImpl.h b/native/Avalonia.Native/src/OSX/WindowBaseImpl.h index 8c82bba98cb..eff13bcb23e 100644 --- a/native/Avalonia.Native/src/OSX/WindowBaseImpl.h +++ b/native/Avalonia.Native/src/OSX/WindowBaseImpl.h @@ -123,6 +123,7 @@ BEGIN_INTERFACE_MAP() private: void CreateNSWindow (bool isDialog); + void CleanNSWindow (); void InitialiseNSWindow (); }; diff --git a/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm b/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm index 227f3483337..a7c38bf6529 100644 --- a/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm +++ b/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm @@ -525,14 +525,25 @@ [Window setStyleMask:GetStyle()]; } +void WindowBaseImpl::CleanNSWindow() { + if(Window != nullptr) { + [GetWindowProtocol() disconnectParent]; + [Window close]; + Window = nullptr; + } +} + void WindowBaseImpl::CreateNSWindow(bool isDialog) { - if(Window == nullptr) { - if(isDialog) - { + if (isDialog) { + if (![Window isKindOfClass:[AvnPanel class]]) { + CleanNSWindow(); + Window = [[AvnPanel alloc] initWithParent:this contentRect:NSRect{0, 0, lastSize} styleMask:GetStyle()]; } - else - { + } else { + if (![Window isKindOfClass:[AvnWindow class]]) { + CleanNSWindow(); + Window = [[AvnWindow alloc] initWithParent:this contentRect:NSRect{0, 0, lastSize} styleMask:GetStyle()]; } } diff --git a/native/Avalonia.Native/src/OSX/WindowProtocol.h b/native/Avalonia.Native/src/OSX/WindowProtocol.h index 1c97d89f392..92194706de0 100644 --- a/native/Avalonia.Native/src/OSX/WindowProtocol.h +++ b/native/Avalonia.Native/src/OSX/WindowProtocol.h @@ -20,5 +20,6 @@ -(double) getExtendedTitleBarHeight; -(void) setIsExtended:(bool)value; +-(void) disconnectParent; -(bool) isDialog; @end \ No newline at end of file From c756f812ec887cbdf77fd2d3d420a7164f25ee0f Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 9 May 2022 11:19:20 +0100 Subject: [PATCH 13/13] remove shadow invalidation hack. --- native/Avalonia.Native/src/OSX/WindowBaseImpl.mm | 1 - 1 file changed, 1 deletion(-) diff --git a/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm b/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm index a7c38bf6529..db5eb54e3f3 100644 --- a/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm +++ b/native/Avalonia.Native/src/OSX/WindowBaseImpl.mm @@ -286,7 +286,6 @@ if(Window != nullptr) { [Window setContentSize:lastSize]; - [Window invalidateShadow]; } } @finally {