Browse Source

[OSX] Fixed NativeMenu memory leak

pull/9451/head
Nikita Tsukanov 3 years ago
parent
commit
c7d76e49e4
  1. 13
      native/Avalonia.Native/src/OSX/menu.h
  2. 26
      native/Avalonia.Native/src/OSX/menu.mm
  3. 2
      src/Avalonia.MicroCom/CallbackBase.cs
  4. 13
      src/Avalonia.Native/IAvnMenu.cs

13
native/Avalonia.Native/src/OSX/menu.h

@ -59,11 +59,20 @@ public:
void RaiseOnClicked(); void RaiseOnClicked();
}; };
class AvnAppMenu;
@interface AvnMenuDelegate : NSObject<NSMenuDelegate>
- (id) initWithParent: (AvnAppMenu*) parent;
- (void) parentDestroyed;
@end
class AvnAppMenu : public ComSingleObject<IAvnMenu, &IID_IAvnMenu> class AvnAppMenu : public ComSingleObject<IAvnMenu, &IID_IAvnMenu>
{ {
private: private:
AvnMenu* _native; AvnMenu* _native;
ComPtr<IAvnMenuEvents> _baseEvents; ComPtr<IAvnMenuEvents> _baseEvents;
AvnMenuDelegate* _delegate;
public: public:
FORWARD_IUNKNOWN() FORWARD_IUNKNOWN()
@ -83,12 +92,10 @@ public:
virtual HRESULT SetTitle (char* utf8String) override; virtual HRESULT SetTitle (char* utf8String) override;
virtual HRESULT Clear () override; virtual HRESULT Clear () override;
virtual ~AvnAppMenu() override;
}; };
@interface AvnMenuDelegate : NSObject<NSMenuDelegate>
- (id) initWithParent: (AvnAppMenu*) parent;
@end
#endif #endif

26
native/Avalonia.Native/src/OSX/menu.mm

@ -292,8 +292,13 @@ void AvnAppMenuItem::RaiseOnClicked()
AvnAppMenu::AvnAppMenu(IAvnMenuEvents* events) AvnAppMenu::AvnAppMenu(IAvnMenuEvents* events)
{ {
_baseEvents = events; _baseEvents = events;
id del = [[AvnMenuDelegate alloc] initWithParent: this]; _delegate = [[AvnMenuDelegate alloc] initWithParent: this];
_native = [[AvnMenu alloc] initWithDelegate: del]; _native = [[AvnMenu alloc] initWithDelegate: _delegate];
}
AvnAppMenu::~AvnAppMenu()
{
[_delegate parentDestroyed];
} }
@ -394,7 +399,7 @@ HRESULT AvnAppMenu::Clear()
@implementation AvnMenuDelegate @implementation AvnMenuDelegate
{ {
ComPtr<AvnAppMenu> _parent; AvnAppMenu* _parent;
} }
- (id) initWithParent:(AvnAppMenu *)parent - (id) initWithParent:(AvnAppMenu *)parent
{ {
@ -402,6 +407,12 @@ HRESULT AvnAppMenu::Clear()
_parent = parent; _parent = parent;
return self; return self;
} }
- (void) parentDestroyed
{
_parent = nullptr;
}
- (BOOL)menu:(NSMenu *)menu updateItem:(NSMenuItem *)item atIndex:(NSInteger)index shouldCancel:(BOOL)shouldCancel - (BOOL)menu:(NSMenu *)menu updateItem:(NSMenuItem *)item atIndex:(NSInteger)index shouldCancel:(BOOL)shouldCancel
{ {
if(shouldCancel) if(shouldCancel)
@ -416,17 +427,20 @@ HRESULT AvnAppMenu::Clear()
- (void)menuNeedsUpdate:(NSMenu *)menu - (void)menuNeedsUpdate:(NSMenu *)menu
{ {
_parent->RaiseNeedsUpdate(); if(_parent)
_parent->RaiseNeedsUpdate();
} }
- (void)menuWillOpen:(NSMenu *)menu - (void)menuWillOpen:(NSMenu *)menu
{ {
_parent->RaiseOpening(); if(_parent)
_parent->RaiseOpening();
} }
- (void)menuDidClose:(NSMenu *)menu - (void)menuDidClose:(NSMenu *)menu
{ {
_parent->RaiseClosed(); if(_parent)
_parent->RaiseClosed();
} }
@end @end

2
src/Avalonia.MicroCom/CallbackBase.cs

@ -32,6 +32,8 @@ namespace Avalonia.MicroCom
if (_referencedFromManaged == false && _referencedFromNative == false) if (_referencedFromManaged == false && _referencedFromNative == false)
{ {
_destroyed = true; _destroyed = true;
Shadow?.Dispose();
Shadow = null;
Destroyed(); Destroyed();
} }
} }

13
src/Avalonia.Native/IAvnMenu.cs

@ -44,7 +44,6 @@ namespace Avalonia.Native.Interop.Impl
{ {
partial class __MicroComIAvnMenuProxy partial class __MicroComIAvnMenuProxy
{ {
private MenuEvents _events;
private AvaloniaNativeMenuExporter _exporter; private AvaloniaNativeMenuExporter _exporter;
private List<__MicroComIAvnMenuItemProxy> _menuItems = new List<__MicroComIAvnMenuItemProxy>(); private List<__MicroComIAvnMenuItemProxy> _menuItems = new List<__MicroComIAvnMenuItemProxy>();
private Dictionary<NativeMenuItemBase, __MicroComIAvnMenuItemProxy> _menuItemLookup = new Dictionary<NativeMenuItemBase, __MicroComIAvnMenuItemProxy>(); private Dictionary<NativeMenuItemBase, __MicroComIAvnMenuItemProxy> _menuItemLookup = new Dictionary<NativeMenuItemBase, __MicroComIAvnMenuItemProxy>();
@ -71,25 +70,15 @@ namespace Avalonia.Native.Interop.Impl
public static __MicroComIAvnMenuProxy Create(IAvaloniaNativeFactory factory) public static __MicroComIAvnMenuProxy Create(IAvaloniaNativeFactory factory)
{ {
var events = new MenuEvents(); using var events = new MenuEvents();
var menu = (__MicroComIAvnMenuProxy)factory.CreateMenu(events); var menu = (__MicroComIAvnMenuProxy)factory.CreateMenu(events);
events.Initialise(menu); events.Initialise(menu);
menu._events = events;
return menu; return menu;
} }
protected override void Dispose(bool disposing)
{
if (disposing)
{
_events.Dispose();
}
}
private void RemoveAndDispose(__MicroComIAvnMenuItemProxy item) private void RemoveAndDispose(__MicroComIAvnMenuItemProxy item)
{ {
_menuItemLookup.Remove(item.ManagedMenuItem); _menuItemLookup.Remove(item.ManagedMenuItem);

Loading…
Cancel
Save