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