mirror of
https://github.com/wailsapp/wails.git
synced 2026-03-14 14:45:49 +01:00
feat(v3): Add UseApplicationMenu option for cross-platform menu support (#4944)
* feat(v3): Add UseApplicationMenu option for cross-platform menu support Add `UseApplicationMenu` option to `WebviewWindowOptions` that allows windows on Windows and Linux to inherit the application menu set via `app.Menu.Set()`. This provides a simpler cross-platform approach: - On macOS: No effect (app menu is always global) - On Windows/Linux: Window displays the application menu Benefits: - Eliminates need for platform-specific menu code - Per-window opt-in maintains backwards compatibility - Explicit window menus still take priority Updated: - webview_window_options.go: Added UseApplicationMenu bool field - webview_window_windows.go: Check UseApplicationMenu when no window menu set - webview_window_linux.go: Check UseApplicationMenu when no window menu set - examples/dialogs: Use UseApplicationMenu instead of conditional SetMenu - examples/menu: Use UseApplicationMenu instead of explicit SetMenu - docs: Updated menu and window options documentation Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * docs: Remove incorrect 'Menu Options' section header --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
470c929b42
commit
fa06d48497
8 changed files with 144 additions and 33 deletions
|
|
@ -56,16 +56,19 @@ func main() {
|
|||
menu.AddRole(application.WindowMenu)
|
||||
menu.AddRole(application.HelpMenu)
|
||||
|
||||
// Set the menu
|
||||
app.SetMenu(menu)
|
||||
// Set the application menu
|
||||
app.Menu.Set(menu)
|
||||
|
||||
// Create window with UseApplicationMenu to inherit the menu on Windows/Linux
|
||||
app.Window.NewWithOptions(application.WebviewWindowOptions{
|
||||
UseApplicationMenu: true,
|
||||
})
|
||||
|
||||
// Create window and run
|
||||
app.Window.New()
|
||||
app.Run()
|
||||
}
|
||||
```
|
||||
|
||||
**That's it!** You now have platform-native menus with standard items.
|
||||
**That's it!** You now have platform-native menus with standard items. The `UseApplicationMenu` option ensures Windows and Linux windows display the menu without additional code.
|
||||
|
||||
## Creating Menus
|
||||
|
||||
|
|
@ -96,33 +99,63 @@ fileMenu.Add("Quit").OnClick(func(ctx *application.Context) {
|
|||
|
||||
### Setting the Menu
|
||||
|
||||
Platform-specific API:
|
||||
**Recommended approach** — Use `UseApplicationMenu` for cross-platform consistency:
|
||||
|
||||
```go
|
||||
// Set the application menu once
|
||||
app.Menu.Set(menu)
|
||||
|
||||
// Create windows that inherit the menu on Windows/Linux
|
||||
app.Window.NewWithOptions(application.WebviewWindowOptions{
|
||||
UseApplicationMenu: true, // Window uses the app menu
|
||||
})
|
||||
```
|
||||
|
||||
This approach:
|
||||
- On **macOS**: The menu appears at the top of screen (standard behaviour)
|
||||
- On **Windows/Linux**: Each window with `UseApplicationMenu: true` displays the app menu
|
||||
|
||||
**Platform-specific details:**
|
||||
|
||||
<Tabs syncKey="platform">
|
||||
<TabItem label="macOS" icon="apple">
|
||||
**Global menu bar** (one per application):
|
||||
|
||||
```go
|
||||
app.SetMenu(menu)
|
||||
app.Menu.Set(menu)
|
||||
```
|
||||
|
||||
The menu appears at the top of the screen and persists even when all windows are closed.
|
||||
The menu appears at the top of the screen and persists even when all windows are closed. The `UseApplicationMenu` option has no effect on macOS since all apps use the global menu.
|
||||
</TabItem>
|
||||
|
||||
<TabItem label="Windows" icon="seti:windows">
|
||||
**Per-window menu bar**:
|
||||
|
||||
```go
|
||||
// Option 1: Use application menu (recommended)
|
||||
app.Menu.Set(menu)
|
||||
window := app.Window.NewWithOptions(application.WebviewWindowOptions{
|
||||
UseApplicationMenu: true,
|
||||
})
|
||||
|
||||
// Option 2: Set menu directly on window
|
||||
window.SetMenu(menu)
|
||||
```
|
||||
|
||||
Each window can have its own menu. The menu appears in the window's title bar.
|
||||
Each window can have its own menu, or inherit the application menu. The menu appears in the window's title bar.
|
||||
</TabItem>
|
||||
|
||||
<TabItem label="Linux" icon="linux">
|
||||
**Per-window menu bar** (usually):
|
||||
|
||||
```go
|
||||
// Option 1: Use application menu (recommended)
|
||||
app.Menu.Set(menu)
|
||||
window := app.Window.NewWithOptions(application.WebviewWindowOptions{
|
||||
UseApplicationMenu: true,
|
||||
})
|
||||
|
||||
// Option 2: Set menu directly on window
|
||||
window.SetMenu(menu)
|
||||
```
|
||||
|
||||
|
|
@ -130,16 +163,24 @@ Platform-specific API:
|
|||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
**Cross-platform helper:**
|
||||
:::tip[Simplify Cross-Platform Menus]
|
||||
Using `UseApplicationMenu: true` eliminates the need for platform-specific code like:
|
||||
```go
|
||||
// Old approach - no longer needed
|
||||
if runtime.GOOS == "darwin" {
|
||||
app.Menu.Set(menu)
|
||||
} else {
|
||||
window.SetMenu(menu)
|
||||
}
|
||||
```
|
||||
:::
|
||||
|
||||
**Per-window custom menus:**
|
||||
|
||||
If a window needs a different menu than the application menu, set it directly:
|
||||
|
||||
```go
|
||||
func setMenuForPlatform(app *application.Application, window *application.WebviewWindow, menu *application.Menu) {
|
||||
if runtime.GOOS == "darwin" {
|
||||
app.SetMenu(menu)
|
||||
} else {
|
||||
window.SetMenu(menu)
|
||||
}
|
||||
}
|
||||
window.SetMenu(customMenu) // Overrides UseApplicationMenu
|
||||
```
|
||||
|
||||
## Menu Roles
|
||||
|
|
@ -486,8 +527,10 @@ func main() {
|
|||
// Create and set menu
|
||||
createMenu(app)
|
||||
|
||||
// Create main window
|
||||
app.Window.New()
|
||||
// Create main window with UseApplicationMenu for cross-platform menu support
|
||||
app.Window.NewWithOptions(application.WebviewWindowOptions{
|
||||
UseApplicationMenu: true,
|
||||
})
|
||||
|
||||
app.Run()
|
||||
}
|
||||
|
|
@ -543,8 +586,8 @@ func createMenu(app *application.Application) {
|
|||
helpMenu.Add("About").OnClick(showAbout)
|
||||
}
|
||||
|
||||
// Set the menu
|
||||
app.SetMenu(menu)
|
||||
// Set the application menu
|
||||
app.Menu.Set(menu)
|
||||
}
|
||||
|
||||
func handleImport(ctx *application.Context) {
|
||||
|
|
|
|||
|
|
@ -52,11 +52,14 @@ type WebviewWindowOptions struct {
|
|||
|
||||
// Security
|
||||
ContentProtectionEnabled bool
|
||||
|
||||
|
||||
// Menu
|
||||
UseApplicationMenu bool
|
||||
|
||||
// Lifecycle
|
||||
OnClose func() bool
|
||||
OnDestroy func()
|
||||
|
||||
|
||||
// Platform-Specific
|
||||
Mac MacOptions
|
||||
Windows WindowsOptions
|
||||
|
|
@ -546,6 +549,48 @@ Assets: application.AssetOptions{
|
|||
|
||||
**See [Build System](/concepts/build-system) for details.**
|
||||
|
||||
### UseApplicationMenu
|
||||
|
||||
**Type:** `bool`
|
||||
**Default:** `false`
|
||||
**Platform:** Windows, Linux (no effect on macOS)
|
||||
|
||||
```go
|
||||
UseApplicationMenu: true,
|
||||
```
|
||||
|
||||
**Purpose:** Use the application menu (set via `app.Menu.Set()`) for this window.
|
||||
|
||||
On **macOS**, this option has no effect because macOS always uses a global application menu at the top of the screen.
|
||||
|
||||
On **Windows** and **Linux**, windows don't display a menu by default. Setting `UseApplicationMenu: true` tells the window to use the application-level menu, providing a simple cross-platform solution.
|
||||
|
||||
**Example:**
|
||||
|
||||
```go
|
||||
// Set the application menu once
|
||||
menu := app.NewMenu()
|
||||
menu.AddRole(application.FileMenu)
|
||||
menu.AddRole(application.EditMenu)
|
||||
app.Menu.Set(menu)
|
||||
|
||||
// All windows with UseApplicationMenu will display this menu
|
||||
app.Window.NewWithOptions(application.WebviewWindowOptions{
|
||||
Title: "Main Window",
|
||||
UseApplicationMenu: true,
|
||||
})
|
||||
|
||||
app.Window.NewWithOptions(application.WebviewWindowOptions{
|
||||
Title: "Second Window",
|
||||
UseApplicationMenu: true, // Also gets the app menu
|
||||
})
|
||||
```
|
||||
|
||||
**Notes:**
|
||||
- If both `UseApplicationMenu` and a window-specific menu are set, the window-specific menu takes priority
|
||||
- This simplifies cross-platform code by eliminating the need for runtime OS checks
|
||||
- See [Application Menus](/features/menus/application) for complete menu documentation
|
||||
|
||||
## Input Options
|
||||
|
||||
### EnableFileDrop
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ After processing, the content will be moved to the main changelog and this file
|
|||
|
||||
## Added
|
||||
<!-- New features, capabilities, or enhancements -->
|
||||
- Add `UseApplicationMenu` option to `WebviewWindowOptions` allowing windows on Windows/Linux to inherit the application menu set via `app.Menu.Set()` by @leaanthony
|
||||
|
||||
## Changed
|
||||
<!-- Changes in existing functionality -->
|
||||
|
|
|
|||
|
|
@ -363,13 +363,13 @@ func main() {
|
|||
}
|
||||
})
|
||||
|
||||
window := app.Window.New()
|
||||
// Set the application menu
|
||||
app.Menu.Set(menu)
|
||||
|
||||
if runtime.GOOS == "darwin" {
|
||||
app.Menu.Set(menu)
|
||||
} else {
|
||||
window.SetMenu(menu)
|
||||
}
|
||||
// Create window with UseApplicationMenu to inherit the app menu on Windows/Linux
|
||||
app.Window.NewWithOptions(application.WebviewWindowOptions{
|
||||
UseApplicationMenu: true,
|
||||
})
|
||||
|
||||
err = app.Run()
|
||||
|
||||
|
|
|
|||
|
|
@ -146,11 +146,12 @@ func main() {
|
|||
|
||||
app.Menu.Set(menu)
|
||||
|
||||
window := app.Window.NewWithOptions(application.WebviewWindowOptions{
|
||||
Name: "menu-example",
|
||||
Title: "Menu Example",
|
||||
// UseApplicationMenu allows Windows/Linux to inherit the app menu
|
||||
app.Window.NewWithOptions(application.WebviewWindowOptions{
|
||||
Name: "menu-example",
|
||||
Title: "Menu Example",
|
||||
UseApplicationMenu: true,
|
||||
}).SetBackgroundColour(application.NewRGB(33, 37, 41))
|
||||
window.SetMenu(menu)
|
||||
|
||||
err := app.Run()
|
||||
|
||||
|
|
|
|||
|
|
@ -273,10 +273,17 @@ func (w *linuxWebviewWindow) run() {
|
|||
|
||||
var menu = w.parent.options.Linux.Menu
|
||||
if menu != nil {
|
||||
// Explicit window menu takes priority
|
||||
InvokeSync(func() {
|
||||
menu.Update()
|
||||
})
|
||||
w.gtkmenu = (menu.impl).(*linuxMenu).native
|
||||
} else if w.parent.options.UseApplicationMenu && globalApplication.applicationMenu != nil {
|
||||
// Use the global application menu if opted in
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -142,6 +142,13 @@ type WebviewWindowOptions struct {
|
|||
// Effective on Windows and macOS only; no-op on Linux.
|
||||
// Best-effort protection with platform-specific caveats (see docs).
|
||||
ContentProtectionEnabled bool
|
||||
|
||||
// UseApplicationMenu indicates this window should use the application menu
|
||||
// set via app.Menu.Set() instead of requiring a window-specific menu.
|
||||
// On macOS this has no effect as the application menu is always global.
|
||||
// On Windows/Linux, if true and no explicit window menu is set, the window
|
||||
// will use the application menu. Defaults to false for backwards compatibility.
|
||||
UseApplicationMenu bool
|
||||
}
|
||||
|
||||
type RGBA struct {
|
||||
|
|
|
|||
|
|
@ -362,10 +362,17 @@ func (w *windowsWebviewWindow) run() {
|
|||
if !options.Frameless {
|
||||
userMenu := w.parent.options.Windows.Menu
|
||||
if userMenu != nil {
|
||||
// Explicit window menu takes priority
|
||||
userMenu.Update()
|
||||
w.menu = NewApplicationMenu(w, userMenu)
|
||||
w.menu.parentWindow = w
|
||||
appMenu = w.menu.menu
|
||||
} else if options.UseApplicationMenu && globalApplication.applicationMenu != nil {
|
||||
// Use the global application menu if opted in
|
||||
globalApplication.applicationMenu.Update()
|
||||
w.menu = NewApplicationMenu(w, globalApplication.applicationMenu)
|
||||
w.menu.parentWindow = w
|
||||
appMenu = w.menu.menu
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue