Browse Source

Promote Help items into the macOS application menu

macOS convention puts About / Check for Updates under the bold app-
named menu next to the Apple logo, not under a separate top-level Help
menu. Add a PromoteHelpToMacAppMenu pass that runs only on macOS:

1. Find the _Help submenu in topLevelByTag (populated by
   AppendRegistryCommands when it sees the Help-targeted MEF commands).
2. Move its children into a new NativeMenu and SetMenu it on
   Application.Current. Avalonia's Cocoa exporter watches
   NativeMenu.MenuProperty on the Application as the channel for the
   bold app menu, and our items get prepended above its auto-inserted
   Services / Hide / Quit block.
3. Remove _Help from the window menu so the items don't appear twice.

On Windows / Linux the gate skips and the _Help top-level renders
inline as before.

The CheckForUpdatesCommand / AboutCommand attributes still declare
ParentMenuID = _Help -- they remain Help-categorised in metadata, just
re-routed at attachment time on macOS. No special Cocoa metadata
needed; the exporter picks up plain NativeMenuItems.

Assisted-by: Claude:claude-opus-4-7:Claude Code
pull/3755/head
Siegfried Pammer 1 month ago
parent
commit
0ff931c37d
  1. 27
      ILSpy/Views/MainMenu.axaml.cs

27
ILSpy/Views/MainMenu.axaml.cs

@ -22,6 +22,7 @@ using System.Composition; @@ -22,6 +22,7 @@ using System.Composition;
using System.Linq;
using System.Windows.Input;
using global::Avalonia;
using global::Avalonia.Controls;
using global::Avalonia.Data;
using global::Avalonia.Input;
@ -70,11 +71,37 @@ public static class MainMenu @@ -70,11 +71,37 @@ public static class MainMenu
AppendWindowDynamicContent(windowItem.Menu!, dockWorkspace);
if (OperatingSystem.IsMacOS())
{
TranslateGesturesForMacOS(menu);
PromoteHelpToMacAppMenu(menu, topLevelByTag);
}
NativeMenu.SetMenu(window, menu);
}
// 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.
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();
foreach (var item in helpItem.Menu.Items.ToArray())
{
helpItem.Menu.Items.Remove(item);
appMenu.Items.Add(item);
}
NativeMenu.SetMenu(Application.Current, appMenu);
rootMenu.Items.Remove(helpItem);
topLevelByTag.Remove("_Help");
}
static bool TryGetExports(
out SettingsService settings,
out MainMenuCommandRegistry registry,

Loading…
Cancel
Save