diff --git a/.github/workflows/automated-releases.yml b/.github/workflows/automated-releases.yml
index e88f54eb9..83445d869 100644
--- a/.github/workflows/automated-releases.yml
+++ b/.github/workflows/automated-releases.yml
@@ -23,6 +23,7 @@ env:
jobs:
check-permissions:
name: Check Release Permissions
+ permissions: {}
runs-on: ubuntu-latest
outputs:
authorized: ${{ steps.check.outputs.authorized }}
diff --git a/.github/workflows/test-nightly-releases.yml b/.github/workflows/test-nightly-releases.yml
index 63df09935..1e6f12a69 100644
--- a/.github/workflows/test-nightly-releases.yml
+++ b/.github/workflows/test-nightly-releases.yml
@@ -1,4 +1,6 @@
name: Test Nightly Releases (Dry Run)
+permissions:
+ contents: read
on:
workflow_dispatch:
diff --git a/docs/src/content/docs/features/windows/basics.mdx b/docs/src/content/docs/features/windows/basics.mdx
index 007c62c52..3137111ac 100644
--- a/docs/src/content/docs/features/windows/basics.mdx
+++ b/docs/src/content/docs/features/windows/basics.mdx
@@ -410,22 +410,29 @@ childWindow := app.NewWebviewWindowWithOptions(application.WebviewWindowOptions{
**macOS-specific features:**
-
+
```go
// Transparent title bar
window := app.NewWebviewWindowWithOptions(application.WebviewWindowOptions{
- Mac: application.MacOptions{
- TitleBarAppearsTransparent: true,
- Backdrop: application.MacBackdropTranslucent,
+ Mac: application.MacWindow{
+ TitleBar: application.MacTitleBar{
+ AppearsTransparent: true,
+ },
+ Backdrop: application.MacBackdropTranslucent,
},
})
```
-
+
**Backdrop types:**
- `MacBackdropNormal` - Standard window
- `MacBackdropTranslucent` - Translucent background
- `MacBackdropTransparent` - Fully transparent
-
+
+ **Collection behavior:**
+ Control how windows behave across Spaces:
+ - `MacWindowCollectionBehaviorCanJoinAllSpaces` - Visible on all Spaces
+ - `MacWindowCollectionBehaviorFullScreenAuxiliary` - Can overlay fullscreen apps
+
**Native fullscreen:**
macOS fullscreen creates a new Space (virtual desktop).
diff --git a/docs/src/content/docs/features/windows/options.mdx b/docs/src/content/docs/features/windows/options.mdx
index 521d50b01..93a468120 100644
--- a/docs/src/content/docs/features/windows/options.mdx
+++ b/docs/src/content/docs/features/windows/options.mdx
@@ -665,39 +665,85 @@ OnDestroy: func() {
### Mac Options
```go
-Mac: application.MacOptions{
- TitleBarAppearsTransparent: true,
- Backdrop: application.MacBackdropTranslucent,
- InvisibleTitleBarHeight: 50,
- TitleBarStyle: application.MacTitleBarStyleHidden,
+Mac: application.MacWindow{
+ TitleBar: application.MacTitleBar{
+ AppearsTransparent: true,
+ Hide: false,
+ HideTitle: true,
+ FullSizeContent: true,
+ },
+ Backdrop: application.MacBackdropTranslucent,
+ InvisibleTitleBarHeight: 50,
+ WindowLevel: application.MacWindowLevelNormal,
+ CollectionBehavior: application.MacWindowCollectionBehaviorDefault,
},
```
-**TitleBarAppearsTransparent** (`bool`)
-- Makes title bar transparent
-- Content extends into title bar area
+**TitleBar** (`MacTitleBar`)
+- `AppearsTransparent` - Makes title bar transparent, content extends into title bar area
+- `Hide` - Hides the title bar completely
+- `HideTitle` - Hides only the title text
+- `FullSizeContent` - Extends content to full window size
**Backdrop** (`MacBackdrop`)
-- `MacBackdropNormal` - Standard
-- `MacBackdropTranslucent` - Blurred translucent
-- `MacBackdropTransparent` - Fully transparent
+- `MacBackdropNormal` - Standard opaque background
+- `MacBackdropTranslucent` - Blurred translucent background
+- `MacBackdropTransparent` - Fully transparent background
**InvisibleTitleBarHeight** (`int`)
-- Height of invisible title bar (for dragging)
-- Only when `TitleBarStyle` is `MacTitleBarStyleHidden`
+- Height of invisible title bar area (for dragging)
+- Useful when title bar is hidden
-**TitleBarStyle** (`MacTitleBarStyle`)
-- `MacTitleBarStyleDefault` - Standard title bar
-- `MacTitleBarStyleHidden` - Hidden title bar
-- `MacTitleBarStyleHiddenInset` - Hidden with inset
+**WindowLevel** (`MacWindowLevel`)
+- `MacWindowLevelNormal` - Standard window level (default)
+- `MacWindowLevelFloating` - Floats above normal windows
+- `MacWindowLevelTornOffMenu` - Torn-off menu level
+- `MacWindowLevelModalPanel` - Modal panel level
+- `MacWindowLevelMainMenu` - Main menu level
+- `MacWindowLevelStatus` - Status window level
+- `MacWindowLevelPopUpMenu` - Pop-up menu level
+- `MacWindowLevelScreenSaver` - Screen saver level
-**Example:**
+**CollectionBehavior** (`MacWindowCollectionBehavior`)
+
+Controls how the window behaves across macOS Spaces and fullscreen. These are bitmask values that can be combined using bitwise OR (`|`).
+
+**Space behavior:**
+- `MacWindowCollectionBehaviorDefault` - Uses FullScreenPrimary (default, backwards compatible)
+- `MacWindowCollectionBehaviorCanJoinAllSpaces` - Window appears on all Spaces
+- `MacWindowCollectionBehaviorMoveToActiveSpace` - Moves to active Space when shown
+- `MacWindowCollectionBehaviorManaged` - Default managed window behavior
+- `MacWindowCollectionBehaviorTransient` - Temporary/transient window
+- `MacWindowCollectionBehaviorStationary` - Stays stationary during Space switches
+
+**Window cycling:**
+- `MacWindowCollectionBehaviorParticipatesInCycle` - Included in Cmd+` cycling
+- `MacWindowCollectionBehaviorIgnoresCycle` - Excluded from Cmd+` cycling
+
+**Fullscreen behavior:**
+- `MacWindowCollectionBehaviorFullScreenPrimary` - Can enter fullscreen mode
+- `MacWindowCollectionBehaviorFullScreenAuxiliary` - Can overlay fullscreen apps
+- `MacWindowCollectionBehaviorFullScreenNone` - Disables fullscreen capability
+- `MacWindowCollectionBehaviorFullScreenAllowsTiling` - Allows side-by-side tiling (macOS 10.11+)
+- `MacWindowCollectionBehaviorFullScreenDisallowsTiling` - Prevents tiling (macOS 10.11+)
+
+**Example - Spotlight-like window:**
```go
-Mac: application.MacOptions{
- TitleBarAppearsTransparent: true,
- Backdrop: application.MacBackdropTranslucent,
- InvisibleTitleBarHeight: 50,
+// Window that appears on all Spaces AND can overlay fullscreen apps
+Mac: application.MacWindow{
+ CollectionBehavior: application.MacWindowCollectionBehaviorCanJoinAllSpaces |
+ application.MacWindowCollectionBehaviorFullScreenAuxiliary,
+ WindowLevel: application.MacWindowLevelFloating,
+},
+```
+
+**Example - Single behavior:**
+
+```go
+// Window that can appear over fullscreen applications
+Mac: application.MacWindow{
+ CollectionBehavior: application.MacWindowCollectionBehaviorFullScreenAuxiliary,
},
```
diff --git a/v3/UNRELEASED_CHANGELOG.md b/v3/UNRELEASED_CHANGELOG.md
index 21cde115e..a3289242e 100644
--- a/v3/UNRELEASED_CHANGELOG.md
+++ b/v3/UNRELEASED_CHANGELOG.md
@@ -17,6 +17,7 @@ After processing, the content will be moved to the main changelog and this file
## Added
+- Add `CollectionBehavior` option to `MacWindow` for controlling window behavior across macOS Spaces and fullscreen (#4756) by @leaanthony
## Changed
diff --git a/v3/examples/spotlight/README.md b/v3/examples/spotlight/README.md
new file mode 100644
index 000000000..bda8f464e
--- /dev/null
+++ b/v3/examples/spotlight/README.md
@@ -0,0 +1,66 @@
+# Spotlight Example
+
+This example demonstrates how to create a Spotlight-like launcher window using the `CollectionBehavior` option on macOS.
+
+## Features
+
+- **Appears on all Spaces**: Using `MacWindowCollectionBehaviorCanJoinAllSpaces`, the window is visible across all virtual desktops
+- **Overlays fullscreen apps**: Using `MacWindowCollectionBehaviorFullScreenAuxiliary`, the window can appear over fullscreen applications
+- **Combined behaviors**: Demonstrates combining multiple behaviors with bitwise OR
+- **Floating window**: `MacWindowLevelFloating` keeps the window above other windows
+- **Accessory app**: Doesn't appear in the Dock (uses `ActivationPolicyAccessory`)
+- **Frameless design**: Clean, borderless appearance with translucent backdrop
+
+## Running the example
+
+```bash
+go run .
+```
+
+**Note**: This example is macOS-specific due to the use of `CollectionBehavior`.
+
+## Combining CollectionBehaviors
+
+Behaviors can be combined using bitwise OR (`|`):
+
+```go
+CollectionBehavior: application.MacWindowCollectionBehaviorCanJoinAllSpaces |
+ application.MacWindowCollectionBehaviorFullScreenAuxiliary,
+```
+
+## CollectionBehavior Options
+
+These are bitmask values that can be combined:
+
+**Space behavior:**
+| Option | Description |
+|--------|-------------|
+| `MacWindowCollectionBehaviorDefault` | Uses FullScreenPrimary (default) |
+| `MacWindowCollectionBehaviorCanJoinAllSpaces` | Window appears on all Spaces |
+| `MacWindowCollectionBehaviorMoveToActiveSpace` | Moves to active Space when shown |
+| `MacWindowCollectionBehaviorManaged` | Default managed window behavior |
+| `MacWindowCollectionBehaviorTransient` | Temporary/transient window |
+| `MacWindowCollectionBehaviorStationary` | Stays stationary during Space switches |
+
+**Fullscreen behavior:**
+| Option | Description |
+|--------|-------------|
+| `MacWindowCollectionBehaviorFullScreenPrimary` | Can enter fullscreen mode |
+| `MacWindowCollectionBehaviorFullScreenAuxiliary` | Can overlay fullscreen apps |
+| `MacWindowCollectionBehaviorFullScreenNone` | Disables fullscreen |
+| `MacWindowCollectionBehaviorFullScreenAllowsTiling` | Allows side-by-side tiling |
+
+## Use Cases
+
+- **Launcher apps** (like Spotlight, Alfred, Raycast)
+- **Quick capture tools** (notes, screenshots)
+- **System utilities** that need to be accessible anywhere
+- **Overlay widgets** that should appear over fullscreen apps
+
+## Status
+
+| Platform | Status |
+|----------|--------|
+| Mac | Working |
+| Windows | N/A (macOS-specific feature) |
+| Linux | N/A (macOS-specific feature) |
diff --git a/v3/examples/spotlight/main.go b/v3/examples/spotlight/main.go
new file mode 100644
index 000000000..d961f1f54
--- /dev/null
+++ b/v3/examples/spotlight/main.go
@@ -0,0 +1,142 @@
+package main
+
+import (
+ "log"
+ "net/http"
+
+ "github.com/wailsapp/wails/v3/pkg/application"
+)
+
+// This example demonstrates how to create a Spotlight-like launcher window
+// that appears on all macOS Spaces and can overlay fullscreen applications.
+//
+// Key features:
+// - Window appears on all Spaces (virtual desktops)
+// - Can overlay fullscreen applications
+// - Floating window level keeps it above other windows
+// - Accessory activation policy hides from Dock
+// - Frameless design with translucent backdrop
+
+func main() {
+ app := application.New(application.Options{
+ Name: "Spotlight Example",
+ Description: "A Spotlight-like launcher demonstrating CollectionBehavior",
+ Mac: application.MacOptions{
+ // Accessory apps don't appear in the Dock
+ ActivationPolicy: application.ActivationPolicyAccessory,
+ ApplicationShouldTerminateAfterLastWindowClosed: true,
+ },
+ Assets: application.AssetOptions{
+ Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ w.WriteHeader(http.StatusOK)
+ w.Write([]byte(spotlightHTML))
+ }),
+ },
+ })
+
+ // Create a Spotlight-like window
+ app.Window.NewWithOptions(application.WebviewWindowOptions{
+ Title: "Spotlight",
+ Width: 680,
+ Height: 80,
+ Frameless: true,
+ // Center the window
+ InitialPosition: application.WindowCentered,
+ // Prevent resizing
+ DisableResize: true,
+ Mac: application.MacWindow{
+ // Combine multiple behaviors using bitwise OR:
+ // - CanJoinAllSpaces: window appears on ALL Spaces (virtual desktops)
+ // - FullScreenAuxiliary: window can overlay fullscreen applications
+ CollectionBehavior: application.MacWindowCollectionBehaviorCanJoinAllSpaces |
+ application.MacWindowCollectionBehaviorFullScreenAuxiliary,
+ // Float above other windows
+ WindowLevel: application.MacWindowLevelFloating,
+ // Translucent vibrancy effect
+ Backdrop: application.MacBackdropTranslucent,
+ // Hidden title bar for clean look
+ TitleBar: application.MacTitleBar{
+ AppearsTransparent: true,
+ Hide: true,
+ },
+ },
+ URL: "/",
+ })
+
+ err := app.Run()
+ if err != nil {
+ log.Fatal(err)
+ }
+}
+
+const spotlightHTML = `
+
+
+ Spotlight
+
+
+
+
+
+
+`
diff --git a/v3/pkg/application/webview_window_darwin.go b/v3/pkg/application/webview_window_darwin.go
index b8d3736d3..fc81974bf 100644
--- a/v3/pkg/application/webview_window_darwin.go
+++ b/v3/pkg/application/webview_window_darwin.go
@@ -34,8 +34,8 @@ void* windowNew(unsigned int id, int width, int height, bool fraudulentWebsiteWa
backing:NSBackingStoreBuffered
defer:NO];
- // Allow fullscreen. Needed for frameless windows
- window.collectionBehavior = NSWindowCollectionBehaviorFullScreenPrimary;
+ // Note: collectionBehavior is set later via windowSetCollectionBehavior()
+ // to allow user configuration of Space and fullscreen behavior
// Create delegate
WebviewWindowDelegate* delegate = [[WebviewWindowDelegate alloc] init];
@@ -234,6 +234,19 @@ void setModalPanelWindowLevel(void* nsWindow) { [(WebviewWindow*)nsWindow setLev
void setScreenSaverWindowLevel(void* nsWindow) { [(WebviewWindow*)nsWindow setLevel:NSScreenSaverWindowLevel]; }
void setTornOffMenuWindowLevel(void* nsWindow) { [(WebviewWindow*)nsWindow setLevel:NSTornOffMenuWindowLevel]; }
+// Set NSWindow collection behavior for Spaces and fullscreen
+// The behavior parameter is a bitmask that can combine multiple NSWindowCollectionBehavior values
+void windowSetCollectionBehavior(void* nsWindow, int behavior) {
+ WebviewWindow* window = (WebviewWindow*)nsWindow;
+ if (behavior == 0) {
+ // Default: use FullScreenPrimary for backwards compatibility
+ window.collectionBehavior = NSWindowCollectionBehaviorFullScreenPrimary;
+ } else {
+ // Pass through the combined bitmask directly
+ window.collectionBehavior = (NSWindowCollectionBehavior)behavior;
+ }
+}
+
// Load URL in NSWindow
void navigationLoadURL(void* nsWindow, char* url) {
// Load URL on main thread
@@ -1162,6 +1175,10 @@ func (w *macosWebviewWindow) setWindowLevel(level MacWindowLevel) {
}
}
+func (w *macosWebviewWindow) setCollectionBehavior(behavior MacWindowCollectionBehavior) {
+ C.windowSetCollectionBehavior(w.nsWindow, C.int(behavior))
+}
+
func (w *macosWebviewWindow) width() int {
var width C.int
var wg sync.WaitGroup
@@ -1260,6 +1277,9 @@ func (w *macosWebviewWindow) run() {
}
w.setWindowLevel(macOptions.WindowLevel)
+ // Set collection behavior (defaults to FullScreenPrimary for backwards compatibility)
+ w.setCollectionBehavior(macOptions.CollectionBehavior)
+
// Initialise the window buttons
w.setMinimiseButtonState(options.MinimiseButtonState)
w.setMaximiseButtonState(options.MaximiseButtonState)
diff --git a/v3/pkg/application/webview_window_options.go b/v3/pkg/application/webview_window_options.go
index 4c9c0f57a..8ca629559 100644
--- a/v3/pkg/application/webview_window_options.go
+++ b/v3/pkg/application/webview_window_options.go
@@ -489,6 +489,9 @@ type MacWindow struct {
// WindowLevel sets the window level to control the order of windows in the screen
WindowLevel MacWindowLevel
+ // CollectionBehavior controls how the window behaves across macOS Spaces and fullscreen
+ CollectionBehavior MacWindowCollectionBehavior
+
// LiquidGlass contains configuration for the Liquid Glass effect
LiquidGlass MacLiquidGlass
}
@@ -506,6 +509,40 @@ const (
MacWindowLevelScreenSaver MacWindowLevel = "screenSaver"
)
+// MacWindowCollectionBehavior controls window behavior across macOS Spaces and fullscreen.
+// These correspond to NSWindowCollectionBehavior bitmask values and can be combined using bitwise OR.
+// For example: MacWindowCollectionBehaviorCanJoinAllSpaces | MacWindowCollectionBehaviorFullScreenAuxiliary
+type MacWindowCollectionBehavior int
+
+const (
+ // MacWindowCollectionBehaviorDefault is zero value - when set, FullScreenPrimary is used for backwards compatibility
+ MacWindowCollectionBehaviorDefault MacWindowCollectionBehavior = 0
+ // MacWindowCollectionBehaviorCanJoinAllSpaces allows window to appear on all Spaces
+ MacWindowCollectionBehaviorCanJoinAllSpaces MacWindowCollectionBehavior = 1 << 0 // 1
+ // MacWindowCollectionBehaviorMoveToActiveSpace moves window to active Space when shown
+ MacWindowCollectionBehaviorMoveToActiveSpace MacWindowCollectionBehavior = 1 << 1 // 2
+ // MacWindowCollectionBehaviorManaged is the default managed window behavior
+ MacWindowCollectionBehaviorManaged MacWindowCollectionBehavior = 1 << 2 // 4
+ // MacWindowCollectionBehaviorTransient marks window as temporary/transient
+ MacWindowCollectionBehaviorTransient MacWindowCollectionBehavior = 1 << 3 // 8
+ // MacWindowCollectionBehaviorStationary keeps window stationary during Space switches
+ MacWindowCollectionBehaviorStationary MacWindowCollectionBehavior = 1 << 4 // 16
+ // MacWindowCollectionBehaviorParticipatesInCycle includes window in Cmd+` cycling (default for normal windows)
+ MacWindowCollectionBehaviorParticipatesInCycle MacWindowCollectionBehavior = 1 << 5 // 32
+ // MacWindowCollectionBehaviorIgnoresCycle excludes window from Cmd+` cycling
+ MacWindowCollectionBehaviorIgnoresCycle MacWindowCollectionBehavior = 1 << 6 // 64
+ // MacWindowCollectionBehaviorFullScreenPrimary allows the window to enter fullscreen
+ MacWindowCollectionBehaviorFullScreenPrimary MacWindowCollectionBehavior = 1 << 7 // 128
+ // MacWindowCollectionBehaviorFullScreenAuxiliary allows window to overlay fullscreen apps
+ MacWindowCollectionBehaviorFullScreenAuxiliary MacWindowCollectionBehavior = 1 << 8 // 256
+ // MacWindowCollectionBehaviorFullScreenNone prevents window from entering fullscreen (macOS 10.7+)
+ MacWindowCollectionBehaviorFullScreenNone MacWindowCollectionBehavior = 1 << 9 // 512
+ // MacWindowCollectionBehaviorFullScreenAllowsTiling allows side-by-side tiling in fullscreen (macOS 10.11+)
+ MacWindowCollectionBehaviorFullScreenAllowsTiling MacWindowCollectionBehavior = 1 << 11 // 2048
+ // MacWindowCollectionBehaviorFullScreenDisallowsTiling prevents tiling in fullscreen (macOS 10.11+)
+ MacWindowCollectionBehaviorFullScreenDisallowsTiling MacWindowCollectionBehavior = 1 << 12 // 4096
+)
+
// MacWebviewPreferences contains preferences for the Mac webview
type MacWebviewPreferences struct {
// TabFocusesLinks will enable tabbing to links