Skip to content

Commit 5e8b7ac

Browse files
authored
Merge pull request #9451 from AvaloniaUI/fixes/osx-native-menu-memory-leak
[OSX] Fixed NativeMenu memory leak
2 parents 061beb6 + 71212dc commit 5e8b7ac

File tree

4 files changed

+33
-21
lines changed

4 files changed

+33
-21
lines changed

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

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,20 @@ class AvnAppMenuItem : public ComSingleObject<IAvnMenuItem, &IID_IAvnMenuItem>
5959
void RaiseOnClicked();
6060
};
6161

62+
class AvnAppMenu;
63+
64+
@interface AvnMenuDelegate : NSObject<NSMenuDelegate>
65+
- (id) initWithParent: (AvnAppMenu*) parent;
66+
- (void) parentDestroyed;
67+
@end
68+
69+
6270
class AvnAppMenu : public ComSingleObject<IAvnMenu, &IID_IAvnMenu>
6371
{
6472
private:
6573
AvnMenu* _native;
6674
ComPtr<IAvnMenuEvents> _baseEvents;
75+
AvnMenuDelegate* _delegate;
6776

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

8594
virtual HRESULT Clear () override;
95+
virtual ~AvnAppMenu() override;
8696
};
8797

8898

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

93100
#endif
94101

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

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -292,8 +292,13 @@ - (void)didSelectItem:(nullable id)sender
292292
AvnAppMenu::AvnAppMenu(IAvnMenuEvents* events)
293293
{
294294
_baseEvents = events;
295-
id del = [[AvnMenuDelegate alloc] initWithParent: this];
296-
_native = [[AvnMenu alloc] initWithDelegate: del];
295+
_delegate = [[AvnMenuDelegate alloc] initWithParent: this];
296+
_native = [[AvnMenu alloc] initWithDelegate: _delegate];
297+
}
298+
299+
AvnAppMenu::~AvnAppMenu()
300+
{
301+
[_delegate parentDestroyed];
297302
}
298303

299304

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

395400
@implementation AvnMenuDelegate
396401
{
397-
ComPtr<AvnAppMenu> _parent;
402+
AvnAppMenu* _parent;
398403
}
399404
- (id) initWithParent:(AvnAppMenu *)parent
400405
{
401406
self = [super init];
402407
_parent = parent;
403408
return self;
404409
}
410+
411+
- (void) parentDestroyed
412+
{
413+
_parent = nullptr;
414+
}
415+
405416
- (BOOL)menu:(NSMenu *)menu updateItem:(NSMenuItem *)item atIndex:(NSInteger)index shouldCancel:(BOOL)shouldCancel
406417
{
407418
if(shouldCancel)
@@ -416,17 +427,20 @@ - (NSInteger)numberOfItemsInMenu:(NSMenu *)menu
416427

417428
- (void)menuNeedsUpdate:(NSMenu *)menu
418429
{
419-
_parent->RaiseNeedsUpdate();
430+
if(_parent)
431+
_parent->RaiseNeedsUpdate();
420432
}
421433

422434
- (void)menuWillOpen:(NSMenu *)menu
423435
{
424-
_parent->RaiseOpening();
436+
if(_parent)
437+
_parent->RaiseOpening();
425438
}
426439

427440
- (void)menuDidClose:(NSMenu *)menu
428441
{
429-
_parent->RaiseClosed();
442+
if(_parent)
443+
_parent->RaiseClosed();
430444
}
431445

432446
@end

src/Avalonia.MicroCom/CallbackBase.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ void DestroyIfNeeded()
3232
if (_referencedFromManaged == false && _referencedFromNative == false)
3333
{
3434
_destroyed = true;
35+
Shadow?.Dispose();
36+
Shadow = null;
3537
Destroyed();
3638
}
3739
}

src/Avalonia.Native/IAvnMenu.cs

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ namespace Avalonia.Native.Interop.Impl
4444
{
4545
partial class __MicroComIAvnMenuProxy
4646
{
47-
private MenuEvents _events;
4847
private AvaloniaNativeMenuExporter _exporter;
4948
private List<__MicroComIAvnMenuItemProxy> _menuItems = new List<__MicroComIAvnMenuItemProxy>();
5049
private Dictionary<NativeMenuItemBase, __MicroComIAvnMenuItemProxy> _menuItemLookup = new Dictionary<NativeMenuItemBase, __MicroComIAvnMenuItemProxy>();
@@ -71,25 +70,15 @@ public void RaiseClosed()
7170

7271
public static __MicroComIAvnMenuProxy Create(IAvaloniaNativeFactory factory)
7372
{
74-
var events = new MenuEvents();
73+
using var events = new MenuEvents();
7574

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

7877
events.Initialise(menu);
7978

80-
menu._events = events;
81-
8279
return menu;
8380
}
8481

85-
protected override void Dispose(bool disposing)
86-
{
87-
if (disposing)
88-
{
89-
_events.Dispose();
90-
}
91-
}
92-
9382
private void RemoveAndDispose(__MicroComIAvnMenuItemProxy item)
9483
{
9584
_menuItemLookup.Remove(item.ManagedMenuItem);

0 commit comments

Comments
 (0)