Content Privacy flag for Windows and MacOS (#4241)

* feat(options): add ContentProtection bool config to macos and windows options

* feat(darwin): implement ContentProtection for darwin

* feat(windows): implement ContentProtection for windows

* chore(website): add feature to changelog

* feat(examples): add an example showcasing the ContentPrivacy flag

* chore(examples): update readme

* fix(example): format and build

* fix(winc): rename to wda and add version check

* chore(reference): add docs for ContentProtection

* fix(darwin): future-proof setting the sharing type

* fix(example): wording consistency

* chore(examples): remove privatewindow example

---------

Co-authored-by: Lea Anthony <lea.anthony@gmail.com>
This commit is contained in:
Taite Nazifi 2025-07-18 23:58:34 -07:00 committed by GitHub
commit 7002f2e943
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 95 additions and 5 deletions

View file

@ -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);

View file

@ -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];

View file

@ -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,
)

View file

@ -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

View file

@ -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
}

View file

@ -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()
}

View file

@ -18,6 +18,7 @@ type AboutInfo struct {
type Options struct {
TitleBar *TitleBar
Appearance AppearanceType
ContentProtection bool
WebviewIsTransparent bool
WindowIsTranslucent bool
Preferences *Preferences

View file

@ -61,6 +61,7 @@ type ThemeSettings struct {
// Options are options specific to Windows
type Options struct {
ContentProtection bool
WebviewIsTransparent bool
WindowIsTranslucent bool
DisableWindowIcon bool