Browse Source

working reparenting of app menu.

pull/2978/head
Dan Walmsley 6 years ago
parent
commit
4bd7c39609
  1. 2
      native/Avalonia.Native/inc/avalonia-native.h
  2. 3
      native/Avalonia.Native/src/OSX/common.h
  3. 18
      native/Avalonia.Native/src/OSX/main.mm
  4. 31
      native/Avalonia.Native/src/OSX/menu.mm
  5. 51
      native/Avalonia.Native/src/OSX/window.mm
  6. 44
      src/Avalonia.Native/AvaloniaNativeMenuExporter.cs
  7. 7
      src/Avalonia.Native/AvaloniaNativePlatform.cs
  8. 1
      src/Avalonia.Native/AvaloniaNativePlatformExtensions.cs

2
native/Avalonia.Native/inc/avalonia-native.h

@ -175,6 +175,8 @@ public:
virtual HRESULT CreateClipboard(IAvnClipboard** ppv) = 0;
virtual HRESULT CreateCursorFactory(IAvnCursorFactory** ppv) = 0;
virtual HRESULT ObtainGlFeature(IAvnGlFeature** ppv) = 0;
virtual HRESULT ObtainAppMenu(IAvnAppMenu** retOut) = 0;
virtual HRESULT SetAppMenu(IAvnAppMenu* menu) = 0;
virtual HRESULT CreateMenu (IAvnAppMenu** ppv) = 0;
virtual HRESULT CreateMenuItem (IAvnAppMenuItem** ppv) = 0;
};

3
native/Avalonia.Native/src/OSX/common.h

@ -21,6 +21,9 @@ extern IAvnGlFeature* GetGlFeature();
extern IAvnGlSurfaceRenderTarget* CreateGlRenderTarget(NSWindow* window, NSView* view);
extern IAvnAppMenu* CreateAppMenu();
extern IAvnAppMenuItem* CreateAppMenuItem();
extern void SetAppMenu (IAvnAppMenu* appMenu);
extern IAvnAppMenu* GetAppMenu ();
extern NSMenuItem* GetAppMenuItem ();
extern void InitializeAvnApp();
extern NSApplicationActivationPolicy AvnDesiredActivationPolicy;

18
native/Avalonia.Native/src/OSX/main.mm

@ -236,6 +236,24 @@ public:
*ppv = ::CreateAppMenuItem();
return S_OK;
}
virtual HRESULT SetAppMenu (IAvnAppMenu* appMenu) override
{
::SetAppMenu(appMenu);
return S_OK;
}
virtual HRESULT ObtainAppMenu(IAvnAppMenu** retOut) override
{
if(retOut == nullptr)
{
return E_POINTER;
}
*retOut = ::GetAppMenu();
return S_OK;
}
};
extern "C" IAvaloniaNativeFactory* CreateAvaloniaNative()

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

@ -189,3 +189,34 @@ extern IAvnAppMenuItem* CreateAppMenuItem()
return new AvnAppMenuItem();
}
}
static IAvnAppMenu* s_appMenu = nullptr;
static NSMenuItem* s_appMenuItem = nullptr;
extern void SetAppMenu (IAvnAppMenu* appMenu)
{
s_appMenu = appMenu;
if(s_appMenu != nullptr)
{
auto nativeMenu = dynamic_cast<AvnAppMenu*>(s_appMenu);
s_appMenuItem = [nativeMenu->GetNative() itemAtIndex:0];
}
else
{
s_appMenuItem = nullptr;
}
}
extern IAvnAppMenu* GetAppMenu ()
{
return s_appMenu;
}
extern NSMenuItem* GetAppMenuItem ()
{
return s_appMenuItem;
}

51
native/Avalonia.Native/src/OSX/window.mm

@ -1073,6 +1073,7 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
bool _canBecomeKeyAndMain;
bool _closed;
NSMenu* _menu;
bool _isAppMenuApplied;
}
- (void)dealloc
@ -1104,7 +1105,22 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
}
_menu = menu;
[NSApp setMenu:menu];
if ([self isKeyWindow])
{
auto appMenu = ::GetAppMenuItem();
if(appMenu != nullptr)
{
[[appMenu menu] removeItem:appMenu];
[_menu insertItem:appMenu atIndex:0];
_isAppMenuApplied = true;
}
[NSApp setMenu:menu];
}
}
-(void) setCanBecomeKeyAndMain
@ -1204,6 +1220,17 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
_menu = [NSMenu new];
}
auto appMenu = ::GetAppMenuItem();
if(appMenu != nullptr)
{
[[appMenu menu] removeItem:appMenu];
[_menu insertItem:appMenu atIndex:0];
_isAppMenuApplied = true;
}
[NSApp setMenu:_menu];
_parent->BaseEvents->Activated();
@ -1251,7 +1278,27 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
if(_parent)
_parent->BaseEvents->Deactivated();
[NSApp setMenu:nullptr];
auto appMenuItem = ::GetAppMenuItem();
if(appMenuItem != nullptr)
{
auto appMenu = ::GetAppMenu();
auto nativeAppMenu = dynamic_cast<AvnAppMenu*>(appMenu);
[[appMenuItem menu] removeItem:appMenuItem];
[nativeAppMenu->GetNative() addItem:appMenuItem];
[NSApp setMenu:nativeAppMenu->GetNative()];
}
else
{
[NSApp setMenu:nullptr];
}
// remove window menu items from appmenu?
[super resignKeyWindow];
}

44
src/Avalonia.Native/AvaloniaNativeMenuExporter.cs

@ -58,6 +58,14 @@ namespace Avalonia.Native
DoLayoutReset();
}
public AvaloniaNativeMenuExporter(IAvaloniaNativeFactory factory)
{
_factory = factory;
_menu = NativeMenu.GetMenu(Application.Current);
DoLayoutReset();
}
public bool IsNativeMenuExported => _exported;
public event EventHandler OnIsNativeMenuExportedChanged;
@ -109,7 +117,14 @@ namespace Avalonia.Native
_menuItems.Clear();
SetMenu(_nativeWindow, _menu?.Items);
if(_nativeWindow is null)
{
SetMenu(_menu?.Items);
}
else
{
SetMenu(_nativeWindow, _menu?.Items);
}
_exported = true;
}
@ -236,7 +251,7 @@ namespace Avalonia.Native
}
}
private void SetMenu(IAvnWindow avnWindow, ICollection<NativeMenuItem> menuItems)
private void SetMenu(ICollection<NativeMenuItem> menuItems)
{
if (menuItems is null)
{
@ -247,11 +262,24 @@ namespace Avalonia.Native
if (menu != null)
{
var items = menuItems.ToList();
var appMenu = _factory.ObtainAppMenu ();
items.InsertRange(0, menu.Items);
if (appMenu is null)
{
appMenu = _factory.CreateMenu();
}
menuItems = items;
AddItemsToMenu(appMenu, menuItems);
_factory.SetAppMenu(appMenu);
}
}
private void SetMenu(IAvnWindow avnWindow, ICollection<NativeMenuItem> menuItems)
{
if (menuItems is null)
{
menuItems = new List<NativeMenuItem>();
}
var appMenu = avnWindow.ObtainMainMenu();
@ -259,13 +287,11 @@ namespace Avalonia.Native
if (appMenu is null)
{
appMenu = _factory.CreateMenu();
avnWindow.SetMainMenu(appMenu);
}
appMenu.Clear();
AddItemsToMenu(appMenu, menuItems);
avnWindow.SetMainMenu(appMenu);
}
}
}

7
src/Avalonia.Native/AvaloniaNativePlatform.cs

@ -57,7 +57,12 @@ namespace Avalonia.Native
return Initialize(CreateAvaloniaNative(), options);
}
public void SetupApplicationName()
public void SetupApplicationMenuExporter ()
{
var exporter = new AvaloniaNativeMenuExporter(_factory);
}
public void SetupApplicationName ()
{
if(!string.IsNullOrWhiteSpace(Application.Current.Name))
{

1
src/Avalonia.Native/AvaloniaNativePlatformExtensions.cs

@ -20,6 +20,7 @@ namespace Avalonia
builder.AfterSetup (x=>
{
platform.SetupApplicationMenuExporter();
platform.SetupApplicationName();
});
});

Loading…
Cancel
Save