From 762a4a70f889dacd32d22e49a5ff5fb62b44aa8d Mon Sep 17 00:00:00 2001 From: Heitor Faria Date: Sun, 31 May 2026 13:28:39 -0400 Subject: [PATCH] feat(webview2): add with_native_window_occlusion option Allow disabling WebView2's native window occlusion detection (CalculateNativeWinOcclusion) so a webview keeps rendering while its window is hidden or occluded. Webviews created while hidden otherwise may never bring up their render surface and paint blank when first shown, which breaks apps that pre-create and show/hide multiple webviews (tabbed/multi-service shells). Defaults to true (current WebView2 behavior); opt out via WebViewBuilderExtWindows::with_native_window_occlusion(false). Refs: tauri-apps/tauri#9798, MicrosoftEdge/WebView2Feedback#1077 --- .changes/windows-native-window-occlusion.md | 5 ++++ src/lib.rs | 28 +++++++++++++++++++++ src/webview2/mod.rs | 11 ++++++-- 3 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 .changes/windows-native-window-occlusion.md diff --git a/.changes/windows-native-window-occlusion.md b/.changes/windows-native-window-occlusion.md new file mode 100644 index 000000000..7624b494e --- /dev/null +++ b/.changes/windows-native-window-occlusion.md @@ -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. diff --git a/src/lib.rs b/src/lib.rs index 1a8664ae1..40ebd21fe 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1671,6 +1671,7 @@ pub(crate) struct PlatformSpecificWebViewAttributes { default_context_menus: bool, environment: Option, profile_name: Option, + native_window_occlusion: bool, } #[cfg(windows)] @@ -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 } } } @@ -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>(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 and + /// . + /// + /// ## 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)] @@ -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")] diff --git a/src/webview2/mod.rs b/src/webview2/mod.rs index c9330c9be..f0c7be6dc 100644 --- a/src/webview2/mod.rs +++ b/src/webview2/mod.rs @@ -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");