Skip to content

Commit

Permalink
Merge pull request #9451 from AvaloniaUI/fixes/osx-native-menu-memory…
Browse files Browse the repository at this point in the history
…-leak

[OSX] Fixed NativeMenu memory leak
# Conflicts:
#	src/Avalonia.MicroCom/CallbackBase.cs
  • Loading branch information
maxkatz6 authored and Dan Walmsley committed Dec 6, 2022
1 parent fdb32b7 commit 0af2a96
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 21 deletions.
13 changes: 10 additions & 3 deletions native/Avalonia.Native/src/OSX/menu.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,20 @@ class AvnAppMenuItem : public ComSingleObject<IAvnMenuItem, &IID_IAvnMenuItem>
void RaiseOnClicked();
};

class AvnAppMenu;

@interface AvnMenuDelegate : NSObject<NSMenuDelegate>
- (id) initWithParent: (AvnAppMenu*) parent;
- (void) parentDestroyed;
@end


class AvnAppMenu : public ComSingleObject<IAvnMenu, &IID_IAvnMenu>
{
private:
AvnMenu* _native;
ComPtr<IAvnMenuEvents> _baseEvents;
AvnMenuDelegate* _delegate;

public:
FORWARD_IUNKNOWN()
Expand All @@ -83,12 +92,10 @@ class AvnAppMenu : public ComSingleObject<IAvnMenu, &IID_IAvnMenu>
virtual HRESULT SetTitle (char* utf8String) override;

virtual HRESULT Clear () override;
virtual ~AvnAppMenu() override;
};


@interface AvnMenuDelegate : NSObject<NSMenuDelegate>
- (id) initWithParent: (AvnAppMenu*) parent;
@end

#endif

26 changes: 20 additions & 6 deletions native/Avalonia.Native/src/OSX/menu.mm
Original file line number Diff line number Diff line change
Expand Up @@ -292,8 +292,13 @@ - (void)didSelectItem:(nullable id)sender
AvnAppMenu::AvnAppMenu(IAvnMenuEvents* events)
{
_baseEvents = events;
id del = [[AvnMenuDelegate alloc] initWithParent: this];
_native = [[AvnMenu alloc] initWithDelegate: del];
_delegate = [[AvnMenuDelegate alloc] initWithParent: this];
_native = [[AvnMenu alloc] initWithDelegate: _delegate];
}

AvnAppMenu::~AvnAppMenu()
{
[_delegate parentDestroyed];
}


Expand Down Expand Up @@ -394,14 +399,20 @@ - (void)didSelectItem:(nullable id)sender

@implementation AvnMenuDelegate
{
ComPtr<AvnAppMenu> _parent;
AvnAppMenu* _parent;
}
- (id) initWithParent:(AvnAppMenu *)parent
{
self = [super init];
_parent = parent;
return self;
}

- (void) parentDestroyed
{
_parent = nullptr;
}

- (BOOL)menu:(NSMenu *)menu updateItem:(NSMenuItem *)item atIndex:(NSInteger)index shouldCancel:(BOOL)shouldCancel
{
if(shouldCancel)
Expand All @@ -416,17 +427,20 @@ - (NSInteger)numberOfItemsInMenu:(NSMenu *)menu

- (void)menuNeedsUpdate:(NSMenu *)menu
{
_parent->RaiseNeedsUpdate();
if(_parent)
_parent->RaiseNeedsUpdate();
}

- (void)menuWillOpen:(NSMenu *)menu
{
_parent->RaiseOpening();
if(_parent)
_parent->RaiseOpening();
}

- (void)menuDidClose:(NSMenu *)menu
{
_parent->RaiseClosed();
if(_parent)
_parent->RaiseClosed();
}

@end
Expand Down
2 changes: 2 additions & 0 deletions src/Avalonia.Native/CallbackBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ void DestroyIfNeeded()
if (_referencedFromManaged == false && _referencedFromNative == false)
{
_destroyed = true;
Shadow?.Dispose();
Shadow = null;
Destroyed();
}
}
Expand Down
13 changes: 1 addition & 12 deletions src/Avalonia.Native/IAvnMenu.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ namespace Avalonia.Native.Interop.Impl
{
partial class __MicroComIAvnMenuProxy
{
private MenuEvents _events;
private AvaloniaNativeMenuExporter _exporter;
private List<__MicroComIAvnMenuItemProxy> _menuItems = new List<__MicroComIAvnMenuItemProxy>();
private Dictionary<NativeMenuItemBase, __MicroComIAvnMenuItemProxy> _menuItemLookup = new Dictionary<NativeMenuItemBase, __MicroComIAvnMenuItemProxy>();
Expand All @@ -71,25 +70,15 @@ public void RaiseClosed()

public static __MicroComIAvnMenuProxy Create(IAvaloniaNativeFactory factory)
{
var events = new MenuEvents();
using var events = new MenuEvents();

var menu = (__MicroComIAvnMenuProxy)factory.CreateMenu(events);

events.Initialise(menu);

menu._events = events;

return menu;
}

protected override void Dispose(bool disposing)
{
if (disposing)
{
_events.Dispose();
}
}

private void RemoveAndDispose(__MicroComIAvnMenuItemProxy item)
{
_menuItemLookup.Remove(item.ManagedMenuItem);
Expand Down

0 comments on commit 0af2a96

Please sign in to comment.