Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 5 additions & 0 deletions .changes/windows-native-window-occlusion.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"wry": minor
---

Add `WebViewBuilderExtWindows::with_native_window_occlusion` to optionally disable WebView2's native window occlusion detection, so a webview keeps rendering while its window is hidden or occluded. Useful for apps that pre-create and show/hide multiple webviews.
28 changes: 28 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1671,6 +1671,7 @@ pub(crate) struct PlatformSpecificWebViewAttributes {
default_context_menus: bool,
environment: Option<ICoreWebView2Environment>,
profile_name: Option<String>,
native_window_occlusion: bool,
}

#[cfg(windows)]
Expand All @@ -1687,6 +1688,7 @@ impl Default for PlatformSpecificWebViewAttributes {
extension_path: None,
environment: None,
profile_name: None,
native_window_occlusion: true, // This is WebView2's default behavior
}
}
}
Expand Down Expand Up @@ -1784,6 +1786,27 @@ pub trait WebViewBuilderExtWindows {
/// Profile names must follow the WebView2 naming rules (alphanumeric, `.`,
/// `_`, `-`, ` `, up to 64 chars, not starting/ending with `.` or ` `).
fn with_profile_name<S: Into<String>>(self, name: S) -> Self;

/// Determines whether WebView2's native window occlusion detection is enabled.
///
/// The default value is `true`, which matches WebView2's default behavior: when the
/// webview's window is fully covered by other windows, or hidden, WebView2 may stop
/// rendering it to save resources (the `CalculateNativeWinOcclusion` feature).
///
/// Setting this to `false` disables that detection so a webview keeps rendering even
/// while its window is hidden or occluded. This is useful for apps that pre-create
/// several webviews and show/hide them on demand (e.g. a tabbed/multi-service shell):
/// with occlusion enabled, a webview created while hidden may never initialize its
/// render surface and paints blank when first shown.
///
/// See <https://github.com/MicrosoftEdge/WebView2Feedback/issues/1077> and
/// <https://github.com/tauri-apps/tauri/issues/9798>.
///
/// ## Warning
///
/// This has no effect if [`with_additional_browser_args`](Self::with_additional_browser_args)
/// is also used, since that fully overrides the browser arguments wry passes by default.
fn with_native_window_occlusion(self, enabled: bool) -> Self;
}

#[cfg(windows)]
Expand Down Expand Up @@ -1837,6 +1860,11 @@ impl WebViewBuilderExtWindows for WebViewBuilder<'_> {
self.platform_specific.profile_name = Some(name.into());
self
}

fn with_native_window_occlusion(mut self, enabled: bool) -> Self {
self.platform_specific.native_window_occlusion = enabled;
self
}
}

#[cfg(target_os = "android")]
Expand Down
11 changes: 9 additions & 2 deletions src/webview2/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -297,11 +297,18 @@ impl InnerWebView {
.map(HSTRING::from);

// additional browser args
let native_window_occlusion = pl_attrs.native_window_occlusion;
let additional_browser_args = pl_attrs.additional_browser_args.unwrap_or_else(|| {
// remove "mini menu" - See https://github.com/tauri-apps/wry/issues/535
// and "smart screen" - See https://github.com/tauri-apps/tauri/issues/1345
let default_args = "--disable-features=msWebOOUI,msPdfOOUI,msSmartScreenProtection";
let mut arguments = String::from(default_args);
let mut disabled_features =
String::from("--disable-features=msWebOOUI,msPdfOOUI,msSmartScreenProtection");
// optionally disable native window occlusion so webviews keep rendering while
// their window is hidden/occluded - See https://github.com/tauri-apps/tauri/issues/9798
if !native_window_occlusion {
disabled_features.push_str(",CalculateNativeWinOcclusion");
}
let mut arguments = disabled_features;

if attributes.autoplay {
arguments.push_str(" --autoplay-policy=no-user-gesture-required");
Expand Down