diff --git a/v2/internal/frontend/desktop/darwin/Application.h b/v2/internal/frontend/desktop/darwin/Application.h
index 2582eb6e8..4d8bbd37b 100644
--- a/v2/internal/frontend/desktop/darwin/Application.h
+++ b/v2/internal/frontend/desktop/darwin/Application.h
@@ -17,7 +17,7 @@
#define WindowStartsMinimised 2
#define WindowStartsFullscreen 3
-WailsContext* Create(const char* title, int width, int height, int frameless, int resizable, int zoomable, int fullscreen, int fullSizeContent, int hideTitleBar, int titlebarAppearsTransparent, int hideTitle, int useToolbar, int hideToolbarSeparator, int webviewIsTransparent, int alwaysOnTop, int hideWindowOnClose, const char *appearance, int windowIsTranslucent, int devtoolsEnabled, int defaultContextMenuEnabled, int windowStartState, int startsHidden, int minWidth, int minHeight, int maxWidth, int maxHeight, bool fraudulentWebsiteWarningEnabled, struct Preferences preferences, int singleInstanceEnabled, const char* singleInstanceUniqueId, bool enableDragAndDrop, bool disableWebViewDragAndDrop);
+WailsContext* Create(const char* title, int width, int height, int frameless, int resizable, int zoomable, int fullscreen, int fullSizeContent, int hideTitleBar, int titlebarAppearsTransparent, int hideTitle, int useToolbar, int hideToolbarSeparator, int webviewIsTransparent, int alwaysOnTop, int hideWindowOnClose, const char *appearance, int windowIsTranslucent, int contentProtection, int devtoolsEnabled, int defaultContextMenuEnabled, int windowStartState, int startsHidden, int minWidth, int minHeight, int maxWidth, int maxHeight, bool fraudulentWebsiteWarningEnabled, struct Preferences preferences, int singleInstanceLockEnabled, const char* singleInstanceUniqueId, bool enableDragAndDrop, bool disableWebViewDragAndDrop);
void Run(void*, const char* url);
void SetTitle(void* ctx, const char *title);
diff --git a/v2/internal/frontend/desktop/darwin/Application.m b/v2/internal/frontend/desktop/darwin/Application.m
index 941e6e922..38d349c2c 100644
--- a/v2/internal/frontend/desktop/darwin/Application.m
+++ b/v2/internal/frontend/desktop/darwin/Application.m
@@ -14,7 +14,7 @@
#import "WailsMenu.h"
#import "WailsMenuItem.h"
-WailsContext* Create(const char* title, int width, int height, int frameless, int resizable, int zoomable, int fullscreen, int fullSizeContent, int hideTitleBar, int titlebarAppearsTransparent, int hideTitle, int useToolbar, int hideToolbarSeparator, int webviewIsTransparent, int alwaysOnTop, int hideWindowOnClose, const char *appearance, int windowIsTranslucent, int devtoolsEnabled, int defaultContextMenuEnabled, int windowStartState, int startsHidden, int minWidth, int minHeight, int maxWidth, int maxHeight, bool fraudulentWebsiteWarningEnabled, struct Preferences preferences, int singleInstanceLockEnabled, const char* singleInstanceUniqueId, bool enableDragAndDrop, bool disableWebViewDragAndDrop) {
+WailsContext* Create(const char* title, int width, int height, int frameless, int resizable, int zoomable, int fullscreen, int fullSizeContent, int hideTitleBar, int titlebarAppearsTransparent, int hideTitle, int useToolbar, int hideToolbarSeparator, int webviewIsTransparent, int alwaysOnTop, int hideWindowOnClose, const char *appearance, int windowIsTranslucent, int contentProtection, int devtoolsEnabled, int defaultContextMenuEnabled, int windowStartState, int startsHidden, int minWidth, int minHeight, int maxWidth, int maxHeight, bool fraudulentWebsiteWarningEnabled, struct Preferences preferences, int singleInstanceLockEnabled, const char* singleInstanceUniqueId, bool enableDragAndDrop, bool disableWebViewDragAndDrop) {
[NSApplication sharedApplication];
@@ -31,6 +31,11 @@ WailsContext* Create(const char* title, int width, int height, int frameless, in
[result SetTitle:safeInit(title)];
[result Center];
+ if (contentProtection == 1 &&
+ [result.mainWindow respondsToSelector:@selector(setSharingType:)]) {
+ [result.mainWindow setSharingType:NSWindowSharingNone];
+ }
+
switch( windowStartState ) {
case WindowStartsMaximised:
[result.mainWindow zoom:nil];
diff --git a/v2/internal/frontend/desktop/darwin/window.go b/v2/internal/frontend/desktop/darwin/window.go
index 04b9f888d..87d4213d9 100644
--- a/v2/internal/frontend/desktop/darwin/window.go
+++ b/v2/internal/frontend/desktop/darwin/window.go
@@ -63,7 +63,7 @@ func NewWindow(frontendOptions *options.App, debug bool, devtools bool) *Window
singleInstanceEnabled := bool2Cint(frontendOptions.SingleInstanceLock != nil)
var fullSizeContent, hideTitleBar, zoomable, hideTitle, useToolbar, webviewIsTransparent C.int
- var titlebarAppearsTransparent, hideToolbarSeparator, windowIsTranslucent C.int
+ var titlebarAppearsTransparent, hideToolbarSeparator, windowIsTranslucent, contentProtection C.int
var appearance, title *C.char
var preferences C.struct_Preferences
@@ -117,12 +117,13 @@ func NewWindow(frontendOptions *options.App, debug bool, devtools bool) *Window
windowIsTranslucent = bool2Cint(mac.WindowIsTranslucent)
webviewIsTransparent = bool2Cint(mac.WebviewIsTransparent)
+ contentProtection = bool2Cint(mac.ContentProtection)
appearance = c.String(string(mac.Appearance))
}
var context *C.WailsContext = C.Create(title, width, height, frameless, resizable, zoomable, fullscreen, fullSizeContent,
hideTitleBar, titlebarAppearsTransparent, hideTitle, useToolbar, hideToolbarSeparator, webviewIsTransparent,
- alwaysOnTop, hideWindowOnClose, appearance, windowIsTranslucent, devtoolsEnabled, defaultContextMenuEnabled,
+ alwaysOnTop, hideWindowOnClose, appearance, windowIsTranslucent, contentProtection, devtoolsEnabled, defaultContextMenuEnabled,
windowStartState, startsHidden, minWidth, minHeight, maxWidth, maxHeight, enableFraudulentWebsiteWarnings,
preferences, singleInstanceEnabled, singleInstanceUniqueId, enableDragAndDrop, disableWebViewDragAndDrop,
)
diff --git a/v2/internal/frontend/desktop/windows/winc/controlbase.go b/v2/internal/frontend/desktop/windows/winc/controlbase.go
index 39b92d5a7..cdb29518c 100644
--- a/v2/internal/frontend/desktop/windows/winc/controlbase.go
+++ b/v2/internal/frontend/desktop/windows/winc/controlbase.go
@@ -170,6 +170,14 @@ func (cba *ControlBase) SetTranslucentBackground() {
w32.SetWindowCompositionAttribute(cba.hwnd, &data)
}
+func (cba *ControlBase) SetContentProtection(enable bool) {
+ if enable {
+ w32.SetWindowDisplayAffinity(uintptr(cba.hwnd), w32.WDA_EXCLUDEFROMCAPTURE)
+ } else {
+ w32.SetWindowDisplayAffinity(uintptr(cba.hwnd), w32.WDA_NONE)
+ }
+}
+
func min(a, b int) int {
if a < b {
return a
diff --git a/v2/internal/frontend/desktop/windows/winc/w32/wda.go b/v2/internal/frontend/desktop/windows/winc/w32/wda.go
new file mode 100644
index 000000000..3925f2805
--- /dev/null
+++ b/v2/internal/frontend/desktop/windows/winc/w32/wda.go
@@ -0,0 +1,47 @@
+//go:build windows
+
+package w32
+
+import (
+ "syscall"
+
+ "github.com/wailsapp/wails/v2/internal/system/operatingsystem"
+)
+
+var user32 = syscall.NewLazyDLL("user32.dll")
+var procSetWindowDisplayAffinity = user32.NewProc("SetWindowDisplayAffinity")
+var windowsVersion, _ = operatingsystem.GetWindowsVersionInfo()
+
+const (
+ WDA_NONE = 0x00000000
+ WDA_MONITOR = 0x00000001
+ WDA_EXCLUDEFROMCAPTURE = 0x00000011 // windows 10 2004+
+)
+
+func isWindowsVersionAtLeast(major, minor, build int) bool {
+ if windowsVersion.Major > major {
+ return true
+ }
+ if windowsVersion.Major < major {
+ return false
+ }
+ if windowsVersion.Minor > minor {
+ return true
+ }
+ if windowsVersion.Minor < minor {
+ return false
+ }
+ return windowsVersion.Build >= build
+}
+
+func SetWindowDisplayAffinity(hwnd uintptr, affinity uint32) bool {
+ if affinity == WDA_EXCLUDEFROMCAPTURE && !isWindowsVersionAtLeast(10, 0, 19041) {
+ // for older windows versions, use WDA_MONITOR
+ affinity = WDA_MONITOR
+ }
+ ret, _, _ := procSetWindowDisplayAffinity.Call(
+ hwnd,
+ uintptr(affinity),
+ )
+ return ret != 0
+}
diff --git a/v2/internal/frontend/desktop/windows/window.go b/v2/internal/frontend/desktop/windows/window.go
index 19ea9db26..b04d61814 100644
--- a/v2/internal/frontend/desktop/windows/window.go
+++ b/v2/internal/frontend/desktop/windows/window.go
@@ -131,6 +131,10 @@ func NewWindow(parent winc.Controller, appoptions *options.App, versionInfo *ope
}
}
+ if windowsOptions.ContentProtection {
+ w32.SetWindowDisplayAffinity(result.Handle(), w32.WDA_EXCLUDEFROMCAPTURE)
+ }
+
if windowsOptions.DisableWindowIcon {
result.DisableIcon()
}
diff --git a/v2/pkg/options/mac/mac.go b/v2/pkg/options/mac/mac.go
index 85e52755b..152145114 100644
--- a/v2/pkg/options/mac/mac.go
+++ b/v2/pkg/options/mac/mac.go
@@ -18,6 +18,7 @@ type AboutInfo struct {
type Options struct {
TitleBar *TitleBar
Appearance AppearanceType
+ ContentProtection bool
WebviewIsTransparent bool
WindowIsTranslucent bool
Preferences *Preferences
diff --git a/v2/pkg/options/windows/windows.go b/v2/pkg/options/windows/windows.go
index 8f3bce44a..aa065ecd9 100644
--- a/v2/pkg/options/windows/windows.go
+++ b/v2/pkg/options/windows/windows.go
@@ -61,6 +61,7 @@ type ThemeSettings struct {
// Options are options specific to Windows
type Options struct {
+ ContentProtection bool
WebviewIsTransparent bool
WindowIsTranslucent bool
DisableWindowIcon bool
diff --git a/website/docs/reference/options.mdx b/website/docs/reference/options.mdx
index 9d999f421..fae89c085 100644
--- a/website/docs/reference/options.mdx
+++ b/website/docs/reference/options.mdx
@@ -73,8 +73,9 @@ func main() {
Windows: &windows.Options{
WebviewIsTransparent: false,
WindowIsTranslucent: false,
+ ContentProtection: false,
BackdropType: windows.Mica,
- DisablePinchZoom: false,
+ DisablePinchZoom: false,
DisableWindowIcon: false,
DisableFramelessWindowDecorations: false,
WebviewUserDataPath: "",
@@ -117,6 +118,7 @@ func main() {
Appearance: mac.NSAppearanceNameDarkAqua,
WebviewIsTransparent: true,
WindowIsTranslucent: false,
+ ContentProtection: false,
About: &mac.AboutInfo{
Title: "My Application",
Message: "© 2021 Me",
@@ -613,6 +615,17 @@ by Windows. To configure this, use the [BackdropType](#BackdropType) option.
Name: WindowIsTranslucent
Type: `bool`
+#### ContentProtection
+
+Prevents window contents from being captured by other applications.
+
+On Windows it calls SetWindowDisplayAffinity with `WDA_EXCLUDEFROMCAPTURE`.
+For Windows 10 version 2004 and later the window will be completely removed from capture.
+Older Windows versions will call SetWindowDisplayAffinity with `WDA_MONITOR`, capturing a black window.
+
+Name: ContentProtection
+Type: `bool`
+
#### BackdropType
:::note
@@ -923,6 +936,15 @@ with [WebviewIsTransparent](#WebviewIsTransparent) to make frosty-looking applic
Name: WindowIsTranslucent
Type: `bool`
+#### ContentProtection
+
+Prevents window contents from being captured by other applications.
+
+On MacOS it sets the NSWindow's sharingType to NSWindowSharingNone, removing the window from capture entirely.
+
+Name: ContentProtection
+Type: `bool`
+
#### OnFileOpen
Callback that is called when a file is opened with the application.
diff --git a/website/src/pages/changelog.mdx b/website/src/pages/changelog.mdx
index d077b6c2d..2a7ab13d3 100644
--- a/website/src/pages/changelog.mdx
+++ b/website/src/pages/changelog.mdx
@@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- Configure Vite timeout by @leaanthony in [PR](https://github.com/wailsapp/wails/pull/4374)
+- Added `ContentProtection` option to allow hiding the application window from screen sharing software [#4241](https://github.com/wailsapp/wails/pull/4241) by [@Taiterbase](https://github.com/Taiterbase)
## v2.10.2 - 2025-07-06