escape ampersand in tray menu labels on Windows

Win32 swallows a lone & in an MFT_STRING menu item as the mnemonic
prefix, so "Help & Support" rendered as "Help  Support". Add a
build-tagged menuLabel() helper that doubles & to && on Windows and is
the identity on macOS/Linux (which render & literally), and apply it to
the About submenu label.
This commit is contained in:
Zoltán Papp
2026-06-01 16:44:18 +02:00
parent c5611dd766
commit 49df24b18c
3 changed files with 26 additions and 1 deletions

View File

@@ -459,7 +459,7 @@ func (t *Tray) buildMenu() *application.Menu {
SetAccelerator("CmdOrCtrl+,").
OnClick(func(*application.Context) { t.svc.WindowManager.OpenSettings("") })
aboutLabel := t.loc.T("tray.menu.about")
aboutLabel := menuLabel(t.loc.T("tray.menu.about"))
about := menu.AddSubmenu(aboutLabel)
about.Add(t.loc.T("tray.menu.github")).OnClick(func(*application.Context) {
_ = t.app.Browser.OpenURL(urlGitHubRepo)

View File

@@ -0,0 +1,9 @@
//go:build !windows && !android && !ios && !freebsd && !js
package main
// menuLabel is the identity on macOS and Linux — both render an ampersand
// literally in tray-menu labels, so no escaping is needed. Windows opts in via
// the sibling tray_label_windows.go file, where a lone "&" would otherwise be
// swallowed as a Win32 mnemonic prefix.
func menuLabel(s string) string { return s }

View File

@@ -0,0 +1,16 @@
//go:build windows
package main
import "strings"
// menuLabel escapes a tray-menu label for Win32. A single ampersand in an
// MFT_STRING menu item is consumed as the mnemonic (accelerator) prefix and
// never painted — so "Help & Support" renders as "Help Support". Doubling it
// to "&&" tells Win32 to draw a literal ampersand. Wails v3 passes the label
// straight to InsertMenuItem without escaping (see menuitem_windows.go), so we
// do it here. macOS/Linux render "&" literally and use the identity helper in
// the sibling tray_label_other.go.
func menuLabel(s string) string {
return strings.ReplaceAll(s, "&", "&&")
}