Browse Source

Fix macOS app menu by populating NativeMenu in place

The Cocoa menu exporter samples Application.Current's NativeMenu once at
startup and never watches the property afterwards, so the previous code's
NativeMenu.SetMenu(Application.Current, freshMenu) was never observed: About
and Check for Updates simply went missing from the app-named menu. Declare an
empty NativeMenu in App.axaml so it exists before that sampling, then insert
the Help items into that same instance at startup, which fires the exporter's
re-export. Inert on Windows / Linux.

Assisted-by: Claude:claude-opus-4-8:Claude Code
pull/3755/head
Siegfried Pammer 1 month ago
parent
commit
bb94f85f0e
  1. 8
      ILSpy/App.axaml
  2. 20
      ILSpy/Views/MainMenu.axaml.cs

8
ILSpy/App.axaml

@ -19,6 +19,14 @@ @@ -19,6 +19,14 @@
RequestedThemeVariant="Default">
<!-- "Default" ThemeVariant follows system theme variant. "Dark" or "Light" are other available options. -->
<!-- Empty placeholder for the macOS application menu (the bold app-named menu). Only the
Cocoa menu exporter reads this; on Windows / Linux it is inert. It must exist before
the exporter samples it at startup, so MainMenu.PromoteHelpToMacAppMenu can populate
this same instance in place rather than replacing it (a replacement is never observed). -->
<NativeMenu.Menu>
<NativeMenu />
</NativeMenu.Menu>
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>

20
ILSpy/Views/MainMenu.axaml.cs

@ -80,24 +80,28 @@ public static class MainMenu @@ -80,24 +80,28 @@ public static class MainMenu
}
// macOS convention puts About / Check for Updates under the bold app-named menu
// next to the Apple logo, not under a separate "Help" top-level. Avalonia's Cocoa
// menu exporter watches NativeMenu.MenuProperty on Application.Current as the
// channel for that menu; setting a NativeMenu there prepends our items above
// the auto-inserted Services / Hide / Quit block. We then remove _Help from the
// window menu so the items don't appear in both places.
// next to the Apple logo, not under a separate "Help" top-level. The Cocoa exporter
// samples Application.Current's NativeMenu ONCE at startup (before this window exists)
// and never watches the property afterwards -- so swapping in a fresh menu here would
// be ignored. Instead we populate the empty NativeMenu declared in App.axaml IN PLACE:
// the exporter subscribes to that instance's Items, so inserting fires a re-export.
// Items go at the top, above the Services / Hide / Quit block the exporter appended.
// We then remove _Help from the window menu so the items don't appear in both places.
static void PromoteHelpToMacAppMenu(NativeMenu rootMenu, Dictionary<string, NativeMenuItem> topLevelByTag)
{
if (!topLevelByTag.TryGetValue("_Help", out var helpItem) || helpItem.Menu is null)
return;
if (Application.Current is null)
return;
var appMenu = new NativeMenu();
var appMenu = NativeMenu.GetMenu(Application.Current);
if (appMenu is null)
return;
var index = 0;
foreach (var item in helpItem.Menu.Items.ToArray())
{
helpItem.Menu.Items.Remove(item);
appMenu.Items.Add(item);
appMenu.Items.Insert(index++, item);
}
NativeMenu.SetMenu(Application.Current, appMenu);
rootMenu.Items.Remove(helpItem);
topLevelByTag.Remove("_Help");
}

Loading…
Cancel
Save