Event cancellation for standard listeners.

Major doc updates.
Runtime build tidy up.
Removed redundant default event mappings.
This commit is contained in:
Lea Anthony 2025-01-27 09:29:22 +11:00
commit db61f9f263
No known key found for this signature in database
GPG key ID: 33DAF7BB90A58405
44 changed files with 1828 additions and 6289 deletions

View file

@ -41,6 +41,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- New Menu guide by [@leaanthony](https://github.com/leaanthony)
- Add doc comments for Service API by [@fbbdev](https://github.com/fbbdev) in [#4024](https://github.com/wailsapp/wails/pull/4024)
- Add function `application.NewServiceWithOptions` to initialise services with additional configuration by [@leaanthony](https://github.com/leaanthony) in [#4024](https://github.com/wailsapp/wails/pull/4024)
- More documentation by [@leaanthony](https://github.com/leaanthony)
- Support cancellation of events in standard event listeners by [@leaanthony](https://github.com/leaanthony)
### Fixed
@ -59,6 +61,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- In JS/TS bindings, class fields of fixed-length array types are now initialized with their expected length instead of being empty by [@fbbdev](https://github.com/fbbdev) in [#4001](https://github.com/wailsapp/wails/pull/4001)
- ContextMenuData now returns a string instead of any by [@leaanthony](https://github.com/leaanthony)
- `application.NewService` does not accept options as an optional parameter anymore (use `application.NewServiceWithOptions` instead) by [@leaanthony](https://github.com/leaanthony) in [#4024](https://github.com/wailsapp/wails/pull/4024)
- Removed `nanoid` dependency by [@leaanthony](https://github.com/leaanthony)
## v3.0.0-alpha.9 - 2025-01-13

View file

@ -4,7 +4,6 @@ sidebar:
order: 20
---
# File Associations <Badge text="Windows" variant="note" /> <Badge text="macOS" variant="success" />
import { Steps } from "@astrojs/starlight/components";
import {Badge} from '@astrojs/starlight/components';

View file

@ -0,0 +1,225 @@
---
title: Application Menu
sidebar:
order: 53
---
import { Tabs, TabItem } from "@astrojs/starlight/components";
Application menus provide the main menu bar interface for your application. They appear at the top of the window on Windows and Linux, and at the top of the screen on macOS.
## Creating an Application Menu
Create a new application menu using the `NewMenu` method:
```go
menu := app.NewMenu()
```
## Menu Roles
Wails provides predefined menu roles that automatically create platform-appropriate menu structures:
```go
// Add standard application menu on macOS
if runtime.GOOS == "darwin" {
menu.AddRole(application.AppMenu)
}
// Add standard menus
menu.AddRole(application.FileMenu)
menu.AddRole(application.EditMenu)
menu.AddRole(application.WindowMenu)
menu.AddRole(application.HelpMenu)
```
:::note[Platform Behaviour]
The AppMenu role is specific to macOS and provides the standard application menu containing About, Preferences, and Quit items.
:::
### Available Roles
| Role | Description | Platform Notes |
|------|-------------|----------------|
| `AppMenu` | Standard application menu | macOS only |
| `FileMenu` | File operations menu | All platforms |
| `EditMenu` | Text editing operations | All platforms |
| `WindowMenu` | Window management | All platforms |
| `HelpMenu` | Help and information | All platforms |
## Custom Menus
Create custom menus by adding items directly:
```go
// Add a custom menu
customMenu := menu.AddSubmenu("Tools")
customMenu.Add("Settings").OnClick(func(ctx *application.Context) {
// Show settings dialogue
})
```
:::tip[Menu Items]
For detailed information about available menu item types and properties, refer to the [Menu Reference](./menu-reference) documentation.
:::
## Window Control
Menu items can control the application windows:
```go
viewMenu := menu.AddSubmenu("View")
viewMenu.Add("Toggle Fullscreen").OnClick(func(ctx *application.Context) {
window := app.CurrentWindow()
if window.Fullscreen() {
window.SetFullscreen(false)
} else {
window.SetFullscreen(true)
}
})
```
## Dynamic Menus
Menus can be updated dynamically based on application state:
```go
projectMenu := menu.AddSubmenu("Project")
saveItem := projectMenu.Add("Save Project")
// Update based on state
saveItem.OnClick(func(ctx *application.Context) {
if projectSaved {
saveItem.SetEnabled(false)
saveItem.SetLabel("Project Saved")
}
menu.Update()
})
```
## Platform-Specific Considerations
<Tabs>
<TabItem label="macOS" icon="fa-brands:apple">
On macOS, menus are deeply integrated with the system:
- Menus appear in the system menu bar at the top of the screen
- The application menu (⌘) is required and should be added using `menu.AddRole(application.AppMenu)`
- Standard keyboard shortcuts are automatically handled
- Menu styling follows system appearance
- The "About" menu item appears in the application menu
- Preferences are typically placed in the application menu
</TabItem>
<TabItem label="Windows" icon="fa-brands:windows">
On Windows, menus follow the traditional Windows UI guidelines:
- Menus appear in the application window's title bar
- Standard keyboard shortcuts should be explicitly set using `SetAccelerator`
- Menu styling matches the Windows theme
- The "About" menu item typically appears in the Help menu
- Settings/Preferences are typically placed in the Tools menu
</TabItem>
<TabItem label="Linux" icon="fa-brands:linux">
On Linux, menu behaviour depends on the desktop environment:
- Menu appearance adapts to the desktop environment's theme
- Some desktop environments (like Unity) support global menu bars
- Menu placement follows the desktop environment's conventions
- Keyboard shortcuts should be explicitly set
- Settings are typically placed in the Edit menu
</TabItem>
</Tabs>
## Best Practices
1. Use standard menu roles where appropriate
2. Follow platform-specific menu conventions
3. Provide keyboard shortcuts for common actions
4. Keep menu structures shallow and organised
5. Update menu items to reflect application state
6. Use clear, concise menu labels
7. Group related items logically
:::danger[Warning]
Always test menu functionality across all target platforms to ensure consistent behaviour and appearance.
:::
:::tip[Pro Tip]
Consider using the `application.CurrentWindow()` method in menu handlers to affect the active window, rather than storing window references.
:::
## Complete Example
Here's a comprehensive example demonstrating various menu features:
```go
package main
import (
"runtime"
"github.com/wailsapp/wails/v3/pkg/application"
)
func main() {
app := application.New(application.Options{
Name: "Menu Demo",
})
// Create main menu
menu := app.NewMenu()
// Add platform-specific application menu
if runtime.GOOS == "darwin" {
menu.AddRole(application.AppMenu)
}
// Add standard menus
fileMenu := menu.AddRole(application.FileMenu)
menu.AddRole(application.EditMenu)
menu.AddRole(application.WindowMenu)
menu.AddRole(application.HelpMenu)
// Add custom menu
toolsMenu := menu.AddSubmenu("Tools")
// Add checkbox item
toolsMenu.AddCheckbox("Dark Mode", false).OnClick(func(ctx *application.Context) {
isDark := ctx.ClickedMenuItem().Checked()
// Toggle theme
})
// Add radio group
toolsMenu.AddRadio("Small Text", true).OnClick(handleFontSize)
toolsMenu.AddRadio("Medium Text", false).OnClick(handleFontSize)
toolsMenu.AddRadio("Large Text", false).OnClick(handleFontSize)
// Add submenu
advancedMenu := toolsMenu.AddSubmenu("Advanced")
advancedMenu.Add("Configure...").OnClick(func(ctx *application.Context) {
// Show configuration
})
// Set the menu
app.SetMenu(menu)
// Create main window
app.NewWebviewWindow()
err := app.Run()
if err != nil {
panic(err)
}
}
func handleFontSize(ctx *application.Context) {
size := ctx.ClickedMenuItem().Label()
// Update font size
}

View file

@ -1,5 +1,5 @@
---
title: Wails v3 Build System
title: Build System
sidebar:
order: 40
---
@ -8,7 +8,7 @@ import { FileTree } from "@astrojs/starlight/components";
## Overview
The Wails v3 build system is a flexible and powerful tool designed to streamline
The Wails build system is a flexible and powerful tool designed to streamline
the build process for your Wails applications. It leverages
[Task](https://taskfile.dev), a task runner that allows you to define and run
tasks easily. While the v3 build system is the default, Wails encourages a
@ -21,7 +21,7 @@ Learn more about how to use Task in the
## Task: The Heart of the Build System
[Task](https://taskfile.dev) is a modern alternative to Make, written in Go. It
uses a YAML file to define tasks and their dependencies. In the Wails v3 build
uses a YAML file to define tasks and their dependencies. In the Wails build
system, [Task](https://taskfile.dev) plays a central role in orchestrating the
build process.
@ -98,6 +98,7 @@ The Windows-specific Taskfile includes tasks for building, packaging, and
running the application on Windows. Key features include:
- Building with optional production flags
- Generating `.ico` icon file
- Generating Windows `.syso` file
- Creating an NSIS installer for packaging
@ -120,10 +121,11 @@ The macOS-specific Taskfile includes tasks for building, packaging, and running
the application on macOS. Key features include:
- Building binaries for amd64, arm64 and universal (both) architectures
- Generating `.icns` icon file
- Creating an `.app` bundle for distributing
- Setting macOS-specific build flags and environment variables
## Wails3 Commands and Task Execution
## Task Execution and Command Aliases
The `wails3 task` command is an embedded version of [Taskfile](https://taskfile.dev), which executes
the tasks defined in your `Taskfile.yml`.
@ -157,7 +159,7 @@ platform-specific Taskfiles, you can:
- Integrate with other tools and scripts
This flexibility allows you to tailor the build process to your specific
requirements while still benefiting from the structure provided by the Wails v3
requirements while still benefiting from the structure provided by the Wails
build system.
:::tip[Learning Taskfile]
@ -168,7 +170,7 @@ You can find out which version of Taskfile is embedded in the Wails CLI by runni
## Development Mode
The Wails v3 build system includes a powerful development mode that enhances the
The Wails build system includes a powerful development mode that enhances the
developer experience by providing live reloading and hot module replacement.
This mode is activated using the `wails3 dev` command.

View file

@ -0,0 +1,135 @@
---
title: Clipboard
sidebar:
order: 50
---
The Wails Clipboard API provides a simple interface for interacting with the system clipboard. It allows you to read from and write to the clipboard, whilst supporting text data.
## Accessing the Clipboard
The clipboard can be accessed through the application instance:
```go
clipboard := app.Clipboard()
```
## Setting Text
To set text to the clipboard, utilise the `SetText` method:
```go
success := app.Clipboard().SetText("Hello World")
if !success {
// Handle error
}
```
The `SetText` method returns a boolean indicating whether the operation was successful.
:::tip[Empty Text]
Setting an empty string (`""`) effectively clears the text content from the clipboard.
:::
## Getting Text
To retrieve text from the clipboard, utilise the `Text` method:
```go
text, ok := app.Clipboard().Text()
if !ok {
// Handle error
} else {
// Use the text
}
```
The `Text` method returns two values:
- The text content from the clipboard (string)
- A boolean indicating whether the operation was successful
:::note[Platform Behaviour]
The clipboard behaviour might vary slightly amongst operating systems. Always check the return values to ensure operations were successful.
:::
## Example
Here's a complete example showing how to create a menu-driven application that demonstrates clipboard operations:
```go
package main
import (
"log"
"runtime"
"time"
"github.com/wailsapp/wails/v3/pkg/application"
)
func main() {
app := application.New(application.Options{
Name: "Clipboard Demo",
Description: "A demo of the clipboard API",
Assets: application.AlphaAssets,
})
// Create a custom menu
menu := app.NewMenu()
if runtime.GOOS == "darwin" {
menu.AddRole(application.AppMenu)
}
// Add clipboard operations to menu
setClipboardMenu := menu.AddSubmenu("Set Clipboard")
setClipboardMenu.Add("Set Text 'Hello'").OnClick(func(ctx *application.Context) {
success := app.Clipboard().SetText("Hello")
if !success {
application.InfoDialog().SetMessage("Failed to set clipboard text").Show()
}
})
getClipboardMenu := menu.AddSubmenu("Get Clipboard")
getClipboardMenu.Add("Get Text").OnClick(func(ctx *application.Context) {
result, ok := app.Clipboard().Text()
if !ok {
application.InfoDialog().SetMessage("Failed to get clipboard text").Show()
} else {
application.InfoDialog().SetMessage("Got:\n\n" + result).Show()
}
})
clearClipboardMenu := menu.AddSubmenu("Clear Clipboard")
clearClipboardMenu.Add("Clear Text").OnClick(func(ctx *application.Context) {
success := app.Clipboard().SetText("")
if success {
application.InfoDialog().SetMessage("Clipboard text cleared").Show()
} else {
application.InfoDialog().SetMessage("Clipboard text not cleared").Show()
}
})
app.SetMenu(menu)
app.NewWebviewWindow()
err := app.Run()
if err != nil {
log.Fatal(err.Error())
}
}
```
:::danger[Warning]
Always handle clipboard operation failures gracefully, as they can fail due to various system-level reasons such as permissions or resource constraints.
:::
## Best Practices
1. Always check the return values of clipboard operations
2. Handle failures gracefully with appropriate user feedback
3. Clear sensitive data from the clipboard when your application exits if it was responsible for putting it there
4. Consider implementing a timeout mechanism for clipboard operations in critical sections of your application
:::tip[Pro Tip]
Whilst working with the clipboard in a production environment, consider implementing retry logic for critical clipboard operations, as they can occasionally fail due to temporary system conditions.
:::

View file

@ -0,0 +1,221 @@
---
title: Context Menus
sidebar:
order: 51
---
import { Tabs, TabItem } from "@astrojs/starlight/components";
Context menus are popup menus that appear when right-clicking elements in your application. They provide quick access to relevant actions for the clicked element.
## Creating a Context Menu
To create a context menu, utilise the `NewContextMenu` method from your application instance:
```go
contextMenu := application.NewContextMenu("menu-id")
```
The `menu-id` parameter is a unique identifier for the menu that will be used to associate it with HTML elements.
## Adding Menu Items
You can add items to your context menu using the same methods as application menus. Here's a simple example:
```go
contextMenu := application.NewContextMenu("editor-menu")
contextMenu.Add("Cut").OnClick(func(ctx *application.Context) {
// Handle cut action
})
contextMenu.Add("Copy").OnClick(func(ctx *application.Context) {
// Handle copy action
})
contextMenu.Add("Paste").OnClick(func(ctx *application.Context) {
// Handle paste action
})
```
:::tip[Menu Items]
For detailed information about available menu item types and properties, refer to the [Menu Reference](./menu-reference) documentation.
:::
## Context Data
Context menus can receive data from the HTML element that triggered them. This data can be accessed in the click handlers:
```go
contextMenu := application.NewContextMenu("image-menu")
menuItem := contextMenu.Add("Process Image")
menuItem.OnClick(func(ctx *application.Context) {
imageID := ctx.ContextMenuData()
// Process the image using the ID
})
```
## Associating with HTML Elements
To associate a context menu with an HTML element, use the `--custom-contextmenu` and `--custom-contextmenu-data` CSS properties:
```html
<div style="--custom-contextmenu: menu-id; --custom-contextmenu-data: some-data">
Right click me!
</div>
```
- `--custom-contextmenu`: Specifies the menu ID (must match the ID used in `NewContextMenu`)
- `--custom-contextmenu-data`: Optional data that will be passed to the click handlers
## Default Context Menu
The default context menu is the webview's built-in context menu that provides system-level operations. You can control its visibility using the `--default-contextmenu` CSS property:
```html
<!-- Hide the default context menu -->
<div style="--default-contextmenu: hide">
No default menu here
</div>
<!-- Show the default context menu -->
<div style="--default-contextmenu: show">
Default menu always shown
</div>
<!-- Smart context menu (default behaviour) -->
<div style="--default-contextmenu: auto">
Shows menu when appropriate
</div>
```
:::note[Smart Context Menu]
The `auto` setting enables "smart" context menu behaviour:
- Shows when text is selected
- Shows in text input fields
- Shows in editable content
- Hides in other contexts
:::
## Updating Menu Items
Menu items can be updated dynamically using the `SetLabel` method and other property setters. After making changes, call `Update` on the menu to apply them:
```go
contextMenu := application.NewContextMenu("dynamic-menu")
menuItem := contextMenu.Add("Initial Label")
// Later, update the menu item
menuItem.SetLabel("New Label")
contextMenu.Update()
```
## Platform Considerations
<Tabs>
<TabItem label="macOS" icon="fa-brands:apple">
On macOS, context menus follow system conventions:
- Menus use native system animations and transitions
- Right-click is automatically mapped to Control+Click
- Menu styling automatically adapts to system appearance
- Standard text operations appear in the default context menu
- Context menus support native macOS scrolling behaviour
</TabItem>
<TabItem label="Windows" icon="fa-brands:windows">
On Windows, context menus integrate with the Windows UI:
- Menus use the Windows native context menu style
- Right-click handling is native
- Menu appearance follows the Windows theme
- Default context menu includes standard Windows operations
- Context menus support Windows touch and pen input
</TabItem>
<TabItem label="Linux" icon="fa-brands:linux">
On Linux, context menu behaviour varies by desktop environment:
- Menu styling adapts to the current desktop theme
- Right-click behaviour follows system settings
- Default context menu content may vary by environment
- Menu positioning follows desktop environment conventions
- GTK/Qt integration depends on the environment
</TabItem>
</Tabs>
:::tip[Pro Tip]
Consider using different context menus for different types of elements in your application. This allows you to provide context-specific actions that make sense for each element type.
:::
## Best Practices
1. Keep context menus focused and relevant to the clicked element
2. Use clear, concise labels for menu items
3. Group related items together
4. Consider using separators to organise menu items
5. Provide keyboard shortcuts for common actions
6. Update menu items dynamically based on application state
7. Handle errors gracefully when processing context data
:::danger[Warning]
Always validate context data received from the frontend before using it in your application logic, as it could be manipulated by users.
:::
## Example
Here's a complete example demonstrating context menu features:
```go
package main
import (
"github.com/wailsapp/wails/v3/pkg/application"
)
func main() {
app := application.New(application.Options{
Name: "Context Menu Demo",
})
// Create a context menu
contextMenu := application.NewContextMenu("test")
// Add items that respond to context data
clickMe := contextMenu.Add("Click to show context data")
dataLabel := contextMenu.Add("Current data: None")
clickMe.OnClick(func(ctx *application.Context) {
data := ctx.ContextMenuData()
dataLabel.SetLabel("Current data: " + data)
contextMenu.Update()
})
window := app.NewWebviewWindow()
window.SetTitle("Context Menu Demo")
err := app.Run()
if err != nil {
panic(err)
}
}
```
Associated HTML:
```html
<div class="region" style="--custom-contextmenu: test; --custom-contextmenu-data: item-123">
Right click me to see the custom menu!
</div>
<div style="--default-contextmenu: hide">
No context menu here
</div>
<div style="--default-contextmenu: auto">
<p style="user-select: text">Select this text to see the default menu</p>
<input type="text" placeholder="Type here to see the default menu"/>
</div>

View file

@ -0,0 +1,230 @@
---
title: Dialogs
sidebar:
order: 54
---
import { Tabs, TabItem } from "@astrojs/starlight/components";
Wails provides a comprehensive dialog system for displaying native system dialogs. These include informational messages, questions, file selection, and more.
## Dialog Types
### Information Dialog
Display simple informational messages to users:
```go
dialog := application.InfoDialog()
dialog.SetTitle("Welcome")
dialog.SetMessage("Welcome to our application!")
dialog.Show()
```
### Question Dialog
Present users with questions and customisable buttons:
```go
dialog := application.QuestionDialog()
dialog.SetTitle("Save Changes")
dialog.SetMessage("Do you want to save your changes?")
dialog.AddButton("Save").OnClick(func() {
// Handle save
})
saveButton := dialog.AddButton("Don't Save")
dialog.SetDefaultButton(saveButton)
dialog.Show()
```
### Error Dialog
Display error messages:
```go
dialog := application.ErrorDialog()
dialog.SetTitle("Error")
dialog.SetMessage("Failed to save file")
dialog.Show()
```
### File Dialogs
#### Open File Dialog
Allow users to select files to open:
```go
dialog := application.OpenFileDialog()
dialog.SetTitle("Select Image")
dialog.SetFilters([]*application.FileFilter{
{
DisplayName: "Images (*.png;*.jpg)",
Pattern: "*.png;*.jpg",
},
})
// Single file selection
if path, err := dialog.PromptForSingleSelection(); err == nil {
// Use selected file path
}
// Multiple file selection
if paths, err := dialog.PromptForMultipleSelection(); err == nil {
// Use selected file paths
}
```
#### Save File Dialog
Allow users to choose where to save files:
```go
dialog := application.SaveFileDialog()
dialog.SetTitle("Save Document")
dialog.SetDefaultFilename("document.txt")
dialog.SetFilters([]*application.FileFilter{
{
DisplayName: "Text Files (*.txt)",
Pattern: "*.txt",
},
})
if path, err := dialog.PromptForSingleSelection(); err == nil {
// Save file to selected path
}
```
## Dialog Customisation
### Setting Icons
Dialogs can use custom icons from the built-in icon set:
```go
dialog := application.InfoDialog()
dialog.SetIcon(icons.ApplicationDarkMode256)
```
### Window Attachment
Dialogs can be attached to specific windows:
```go
dialog := application.QuestionDialog()
dialog.AttachToWindow(app.CurrentWindow())
dialog.Show()
```
### Button Customisation
Create buttons with custom labels and actions:
```go
dialog := application.QuestionDialog()
dialog.SetMessage("Choose an action")
// Add buttons with custom handlers
dialog.AddButton("Save").OnClick(func() {
// Handle save
})
dialog.AddButton("Don't Save").OnClick(func() {
// Handle don't save
})
cancelButton := dialog.AddButton("Cancel")
dialog.SetDefaultButton(cancelButton) // Set default button
```
## Platform Considerations
<Tabs>
<TabItem label="macOS" icon="fa-brands:apple">
On macOS, dialogs follow system conventions:
- Use system-standard dialog appearances
- Support keyboard navigation (Tab, Space, Return)
- Support standard keyboard shortcuts (⌘+.)
- Automatically handle dark/light mode
- Support system accessibility features
- Position relative to parent window
</TabItem>
<TabItem label="Windows" icon="fa-brands:windows">
On Windows, dialogs integrate with the Windows UI:
- Use Windows system dialog styles
- Support keyboard navigation (Tab, Space, Enter)
- Support Windows accessibility features
- Follow Windows dialog positioning rules
- Adapt to Windows theme settings
- Support high DPI displays
</TabItem>
<TabItem label="Linux" icon="fa-brands:linux">
On Linux, dialog behaviour depends on the desktop environment:
- Use native dialog widgets when available
- Follow desktop environment theme
- Support keyboard navigation
- Adapt to desktop environment settings
- Position according to window manager rules
- Support desktop environment accessibility
</TabItem>
</Tabs>
## Directory Selection
Allow users to select directories:
```go
dialog := application.DirectoryDialog()
dialog.SetTitle("Select Project Directory")
if path, err := dialog.PromptForSingleSelection(); err == nil {
// Use selected directory path
}
```
## About Dialog
Display application information:
```go
app.ShowAboutDialog()
```
## Best Practices
1. Use appropriate dialog types for different scenarios:
- InfoDialog for general messages
- QuestionDialog for user decisions
- ErrorDialog for error messages
- FileDialog for file operations
2. Provide clear and concise messages:
- Use descriptive titles
- Keep messages brief but informative
- Clearly state any required user action
3. Handle dialog responses appropriately:
- Check for errors in file dialogs
- Provide feedback for user actions
- Handle cancellation gracefully
4. Consider platform conventions:
- Follow platform-specific dialog patterns
- Use appropriate button ordering
- Respect system settings
:::tip[Pro Tip]
When using file dialogs, always set appropriate filters to help users select the correct file types for your application.
:::
:::danger[Warning]
Always handle potential errors from file and directory dialogs, as they may fail due to permissions or other system issues.
:::

View file

@ -0,0 +1,491 @@
---
title: Events
sidebar:
order: 55
---
import { Tabs, TabItem } from "@astrojs/starlight/components";
Wails provides a flexible event system that enables communication between different parts of your application. This includes both application-level and window-level events.
## Application Events
Application events are triggered by application-level state changes such as application startup, theme changes, and power events. You can listen for these events using the `OnApplicationEvent` method:
```go
app.OnApplicationEvent(events.Mac.ApplicationDidBecomeActive, func(event *application.ApplicationEvent) {
app.Logger.Info("Application started!")
})
app.OnApplicationEvent(events.Windows.SystemThemeChanged, func(event *application.ApplicationEvent) {
app.Logger.Info("System theme changed!")
if event.Context().IsDarkMode() {
app.Logger.Info("System is now using dark mode!")
} else {
app.Logger.Info("System is now using light mode!")
}
})
```
### Common Application Events
Common application events are aliases for platform-specific application events. These events are triggered by application-level state
changes such as application startup, theme changes, and power events.
Here is the same example as above, but using common application events to make it work across all platforms:
```go
app.OnApplicationEvent(events.Common.ApplicationStarted, func(event *application.ApplicationEvent) {
app.Logger.Info("Application started!")
})
app.OnApplicationEvent(events.Common.ThemeChanged, func(event *application.ApplicationEvent) {
if event.Context().IsDarkMode() {
app.Logger.Info("System is now using dark mode!")
} else {
app.Logger.Info("System is now using light mode!")
}
})
```
#### Common Application Event List
| Event Name | Description |
|---------------------------|----------------------------------------------------------------------------------------------------------|
| ApplicationOpenedWithFile | Application opened with a file. See [File Associations](/guides/file-associations) for more information. |
| ApplicationStarted | Application has started |
| ThemeChanged | System theme changed |
### Platform-Specific Application Events
Below is a list of all platform-specific application events.
<Tabs>
<TabItem label="macOS" icon="fa-brands:apple">
| Event Name | Common Event | Description |
|------------|--------------|-------------|
| ApplicationDidBecomeActive | - | Application became active |
| ApplicationDidChangeBackingProperties | - | Application backing properties changed |
| ApplicationDidChangeEffectiveAppearance | ThemeChanged | Application appearance changed |
| ApplicationDidChangeIcon | - | Application icon changed |
| ApplicationDidChangeOcclusionState | - | Application occlusion state changed |
| ApplicationDidChangeScreenParameters | - | Screen parameters changed |
| ApplicationDidChangeStatusBarFrame | - | Status bar frame changed |
| ApplicationDidChangeStatusBarOrientation | - | Status bar orientation changed |
| ApplicationDidChangeTheme | ThemeChanged | System theme changed |
| ApplicationDidFinishLaunching | ApplicationStarted | Application finished launching |
| ApplicationDidHide | - | Application hidden |
| ApplicationDidResignActiveNotification | - | Application resigned active state |
| ApplicationDidUnhide | - | Application unhidden |
| ApplicationDidUpdate | - | Application updated |
| ApplicationShouldHandleReopen | - | Application should handle reopen |
| ApplicationWillBecomeActive | - | Application will become active |
| ApplicationWillFinishLaunching | - | Application will finish launching |
| ApplicationWillHide | - | Application will hide |
| ApplicationWillResignActiveNotification | - | Application will resign active state |
| ApplicationWillTerminate | - | Application will terminate |
| ApplicationWillUnhide | - | Application will unhide |
| ApplicationWillUpdate | - | Application will update |
</TabItem>
<TabItem label="Windows" icon="fa-brands:windows">
| Event Name | Common Event | Description |
|------------|--------------|-------------|
| APMPowerSettingChange | - | Power settings changed |
| APMPowerStatusChange | - | Power status changed |
| APMResumeAutomatic | - | System resuming automatically |
| APMResumeSuspend | - | System resuming from suspend |
| APMSuspend | - | System suspending |
| ApplicationStarted | ApplicationStarted | Application started |
| SystemThemeChanged | ThemeChanged | System theme changed |
</TabItem>
<TabItem label="Linux" icon="fa-brands:linux">
| Event Name | Common Event | Description |
|------------|--------------|-------------|
| ApplicationStartup | ApplicationStarted | Application started |
| SystemThemeChanged | ThemeChanged | System theme changed |
</TabItem>
</Tabs>
## Window Events
Window events are triggered by window-specific actions such as resizing, moving, or changing focus state. You can listen for these events using the `OnWindowEvent` method:
```go
window.OnWindowEvent(events.Common.WindowClosing, func(e *application.WindowEvent) {
app.Logger.Info("Window is closing!")
})
window.OnWindowEvent(events.Common.WindowFocus, func(e *application.WindowEvent) {
app.Logger.Info("Window gained focus!")
})
```
### Hooks vs Standard Listeners
Wails provides two ways to handle window events: standard listeners (OnWindowEvent) and hooks (RegisterHook). The key differences are:
1. **Execution Order**: Hooks are executed first and in the order they are registered, while standard listeners execute after Hooks and have no guaranteed order.
2. **Blocking**: Hooks are blocking and must complete before the next hook is executed. Standard listeners are non-blocking.
3. **Event Cancellation**: When cancelling an event in a Hook, it prevents it from propagating further. This is useful to prevent
default behaviour, such as closing a window. Cancelling an event in a standard listener will only prevent it from being emitted
from that point in time.
In this example, the window will only close after the close button has been clicked three times, demonstrating how hooks can be used to control event flow.
```go
// Hook - runs synchronously. The window will not close until the countdown reaches zero.
var countdown = 3
window.RegisterHook(events.Common.WindowClosing, func(e *application.WindowEvent) {
countdown--
if countdown == 0 {
app.Logger.Info("Window closing - countdown reached zero!")
return
}
app.Logger.Info("Preventing window from closing - countdown:", countdown)
e.Cancel()
})
```
This next example demonstrates the execution order of hooks vs standard listeners.
```go
window.OnWindowEvent(events.Common.WindowFocus, func(e *application.WindowEvent) {
app.Logger.Info("I always run after hooks!")
})
// Multiple hooks are executed in order
window.RegisterHook(events.Common.WindowFocus, func(e *application.WindowEvent) {
app.Logger.Info("First focus hook - will always run first!")
})
window.RegisterHook(events.Common.WindowFocus, func(e *application.WindowEvent) {
app.Logger.Info("Second focus hook - will always run second!")
})
```
This produces the following output:
```
INF First focus hook - will always run first!
INF Second focus hook - will always run second!
INF I always run after hooks!
```
### Common Window Events
| Event Name | Description |
|--------------------|---------------------------|
| WindowClosing | Window is closing |
| WindowDidMove | Window moved |
| WindowDidResize | Window resized |
| WindowDPIChanged | Window DPI changed |
| WindowFilesDropped | Files dropped on window |
| WindowFocus | Window gained focus |
| WindowFullscreen | Window entered fullscreen |
| WindowHide | Window hidden |
| WindowLostFocus | Window lost focus |
| WindowMaximise | Window maximised |
| WindowMinimise | Window minimised |
| WindowRestore | Window restored |
| WindowRuntimeReady | Window runtime is ready |
| WindowShow | Window shown |
| WindowUnFullscreen | Window exited fullscreen |
| WindowUnMaximise | Window unmaximised |
| WindowUnMinimise | Window unminimised |
| WindowZoom | Window zoomed |
| WindowZoomIn | Window zoomed in |
| WindowZoomOut | Window zoomed out |
| WindowZoomReset | Window zoom reset |
### Platform-Specific Window Events
<Tabs>
<TabItem label="macOS" icon="fa-brands:apple">
| Event Name | Common Event | Description |
| WindowDidBecomeKey | WindowFocus | Window became key window |
| WindowDidBecomeMain | - | Window became main window |
| WindowDidBeginSheet | - | Sheet began |
| WindowDidChangeAlpha | - | Window alpha changed |
| WindowDidChangeBackingLocation | - | Window backing location changed |
| WindowDidChangeBackingProperties | - | Window backing properties changed |
| WindowDidChangeCollectionBehavior | - | Window collection behaviour changed |
| WindowDidChangeEffectiveAppearance | - | Window appearance changed |
| WindowDidChangeOcclusionState | - | Window occlusion state changed |
| WindowDidChangeOrderingMode | - | Window ordering mode changed |
| WindowDidChangeScreen | - | Window screen changed |
| WindowDidChangeScreenParameters | - | Window screen parameters changed |
| WindowDidChangeScreenProfile | - | Window screen profile changed |
| WindowDidChangeScreenSpace | - | Window screen space changed |
| WindowDidChangeScreenSpaceProperties | - | Window screen space properties changed |
| WindowDidChangeSharingType | - | Window sharing type changed |
| WindowDidChangeSpace | - | Window space changed |
| WindowDidChangeSpaceOrderingMode | - | Window space ordering mode changed |
| WindowDidChangeTitle | - | Window title changed |
| WindowDidChangeToolbar | - | Window toolbar changed |
| WindowDidDeminiaturize | WindowUnMinimise | Window unminimised |
| WindowDidEndSheet | - | Sheet ended |
| WindowDidEnterFullScreen | WindowFullscreen | Window entered fullscreen |
| WindowDidEnterVersionBrowser | - | Window entered version browser |
| WindowDidExitFullScreen | WindowUnFullscreen | Window exited fullscreen |
| WindowDidExitVersionBrowser | - | Window exited version browser |
| WindowDidExpose | - | Window exposed |
| WindowDidFocus | WindowFocus | Window gained focus |
| WindowDidMiniaturise | WindowMinimise | Window minimised |
| WindowDidMove | WindowDidMove | Window moved |
| WindowDidOrderOffScreen | - | Window ordered off screen |
| WindowDidOrderOnScreen | - | Window ordered on screen |
| WindowDidResignKey | - | Window resigned key window |
| WindowDidResignMain | - | Window resigned main window |
| WindowDidResize | WindowDidResize | Window resized |
| WindowDidUpdate | - | Window updated |
| WindowDidUpdateAlpha | - | Window alpha updated |
| WindowDidUpdateCollectionBehavior | - | Window collection behaviour updated |
| WindowDidUpdateCollectionProperties | - | Window collection properties updated |
| WindowDidUpdateShadow | - | Window shadow updated |
| WindowDidUpdateTitle | - | Window title updated |
| WindowDidUpdateToolbar | - | Window toolbar updated |
| WindowDidZoom | WindowZoom | Window zoomed |
| WindowFileDraggingEntered | - | File dragging entered window |
| WindowFileDraggingExited | - | File dragging exited window |
| WindowFileDraggingPerformed | - | File dragging performed |
| WindowHide | WindowHide | Window hidden |
| WindowMaximise | WindowMaximise | Window maximised |
| WindowShouldClose | WindowClosing | Window should close |
| WindowShow | WindowShow | Window shown |
| WindowUnMaximise | WindowUnMaximise | Window unmaximised |
| WindowZoomIn | WindowZoomIn | Window zoomed in |
| WindowZoomOut | WindowZoomOut | Window zoomed out |
| WindowZoomReset | WindowZoomReset | Window zoom reset |
|------------|--------------|-------------|
</TabItem>
<TabItem label="Windows" icon="fa-brands:windows">
| Event Name | Common Event | Description |
|------------|--------------|-------------|
| WebViewNavigationCompleted | - | WebView navigation completed |
| WindowActive | - | Window became active |
| WindowBackgroundErase | - | Window background needs erasing |
| WindowClickActive | - | Window clicked whilst active |
| WindowClosing | WindowClosing | Window closing |
| WindowDidMove | WindowDidMove | Window moved |
| WindowDidResize | WindowDidResize | Window resized |
| WindowEndMove | - | Window finished moving |
| WindowEndResize | - | Window finished resising |
| WindowFullscreen | WindowFullscreen | Window entered fullscreen |
| WindowHide | WindowHide | Window hidden |
| WindowInactive | - | Window became inactive |
| WindowKillFocus | WindowLostFocus | Window lost focus |
| WindowMaximise | WindowMaximise | Window maximised |
| WindowMinimise | WindowMinimise | Window minimised |
| WindowPaint | - | Window needs painting |
| WindowRestore | WindowRestore | Window restored |
| WindowSetFocus | WindowFocus | Window gained focus |
| WindowShow | WindowShow | Window shown |
| WindowStartMove | - | Window started moving |
| WindowStartResize | - | Window started resising |
| WindowUnFullscreen | WindowUnFullscreen | Window exited fullscreen |
| WindowUnMaximise | WindowUnMaximise | Window unmaximised |
| WindowUnMinimise | WindowUnMinimise | Window unminimised |
| WindowZOrderChanged | - | Window z-order changed |
#### Input Events
| Event Name | Description |
|------------|-------------|
| WindowDragDrop | Files dragged and dropped |
| WindowDragEnter | Drag entered window |
| WindowDragLeave | Drag left window |
| WindowDragOver | Drag over window |
| WindowKeyDown | Key pressed |
| WindowKeyUp | Key released |
| WindowNonClientHit | Mouse hit in non-client area |
| WindowNonClientMouseDown | Mouse down in non-client area |
| WindowNonClientMouseLeave | Mouse left non-client area |
| WindowNonClientMouseMove | Mouse move in non-client area |
| WindowNonClientMouseUp | Mouse up in non-client area |
</TabItem>
<TabItem label="Linux" icon="fa-brands:linux">
| Event Name | Common Event | Description |
|------------|--------------|-------------|
| WindowDeleteEvent | WindowClosing | Window delete requested |
| WindowDidMove | WindowDidMove | Window moved |
| WindowDidResize | WindowDidResize | Window resized |
| WindowFocusIn | WindowFocus | Window gained focus |
| WindowFocusOut | WindowLostFocus | Window lost focus |
| WindowLoadChanged | WindowShow | Window load state changed |
</TabItem>
</Tabs>
## Menu Events
Menu events are triggered by menu-specific actions such as opening, closing, and interacting with menu items. These events are useful for creating dynamic menus and responding to menu interactions.
```go
// Listen for menu events
app.OnApplicationEvent(events.Mac.MenuDidOpen, func(event *application.ApplicationEvent) {
app.Logger.Info("Menu opened!")
})
app.OnApplicationEvent(events.Mac.MenuWillSendAction, func(event *application.ApplicationEvent) {
app.Logger.Info("Menu about to send action!")
})
```
For more information about menus, see the [Application Menu](/learn/application-menu) and [Context Menu](/learn/context-menu) documentation.
### Platform-Specific Menu Events
<Tabs>
<TabItem label="macOS" icon="fa-brands:apple">
| Event Name | Description |
|------------|-------------|
| MenuDidAddItem | Menu item added |
| MenuDidBeginTracking | Menu began tracking |
| MenuDidClose | Menu closed |
| MenuDidDisplayItem | Menu item displayed |
| MenuDidEndTracking | Menu ended tracking |
| MenuDidHighlightItem | Menu item highlighted |
| MenuDidOpen | Menu opened |
| MenuDidPopUp | Menu popped up |
| MenuDidRemoveItem | Menu item removed |
| MenuDidSendAction | Menu sent action |
| MenuDidSendActionToItem | Menu sent action to item |
| MenuDidUpdate | Menu updated |
| MenuWillAddItem | Menu will add item |
| MenuWillBeginTracking | Menu will begin tracking |
| MenuWillDisplayItem | Menu will display item |
| MenuWillEndTracking | Menu will end tracking |
| MenuWillHighlightItem | Menu will highlight item |
| MenuWillOpen | Menu will open |
| MenuWillPopUp | Menu will pop up |
| MenuWillRemoveItem | Menu will remove item |
| MenuWillSendAction | Menu will send action |
| MenuWillSendActionToItem | Menu will send action to item |
| MenuWillUpdate | Menu will update |
</TabItem>
<TabItem label="Windows" icon="fa-brands:windows">
Windows does not currently provide specific menu events.
</TabItem>
<TabItem label="Linux" icon="fa-brands:linux">
Linux does not currently provide specific menu events.
</TabItem>
</Tabs>
## WebView Events
WebView events are triggered by navigation and loading state changes in the WebView component. These events are useful for tracking page loads and navigation state.
```go
// Listen for WebView navigation events
app.OnApplicationEvent(events.Mac.WebViewDidStartProvisionalNavigation, func(event *application.ApplicationEvent) {
app.Logger.Info("WebView started loading a page!")
})
app.OnApplicationEvent(events.Mac.WebViewDidFinishNavigation, func(event *application.ApplicationEvent) {
app.Logger.Info("WebView finished loading the page!")
})
// On Windows
app.OnApplicationEvent(events.Windows.WebViewNavigationCompleted, func(event *application.ApplicationEvent) {
app.Logger.Info("WebView navigation completed!")
})
```
### Platform-Specific WebView Events
<Tabs>
<TabItem label="macOS" icon="fa-brands:apple">
| Event Name | Description |
|------------|-------------|
| WebViewDidCommitNavigation | Navigation committed |
| WebViewDidFinishNavigation | Navigation finished |
| WebViewDidReceiveServerRedirectForProvisionalNavigation | Server redirect received |
| WebViewDidStartProvisionalNavigation | Provisional navigation started |
</TabItem>
<TabItem label="Windows" icon="fa-brands:windows">
| Event Name | Description |
|------------|-------------|
| WebViewNavigationCompleted | Navigation completed |
</TabItem>
<TabItem label="Linux" icon="fa-brands:linux">
Linux does not currently provide specific WebView events.
</TabItem>
</Tabs>
## Custom Events
You can emit and listen for custom events to enable communication between different parts of your application.
### Emitting Events
You can emit custom events from anywhere in your application:
```go
// Emit an event with data from the application
app.EmitEvent("myevent", "hello")
// Emit from a specific window
window.EmitEvent("windowevent", "window specific data")
```
### Handling Custom Events
Listen for custom events using the `OnEvent` method:
```go
app.OnEvent("myevent", func(e *application.CustomEvent) {
// Access event information
name := e.Name // Event name
data := e.Data // Event data
sender := e.Sender // Event sender
cancelled := e.IsCancelled() // Event cancellation status
})
## Event Cancellation
Events can be cancelled to prevent their default behaviour or stop propagation to other listeners. This is particularly useful for hooks that need to control window closing, menu actions, or other system events.
### Cancelling Events
To cancel an event, call the `Cancel()` method on the event object:
```go
window.RegisterHook(events.Common.WindowClosing, func(e *application.WindowEvent) {
// Prevent the window from closing
e.Cancel()
})
```
### Checking Event Cancellation
You can check if an event has been cancelled using the `IsCancelled()` method:
```go
window.RegisterHook(events.Common.WindowClosing, func(e *application.WindowEvent) {
if e.IsCancelled() {
app.Logger.Info("Window closing was cancelled by another hook")
return
}
// Process event
})
// For custom events
app.OnEvent("myevent", func(e *application.CustomEvent) {
if e.IsCancelled() {
app.Logger.Info("Event was cancelled")
return
}
// Process event
})
```
:::tip[Pro Tip]
Remember that event cancellation in hooks affects all subsequent hooks and listeners, whilst cancellation in standard listeners only affects listeners that haven't yet been called.
:::

View file

@ -0,0 +1,188 @@
---
title: Menu Reference
sidebar:
order: 52
---
This reference document covers the common menu item types and properties available in Wails v3. These features are shared between application menus and context menus.
## Menu Item Types
### Regular Menu Items
The most basic type of menu item displays text and triggers an action when clicked:
```go
menuItem := menu.Add("Click Me")
menuItem.OnClick(func(ctx *application.Context) {
// Handle click
})
```
### Checkboxes
Checkbox menu items provide a toggleable state:
```go
checkbox := menu.AddCheckbox("Enable Feature", true) // true = initially checked
checkbox.OnClick(func(ctx *application.Context) {
isChecked := ctx.ClickedMenuItem().Checked()
// Handle state change
})
```
### Radio Groups
Radio items create mutually exclusive options. Items are grouped automatically when placed adjacently:
```go
menu.AddRadio("Option 1", true) // true = initially selected
menu.AddRadio("Option 2", false)
menu.AddRadio("Option 3", false)
```
### Submenus
Submenus allow you to create nested menu structures:
```go
submenu := menu.AddSubmenu("More Options")
submenu.Add("Submenu Item 1")
submenu.Add("Submenu Item 2")
```
### Separators
Separators add visual dividers between menu items:
```go
menu.Add("Item 1")
menu.AddSeparator()
menu.Add("Item 2")
```
## Menu Item Properties
### Label
The text displayed for the menu item:
```go
menuItem := menu.Add("Initial Label")
menuItem.SetLabel("New Label")
```
### Enabled State
Control whether the menu item can be interacted with:
```go
menuItem := menu.Add("Disabled Item")
menuItem.SetEnabled(false)
```
### Checked State
For checkbox and radio items, control or query their checked state:
```go
checkbox := menu.AddCheckbox("Feature", false)
checkbox.SetChecked(true)
isChecked := checkbox.Checked()
```
### Accelerators
Add keyboard shortcuts to menu items:
```go
menuItem := menu.Add("Save")
menuItem.SetAccelerator("CmdOrCtrl+S")
```
Common accelerator modifiers:
- `CmdOrCtrl`: Command on macOS, Control on Windows/Linux
- `Shift`
- `Alt`: Option on macOS
- `Ctrl`: Control key on all platforms
## Event Handling
### Click Events
Handle menu item clicks using the `OnClick` method:
```go
menuItem.OnClick(func(ctx *application.Context) {
// Access the clicked item
clickedItem := ctx.ClickedMenuItem()
// Get current state
label := clickedItem.Label()
isChecked := clickedItem.Checked()
// Update the item
clickedItem.SetLabel("New Label")
})
```
### Shared Event Handlers
Event handlers can be shared amongst multiple menu items:
```go
handleClick := func(ctx *application.Context) {
item := ctx.ClickedMenuItem()
// Common handling logic
}
menu.Add("Item 1").OnClick(handleClick)
menu.Add("Item 2").OnClick(handleClick)
```
## Dynamic Updates
Menu items can be updated dynamically during runtime:
```go
menuItem := menu.Add("Initial State")
// Later, update the item
menuItem.SetLabel("New Label")
menuItem.SetEnabled(false)
menuItem.SetChecked(true)
// Apply changes
menu.Update()
```
:::note[Update Required]
After modifying menu items, call `Update()` on the parent menu to apply the changes.
:::
## Best Practices
1. Use clear, concise labels that describe the action
2. Group related items together using separators
3. Limit submenu depth to maintain usability
4. Provide keyboard shortcuts for common actions
5. Keep radio groups focused on a single choice
6. Update menu items to reflect application state
7. Handle all possible states in click handlers
:::tip[Pro Tip]
When sharing event handlers, use the `ctx.ClickedMenuItem()` method to determine which item triggered the event and handle it accordingly.
:::
## Platform Considerations
:::note[Platform Behaviour]
Menu appearance and behaviour varies by platform:
- macOS: Uses native menu styling and supports system roles
- Windows: Follows Windows menu conventions
- Linux: Adapts to the desktop environment's theme
:::
:::danger[Warning]
Always test menu functionality across all supported platforms, as behaviour and appearance may vary significantly.
:::

View file

@ -94,7 +94,7 @@ func main() {
func printFooter() {
if !commands.DisableFooter {
docsLink := term.Hyperlink("https://v3alpha.wails.io/getting-started/your-first-app/", "wails3 docs")
docsLink := term.Hyperlink("https://v3.wails.io/getting-started/your-first-app/", "wails3 docs")
pterm.Println(pterm.LightGreen("\nNeed documentation? Run: ") + pterm.LightBlue(docsLink))
// Check if we're in a teminal
@ -113,7 +113,7 @@ func printFooter() {
func openDocs() error {
commands.DisableFooter = true
return browser.OpenURL("https://v3alpha.wails.io/getting-started/your-first-app/")
return browser.OpenURL("https://v3.wails.io/getting-started/your-first-app/")
}
func openSponsor() error {

View file

@ -28,7 +28,7 @@ func main() {
// Custom event handling
app.OnEvent("myevent", func(e *application.CustomEvent) {
app.Logger.Info("[Go] CustomEvent received", "name", e.Name, "data", e.Data, "sender", e.Sender, "cancelled", e.Cancelled)
app.Logger.Info("[Go] CustomEvent received", "name", e.Name, "data", e.Data, "sender", e.Sender, "cancelled", e.IsCancelled())
})
// OS specific application events
@ -104,7 +104,7 @@ func main() {
})
win2.OnWindowEvent(events.Common.WindowFocus, func(e *application.WindowEvent) {
app.Logger.Info("[ApplicationEvent] Window focus!")
app.Logger.Info("[OnWindowEvent] Window focus!")
})
err := app.Run()

View file

@ -1,7 +1,7 @@
# File Association Sample Project
This sample project demonstrates how to associate a file type with an application.
More info at: https://v3alpha.wails.io/learn/guides/file-associations/
More info at: https://v3.wails.io/learn/guides/file-associations/
To run the sample, follow these steps:

View file

@ -14,7 +14,7 @@ info:
version: "v0.0.1" # The application version
# File Associations
# More information at: https://v3alpha.wails.io/noit/done/yet
# More information at: https://v3.wails.io/noit/done/yet
fileAssociations:
- ext: wails
name: Wails

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -334,7 +334,7 @@ func main() {
<button onclick="window.location.reload()" class="button button-primary">
Reload Page
</button>
<button onclick="window.location.replace('https://v3alpha.wails.io/')" class="button button-secondary">
<button onclick="window.location.replace('https://v3.wails.io/')" class="button button-secondary">
View Documentation
</button>
</div>

View file

@ -286,7 +286,7 @@ func main() {
<button onclick="window.location.reload()" class="button button-primary">
立即重新加载页面
</button>
<button onclick="window.location.replace('https://v3alpha.wails.io/')" class="button button-secondary">
<button onclick="window.location.replace('https://v3.wails.io/')" class="button button-secondary">
查看解决方案文档 ►
</button>
</div>

View file

@ -44,7 +44,7 @@ dev_mode:
type: primary
# File Associations
# More information at: https://v3alpha.wails.io/noit/done/yet
# More information at: https://v3.wails.io/noit/done/yet
fileAssociations:
# - ext: wails
# name: Wails

View file

@ -257,7 +257,7 @@ func Run() (err error) {
pterm.Printf("• %s: %s\n", result.TestName, result.ErrorMsg)
url := result.HelpURL
if strings.HasPrefix(url, "/") {
url = "https://v3alpha.wails.io" + url
url = "https://v3.wails.io" + url
}
pterm.Printf(" For more information: %s\n", term.Hyperlink(url, url))
}

View file

@ -1,3 +1,3 @@
# Runtime
To rebuild the runtime run `task build-runtime` or if you have Wails v3 CLI, you can use `wails3 task build-runtime`.
To rebuild the runtime run `task build` or if you have Wails v3 CLI, you can use `wails3 task build`.

View file

@ -5,6 +5,7 @@ version: "3"
tasks:
install-deps:
internal: true
dir: desktop/@wailsio/runtime
sources:
- package.json
cmds:

View file

@ -1,16 +1,13 @@
{
"name": "@wailsio/runtime",
"version": "3.0.0-alpha.22",
"version": "3.0.0-alpha.39",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@wailsio/runtime",
"version": "3.0.0-alpha.22",
"version": "3.0.0-alpha.39",
"license": "MIT",
"dependencies": {
"nanoid": "^5.0.7"
},
"devDependencies": {
"rimraf": "^5.0.5",
"typedoc": "^0.25.7",
@ -109,9 +106,9 @@
"dev": true
},
"node_modules/cross-spawn": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
"dev": true,
"dependencies": {
"path-key": "^3.1.0",
@ -292,23 +289,6 @@
"node": ">=16 || 14 >=14.17"
}
},
"node_modules/nanoid": {
"version": "5.0.7",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.7.tgz",
"integrity": "sha512-oLxFY2gd2IqnjcYyOXD8XGCftpGtZP2AbHbOkthDkvRywH5ayNtPVy9YlOPcHckXzbLTCHpkb7FB+yuxKV13pQ==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"bin": {
"nanoid": "bin/nanoid.js"
},
"engines": {
"node": "^18 || >=20"
}
},
"node_modules/neo-async": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",

View file

@ -1,7 +1,7 @@
{
"name": "@wailsio/runtime",
"type": "module",
"version": "3.0.0-alpha.36",
"version": "3.0.0-alpha.39",
"description": "Wails Runtime",
"types": "types/index.d.ts",
"exports": {
@ -34,8 +34,5 @@
"typedoc": "^0.25.7",
"typedoc-plugin-markdown": "^3.17.1",
"typescript": "^5.3.3"
},
"dependencies": {
"nanoid": "^5.0.7"
}
}

View file

@ -10,7 +10,7 @@ The electron alternative for Go
/* jshint esversion: 9 */
import { newRuntimeCallerWithID, objectNames } from "./runtime";
import { nanoid } from 'nanoid/non-secure';
import { nanoid } from './nanoid.js';
// Setup
window._wails = window._wails || {};

View file

@ -80,7 +80,7 @@ window._wails.dialogResultCallback = dialogResultCallback;
import {newRuntimeCallerWithID, objectNames} from "./runtime";
import { nanoid } from 'nanoid/non-secure';
import { nanoid } from './nanoid.js';
// Define constants from the `methods` object in Title Case
const DialogInfo = 0;

View file

@ -44,6 +44,7 @@ export const EventTypes = {
WindowNonClientMouseUp: "windows:WindowNonClientMouseUp",
WindowNonClientMouseMove: "windows:WindowNonClientMouseMove",
WindowNonClientMouseLeave: "windows:WindowNonClientMouseLeave",
WindowDPIChanged: "windows:WindowDPIChanged",
},
Mac: {
ApplicationDidBecomeActive: "mac:ApplicationDidBecomeActive",

View file

@ -0,0 +1,42 @@
// Source: https://github.com/ai/nanoid
// The MIT License (MIT)
//
// Copyright 2017 Andrey Sitnik <andrey@sitnik.ru>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// This alphabet uses `A-Za-z0-9_-` symbols.
// The order of characters is optimized for better gzip and brotli compression.
// References to the same file (works both for gzip and brotli):
// `'use`, `andom`, and `rict'`
// References to the brotli default dictionary:
// `-26T`, `1983`, `40px`, `75px`, `bush`, `jack`, `mind`, `very`, and `wolf`
let urlAlphabet =
'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict'
export let nanoid = (size = 21) => {
let id = ''
// A compact alternative for `for (var i = 0; i < step; i++)`.
let i = size | 0
while (i--) {
// `| 0` is more compact and faster than `Math.floor()`.
id += urlAlphabet[(Math.random() * 64) | 0]
}
return id
}

View file

@ -9,7 +9,7 @@ The electron alternative for Go
*/
/* jshint esversion: 9 */
import { nanoid } from 'nanoid/non-secure';
import { nanoid } from './nanoid.js';
const runtimeURL = window.location.origin + "/wails/runtime";

View file

@ -24,7 +24,7 @@ const _invoke = (() => {
return (msg) => window.webkit.messageHandlers.external.postMessage(msg);
}
} catch(e) {
console.warn('\n%c⚠ Browser Environment Detected %c\n\n%cOnly UI previews are available in the browser. For full functionality, please run the application in desktop mode.\nMore information at: https://v3alpha.wails.io/learn/build/#using-a-browser-for-development\n',
console.warn('\n%c⚠ Browser Environment Detected %c\n\n%cOnly UI previews are available in the browser. For full functionality, please run the application in desktop mode.\nMore information at: https://v3.wails.io/learn/build/#using-a-browser-for-development\n',
'background: #ffffff; color: #000000; font-weight: bold; padding: 4px 8px; border-radius: 4px; border: 2px solid #000000;',
'background: transparent;',
'color: #ffffff; font-style: italic; font-weight: bold;');

View file

@ -44,6 +44,7 @@ export declare const EventTypes: {
WindowNonClientMouseUp: string,
WindowNonClientMouseMove: string,
WindowNonClientMouseLeave: string,
WindowDPIChanged: string,
},
Mac: {
ApplicationDidBecomeActive: string,

File diff suppressed because it is too large Load diff

View file

@ -1,17 +0,0 @@
{
"name": "runtime",
"version": "3.0.0",
"description": "Wails JS Runtime",
"main": "index.js",
"scripts": {},
"author": "Lea Anthony <lea.anthony@gmail.com>",
"license": "ISC",
"devDependencies": {
"esbuild": "^0.20.1",
"happy-dom": "^13.6.2",
"nanoid": "^5.0.6",
"npm-check-updates": "^16.14.15",
"svelte": "^4.2.12",
"vitest": "^1.3.1"
}
}

View file

@ -36,7 +36,7 @@ Now that you have your project set up, it's time to explore the features that Wa
Note: Some examples may be under development during the alpha phase.
3. **Explore the documentation**: Visit the [Wails3 documentation](https://v3alpha.wails.io/) for in-depth guides and API references.
3. **Explore the documentation**: Visit the [Wails3 documentation](https://v3.wails.io/) for in-depth guides and API references.
4. **Join the community**: Have questions or want to share your progress? Join the [Wails Discord](https://discord.gg/JDdSxwjhGf) or visit the [Wails discussions on GitHub](https://github.com/wailsapp/wails/discussions).

View file

@ -1,3 +1,3 @@
# Next Steps
For a full guide on how to create templates, see [Creating Custom Templates](https://v3alpha.wails.io/guides/custom-templates).
For a full guide on how to create templates, see [Creating Custom Templates](https://v3.wails.io/guides/custom-templates).

View file

@ -697,7 +697,7 @@ func (a *App) handleApplicationEvent(event *ApplicationEvent) {
if ok {
for _, thisHook := range hooks {
thisHook.callback(event)
if event.Cancelled {
if event.IsCancelled() {
return
}
}
@ -705,6 +705,9 @@ func (a *App) handleApplicationEvent(event *ApplicationEvent) {
for _, listener := range listeners {
go func() {
if event.IsCancelled() {
return
}
defer handlePanic()
listener.callback(event)
}()
@ -925,10 +928,16 @@ func (a *App) dispatchEventToListeners(event *CustomEvent) {
listeners := a.wailsEventListeners
for _, window := range a.windows {
if event.IsCancelled() {
return
}
window.DispatchWailsEvent(event)
}
for _, listener := range listeners {
if event.IsCancelled() {
return
}
listener.DispatchWailsEvent(event)
}
}

File diff suppressed because one or more lines are too long

View file

@ -11,7 +11,8 @@ import (
type ApplicationEvent struct {
Id uint
ctx *ApplicationEventContext
Cancelled bool
cancelled bool
lock sync.RWMutex
}
func (w *ApplicationEvent) Context() *ApplicationEventContext {
@ -26,7 +27,15 @@ func newApplicationEvent(id events.ApplicationEventType) *ApplicationEvent {
}
func (w *ApplicationEvent) Cancel() {
w.Cancelled = true
w.lock.Lock()
defer w.lock.Unlock()
w.cancelled = true
}
func (w *ApplicationEvent) IsCancelled() bool {
w.lock.RLock()
defer w.lock.RUnlock()
return w.cancelled
}
var applicationEvents = make(chan *ApplicationEvent, 5)
@ -44,11 +53,20 @@ type CustomEvent struct {
Name string `json:"name"`
Data any `json:"data"`
Sender string `json:"sender"`
Cancelled bool
cancelled bool
lock sync.RWMutex
}
func (e *CustomEvent) Cancel() {
e.Cancelled = true
e.lock.Lock()
defer e.lock.Unlock()
e.cancelled = true
}
func (e *CustomEvent) IsCancelled() bool {
e.lock.Lock()
defer e.lock.Unlock()
return e.cancelled
}
func (e *CustomEvent) ToJSON() string {
@ -124,7 +142,7 @@ func (e *EventProcessor) Emit(thisEvent *CustomEvent) {
if hooks, ok := e.hooks[thisEvent.Name]; ok {
for _, thisHook := range hooks {
thisHook.callback(thisEvent)
if thisEvent.Cancelled {
if thisEvent.IsCancelled() {
return
}
}
@ -226,6 +244,9 @@ func (e *EventProcessor) dispatchEventToListeners(event *CustomEvent) {
listener.counter--
}
go func() {
if event.IsCancelled() {
return
}
defer handlePanic()
listener.callback(event)
}()

View file

@ -35,6 +35,6 @@ func (m *MessageProcessor) processEventsMethod(method int, rw http.ResponseWrite
return
}
m.Info("Runtime Call:", "method", "Events."+eventsMethodNames[method], "name", event.Name, "sender", event.Sender, "data", event.Data, "cancelled", event.Cancelled)
m.Info("Runtime Call:", "method", "Events."+eventsMethodNames[method], "name", event.Name, "sender", event.Sender, "data", event.Data, "cancelled", event.IsCancelled())
}

View file

@ -1299,22 +1299,6 @@ func (w *macosWebviewWindow) run() {
})
})
// Translate ShouldClose to common WindowClosing event
w.parent.OnWindowEvent(events.Mac.WindowShouldClose, func(_ *WindowEvent) {
w.parent.emit(events.Common.WindowClosing)
})
// Translate WindowDidResignKey to common WindowLostFocus event
w.parent.OnWindowEvent(events.Mac.WindowDidResignKey, func(_ *WindowEvent) {
w.parent.emit(events.Common.WindowLostFocus)
})
w.parent.OnWindowEvent(events.Mac.WindowDidResignMain, func(_ *WindowEvent) {
w.parent.emit(events.Common.WindowLostFocus)
})
w.parent.OnWindowEvent(events.Mac.WindowDidResize, func(_ *WindowEvent) {
w.parent.emit(events.Common.WindowDidResize)
})
if options.HTML != "" {
w.setHTML(options.HTML)
}

View file

@ -344,21 +344,6 @@ func (w *linuxWebviewWindow) run() {
}
})
})
w.parent.OnWindowEvent(events.Linux.WindowFocusIn, func(e *WindowEvent) {
w.parent.emit(events.Common.WindowFocus)
})
w.parent.OnWindowEvent(events.Linux.WindowFocusOut, func(e *WindowEvent) {
w.parent.emit(events.Common.WindowLostFocus)
})
w.parent.OnWindowEvent(events.Linux.WindowDeleteEvent, func(e *WindowEvent) {
w.parent.emit(events.Common.WindowClosing)
})
w.parent.OnWindowEvent(events.Linux.WindowDidMove, func(e *WindowEvent) {
w.parent.emit(events.Common.WindowDidMove)
})
w.parent.OnWindowEvent(events.Linux.WindowDidResize, func(e *WindowEvent) {
w.parent.emit(events.Common.WindowDidResize)
})
w.parent.RegisterHook(events.Linux.WindowLoadChanged, func(e *WindowEvent) {
w.execJS(runtime.Core())

View file

@ -1292,7 +1292,7 @@ func (w *windowsWebviewWindow) WndProc(msg uint32, wparam, lparam uintptr) uintp
int(newWindowRect.Bottom-newWindowRect.Top),
w32.SWP_NOZORDER|w32.SWP_NOACTIVATE)
}
w.parent.emit(events.Common.WindowDPIChanged)
w.parent.emit(events.Windows.WindowDPIChanged)
}
if w.parent.options.Windows.WindowMask != nil {

View file

@ -21,6 +21,7 @@ var defaultWindowEventMapping = map[string]map[WindowEventType]WindowEventType{
Windows.WindowDidResize: Common.WindowDidResize,
Windows.WindowSetFocus: Common.WindowFocus,
Windows.WindowKillFocus: Common.WindowLostFocus,
Windows.WindowDPIChanged: Common.WindowDPIChanged,
},
"darwin": {
Mac.WindowDidResignKey: Common.WindowLostFocus,
@ -39,6 +40,10 @@ var defaultWindowEventMapping = map[string]map[WindowEventType]WindowEventType{
Mac.WindowZoomIn: Common.WindowZoomIn,
Mac.WindowZoomOut: Common.WindowZoomOut,
Mac.WindowZoomReset: Common.WindowZoomReset,
Mac.WindowShouldClose: Common.WindowClosing,
Mac.WindowDidResignKey: Common.WindowLostFocus,
Mac.WindowDidResignMain: Common.WindowLostFocus,
Mac.WindowDidResize: Common.WindowDidResize,
},
"linux": {
Linux.WindowDeleteEvent: Common.WindowClosing,

View file

@ -34,30 +34,30 @@ type commonEvents struct {
func newCommonEvents() commonEvents {
return commonEvents{
ApplicationStarted: 1205,
WindowMaximise: 1206,
WindowUnMaximise: 1207,
WindowFullscreen: 1208,
WindowUnFullscreen: 1209,
WindowRestore: 1210,
WindowMinimise: 1211,
WindowUnMinimise: 1212,
WindowClosing: 1213,
WindowZoom: 1214,
WindowZoomIn: 1215,
WindowZoomOut: 1216,
WindowZoomReset: 1217,
WindowFocus: 1218,
WindowLostFocus: 1219,
WindowShow: 1220,
WindowHide: 1221,
WindowDPIChanged: 1222,
WindowFilesDropped: 1223,
WindowRuntimeReady: 1224,
ThemeChanged: 1225,
WindowDidMove: 1226,
WindowDidResize: 1227,
ApplicationOpenedWithFile: 1228,
ApplicationStarted: 1206,
WindowMaximise: 1207,
WindowUnMaximise: 1208,
WindowFullscreen: 1209,
WindowUnFullscreen: 1210,
WindowRestore: 1211,
WindowMinimise: 1212,
WindowUnMinimise: 1213,
WindowClosing: 1214,
WindowZoom: 1215,
WindowZoomIn: 1216,
WindowZoomOut: 1217,
WindowZoomReset: 1218,
WindowFocus: 1219,
WindowLostFocus: 1220,
WindowShow: 1221,
WindowHide: 1222,
WindowDPIChanged: 1223,
WindowFilesDropped: 1224,
WindowRuntimeReady: 1225,
ThemeChanged: 1226,
WindowDidMove: 1227,
WindowDidResize: 1228,
ApplicationOpenedWithFile: 1229,
}
}
@ -403,6 +403,7 @@ type windowsEvents struct {
WindowNonClientMouseUp WindowEventType
WindowNonClientMouseMove WindowEventType
WindowNonClientMouseLeave WindowEventType
WindowDPIChanged WindowEventType
}
func newWindowsEvents() windowsEvents {
@ -450,6 +451,7 @@ func newWindowsEvents() windowsEvents {
WindowNonClientMouseUp: 1202,
WindowNonClientMouseMove: 1203,
WindowNonClientMouseLeave: 1204,
WindowDPIChanged: 1205,
}
}
@ -639,28 +641,29 @@ var eventToJS = map[uint]string{
1202: "windows:WindowNonClientMouseUp",
1203: "windows:WindowNonClientMouseMove",
1204: "windows:WindowNonClientMouseLeave",
1205: "common:ApplicationStarted",
1206: "common:WindowMaximise",
1207: "common:WindowUnMaximise",
1208: "common:WindowFullscreen",
1209: "common:WindowUnFullscreen",
1210: "common:WindowRestore",
1211: "common:WindowMinimise",
1212: "common:WindowUnMinimise",
1213: "common:WindowClosing",
1214: "common:WindowZoom",
1215: "common:WindowZoomIn",
1216: "common:WindowZoomOut",
1217: "common:WindowZoomReset",
1218: "common:WindowFocus",
1219: "common:WindowLostFocus",
1220: "common:WindowShow",
1221: "common:WindowHide",
1222: "common:WindowDPIChanged",
1223: "common:WindowFilesDropped",
1224: "common:WindowRuntimeReady",
1225: "common:ThemeChanged",
1226: "common:WindowDidMove",
1227: "common:WindowDidResize",
1228: "common:ApplicationOpenedWithFile",
1205: "windows:WindowDPIChanged",
1206: "common:ApplicationStarted",
1207: "common:WindowMaximise",
1208: "common:WindowUnMaximise",
1209: "common:WindowFullscreen",
1210: "common:WindowUnFullscreen",
1211: "common:WindowRestore",
1212: "common:WindowMinimise",
1213: "common:WindowUnMinimise",
1214: "common:WindowClosing",
1215: "common:WindowZoom",
1216: "common:WindowZoomIn",
1217: "common:WindowZoomOut",
1218: "common:WindowZoomReset",
1219: "common:WindowFocus",
1220: "common:WindowLostFocus",
1221: "common:WindowShow",
1222: "common:WindowHide",
1223: "common:WindowDPIChanged",
1224: "common:WindowFilesDropped",
1225: "common:WindowRuntimeReady",
1226: "common:ThemeChanged",
1227: "common:WindowDidMove",
1228: "common:WindowDidResize",
1229: "common:ApplicationOpenedWithFile",
}

View file

@ -1,11 +1,35 @@
common:ApplicationOpenedWithFile
common:ApplicationStarted
common:ThemeChanged
common:WindowClosing
common:WindowDidMove
common:WindowDidResize
common:WindowDPIChanged
common:WindowFilesDropped
common:WindowFocus
common:WindowFullscreen
common:WindowHide
common:WindowLostFocus
common:WindowMaximise
common:WindowMinimise
common:WindowRestore
common:WindowRuntimeReady
common:WindowShow
common:WindowUnFullscreen
common:WindowUnMaximise
common:WindowUnMinimise
common:WindowZoom
common:WindowZoomIn
common:WindowZoomOut
common:WindowZoomReset
linux:ApplicationStartup
linux:SystemThemeChanged
linux:WindowLoadChanged
linux:WindowDeleteEvent
linux:WindowDidMove
linux:WindowDidResize
linux:WindowFocusIn
linux:WindowFocusOut
linux:ApplicationStartup
linux:WindowLoadChanged
mac:ApplicationDidBecomeActive
mac:ApplicationDidChangeBackingProperties
mac:ApplicationDidChangeEffectiveAppearance
@ -14,11 +38,13 @@ mac:ApplicationDidChangeOcclusionState
mac:ApplicationDidChangeScreenParameters
mac:ApplicationDidChangeStatusBarFrame
mac:ApplicationDidChangeStatusBarOrientation
mac:ApplicationDidChangeTheme!
mac:ApplicationDidFinishLaunching
mac:ApplicationDidHide
mac:ApplicationDidResignActiveNotification
mac:ApplicationDidUnhide
mac:ApplicationDidUpdate
mac:ApplicationShouldHandleReopen!
mac:ApplicationWillBecomeActive
mac:ApplicationWillFinishLaunching
mac:ApplicationWillHide
@ -26,8 +52,33 @@ mac:ApplicationWillResignActive
mac:ApplicationWillTerminate
mac:ApplicationWillUnhide
mac:ApplicationWillUpdate
mac:ApplicationDidChangeTheme!
mac:ApplicationShouldHandleReopen!
mac:MenuDidAddItem
mac:MenuDidBeginTracking
mac:MenuDidClose
mac:MenuDidDisplayItem
mac:MenuDidEndTracking
mac:MenuDidHighlightItem
mac:MenuDidOpen
mac:MenuDidPopUp
mac:MenuDidRemoveItem
mac:MenuDidSendAction
mac:MenuDidSendActionToItem
mac:MenuDidUpdate
mac:MenuWillAddItem
mac:MenuWillBeginTracking
mac:MenuWillDisplayItem
mac:MenuWillEndTracking
mac:MenuWillHighlightItem
mac:MenuWillOpen
mac:MenuWillPopUp
mac:MenuWillRemoveItem
mac:MenuWillSendAction
mac:MenuWillSendActionToItem
mac:MenuWillUpdate
mac:WebViewDidCommitNavigation
mac:WebViewDidFinishNavigation
mac:WebViewDidReceiveServerRedirectForProvisionalNavigation
mac:WebViewDidStartProvisionalNavigation
mac:WindowDidBecomeKey
mac:WindowDidBecomeMain
mac:WindowDidBeginSheet
@ -51,12 +102,6 @@ mac:WindowDidChangeToolbar
mac:WindowDidDeminiaturize
mac:WindowDidEndSheet
mac:WindowDidEnterFullScreen
mac:WindowMaximise
mac:WindowUnMaximise
mac:WindowDidZoom!
mac:WindowZoomIn!
mac:WindowZoomOut!
mac:WindowZoomReset!
mac:WindowDidEnterVersionBrowser
mac:WindowDidExitFullScreen
mac:WindowDidExitVersionBrowser
@ -76,7 +121,15 @@ mac:WindowDidUpdateCollectionProperties
mac:WindowDidUpdateShadow
mac:WindowDidUpdateTitle
mac:WindowDidUpdateToolbar
mac:WindowDidZoom!
mac:WindowFileDraggingEntered
mac:WindowFileDraggingExited
mac:WindowFileDraggingPerformed
mac:WindowHide
mac:WindowMaximize
mac:WindowShouldClose!
mac:WindowShow
mac:WindowUnMaximise
mac:WindowWillBecomeKey
mac:WindowWillBecomeMain
mac:WindowWillBeginSheet
@ -104,102 +157,50 @@ mac:WindowWillUpdateTitle
mac:WindowWillUpdateToolbar
mac:WindowWillUpdateVisibility
mac:WindowWillUseStandardFrame
mac:MenuWillOpen
mac:MenuDidOpen
mac:MenuDidClose
mac:MenuWillSendAction
mac:MenuDidSendAction
mac:MenuWillHighlightItem
mac:MenuDidHighlightItem
mac:MenuWillDisplayItem
mac:MenuDidDisplayItem
mac:MenuWillAddItem
mac:MenuDidAddItem
mac:MenuWillRemoveItem
mac:MenuDidRemoveItem
mac:MenuWillBeginTracking
mac:MenuDidBeginTracking
mac:MenuWillEndTracking
mac:MenuDidEndTracking
mac:MenuWillUpdate
mac:MenuDidUpdate
mac:MenuWillPopUp
mac:MenuDidPopUp
mac:MenuWillSendActionToItem
mac:MenuDidSendActionToItem
mac:WebViewDidStartProvisionalNavigation
mac:WebViewDidReceiveServerRedirectForProvisionalNavigation
mac:WebViewDidFinishNavigation
mac:WebViewDidCommitNavigation
mac:WindowFileDraggingEntered
mac:WindowFileDraggingPerformed
mac:WindowFileDraggingExited
mac:WindowShow
mac:WindowHide
windows:SystemThemeChanged
mac:WindowZoomIn!
mac:WindowZoomOut!
mac:WindowZoomReset!
windows:APMPowerSettingChange
windows:APMPowerStatusChange
windows:APMSuspend
windows:APMResumeAutomatic
windows:APMResumeSuspend
windows:APMPowerSettingChange
windows:APMSuspend
windows:ApplicationStarted
windows:SystemThemeChanged
windows:WebViewNavigationCompleted
windows:WindowInactive
windows:WindowActive
windows:WindowBackgroundErase
windows:WindowClickActive
windows:WindowMaximise
windows:WindowUnMaximise
windows:WindowFullscreen
windows:WindowUnFullscreen
windows:WindowRestore
windows:WindowMinimise
windows:WindowUnMinimise
windows:WindowClosing
windows:WindowSetFocus
windows:WindowKillFocus
windows:WindowDidMove
windows:WindowDidResize
windows:WindowDPIChanged
windows:WindowDragDrop
windows:WindowDragEnter
windows:WindowDragLeave
windows:WindowDragOver
windows:WindowDidMove
windows:WindowDidResize
windows:WindowShow
windows:WindowHide
windows:WindowStartMove
windows:WindowEndMove
windows:WindowStartResize
windows:WindowEndResize
windows:WindowFullscreen
windows:WindowHide
windows:WindowInactive
windows:WindowKeyDown
windows:WindowKeyUp
windows:WindowZOrderChanged
windows:WindowPaint
windows:WindowBackgroundErase
windows:WindowKillFocus
windows:WindowMaximise
windows:WindowMinimise
windows:WindowNonClientHit
windows:WindowNonClientMouseDown
windows:WindowNonClientMouseUp
windows:WindowNonClientMouseMove
windows:WindowNonClientMouseLeave
common:ApplicationStarted
common:WindowMaximise
common:WindowUnMaximise
common:WindowFullscreen
common:WindowUnFullscreen
common:WindowRestore
common:WindowMinimise
common:WindowUnMinimise
common:WindowClosing
common:WindowZoom
common:WindowZoomIn
common:WindowZoomOut
common:WindowZoomReset
common:WindowFocus
common:WindowLostFocus
common:WindowShow
common:WindowHide
common:WindowDPIChanged
common:WindowFilesDropped
common:WindowRuntimeReady
common:ThemeChanged
common:WindowDidMove
common:WindowDidResize
common:ApplicationOpenedWithFile
windows:WindowNonClientMouseMove
windows:WindowNonClientMouseUp
windows:WindowPaint
windows:WindowRestore
windows:WindowSetFocus
windows:WindowShow
windows:WindowStartMove
windows:WindowStartResize
windows:WindowUnFullscreen
windows:WindowUnMaximise
windows:WindowUnMinimise
windows:WindowZOrderChanged