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 CreateClipboard(IAvnClipboard** ppv) = 0;
virtual HRESULT CreateCursorFactory(IAvnCursorFactory** ppv) = 0; virtual HRESULT CreateCursorFactory(IAvnCursorFactory** ppv) = 0;
virtual HRESULT ObtainGlFeature(IAvnGlFeature** 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 CreateMenu (IAvnAppMenu** ppv) = 0;
virtual HRESULT CreateMenuItem (IAvnAppMenuItem** 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 IAvnGlSurfaceRenderTarget* CreateGlRenderTarget(NSWindow* window, NSView* view);
extern IAvnAppMenu* CreateAppMenu(); extern IAvnAppMenu* CreateAppMenu();
extern IAvnAppMenuItem* CreateAppMenuItem(); extern IAvnAppMenuItem* CreateAppMenuItem();
extern void SetAppMenu (IAvnAppMenu* appMenu);
extern IAvnAppMenu* GetAppMenu ();
extern NSMenuItem* GetAppMenuItem ();
extern void InitializeAvnApp(); extern void InitializeAvnApp();
extern NSApplicationActivationPolicy AvnDesiredActivationPolicy; extern NSApplicationActivationPolicy AvnDesiredActivationPolicy;

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

@ -236,6 +236,24 @@ public:
*ppv = ::CreateAppMenuItem(); *ppv = ::CreateAppMenuItem();
return S_OK; 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() extern "C" IAvaloniaNativeFactory* CreateAvaloniaNative()

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

@ -189,3 +189,34 @@ extern IAvnAppMenuItem* CreateAppMenuItem()
return new AvnAppMenuItem(); 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 _canBecomeKeyAndMain;
bool _closed; bool _closed;
NSMenu* _menu; NSMenu* _menu;
bool _isAppMenuApplied;
} }
- (void)dealloc - (void)dealloc
@ -1104,7 +1105,22 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
} }
_menu = menu; _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 -(void) setCanBecomeKeyAndMain
@ -1204,6 +1220,17 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
_menu = [NSMenu new]; _menu = [NSMenu new];
} }
auto appMenu = ::GetAppMenuItem();
if(appMenu != nullptr)
{
[[appMenu menu] removeItem:appMenu];
[_menu insertItem:appMenu atIndex:0];
_isAppMenuApplied = true;
}
[NSApp setMenu:_menu]; [NSApp setMenu:_menu];
_parent->BaseEvents->Activated(); _parent->BaseEvents->Activated();
@ -1251,7 +1278,27 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent
if(_parent) if(_parent)
_parent->BaseEvents->Deactivated(); _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]; [super resignKeyWindow];
} }

44
src/Avalonia.Native/AvaloniaNativeMenuExporter.cs

@ -58,6 +58,14 @@ namespace Avalonia.Native
DoLayoutReset(); DoLayoutReset();
} }
public AvaloniaNativeMenuExporter(IAvaloniaNativeFactory factory)
{
_factory = factory;
_menu = NativeMenu.GetMenu(Application.Current);
DoLayoutReset();
}
public bool IsNativeMenuExported => _exported; public bool IsNativeMenuExported => _exported;
public event EventHandler OnIsNativeMenuExportedChanged; public event EventHandler OnIsNativeMenuExportedChanged;
@ -109,7 +117,14 @@ namespace Avalonia.Native
_menuItems.Clear(); _menuItems.Clear();
SetMenu(_nativeWindow, _menu?.Items); if(_nativeWindow is null)
{
SetMenu(_menu?.Items);
}
else
{
SetMenu(_nativeWindow, _menu?.Items);
}
_exported = true; _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) if (menuItems is null)
{ {
@ -247,11 +262,24 @@ namespace Avalonia.Native
if (menu != null) 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(); var appMenu = avnWindow.ObtainMainMenu();
@ -259,13 +287,11 @@ namespace Avalonia.Native
if (appMenu is null) if (appMenu is null)
{ {
appMenu = _factory.CreateMenu(); appMenu = _factory.CreateMenu();
avnWindow.SetMainMenu(appMenu);
} }
appMenu.Clear();
AddItemsToMenu(appMenu, menuItems); AddItemsToMenu(appMenu, menuItems);
avnWindow.SetMainMenu(appMenu);
} }
} }
} }

7
src/Avalonia.Native/AvaloniaNativePlatform.cs

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

1
src/Avalonia.Native/AvaloniaNativePlatformExtensions.cs

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

Loading…
Cancel
Save