diff --git a/docs/src/content/docs/guides/menus.mdx b/docs/src/content/docs/guides/menus.mdx index 50023ab4d..5254469ca 100644 --- a/docs/src/content/docs/guides/menus.mdx +++ b/docs/src/content/docs/guides/menus.mdx @@ -284,11 +284,36 @@ fileMenu.AddRole(application.Quit) Application menus are the menus that appear at the top of your application window (Windows/Linux) or at the top of the screen (macOS). +### Global Menu Inheritance: `UseGlobalMenuByDefault` + +On Windows and Linux, menus are usually set per window. However, if you want all windows to use the global application menu by default (unless a window-specific menu is provided), you can enable this behaviour with the `UseGlobalMenuByDefault` option: + +```go +app := application.New(application.Options{ + Name: "MyApp", + UseGlobalMenuByDefault: true, // All windows will use the global menu unless overridden +}) + +menu := app.NewMenu() +// ... add items/roles ... +app.SetMenu(menu) + +app.NewWebviewWindow().SetTitle("Window 1").Show() +app.NewWebviewWindow().SetTitle("Window 2").Show() +``` + +- When `UseGlobalMenuByDefault` is `true`, any window created without an explicit menu will inherit the global application menu. +- If you set a menu directly on a window (via `WebviewWindowOptions.Menu` or `window.SetMenu()`), that menu takes precedence for that window. +- This flag has no effect on macOS, where the application menu is always global. + +**When to use:** +- Use this option if you want a consistent application menu across all windows on Windows/Linux, without having to set it for each window individually. +- Omit this option or set it to `false` if you want to control menus per window. ### Application Menu Behaviour When you set an application menu using `app.SetMenu()`, it becomes the main menu on macOS. -Menus are set on a pre-window basis for Windows/Linux. +Menus are set on a pre-window basis for Windows/Linux (unless `UseGlobalMenuByDefault` is enabled). ```go app.NewWebviewWindowWithOptions(application.WebviewWindowOptions{ diff --git a/v3/examples/menu-fixes/main.go b/v3/examples/menu-fixes/main.go index 4e69f0933..5b543195a 100644 --- a/v3/examples/menu-fixes/main.go +++ b/v3/examples/menu-fixes/main.go @@ -14,9 +14,10 @@ var clickBitmap []byte func main() { app := application.New(application.Options{ - Name: "Menu Demo", - Description: "A demo of the menu system", - Assets: application.AlphaAssets, + UseGlobalMenuByDefault: true, + Name: "Menu Demo", + Description: "A demo of the menu system", + Assets: application.AlphaAssets, Mac: application.MacOptions{ ApplicationShouldTerminateAfterLastWindowClosed: true, }, diff --git a/v3/examples/menu/main.go b/v3/examples/menu/main.go index 90cec9062..811902eef 100644 --- a/v3/examples/menu/main.go +++ b/v3/examples/menu/main.go @@ -14,9 +14,10 @@ var clickBitmap []byte func main() { app := application.New(application.Options{ - Name: "Menu Demo", - Description: "A demo of the menu system", - Assets: application.AlphaAssets, + UseGlobalMenuByDefault: true, + Name: "Menu Demo", + Description: "A demo of the menu system", + Assets: application.AlphaAssets, Mac: application.MacOptions{ ApplicationShouldTerminateAfterLastWindowClosed: true, }, diff --git a/v3/pkg/application/application_linux.go b/v3/pkg/application/application_linux.go index 7fb1c04a1..f58b9d4de 100644 --- a/v3/pkg/application/application_linux.go +++ b/v3/pkg/application/application_linux.go @@ -84,12 +84,10 @@ func (r rnr) run() { } func (a *linuxApp) setApplicationMenu(menu *Menu) { - // FIXME: How do we avoid putting a menu? if menu == nil { - // Create a default menu menu = DefaultApplicationMenu() - globalApplication.ApplicationMenu = menu } + globalApplication.ApplicationMenu = menu } func (a *linuxApp) run() error { diff --git a/v3/pkg/application/application_options.go b/v3/pkg/application/application_options.go index 76d77457d..77d737074 100644 --- a/v3/pkg/application/application_options.go +++ b/v3/pkg/application/application_options.go @@ -28,6 +28,10 @@ type Options struct { // Linux is the Linux specific configuration for Linux builds Linux LinuxOptions + // UseGlobalMenuByDefault determines if the global application menu set via SetMenu should be used by default for all windows on Windows and Linux. + // If false (default), windows do not inherit the global menu unless explicitly set. If true, all windows inherit the global menu unless they opt out. + UseGlobalMenuByDefault bool + // Services allows you to bind Go methods to the frontend. Services []Service diff --git a/v3/pkg/application/webview_window_linux.go b/v3/pkg/application/webview_window_linux.go index 8c50c6117..78c490852 100644 --- a/v3/pkg/application/webview_window_linux.go +++ b/v3/pkg/application/webview_window_linux.go @@ -275,6 +275,12 @@ func (w *linuxWebviewWindow) run() { menu.Update() }) w.gtkmenu = (menu.impl).(*linuxMenu).native + } else if !w.parent.options.Frameless && globalApplication.options.UseGlobalMenuByDefault && globalApplication.ApplicationMenu != nil { + // Use the global application menu if the flag is set and no explicit window menu is provided + InvokeSync(func() { + globalApplication.ApplicationMenu.Update() + }) + w.gtkmenu = (globalApplication.ApplicationMenu.impl).(*linuxMenu).native } w.window, w.webview, w.vbox = windowNew(app.application, w.gtkmenu, w.parent.id, w.parent.options.Linux.WebviewGpuPolicy) diff --git a/v3/pkg/application/webview_window_windows.go b/v3/pkg/application/webview_window_windows.go index a49255dd5..969ca39ea 100644 --- a/v3/pkg/application/webview_window_windows.go +++ b/v3/pkg/application/webview_window_windows.go @@ -322,6 +322,12 @@ func (w *windowsWebviewWindow) run() { w.menu = NewApplicationMenu(w, userMenu) w.menu.parentWindow = w appMenu = w.menu.menu + } else if globalApplication.options.UseGlobalMenuByDefault && globalApplication.ApplicationMenu != nil { + // Use the global application menu if the flag is set and no explicit window menu is provided + globalApplication.ApplicationMenu.Update() + w.menu = NewApplicationMenu(w, globalApplication.ApplicationMenu) + w.menu.parentWindow = w + appMenu = w.menu.menu } }