diff --git a/.gitignore b/.gitignore
index 7d672c7755..abf7674560 100644
--- a/.gitignore
+++ b/.gitignore
@@ -106,6 +106,9 @@ _NCrunch_*/
*.ncrunchsolution.user
nCrunchTemp_*
+# CodeRush
+.cr/
+
# Others
sql/
*.Cache
diff --git a/Avalonia.sln.DotSettings b/Avalonia.sln.DotSettings
index 2c0a6b9dc8..b0692905e7 100644
--- a/Avalonia.sln.DotSettings
+++ b/Avalonia.sln.DotSettings
@@ -1,5 +1,4 @@
- True
ExplicitlyExcluded
ExplicitlyExcluded
ExplicitlyExcluded
@@ -39,4 +38,4 @@
<Policy Inspect="False" Prefix="" Suffix="" Style="AaBb" />
True
True
- True
\ No newline at end of file
+ True
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index fbd8507193..11ef36d43f 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -1,7 +1,7 @@
jobs:
- job: Linux
pool:
- vmImage: 'ubuntu-16.04'
+ vmImage: 'ubuntu-20.04'
steps:
- task: CmdLine@2
displayName: 'Install Nuke'
diff --git a/build/MicroCom.targets b/build/MicroCom.targets
index b48e377fd4..49d2cdce72 100644
--- a/build/MicroCom.targets
+++ b/build/MicroCom.targets
@@ -15,7 +15,8 @@
Inputs="@(AvnComIdl);$(MSBuildThisFileDirectory)../src/tools/MicroComGenerator/**/*.cs"
Outputs="%(AvnComIdl.OutputFile)">
-
+
diff --git a/native/Avalonia.Native/inc/comimpl.h b/native/Avalonia.Native/inc/comimpl.h
index 0ff64b7215..47b0a3c5f2 100644
--- a/native/Avalonia.Native/inc/comimpl.h
+++ b/native/Avalonia.Native/inc/comimpl.h
@@ -8,8 +8,109 @@
#include
+/**
+ START_COM_CALL causes AddRef to be called at the beggining of a function.
+ When a function is exited, it causes ReleaseRef to be called.
+ This ensures that the object cannot be destroyed whilst the function is running.
+ For example: Window Show is called, which triggers an event, and user calls Close inside the event
+ causing the refcount to reach 0, and the object to be destroyed. Function then continues and this pointer
+ will now be invalid.
+
+ START_COM_CALL protects against this scenario.
+ */
+#define START_COM_CALL auto r = this->UnknownSelf()
+
__IID_DEF(IUnknown, 0, 0, 0, C0, 00, 00, 00, 00, 00, 00, 46);
+template
+class ComPtr
+{
+private:
+ TInterface* _obj;
+public:
+ ComPtr()
+ {
+ _obj = 0;
+ }
+
+ ComPtr(TInterface* pObj)
+ {
+ _obj = 0;
+
+ if (pObj)
+ {
+ _obj = pObj;
+ _obj->AddRef();
+ }
+ }
+
+ ComPtr(const ComPtr& ptr)
+ {
+ _obj = 0;
+
+ if (ptr._obj)
+ {
+ _obj = ptr._obj;
+ _obj->AddRef();
+ }
+
+ }
+
+ ComPtr& operator=(ComPtr other)
+ {
+ if(_obj != NULL)
+ _obj->Release();
+ _obj = other._obj;
+ if(_obj != NULL)
+ _obj->AddRef();
+ return *this;
+ }
+
+ ~ComPtr()
+ {
+ if (_obj)
+ {
+ _obj->Release();
+ _obj = 0;
+ }
+ }
+
+ TInterface* getRaw()
+ {
+ return _obj;
+ }
+
+ TInterface* getRetainedReference()
+ {
+ if(_obj == NULL)
+ return NULL;
+ _obj->AddRef();
+ return _obj;
+ }
+
+ TInterface** getPPV()
+ {
+ return &_obj;
+ }
+
+ operator TInterface*() const
+ {
+ return _obj;
+ }
+ TInterface& operator*() const
+ {
+ return *_obj;
+ }
+ TInterface** operator&()
+ {
+ return &_obj;
+ }
+ TInterface* operator->() const
+ {
+ return _obj;
+ }
+};
+
class ComObject : public virtual IUnknown
{
private:
@@ -58,6 +159,12 @@ public:
_refCount++;
return S_OK;
}
+
+protected:
+ ComPtr UnknownSelf()
+ {
+ return this;
+ }
};
@@ -104,94 +211,5 @@ public:
virtual ~ComSingleObject(){}
};
-template
-class ComPtr
-{
-private:
- TInterface* _obj;
-public:
- ComPtr()
- {
- _obj = 0;
- }
-
- ComPtr(TInterface* pObj)
- {
- _obj = 0;
-
- if (pObj)
- {
- _obj = pObj;
- _obj->AddRef();
- }
- }
-
- ComPtr(const ComPtr& ptr)
- {
- _obj = 0;
-
- if (ptr._obj)
- {
- _obj = ptr._obj;
- _obj->AddRef();
- }
-
- }
-
- ComPtr& operator=(ComPtr other)
- {
- if(_obj != NULL)
- _obj->Release();
- _obj = other._obj;
- if(_obj != NULL)
- _obj->AddRef();
- return *this;
- }
-
- ~ComPtr()
- {
- if (_obj)
- {
- _obj->Release();
- _obj = 0;
- }
- }
-
- TInterface* getRaw()
- {
- return _obj;
- }
-
- TInterface* getRetainedReference()
- {
- if(_obj == NULL)
- return NULL;
- _obj->AddRef();
- return _obj;
- }
-
- TInterface** getPPV()
- {
- return &_obj;
- }
-
- operator TInterface*() const
- {
- return _obj;
- }
- TInterface& operator*() const
- {
- return *_obj;
- }
- TInterface** operator&()
- {
- return &_obj;
- }
- TInterface* operator->() const
- {
- return _obj;
- }
-};
-
#endif // COMIMPL_H_INCLUDED
#pragma clang diagnostic pop
diff --git a/native/Avalonia.Native/src/OSX/AvnString.mm b/native/Avalonia.Native/src/OSX/AvnString.mm
index df11ad8715..c69cef5c87 100644
--- a/native/Avalonia.Native/src/OSX/AvnString.mm
+++ b/native/Avalonia.Native/src/OSX/AvnString.mm
@@ -43,6 +43,8 @@ public:
virtual HRESULT Pointer(void**retOut) override
{
+ START_COM_CALL;
+
@autoreleasepool
{
if(retOut == nullptr)
@@ -58,14 +60,19 @@ public:
virtual HRESULT Length(int*retOut) override
{
- if(retOut == nullptr)
+ START_COM_CALL;
+
+ @autoreleasepool
{
- return E_POINTER;
+ if(retOut == nullptr)
+ {
+ return E_POINTER;
+ }
+
+ *retOut = _length;
+
+ return S_OK;
}
-
- *retOut = _length;
-
- return S_OK;
}
};
@@ -109,10 +116,15 @@ public:
virtual HRESULT Get(unsigned int index, IAvnString**ppv) override
{
- if(_list.size() <= index)
- return E_INVALIDARG;
- *ppv = _list[index].getRetainedReference();
- return S_OK;
+ START_COM_CALL;
+
+ @autoreleasepool
+ {
+ if(_list.size() <= index)
+ return E_INVALIDARG;
+ *ppv = _list[index].getRetainedReference();
+ return S_OK;
+ }
}
};
diff --git a/native/Avalonia.Native/src/OSX/KeyTransform.mm b/native/Avalonia.Native/src/OSX/KeyTransform.mm
index 6b7d95b619..4817ad0ccf 100644
--- a/native/Avalonia.Native/src/OSX/KeyTransform.mm
+++ b/native/Avalonia.Native/src/OSX/KeyTransform.mm
@@ -222,6 +222,7 @@ std::map s_QwertyKeyMap =
{ 45, "n" },
{ 46, "m" },
{ 47, "." },
+ { 48, "\t" },
{ 49, " " },
{ 50, "`" },
{ 51, "" },
diff --git a/native/Avalonia.Native/src/OSX/Screens.mm b/native/Avalonia.Native/src/OSX/Screens.mm
index 10f698ff45..b9c75ed742 100644
--- a/native/Avalonia.Native/src/OSX/Screens.mm
+++ b/native/Avalonia.Native/src/OSX/Screens.mm
@@ -8,6 +8,8 @@ class Screens : public ComSingleObject
public:
virtual HRESULT GetScreenCount (int* ret) override
{
+ START_COM_CALL;
+
@autoreleasepool
{
*ret = (int)[NSScreen screens].count;
@@ -18,6 +20,8 @@ public:
virtual HRESULT GetScreen (int index, AvnScreen* ret) override
{
+ START_COM_CALL;
+
@autoreleasepool
{
if(index < 0 || index >= [NSScreen screens].count)
diff --git a/native/Avalonia.Native/src/OSX/app.mm b/native/Avalonia.Native/src/OSX/app.mm
index 460c24ea3a..e1972b22f4 100644
--- a/native/Avalonia.Native/src/OSX/app.mm
+++ b/native/Avalonia.Native/src/OSX/app.mm
@@ -50,6 +50,12 @@ ComPtr _events;
_events->FilesOpened(array);
}
+
+- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
+{
+ return _events->TryShutdown() ? NSTerminateNow : NSTerminateCancel;
+}
+
@end
@interface AvnApplication : NSApplication
diff --git a/native/Avalonia.Native/src/OSX/cgl.mm b/native/Avalonia.Native/src/OSX/cgl.mm
index a9d94cdf04..085037978e 100644
--- a/native/Avalonia.Native/src/OSX/cgl.mm
+++ b/native/Avalonia.Native/src/OSX/cgl.mm
@@ -69,6 +69,8 @@ public:
virtual HRESULT LegacyMakeCurrent() override
{
+ START_COM_CALL;
+
if(CGLSetCurrentContext(Context) != 0)
return E_FAIL;
return S_OK;
@@ -76,6 +78,8 @@ public:
virtual HRESULT MakeCurrent(IUnknown** ppv) override
{
+ START_COM_CALL;
+
CGLContextObj saved = CGLGetCurrentContext();
CGLLockContext(Context);
if(CGLSetCurrentContext(Context) != 0)
@@ -128,6 +132,8 @@ public:
virtual HRESULT CreateContext(IAvnGlContext* share, IAvnGlContext**ppv) override
{
+ START_COM_CALL;
+
CGLContextObj shareContext = nil;
if(share != nil)
{
@@ -144,6 +150,8 @@ public:
virtual HRESULT WrapContext(void* native, IAvnGlContext**ppv) override
{
+ START_COM_CALL;
+
if(native == nil)
return E_INVALIDARG;
*ppv = new AvnGlContext((CGLContextObj) native);
diff --git a/native/Avalonia.Native/src/OSX/clipboard.mm b/native/Avalonia.Native/src/OSX/clipboard.mm
index f148374759..9966971b73 100644
--- a/native/Avalonia.Native/src/OSX/clipboard.mm
+++ b/native/Avalonia.Native/src/OSX/clipboard.mm
@@ -25,6 +25,8 @@ public:
virtual HRESULT GetText (char* type, IAvnString**ppv) override
{
+ START_COM_CALL;
+
@autoreleasepool
{
if(ppv == nullptr)
@@ -42,6 +44,8 @@ public:
virtual HRESULT GetStrings(char* type, IAvnStringArray**ppv) override
{
+ START_COM_CALL;
+
@autoreleasepool
{
*ppv= nil;
@@ -69,56 +73,71 @@ public:
virtual HRESULT SetText (char* type, char* utf8String) override
{
- Clear();
+ START_COM_CALL;
+
@autoreleasepool
{
+ Clear();
+
auto string = [NSString stringWithUTF8String:(const char*)utf8String];
auto typeString = [NSString stringWithUTF8String:(const char*)type];
if(_item == nil)
[_pb setString: string forType: typeString];
else
[_item setString: string forType:typeString];
- }
- return S_OK;
+ return S_OK;
+ }
}
virtual HRESULT SetBytes(char* type, void* bytes, int len) override
{
- auto typeString = [NSString stringWithUTF8String:(const char*)type];
- auto data = [NSData dataWithBytes:bytes length:len];
- if(_item == nil)
- [_pb setData:data forType:typeString];
- else
- [_item setData:data forType:typeString];
- return S_OK;
+ START_COM_CALL;
+
+ @autoreleasepool
+ {
+ auto typeString = [NSString stringWithUTF8String:(const char*)type];
+ auto data = [NSData dataWithBytes:bytes length:len];
+ if(_item == nil)
+ [_pb setData:data forType:typeString];
+ else
+ [_item setData:data forType:typeString];
+ return S_OK;
+ }
}
virtual HRESULT GetBytes(char* type, IAvnString**ppv) override
{
- *ppv = nil;
- auto typeString = [NSString stringWithUTF8String:(const char*)type];
- NSData*data;
- @try
+ START_COM_CALL;
+
+ @autoreleasepool
{
- if(_item)
- data = [_item dataForType:typeString];
- else
- data = [_pb dataForType:typeString];
- if(data == nil)
+ *ppv = nil;
+ auto typeString = [NSString stringWithUTF8String:(const char*)type];
+ NSData*data;
+ @try
+ {
+ if(_item)
+ data = [_item dataForType:typeString];
+ else
+ data = [_pb dataForType:typeString];
+ if(data == nil)
+ return E_FAIL;
+ }
+ @catch(NSException* e)
+ {
return E_FAIL;
+ }
+ *ppv = CreateByteArray((void*)data.bytes, (int)data.length);
+ return S_OK;
}
- @catch(NSException* e)
- {
- return E_FAIL;
- }
- *ppv = CreateByteArray((void*)data.bytes, (int)data.length);
- return S_OK;
}
virtual HRESULT Clear() override
{
+ START_COM_CALL;
+
@autoreleasepool
{
if(_item != nil)
@@ -128,15 +147,20 @@ public:
[_pb clearContents];
[_pb setString:@"" forType:NSPasteboardTypeString];
}
- }
- return S_OK;
+ return S_OK;
+ }
}
virtual HRESULT ObtainFormats(IAvnStringArray** ppv) override
{
- *ppv = CreateAvnStringArray(_item == nil ? [_pb types] : [_item types]);
- return S_OK;
+ START_COM_CALL;
+
+ @autoreleasepool
+ {
+ *ppv = CreateAvnStringArray(_item == nil ? [_pb types] : [_item types]);
+ return S_OK;
+ }
}
};
diff --git a/native/Avalonia.Native/src/OSX/controlhost.mm b/native/Avalonia.Native/src/OSX/controlhost.mm
index 5ee2344ac7..f8e9a3b6d1 100644
--- a/native/Avalonia.Native/src/OSX/controlhost.mm
+++ b/native/Avalonia.Native/src/OSX/controlhost.mm
@@ -16,11 +16,16 @@ public:
virtual HRESULT CreateDefaultChild(void* parent, void** retOut) override
{
- NSView* view = [NSView new];
- [view setWantsLayer: true];
+ START_COM_CALL;
- *retOut = (__bridge_retained void*)view;
- return S_OK;
+ @autoreleasepool
+ {
+ NSView* view = [NSView new];
+ [view setWantsLayer: true];
+
+ *retOut = (__bridge_retained void*)view;
+ return S_OK;
+ }
};
virtual IAvnNativeControlHostTopLevelAttachment* CreateAttachment() override
@@ -69,32 +74,42 @@ public:
virtual HRESULT InitializeWithChildHandle(void* child) override
{
- if(_child != nil)
- return E_FAIL;
- _child = (__bridge NSView*)child;
- if(_child == nil)
- return E_FAIL;
- [_holder addSubview:_child];
- [_child setHidden: false];
- return S_OK;
+ START_COM_CALL;
+
+ @autoreleasepool
+ {
+ if(_child != nil)
+ return E_FAIL;
+ _child = (__bridge NSView*)child;
+ if(_child == nil)
+ return E_FAIL;
+ [_holder addSubview:_child];
+ [_child setHidden: false];
+ return S_OK;
+ }
};
virtual HRESULT AttachTo(IAvnNativeControlHost* host) override
{
- if(host == nil)
- {
- [_holder removeFromSuperview];
- [_holder setHidden: true];
- }
- else
+ START_COM_CALL;
+
+ @autoreleasepool
{
- AvnNativeControlHost* chost = dynamic_cast(host);
- if(chost == nil || chost->View == nil)
- return E_FAIL;
- [_holder setHidden:true];
- [chost->View addSubview:_holder];
+ if(host == nil)
+ {
+ [_holder removeFromSuperview];
+ [_holder setHidden: true];
+ }
+ else
+ {
+ AvnNativeControlHost* chost = dynamic_cast(host);
+ if(chost == nil || chost->View == nil)
+ return E_FAIL;
+ [_holder setHidden:true];
+ [chost->View addSubview:_holder];
+ }
+ return S_OK;
}
- return S_OK;
};
virtual void ShowInBounds(float x, float y, float width, float height) override
diff --git a/native/Avalonia.Native/src/OSX/cursor.mm b/native/Avalonia.Native/src/OSX/cursor.mm
index 1732d6e71f..dc38294a18 100644
--- a/native/Avalonia.Native/src/OSX/cursor.mm
+++ b/native/Avalonia.Native/src/OSX/cursor.mm
@@ -53,36 +53,46 @@ public:
virtual HRESULT GetCursor (AvnStandardCursorType cursorType, IAvnCursor** retOut) override
{
- *retOut = s_cursorMap[cursorType];
+ START_COM_CALL;
- if(*retOut != nullptr)
+ @autoreleasepool
{
- (*retOut)->AddRef();
- }
+ *retOut = s_cursorMap[cursorType];
- return S_OK;
+ if(*retOut != nullptr)
+ {
+ (*retOut)->AddRef();
+ }
+
+ return S_OK;
+ }
}
virtual HRESULT CreateCustomCursor (void* bitmapData, size_t length, AvnPixelSize hotPixel, IAvnCursor** retOut) override
{
- if(bitmapData == nullptr || retOut == nullptr)
+ START_COM_CALL;
+
+ @autoreleasepool
{
- return E_POINTER;
+ if(bitmapData == nullptr || retOut == nullptr)
+ {
+ return E_POINTER;
+ }
+
+ NSData *imageData = [NSData dataWithBytes:bitmapData length:length];
+ NSImage *image = [[NSImage alloc] initWithData:imageData];
+
+
+ NSPoint hotSpot;
+ hotSpot.x = hotPixel.Width;
+ hotSpot.y = hotPixel.Height;
+
+ *retOut = new Cursor([[NSCursor new] initWithImage: image hotSpot: hotSpot]);
+
+ (*retOut)->AddRef();
+
+ return S_OK;
}
-
- NSData *imageData = [NSData dataWithBytes:bitmapData length:length];
- NSImage *image = [[NSImage alloc] initWithData:imageData];
-
-
- NSPoint hotSpot;
- hotSpot.x = hotPixel.Width;
- hotSpot.y = hotPixel.Height;
-
- *retOut = new Cursor([[NSCursor new] initWithImage: image hotSpot: hotSpot]);
-
- (*retOut)->AddRef();
-
- return S_OK;
}
};
diff --git a/native/Avalonia.Native/src/OSX/main.mm b/native/Avalonia.Native/src/OSX/main.mm
index f231ff9a71..2745851611 100644
--- a/native/Avalonia.Native/src/OSX/main.mm
+++ b/native/Avalonia.Native/src/OSX/main.mm
@@ -108,27 +108,42 @@ public:
virtual HRESULT SetApplicationTitle(char* utf8String) override
{
- auto appTitle = [NSString stringWithUTF8String: utf8String];
+ START_COM_CALL;
- [[NSProcessInfo processInfo] setProcessName:appTitle];
-
-
- SetProcessName(appTitle);
-
- return S_OK;
+ @autoreleasepool
+ {
+ auto appTitle = [NSString stringWithUTF8String: utf8String];
+
+ [[NSProcessInfo processInfo] setProcessName:appTitle];
+
+
+ SetProcessName(appTitle);
+
+ return S_OK;
+ }
}
virtual HRESULT SetShowInDock(int show) override
{
- AvnDesiredActivationPolicy = show
- ? NSApplicationActivationPolicyRegular : NSApplicationActivationPolicyAccessory;
- return S_OK;
+ START_COM_CALL;
+
+ @autoreleasepool
+ {
+ AvnDesiredActivationPolicy = show
+ ? NSApplicationActivationPolicyRegular : NSApplicationActivationPolicyAccessory;
+ return S_OK;
+ }
}
virtual HRESULT SetDisableDefaultApplicationMenuItems (bool enabled) override
{
- SetAutoGenerateDefaultAppMenuItems(!enabled);
- return S_OK;
+ START_COM_CALL;
+
+ @autoreleasepool
+ {
+ SetAutoGenerateDefaultAppMenuItems(!enabled);
+ return S_OK;
+ }
}
};
@@ -166,6 +181,8 @@ public:
FORWARD_IUNKNOWN()
virtual HRESULT Initialize(IAvnGCHandleDeallocatorCallback* deallocator, IAvnApplicationEvents* events) override
{
+ START_COM_CALL;
+
_deallocator = deallocator;
@autoreleasepool{
[[ThreadingInitializer new] do];
@@ -181,83 +198,143 @@ public:
virtual HRESULT CreateWindow(IAvnWindowEvents* cb, IAvnGlContext* gl, IAvnWindow** ppv) override
{
- if(cb == nullptr || ppv == nullptr)
- return E_POINTER;
- *ppv = CreateAvnWindow(cb, gl);
- return S_OK;
+ START_COM_CALL;
+
+ @autoreleasepool
+ {
+ if(cb == nullptr || ppv == nullptr)
+ return E_POINTER;
+ *ppv = CreateAvnWindow(cb, gl);
+ return S_OK;
+ }
};
virtual HRESULT CreatePopup(IAvnWindowEvents* cb, IAvnGlContext* gl, IAvnPopup** ppv) override
{
- if(cb == nullptr || ppv == nullptr)
- return E_POINTER;
+ START_COM_CALL;
- *ppv = CreateAvnPopup(cb, gl);
- return S_OK;
+ @autoreleasepool
+ {
+ if(cb == nullptr || ppv == nullptr)
+ return E_POINTER;
+
+ *ppv = CreateAvnPopup(cb, gl);
+ return S_OK;
+ }
}
virtual HRESULT CreatePlatformThreadingInterface(IAvnPlatformThreadingInterface** ppv) override
{
- *ppv = CreatePlatformThreading();
- return S_OK;
+ START_COM_CALL;
+
+ @autoreleasepool
+ {
+ *ppv = CreatePlatformThreading();
+ return S_OK;
+ }
}
virtual HRESULT CreateSystemDialogs(IAvnSystemDialogs** ppv) override
{
- *ppv = ::CreateSystemDialogs();
- return S_OK;
+ START_COM_CALL;
+
+ @autoreleasepool
+ {
+ *ppv = ::CreateSystemDialogs();
+ return S_OK;
+ }
}
virtual HRESULT CreateScreens (IAvnScreens** ppv) override
{
- *ppv = ::CreateScreens ();
- return S_OK;
+ START_COM_CALL;
+
+ @autoreleasepool
+ {
+ *ppv = ::CreateScreens ();
+ return S_OK;
+ }
}
virtual HRESULT CreateClipboard(IAvnClipboard** ppv) override
{
- *ppv = ::CreateClipboard (nil, nil);
- return S_OK;
+ START_COM_CALL;
+
+ @autoreleasepool
+ {
+ *ppv = ::CreateClipboard (nil, nil);
+ return S_OK;
+ }
}
virtual HRESULT CreateDndClipboard(IAvnClipboard** ppv) override
{
- *ppv = ::CreateClipboard (nil, [NSPasteboardItem new]);
- return S_OK;
+ START_COM_CALL;
+
+ @autoreleasepool
+ {
+ *ppv = ::CreateClipboard (nil, [NSPasteboardItem new]);
+ return S_OK;
+ }
}
virtual HRESULT CreateCursorFactory(IAvnCursorFactory** ppv) override
{
- *ppv = ::CreateCursorFactory();
- return S_OK;
+ START_COM_CALL;
+
+ @autoreleasepool
+ {
+ *ppv = ::CreateCursorFactory();
+ return S_OK;
+ }
}
virtual HRESULT ObtainGlDisplay(IAvnGlDisplay** ppv) override
{
- auto rv = ::GetGlDisplay();
- if(rv == NULL)
- return E_FAIL;
- rv->AddRef();
- *ppv = rv;
- return S_OK;
+ START_COM_CALL;
+
+ @autoreleasepool
+ {
+ auto rv = ::GetGlDisplay();
+ if(rv == NULL)
+ return E_FAIL;
+ rv->AddRef();
+ *ppv = rv;
+ return S_OK;
+ }
}
virtual HRESULT CreateMenu (IAvnMenuEvents* cb, IAvnMenu** ppv) override
{
- *ppv = ::CreateAppMenu(cb);
- return S_OK;
+ START_COM_CALL;
+
+ @autoreleasepool
+ {
+ *ppv = ::CreateAppMenu(cb);
+ return S_OK;
+ }
}
virtual HRESULT CreateMenuItem (IAvnMenuItem** ppv) override
{
- *ppv = ::CreateAppMenuItem();
- return S_OK;
+ START_COM_CALL;
+
+ @autoreleasepool
+ {
+ *ppv = ::CreateAppMenuItem();
+ return S_OK;
+ }
}
virtual HRESULT CreateMenuItemSeparator (IAvnMenuItem** ppv) override
{
- *ppv = ::CreateAppMenuItemSeparator();
- return S_OK;
+ START_COM_CALL;
+
+ @autoreleasepool
+ {
+ *ppv = ::CreateAppMenuItemSeparator();
+ return S_OK;
+ }
}
virtual HRESULT CreateAutomationNode (IAvnAutomationPeer* peer, IAvnAutomationNode** ppv) override
@@ -268,8 +345,13 @@ public:
virtual HRESULT SetAppMenu (IAvnMenu* appMenu) override
{
- ::SetAppMenu(s_appTitle, appMenu);
- return S_OK;
+ START_COM_CALL;
+
+ @autoreleasepool
+ {
+ ::SetAppMenu(s_appTitle, appMenu);
+ return S_OK;
+ }
}
};
diff --git a/native/Avalonia.Native/src/OSX/menu.mm b/native/Avalonia.Native/src/OSX/menu.mm
index b9a95e7b3c..38f8c2a7cb 100644
--- a/native/Avalonia.Native/src/OSX/menu.mm
+++ b/native/Avalonia.Native/src/OSX/menu.mm
@@ -95,6 +95,8 @@ NSMenuItem* AvnAppMenuItem::GetNative()
HRESULT AvnAppMenuItem::SetSubMenu (IAvnMenu* menu)
{
+ START_COM_CALL;
+
@autoreleasepool
{
if(menu != nullptr)
@@ -114,6 +116,8 @@ HRESULT AvnAppMenuItem::SetSubMenu (IAvnMenu* menu)
HRESULT AvnAppMenuItem::SetTitle (char* utf8String)
{
+ START_COM_CALL;
+
@autoreleasepool
{
if (utf8String != nullptr)
@@ -128,6 +132,8 @@ HRESULT AvnAppMenuItem::SetTitle (char* utf8String)
HRESULT AvnAppMenuItem::SetGesture (AvnKey key, AvnInputModifiers modifiers)
{
+ START_COM_CALL;
+
@autoreleasepool
{
if(key != AvnKeyNone)
@@ -183,6 +189,8 @@ HRESULT AvnAppMenuItem::SetGesture (AvnKey key, AvnInputModifiers modifiers)
HRESULT AvnAppMenuItem::SetAction (IAvnPredicateCallback* predicate, IAvnActionCallback* callback)
{
+ START_COM_CALL;
+
@autoreleasepool
{
_predicate = predicate;
@@ -193,6 +201,8 @@ HRESULT AvnAppMenuItem::SetAction (IAvnPredicateCallback* predicate, IAvnActionC
HRESULT AvnAppMenuItem::SetIsChecked (bool isChecked)
{
+ START_COM_CALL;
+
@autoreleasepool
{
[_native setState:(isChecked && _isCheckable ? NSOnState : NSOffState)];
@@ -202,6 +212,8 @@ HRESULT AvnAppMenuItem::SetIsChecked (bool isChecked)
HRESULT AvnAppMenuItem::SetToggleType(AvnMenuItemToggleType toggleType)
{
+ START_COM_CALL;
+
@autoreleasepool
{
switch(toggleType)
@@ -231,6 +243,8 @@ HRESULT AvnAppMenuItem::SetToggleType(AvnMenuItemToggleType toggleType)
HRESULT AvnAppMenuItem::SetIcon(void *data, size_t length)
{
+ START_COM_CALL;
+
@autoreleasepool
{
if(data != nullptr)
@@ -317,6 +331,8 @@ void AvnAppMenu::RaiseClosed()
HRESULT AvnAppMenu::InsertItem(int index, IAvnMenuItem *item)
{
+ START_COM_CALL;
+
@autoreleasepool
{
if([_native hasGlobalMenuItem])
@@ -337,6 +353,8 @@ HRESULT AvnAppMenu::InsertItem(int index, IAvnMenuItem *item)
HRESULT AvnAppMenu::RemoveItem (IAvnMenuItem* item)
{
+ START_COM_CALL;
+
@autoreleasepool
{
auto avnMenuItem = dynamic_cast(item);
@@ -352,6 +370,8 @@ HRESULT AvnAppMenu::RemoveItem (IAvnMenuItem* item)
HRESULT AvnAppMenu::SetTitle (char* utf8String)
{
+ START_COM_CALL;
+
@autoreleasepool
{
if (utf8String != nullptr)
@@ -365,6 +385,8 @@ HRESULT AvnAppMenu::SetTitle (char* utf8String)
HRESULT AvnAppMenu::Clear()
{
+ START_COM_CALL;
+
@autoreleasepool
{
[_native removeAllItems];
diff --git a/native/Avalonia.Native/src/OSX/platformthreading.mm b/native/Avalonia.Native/src/OSX/platformthreading.mm
index e83bf53331..6d5bd4aa02 100644
--- a/native/Avalonia.Native/src/OSX/platformthreading.mm
+++ b/native/Avalonia.Native/src/OSX/platformthreading.mm
@@ -114,6 +114,8 @@ public:
virtual HRESULT RunLoop(IAvnLoopCancellation* cancel) override
{
+ START_COM_CALL;
+
auto can = dynamic_cast(cancel);
if(can->Cancelled)
return S_OK;
diff --git a/native/Avalonia.Native/src/OSX/rendertarget.mm b/native/Avalonia.Native/src/OSX/rendertarget.mm
index b2d4341bb9..dc5c24e41e 100644
--- a/native/Avalonia.Native/src/OSX/rendertarget.mm
+++ b/native/Avalonia.Native/src/OSX/rendertarget.mm
@@ -247,6 +247,8 @@ public:
virtual HRESULT GetPixelSize(AvnPixelSize* ret) override
{
+ START_COM_CALL;
+
if(!_surface)
return E_FAIL;
*ret = _surface->size;
@@ -255,6 +257,8 @@ public:
virtual HRESULT GetScaling(double* ret) override
{
+ START_COM_CALL;
+
if(!_surface)
return E_FAIL;
*ret = _surface->scale;
@@ -281,6 +285,8 @@ public:
virtual HRESULT BeginDrawing(IAvnGlSurfaceRenderingSession** ret) override
{
+ START_COM_CALL;
+
ComPtr releaseContext;
@synchronized (_target->lock) {
if(_target->surface == nil)
diff --git a/native/Avalonia.Native/src/OSX/window.h b/native/Avalonia.Native/src/OSX/window.h
index 200b442fcd..84353d2788 100644
--- a/native/Avalonia.Native/src/OSX/window.h
+++ b/native/Avalonia.Native/src/OSX/window.h
@@ -10,6 +10,8 @@ class WindowBaseImpl;
-(void) setSwRenderedFrame: (AvnFramebuffer* _Nonnull) fb dispose: (IUnknown* _Nonnull) dispose;
-(void) onClosed;
-(AvnPixelSize) getPixelSize;
+-(AvnPlatformResizeReason) getResizeReason;
+-(void) setResizeReason:(AvnPlatformResizeReason)reason;
@end
@interface AutoFitContentView : NSView
@@ -34,6 +36,7 @@ class WindowBaseImpl;
-(double) getScaling;
-(double) getExtendedTitleBarHeight;
-(void) setIsExtended:(bool)value;
+-(bool) isDialog;
@end
struct INSWindowHolder
@@ -51,4 +54,23 @@ struct IWindowStateChanged
virtual AvnWindowState WindowState () = 0;
};
+class ResizeScope
+{
+public:
+ ResizeScope(AvnView* _Nonnull view, AvnPlatformResizeReason reason)
+ {
+ _view = view;
+ _restore = [view getResizeReason];
+ [view setResizeReason:reason];
+ }
+
+ ~ResizeScope()
+ {
+ [_view setResizeReason:_restore];
+ }
+private:
+ AvnView* _Nonnull _view;
+ AvnPlatformResizeReason _restore;
+};
+
#endif /* window_h */
diff --git a/native/Avalonia.Native/src/OSX/window.mm b/native/Avalonia.Native/src/OSX/window.mm
index ba563c051a..e3292608bf 100644
--- a/native/Avalonia.Native/src/OSX/window.mm
+++ b/native/Avalonia.Native/src/OSX/window.mm
@@ -40,10 +40,12 @@ public:
IAvnMenu* _mainMenu;
bool _shown;
+ bool _inResize;
WindowBaseImpl(IAvnWindowBaseEvents* events, IAvnGlContext* gl)
{
_shown = false;
+ _inResize = false;
_mainMenu = nullptr;
BaseEvents = events;
_glContext = gl;
@@ -61,10 +63,13 @@ public:
[Window setBackingType:NSBackingStoreBuffered];
[Window setOpaque:false];
+ [Window setContentView: StandardContainer];
}
virtual HRESULT ObtainNSWindowHandle(void** ret) override
{
+ START_COM_CALL;
+
if (ret == nullptr)
{
return E_POINTER;
@@ -77,6 +82,8 @@ public:
virtual HRESULT ObtainNSWindowHandleRetained(void** ret) override
{
+ START_COM_CALL;
+
if (ret == nullptr)
{
return E_POINTER;
@@ -89,6 +96,8 @@ public:
virtual HRESULT ObtainNSViewHandle(void** ret) override
{
+ START_COM_CALL;
+
if (ret == nullptr)
{
return E_POINTER;
@@ -101,6 +110,8 @@ public:
virtual HRESULT ObtainNSViewHandleRetained(void** ret) override
{
+ START_COM_CALL;
+
if (ret == nullptr)
{
return E_POINTER;
@@ -126,25 +137,28 @@ public:
return Window;
}
- virtual HRESULT Show(bool activate) override
+ virtual HRESULT Show(bool activate, bool isDialog) override
{
+ START_COM_CALL;
+
@autoreleasepool
{
SetPosition(lastPositionSet);
UpdateStyle();
- [Window setContentView: StandardContainer];
+ [Window setTitle:_lastTitle];
if(ShouldTakeFocusOnShow() && activate)
{
+ [Window orderFront: Window];
[Window makeKeyAndOrderFront:Window];
+ [Window makeFirstResponder:View];
[NSApp activateIgnoringOtherApps:YES];
}
else
{
[Window orderFront: Window];
}
- [Window setTitle:_lastTitle];
_shown = true;
@@ -159,6 +173,8 @@ public:
virtual HRESULT Hide () override
{
+ START_COM_CALL;
+
@autoreleasepool
{
if(Window != nullptr)
@@ -173,6 +189,8 @@ public:
virtual HRESULT Activate () override
{
+ START_COM_CALL;
+
@autoreleasepool
{
if(Window != nullptr)
@@ -187,6 +205,8 @@ public:
virtual HRESULT SetTopMost (bool value) override
{
+ START_COM_CALL;
+
@autoreleasepool
{
[Window setLevel: value ? NSFloatingWindowLevel : NSNormalWindowLevel];
@@ -197,11 +217,16 @@ public:
virtual HRESULT Close() override
{
+ START_COM_CALL;
+
@autoreleasepool
{
if (Window != nullptr)
{
- [Window close];
+ auto window = Window;
+ Window = nullptr;
+
+ [window close];
}
return S_OK;
@@ -210,6 +235,8 @@ public:
virtual HRESULT GetClientSize(AvnSize* ret) override
{
+ START_COM_CALL;
+
@autoreleasepool
{
if(ret == nullptr)
@@ -223,8 +250,25 @@ public:
}
}
+ virtual HRESULT GetFrameSize(AvnSize* ret) override
+ {
+ @autoreleasepool
+ {
+ if(ret == nullptr)
+ return E_POINTER;
+
+ auto frame = [Window frame];
+ ret->Width = frame.size.width;
+ ret->Height = frame.size.height;
+
+ return S_OK;
+ }
+ }
+
virtual HRESULT GetScaling (double* ret) override
{
+ START_COM_CALL;
+
@autoreleasepool
{
if(ret == nullptr)
@@ -243,6 +287,8 @@ public:
virtual HRESULT SetMinMaxSize (AvnSize minSize, AvnSize maxSize) override
{
+ START_COM_CALL;
+
@autoreleasepool
{
[Window setMinSize: ToNSSize(minSize)];
@@ -252,8 +298,18 @@ public:
}
}
- virtual HRESULT Resize(double x, double y) override
+ virtual HRESULT Resize(double x, double y, AvnPlatformResizeReason reason) override
{
+ if(_inResize)
+ {
+ return S_OK;
+ }
+
+ _inResize = true;
+
+ START_COM_CALL;
+ auto resizeBlock = ResizeScope(View, reason);
+
@autoreleasepool
{
auto maxSize = [Window maxSize];
@@ -279,13 +335,19 @@ public:
y = maxSize.height;
}
- if(!_shown)
+ @try
{
- BaseEvents->Resized(AvnSize{x,y});
+ if(!_shown)
+ {
+ BaseEvents->Resized(AvnSize{x,y}, reason);
+ }
+
+ [Window setContentSize:NSSize{x, y}];
+ }
+ @finally
+ {
+ _inResize = false;
}
-
- [StandardContainer setFrameSize:NSSize{x,y}];
- [Window setContentSize:NSSize{x, y}];
return S_OK;
}
@@ -293,6 +355,8 @@ public:
virtual HRESULT Invalidate (AvnRect rect) override
{
+ START_COM_CALL;
+
@autoreleasepool
{
[View setNeedsDisplayInRect:[View frame]];
@@ -303,6 +367,8 @@ public:
virtual HRESULT SetMainMenu(IAvnMenu* menu) override
{
+ START_COM_CALL;
+
_mainMenu = menu;
auto nativeMenu = dynamic_cast(menu);
@@ -321,6 +387,8 @@ public:
virtual HRESULT BeginMoveDrag () override
{
+ START_COM_CALL;
+
@autoreleasepool
{
auto lastEvent = [View lastMouseDownEvent];
@@ -338,11 +406,15 @@ public:
virtual HRESULT BeginResizeDrag (AvnWindowEdge edge) override
{
+ START_COM_CALL;
+
return S_OK;
}
virtual HRESULT GetPosition (AvnPoint* ret) override
{
+ START_COM_CALL;
+
@autoreleasepool
{
if(ret == nullptr)
@@ -363,6 +435,8 @@ public:
virtual HRESULT SetPosition (AvnPoint point) override
{
+ START_COM_CALL;
+
@autoreleasepool
{
lastPositionSet = point;
@@ -374,6 +448,8 @@ public:
virtual HRESULT PointToClient (AvnPoint point, AvnPoint* ret) override
{
+ START_COM_CALL;
+
@autoreleasepool
{
if(ret == nullptr)
@@ -392,6 +468,8 @@ public:
virtual HRESULT PointToScreen (AvnPoint point, AvnPoint* ret) override
{
+ START_COM_CALL;
+
@autoreleasepool
{
if(ret == nullptr)
@@ -409,12 +487,16 @@ public:
virtual HRESULT ThreadSafeSetSwRenderedFrame(AvnFramebuffer* fb, IUnknown* dispose) override
{
+ START_COM_CALL;
+
[View setSwRenderedFrame: fb dispose: dispose];
return S_OK;
}
virtual HRESULT SetCursor(IAvnCursor* cursor) override
{
+ START_COM_CALL;
+
@autoreleasepool
{
Cursor* avnCursor = dynamic_cast(cursor);
@@ -444,6 +526,8 @@ public:
virtual HRESULT CreateGlRenderTarget(IAvnGlSurfaceRenderTarget** ppv) override
{
+ START_COM_CALL;
+
if(View == NULL)
return E_FAIL;
*ppv = [renderTarget createSurfaceRenderTarget];
@@ -452,6 +536,8 @@ public:
virtual HRESULT CreateNativeControlHost(IAvnNativeControlHost** retOut) override
{
+ START_COM_CALL;
+
if(View == NULL)
return E_FAIL;
*retOut = ::CreateNativeControlHost(View);
@@ -460,6 +546,8 @@ public:
virtual HRESULT SetBlurEnabled (bool enable) override
{
+ START_COM_CALL;
+
[StandardContainer ShowBlur:enable];
return S_OK;
@@ -469,6 +557,8 @@ public:
IAvnClipboard* clipboard, IAvnDndResultCallback* cb,
void* sourceHandle) override
{
+ START_COM_CALL;
+
auto item = TryGetPasteboardItem(clipboard);
[item setString:@"" forType:GetAvnCustomDataType()];
if(item == nil)
@@ -528,6 +618,11 @@ public:
}
}
+ virtual bool IsDialog()
+ {
+ return false;
+ }
+
protected:
virtual NSWindowStyleMask GetStyle()
{
@@ -553,10 +648,12 @@ private:
bool _fullScreenActive;
SystemDecorations _decorations;
AvnWindowState _lastWindowState;
+ AvnWindowState _actualWindowState;
bool _inSetWindowState;
NSRect _preZoomSize;
bool _transitioningWindowState;
bool _isClientAreaExtended;
+ bool _isDialog;
AvnExtendClientAreaChromeHints _extendClientHints;
FORWARD_IUNKNOWN()
@@ -579,14 +676,21 @@ private:
_transitioningWindowState = false;
_inSetWindowState = false;
_lastWindowState = Normal;
+ _actualWindowState = Normal;
WindowEvents = events;
[Window setCanBecomeKeyAndMain];
[Window disableCursorRects];
[Window setTabbingMode:NSWindowTabbingModeDisallowed];
+ [Window setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
}
void HideOrShowTrafficLights ()
{
+ if (Window == nil)
+ {
+ return;
+ }
+
for (id subview in Window.contentView.superview.subviews) {
if ([subview isKindOfClass:NSClassFromString(@"NSTitlebarContainerView")]) {
NSView *titlebarView = [subview subviews][0];
@@ -611,11 +715,14 @@ private:
}
}
- virtual HRESULT Show (bool activate) override
+ virtual HRESULT Show (bool activate, bool isDialog) override
{
+ START_COM_CALL;
+
@autoreleasepool
- {
- WindowBaseImpl::Show(activate);
+ {
+ _isDialog = isDialog;
+ WindowBaseImpl::Show(activate, isDialog);
HideOrShowTrafficLights();
@@ -625,6 +732,8 @@ private:
virtual HRESULT SetEnabled (bool enable) override
{
+ START_COM_CALL;
+
@autoreleasepool
{
[Window setEnabled:enable];
@@ -634,6 +743,8 @@ private:
virtual HRESULT SetParent (IAvnWindow* parent) override
{
+ START_COM_CALL;
+
@autoreleasepool
{
if(parent == nullptr)
@@ -643,6 +754,12 @@ private:
if(cparent == nullptr)
return E_INVALIDARG;
+ // If one tries to show a child window with a minimized parent window, then the parent window will be
+ // restored but MacOS isn't kind enough to *tell* us that, so the window will be left in a non-interactive
+ // state. Detect this and explicitly restore the parent window ourselves to avoid this situation.
+ if (cparent->WindowState() == Minimized)
+ cparent->SetWindowState(Normal);
+
[cparent->Window addChildWindow:Window ordered:NSWindowAbove];
UpdateStyle();
@@ -673,7 +790,7 @@ private:
void WindowStateChanged () override
{
- if(!_inSetWindowState && !_transitioningWindowState)
+ if(_shown && !_inSetWindowState && !_transitioningWindowState)
{
AvnWindowState state;
GetWindowState(&state);
@@ -710,6 +827,7 @@ private:
}
_lastWindowState = state;
+ _actualWindowState = state;
WindowEvents->WindowStateChanged(state);
}
}
@@ -745,6 +863,8 @@ private:
virtual HRESULT SetCanResize(bool value) override
{
+ START_COM_CALL;
+
@autoreleasepool
{
_canResize = value;
@@ -755,6 +875,8 @@ private:
virtual HRESULT SetDecorations(SystemDecorations value) override
{
+ START_COM_CALL;
+
@autoreleasepool
{
auto currentWindowState = _lastWindowState;
@@ -820,6 +942,8 @@ private:
virtual HRESULT SetTitle (char* utf8title) override
{
+ START_COM_CALL;
+
@autoreleasepool
{
_lastTitle = [NSString stringWithUTF8String:(const char*)utf8title];
@@ -831,6 +955,8 @@ private:
virtual HRESULT SetTitleBarColor(AvnColor color) override
{
+ START_COM_CALL;
+
@autoreleasepool
{
float a = (float)color.Alpha / 255.0f;
@@ -860,6 +986,8 @@ private:
virtual HRESULT GetWindowState (AvnWindowState*ret) override
{
+ START_COM_CALL;
+
@autoreleasepool
{
if(ret == nullptr)
@@ -893,100 +1021,118 @@ private:
virtual HRESULT TakeFocusFromChildren () override
{
- if(Window == nil)
- return S_OK;
- if([Window isKeyWindow])
- [Window makeFirstResponder: View];
+ START_COM_CALL;
- return S_OK;
+ @autoreleasepool
+ {
+ if(Window == nil)
+ return S_OK;
+ if([Window isKeyWindow])
+ [Window makeFirstResponder: View];
+
+ return S_OK;
+ }
}
virtual HRESULT SetExtendClientArea (bool enable) override
{
- _isClientAreaExtended = enable;
+ START_COM_CALL;
- if(enable)
+ @autoreleasepool
{
- Window.titleVisibility = NSWindowTitleHidden;
-
- [Window setTitlebarAppearsTransparent:true];
+ _isClientAreaExtended = enable;
- auto wantsTitleBar = (_extendClientHints & AvnSystemChrome) || (_extendClientHints & AvnPreferSystemChrome);
-
- if (wantsTitleBar)
+ if(enable)
{
- [StandardContainer ShowTitleBar:true];
- }
- else
- {
- [StandardContainer ShowTitleBar:false];
- }
-
- if(_extendClientHints & AvnOSXThickTitleBar)
- {
- Window.toolbar = [NSToolbar new];
- Window.toolbar.showsBaselineSeparator = false;
+ Window.titleVisibility = NSWindowTitleHidden;
+
+ [Window setTitlebarAppearsTransparent:true];
+
+ auto wantsTitleBar = (_extendClientHints & AvnSystemChrome) || (_extendClientHints & AvnPreferSystemChrome);
+
+ if (wantsTitleBar)
+ {
+ [StandardContainer ShowTitleBar:true];
+ }
+ else
+ {
+ [StandardContainer ShowTitleBar:false];
+ }
+
+ if(_extendClientHints & AvnOSXThickTitleBar)
+ {
+ Window.toolbar = [NSToolbar new];
+ Window.toolbar.showsBaselineSeparator = false;
+ }
+ else
+ {
+ Window.toolbar = nullptr;
+ }
}
else
{
+ Window.titleVisibility = NSWindowTitleVisible;
Window.toolbar = nullptr;
+ [Window setTitlebarAppearsTransparent:false];
+ View.layer.zPosition = 0;
}
+
+ [Window setIsExtended:enable];
+
+ HideOrShowTrafficLights();
+
+ UpdateStyle();
+
+ return S_OK;
}
- else
- {
- Window.titleVisibility = NSWindowTitleVisible;
- Window.toolbar = nullptr;
- [Window setTitlebarAppearsTransparent:false];
- View.layer.zPosition = 0;
- }
-
- [Window setIsExtended:enable];
-
- HideOrShowTrafficLights();
-
- UpdateStyle();
-
- return S_OK;
}
virtual HRESULT SetExtendClientAreaHints (AvnExtendClientAreaChromeHints hints) override
{
- _extendClientHints = hints;
+ START_COM_CALL;
- SetExtendClientArea(_isClientAreaExtended);
- return S_OK;
+ @autoreleasepool
+ {
+ _extendClientHints = hints;
+
+ SetExtendClientArea(_isClientAreaExtended);
+ return S_OK;
+ }
}
virtual HRESULT GetExtendTitleBarHeight (double*ret) override
{
- if(ret == nullptr)
+ START_COM_CALL;
+
+ @autoreleasepool
{
- return E_POINTER;
+ if(ret == nullptr)
+ {
+ return E_POINTER;
+ }
+
+ *ret = [Window getExtendedTitleBarHeight];
+
+ return S_OK;
}
-
- *ret = [Window getExtendedTitleBarHeight];
-
- return S_OK;
}
virtual HRESULT SetExtendTitleBarHeight (double value) override
{
- [StandardContainer SetTitleBarHeightHint:value];
- return S_OK;
+ START_COM_CALL;
+
+ @autoreleasepool
+ {
+ [StandardContainer SetTitleBarHeightHint:value];
+ return S_OK;
+ }
}
void EnterFullScreenMode ()
{
_fullScreenActive = true;
- [Window setHasShadow:YES];
- [Window setTitleVisibility:NSWindowTitleVisible];
- [Window setTitlebarAppearsTransparent:NO];
[Window setTitle:_lastTitle];
-
- Window.styleMask = Window.styleMask | NSWindowStyleMaskTitled | NSWindowStyleMaskResizable;
- Window.styleMask = Window.styleMask & ~NSWindowStyleMaskFullSizeContentView;
-
[Window toggleFullScreen:nullptr];
}
@@ -1001,16 +1147,23 @@ private:
virtual HRESULT SetWindowState (AvnWindowState state) override
{
+ START_COM_CALL;
+
@autoreleasepool
{
- if(_lastWindowState == state)
+ if(Window == nullptr)
+ {
+ return S_OK;
+ }
+
+ if(_actualWindowState == state)
{
return S_OK;
}
_inSetWindowState = true;
- auto currentState = _lastWindowState;
+ auto currentState = _actualWindowState;
_lastWindowState = state;
if(currentState == Normal)
@@ -1089,8 +1242,12 @@ private:
}
break;
}
+
+ _actualWindowState = _lastWindowState;
+ WindowEvents->WindowStateChanged(_actualWindowState);
}
+
_inSetWindowState = false;
return S_OK;
@@ -1105,6 +1262,11 @@ private:
}
}
+ virtual bool IsDialog() override
+ {
+ return _isDialog;
+ }
+
protected:
virtual NSWindowStyleMask GetStyle() override
{
@@ -1184,6 +1346,9 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
[_blurBehind setWantsLayer:true];
_blurBehind.hidden = true;
+ [_blurBehind setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
+ [_content setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
+
[self addSubview:_blurBehind];
[self addSubview:_content];
@@ -1219,9 +1384,6 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
_settingSize = true;
[super setFrameSize:newSize];
- [_blurBehind setFrameSize:newSize];
- [_content setFrameSize:newSize];
-
auto window = objc_cast([self window]);
// TODO get actual titlebar size
@@ -1237,6 +1399,7 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
[_titleBarMaterial setFrame:tbar];
tbar.size.height = height < 1 ? 0 : 1;
[_titleBarUnderline setFrame:tbar];
+
_settingSize = false;
}
@@ -1264,6 +1427,7 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
bool _lastKeyHandled;
AvnPixelSize _lastPixelSize;
NSObject* _renderTarget;
+ AvnPlatformResizeReason _resizeReason;
}
- (void)onClosed
@@ -1375,7 +1539,8 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
_lastPixelSize.Height = (int)fsize.height;
[self updateRenderTarget];
- _parent->BaseEvents->Resized(AvnSize{newSize.width, newSize.height});
+ auto reason = [self inLiveResize] ? ResizeUser : _resizeReason;
+ _parent->BaseEvents->Resized(AvnSize{newSize.width, newSize.height}, reason);
}
}
@@ -1541,6 +1706,7 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
switch(event.buttonNumber)
{
+ case 2:
case 3:
_isMiddlePressed = true;
[self mouseEvent:event withType:MiddleButtonDown];
@@ -1573,6 +1739,7 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
{
switch(event.buttonNumber)
{
+ case 2:
case 3:
_isMiddlePressed = false;
[self mouseEvent:event withType:MiddleButtonUp];
@@ -1874,6 +2041,16 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
}
+- (AvnPlatformResizeReason)getResizeReason
+{
+ return _resizeReason;
+}
+
+- (void)setResizeReason:(AvnPlatformResizeReason)reason
+{
+ _resizeReason = reason;
+}
+
@end
@@ -1895,6 +2072,11 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
_isExtended = value;
}
+-(bool) isDialog
+{
+ return _parent->IsDialog();
+}
+
-(double) getScaling
{
return _lastScaling;
@@ -1924,18 +2106,7 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
+(void)closeAll
{
- NSArray* windows = [NSArray arrayWithArray:[NSApp windows]];
- auto numWindows = [windows count];
-
- for(int i = 0; i < numWindows; i++)
- {
- auto window = (AvnWindow*)[windows objectAtIndex:i];
-
- if([window parentWindow] == nullptr) // Avalonia will handle the child windows.
- {
- [window performClose:nil];
- }
- }
+ [[NSApplication sharedApplication] terminate:self];
}
- (void)performClose:(id)sender
@@ -1948,7 +2119,7 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
{
if(![self windowShouldClose:self]) return;
}
-
+
[self close];
}
@@ -2084,7 +2255,22 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
-(BOOL)canBecomeKeyWindow
{
- return _canBecomeKeyAndMain;
+ 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])
+ {
+ auto ch = objc_cast(uch);
+ if(ch == nil)
+ continue;
+ if (ch.isDialog)
+ return false;
+ }
+
+ return true;
+ }
+
+ return false;
}
-(BOOL)canBecomeMainWindow
@@ -2092,22 +2278,6 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
return _canBecomeKeyAndMain;
}
--(bool) activateAppropriateChild: (bool)activating
-{
- for(NSWindow* uch in [self childWindows])
- {
- auto ch = objc_cast(uch);
- if(ch == nil)
- continue;
- [ch activateAppropriateChild:false];
- return FALSE;
- }
-
- if(!activating)
- [self makeKeyAndOrderFront:self];
- return TRUE;
-}
-
-(bool)shouldTryToHandleEvents
{
return _isEnabled;
@@ -2118,26 +2288,15 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
_isEnabled = enable;
}
--(void)makeKeyWindow
-{
- if([self activateAppropriateChild: true])
- {
- [super makeKeyWindow];
- }
-}
-
-(void)becomeKeyWindow
{
[self showWindowMenuWithAppMenu];
- if([self activateAppropriateChild: true])
+ if(_parent != nullptr)
{
- if(_parent != nullptr)
- {
- _parent->BaseEvents->Activated();
- }
+ _parent->BaseEvents->Activated();
}
-
+
[super becomeKeyWindow];
}
@@ -2147,7 +2306,6 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
if(parent != nil)
{
[parent removeChildWindow:self];
- [parent activateAppropriateChild: false];
}
}
@@ -2352,13 +2510,14 @@ protected:
return NSWindowStyleMaskBorderless;
}
- virtual HRESULT Resize(double x, double y) override
+ virtual HRESULT Resize(double x, double y, AvnPlatformResizeReason reason) override
{
+ START_COM_CALL;
+
@autoreleasepool
{
if (Window != nullptr)
{
- [StandardContainer setFrameSize:NSSize{x,y}];
[Window setContentSize:NSSize{x, y}];
[Window setFrameTopLeftPoint:ToNSPoint(ConvertPointY(lastPositionSet))];
diff --git a/packages/Avalonia/AvaloniaBuildTasks.targets b/packages/Avalonia/AvaloniaBuildTasks.targets
index 45a7f1aa44..de3830ffea 100644
--- a/packages/Avalonia/AvaloniaBuildTasks.targets
+++ b/packages/Avalonia/AvaloniaBuildTasks.targets
@@ -42,12 +42,24 @@
- $(BuildAvaloniaResourcesDependsOn);AddAvaloniaResources;ResolveReferences
+ $(BuildAvaloniaResourcesDependsOn);AddAvaloniaResources;ResolveReferences;_GenerateAvaloniaResourcesDependencyCache
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/ControlCatalog/MainWindow.xaml.cs b/samples/ControlCatalog/MainWindow.xaml.cs
index 723351ae57..2446c0e1c9 100644
--- a/samples/ControlCatalog/MainWindow.xaml.cs
+++ b/samples/ControlCatalog/MainWindow.xaml.cs
@@ -17,7 +17,10 @@ namespace ControlCatalog
public MainWindow()
{
this.InitializeComponent();
- this.AttachDevTools();
+ this.AttachDevTools(new Avalonia.Diagnostics.DevToolsOptions()
+ {
+ StartupScreenIndex = 1,
+ });
//Renderer.DrawFps = true;
//Renderer.DrawDirtyRects = Renderer.DrawFps = true;
diff --git a/samples/ControlCatalog/Pages/ComboBoxPage.xaml b/samples/ControlCatalog/Pages/ComboBoxPage.xaml
index 025b85492c..d440b7cce3 100644
--- a/samples/ControlCatalog/Pages/ComboBoxPage.xaml
+++ b/samples/ControlCatalog/Pages/ComboBoxPage.xaml
@@ -1,12 +1,20 @@
+ xmlns:sys="using:System"
+ xmlns:col="using:System.Collections">
ComboBox
A drop-down list.
-
+
+
+
+
Inline Items
Inline Item 2
@@ -14,6 +22,24 @@
Inline Item 4
+
+
+
+
+ Hello
+ World
+
+
+
+
+
+
+
+
+
+
+
+
@@ -46,7 +72,7 @@
-
+
diff --git a/samples/ControlCatalog/Pages/ContextFlyoutPage.axaml b/samples/ControlCatalog/Pages/ContextFlyoutPage.axaml
deleted file mode 100644
index e15637aa0f..0000000000
--- a/samples/ControlCatalog/Pages/ContextFlyoutPage.axaml
+++ /dev/null
@@ -1,102 +0,0 @@
-
-
-
-
-
-
- Context Flyout
- A right click Flyout that can be applied to any control.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/samples/ControlCatalog/Pages/ContextFlyoutPage.axaml.cs b/samples/ControlCatalog/Pages/ContextFlyoutPage.axaml.cs
deleted file mode 100644
index e64d4a2cdd..0000000000
--- a/samples/ControlCatalog/Pages/ContextFlyoutPage.axaml.cs
+++ /dev/null
@@ -1,45 +0,0 @@
-using Avalonia;
-using Avalonia.Controls;
-using Avalonia.Markup.Xaml;
-using ControlCatalog.ViewModels;
-using Avalonia.Interactivity;
-namespace ControlCatalog.Pages
-{
- public class ContextFlyoutPage : UserControl
- {
- private TextBox _textBox;
-
- public ContextFlyoutPage()
- {
- InitializeComponent();
-
- var vm = new ContextFlyoutPageViewModel();
- vm.View = this;
- DataContext = vm;
-
- _textBox = this.FindControl("TextBox");
-
- var cutButton = this.FindControl