Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
89e8d89
feat(windows): add support for custom hit-test logic for non-client r…
savely-krasovsky May 16, 2026
bc4951e
fix(windows): address review comments
savely-krasovsky May 16, 2026
2519890
refactor: simplify non-client hit test handling logic
savely-krasovsky May 16, 2026
819da92
fix: remove handling for non-client right mouse button events
savely-krasovsky May 16, 2026
8182aa4
feat(windows): add cursor handling
savely-krasovsky May 16, 2026
a6b8b4c
feat(windows): handle right-click on window caption to display the sy…
savely-krasovsky May 16, 2026
c05ddde
fix(windows): enable non-client region tracking only is the feature i…
savely-krasovsky May 16, 2026
2348d47
fix(windows): preserve native hover state for non-client buttons
savely-krasovsky May 16, 2026
29e50ea
fix(windows): address review comments
savely-krasovsky May 16, 2026
51ccf06
fix(runtime): rename app region css tracking internals
savely-krasovsky May 16, 2026
202b03d
chore(windows): document non-client hit test ordering
savely-krasovsky May 16, 2026
5266af5
feat(runtime): add runtime-config-ready event to improve initializati…
savely-krasovsky May 16, 2026
38a4ca2
Merge branch 'master' into master
savely-krasovsky May 17, 2026
a1691fc
Merge branch 'master' into master
leaanthony May 23, 2026
7038b1a
feat(windows): document `NonClientRegionSupport` and `WebView2Composi…
savely-krasovsky May 31, 2026
da3466b
docs: correct video asset path in frameless windows documentation
savely-krasovsky May 31, 2026
c655fe5
docs: clarify `WebView2CompositionHosting` experimental status
savely-krasovsky May 31, 2026
a87bf7a
docs: fix alignment issue in `WebView2CompositionHosting` example
savely-krasovsky May 31, 2026
b4d7717
docs: clarify Snap Layouts behavior and add reference to native non-c…
savely-krasovsky May 31, 2026
6652cf5
Merge branch 'master' into master
savely-krasovsky Jun 1, 2026
a6366b3
Merge branch 'master' into master
savely-krasovsky Jun 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file not shown.
2 changes: 1 addition & 1 deletion docs/src/content/docs/features/windows/basics.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,7 @@ mainWindow.AttachModal(childWindow)
There is no per-window `SetIcon` — the application icon is set on the app via `app.SetIcon([]byte)` (or for a Linux-specific window icon, the `application.LinuxWindow.Icon` field at window creation).

**Snap Assist:**
Shows Windows 11 snap layout options for the window.
Shows Windows 11 snap layout options through the system shortcut path. For a custom HTML maximize button with native hover Snap Layouts, use [Native Non-Client Regions on Windows](/features/windows/frameless#native-non-client-regions-on-windows) instead.

**Taskbar flashing:**
Useful for notifications when window is minimised.
Expand Down
154 changes: 154 additions & 0 deletions docs/src/content/docs/features/windows/frameless.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ sidebar:
---

import { Tabs, TabItem, Card, CardGrid } from "@astrojs/starlight/components";
import wailsAppRegionVideo from "../../../../assets/windows-native-non-client-regions/wails-app-region.mp4";

## Frameless Windows

Expand Down Expand Up @@ -173,6 +174,158 @@ document.querySelector('.maximize').addEventListener('click', () => Window.Maxim
document.querySelector('.close').addEventListener('click', () => Window.Close())
```

## Native Non-Client Regions on Windows

Windows can treat parts of a custom title bar as native non-client areas. This lets you draw the title bar and caption buttons with any HTML/CSS design while keeping native Windows behavior: the caption area drags the window, the maximize button can show Windows 11 Snap Assist / Snap Layouts, and the minimize, maximize, and close buttons receive native hit testing and mouse state.

The video below shows a custom HTML/CSS title bar using native Windows hit testing, including Windows 11 Snap Assist / Snap Layouts on a custom maximize button.

<video src={wailsAppRegionVideo} controls muted playsInline></video>

Wails supports two Windows-specific mechanisms:

- `app-region` through WebView2's native non-client region support
- `--wails-app-region` through Wails runtime tracking for custom caption buttons

### Choosing a Mode

:::caution[Experimental]
`WebView2CompositionHosting` changes how the window hosts and interacts with WebView2 under the hood. Instead of the default HWND-hosted WebView2 controller, Wails uses composition controller hosting and forwards input explicitly. This mode may have rendering, input, focus, or WebView2 Runtime compatibility issues. Enable it only when you need native custom caption-button behavior, and test your app carefully on the Windows and WebView2 Runtime versions you support.
:::

Choose based on what you need from Windows:

- Use `NonClientRegionSupport` for simple native app dragging with WebView2's `app-region: drag` and `app-region: no-drag`.
- Use `WebView2CompositionHosting` when your custom minimize, maximize, and close buttons should behave like native Windows caption buttons.
- Enable both when the same window needs WebView2-native `app-region` support and Wails-managed custom caption-button regions.

`NonClientRegionSupport` is the lightweight native alternative to Wails' `--wails-draggable` tracking. You mark draggable and non-draggable areas with CSS, WebView2 decides which pixels belong to the caption, and Wails asks WebView2 for the native region when hit testing.

That is the full scope of this mode today. It does not make custom minimize, maximize, or close buttons behave like native Windows caption buttons, and it does not enable Windows 11 Snap Assist / Snap Layouts for a custom maximize button. Use it when you need simple native app dragging without the extra machinery of `--wails-draggable`.

`WebView2CompositionHosting` is for custom caption buttons with native behavior. Wails tracks DOM rectangles marked with `--wails-app-region`, maps them to Windows hit-test values such as `HTMINBUTTON`, `HTMAXBUTTON`, and `HTCLOSE`, and forwards mouse input back into the composition-hosted WebView2 surface. That is what allows a custom maximize button to participate in Windows 11 Snap Assist / Snap Layouts while keeping any visual design you choose.

Put another way: `NonClientRegionSupport` is WebView2-native CSS region support. `WebView2CompositionHosting` is Wails taking responsibility for host-owned composition and custom non-client hit testing.

### WebView2 app-region

Enable WebView2's native non-client region support for the window:

```go
window := app.Window.NewWithOptions(application.WebviewWindowOptions{
Frameless: true,
Windows: application.WindowsWindow{
NonClientRegionSupport: true,
},
})
```

Then mark draggable areas with the CSS `app-region` property:

```css
.titlebar {
app-region: drag;
}

.titlebar button,
.titlebar input,
.titlebar select,
.titlebar textarea {
app-region: no-drag;
}
```

Use this when you only need native caption dragging and your title bar controls are handled with normal frontend clicks.

The limitation of this mode is that it is constrained by WebView2's own non-client region support. In current WebView2 releases, that means drag and no-drag regions only. It is not intended to model fully custom frontend caption buttons with distinct native minimize, maximize, and close roles.

### Custom Caption Buttons with Native Behavior

For custom minimize, maximize, and close buttons that should behave like system caption buttons, enable composition hosting:

:::caution[Experimental]
`WebView2CompositionHosting` uses WebView2 composition controller hosting with DirectComposition. See [Choosing a Mode](#choosing-a-mode) before enabling it.
:::

```go
window := app.Window.NewWithOptions(application.WebviewWindowOptions{
Frameless: true,
Windows: application.WindowsWindow{
WebView2CompositionHosting: true,
},
})
```

Then mark each frontend region with `--wails-app-region`:

```html
<div class="titlebar">
<div class="title">My Application</div>
<div class="window-controls">
<button class="window-button minimize" aria-label="Minimize"></button>
<button class="window-button maximize" aria-label="Maximize"></button>
<button class="window-button close" aria-label="Close"></button>
</div>
</div>
```

```css
.titlebar {
--wails-app-region: caption;
height: 40px;
}

.window-controls {
display: flex;
height: 100%;
}

.window-button {
width: 46px;
border: 0;
background: transparent;
}

.window-button.minimize {
--wails-app-region: minimize;
}

.window-button.maximize {
--wails-app-region: maximize;
}

.window-button.close {
--wails-app-region: close;
}
```

Supported `--wails-app-region` values:

- `caption` - draggable caption area
- `minimize` - native minimize button hit target
- `maximize` - native maximize button hit target, including Windows 11 Snap Assist / Snap Layouts hover behavior
- `close` - native close button hit target

The Wails runtime observes DOM, style, size, scroll, and viewport changes, then sends region snapshots to the native window. Region geometry is measured in CSS pixels and converted to physical pixels for Windows hit testing.

The visual design remains entirely yours. The regions only tell Windows what each rectangle means; the button shape, icon, color, spacing, hover styling, and layout still come from your frontend.

For compatibility with earlier builds of this feature, Wails also accepts the legacy `--wails-non-client-region` property. New code should use `--wails-app-region`.

### Combining Both

You can enable both options when you want WebView2 `app-region` support and Wails-managed caption button regions in the same window:

```go
window := app.Window.NewWithOptions(application.WebviewWindowOptions{
Frameless: true,
Windows: application.WindowsWindow{
NonClientRegionSupport: true,
WebView2CompositionHosting: true,
},
})
```

## System Buttons

### Implementing Close/Minimise/Maximise
Expand Down Expand Up @@ -358,6 +511,7 @@ body {
// Trigger Windows 11 Snap Assist
window.SnapAssist()
```
This triggers Snap Layouts through the Windows hotkey path. For a custom HTML maximize button with native hover Snap Layouts, use [Native Non-Client Regions on Windows](#native-non-client-regions-on-windows) instead.

**Custom title bar height:**
Windows automatically detects drag regions from CSS.
Expand Down
22 changes: 22 additions & 0 deletions docs/src/content/docs/features/windows/options.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -859,6 +859,8 @@ Windows: application.WindowsWindow{
BackdropType: application.Auto,
CustomTheme: application.ThemeSettings{},
DisableFramelessWindowDecorations: false,
NonClientRegionSupport: false,
WebView2CompositionHosting: false,
},
```

Expand All @@ -880,6 +882,15 @@ There are no `WindowsBackdropTypeMica`-style constants — use `application.Mica
**DisableFramelessWindowDecorations** (`bool`)
- Disable default frameless decorations (Aero shadow, rounded corners).

**NonClientRegionSupport** (`bool`)
- Enables WebView2-native `app-region: drag` / `app-region: no-drag` support for frameless custom title bars.
- This is for simple native app dragging only. It does not provide native custom caption-button behavior or Windows 11 Snap Assist / Snap Layouts for custom maximize buttons.

**WebView2CompositionHosting** (`bool`)
- Enables Wails-managed `--wails-app-region` support for custom caption buttons with native Windows behavior, including Windows 11 Snap Assist / Snap Layouts on custom maximize buttons.
- Experimental. This hosts WebView2 through `ICoreWebView2CompositionController` and DirectComposition instead of the default HWND-hosted controller.
- Can be combined with `NonClientRegionSupport` when a window needs both WebView2-native `app-region` support and Wails-managed custom caption-button regions.

**Example:**

```go
Expand All @@ -889,6 +900,17 @@ Windows: application.WindowsWindow{
},
```

**Example - Custom Windows title bar regions:**

```go
Windows: application.WindowsWindow{
NonClientRegionSupport: true,
WebView2CompositionHosting: true,
},
```

See [Frameless Windows](/features/windows/frameless#native-non-client-regions-on-windows) for the detailed behavior, tradeoffs, and matching CSS.

### Linux Options (per-window)

The per-window struct is `application.LinuxWindow` — **not** `LinuxOptions`.
Expand Down
1 change: 1 addition & 0 deletions v3/internal/runtime/desktop/@wailsio/runtime/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
],
"sideEffects": [
"./dist/index.js",
"./dist/appregion.js",
"./dist/contextmenu.js",
"./dist/drag.js"
],
Expand Down
Loading