diff --git a/.changes/macos-private-api-split.md b/.changes/macos-private-api-split.md new file mode 100644 index 000000000000..9b64b0b96ab4 --- /dev/null +++ b/.changes/macos-private-api-split.md @@ -0,0 +1,8 @@ +--- +"tauri": "minor:feat" +"tauri-runtime": "minor:feat" +"tauri-runtime-wry": "minor:feat" +"tauri-utils": "minor:feat" +--- + +Added the `app > privateApiFullscreen` and `app > privateApiTransparent` configuration options to opt into the macOS WKWebView fullscreen API and transparent webview backgrounds independently, along with matching `macos-private-api-fullscreen` and `macos-private-api-transparent` Cargo features. The existing `macOSPrivateApi` flag is now deprecated but keeps working and enables both capabilities. diff --git a/crates/tauri-cli/config.schema.json b/crates/tauri-cli/config.schema.json index f62f28ee4ddd..87c4d744b2b4 100644 --- a/crates/tauri-cli/config.schema.json +++ b/crates/tauri-cli/config.schema.json @@ -46,6 +46,8 @@ "default": { "enableGTKAppId": false, "macOSPrivateApi": false, + "privateApiFullscreen": false, + "privateApiTransparent": false, "security": { "assetProtocol": { "enable": false, @@ -209,7 +211,18 @@ ] }, "macOSPrivateApi": { - "description": "MacOS private API configuration. Enables the transparent background API and sets the `fullScreenEnabled` preference to `true`.", + "description": "Deprecated: use [`AppConfig::private_api_fullscreen`] and/or [`AppConfig::private_api_transparent`] instead.\n\n MacOS private API configuration. Enables the transparent background API and sets the `fullScreenEnabled` preference to `true`.\n\n This is an umbrella that opts into both capabilities at once. Prefer the granular\n `privateApiFullscreen` / `privateApiTransparent` keys so you only enable what you need.", + "default": false, + "deprecated": true, + "type": "boolean" + }, + "privateApiFullscreen": { + "description": "Enables the WKWebView fullscreen JavaScript API by setting the `fullScreenEnabled` preference to `true`.\n\n This relies on a macOS private API and is only respected on macOS.", + "default": false, + "type": "boolean" + }, + "privateApiTransparent": { + "description": "Enables transparent webview backgrounds.\n\n This relies on a macOS private API and is only respected on macOS.", "default": false, "type": "boolean" }, diff --git a/crates/tauri-runtime-wry/Cargo.toml b/crates/tauri-runtime-wry/Cargo.toml index 7c576dea5ec2..c63db1292ae8 100644 --- a/crates/tauri-runtime-wry/Cargo.toml +++ b/crates/tauri-runtime-wry/Cargo.toml @@ -62,10 +62,12 @@ jni = "0.21" default = ["x11", "dbus"] devtools = ["wry/devtools", "tauri-runtime/devtools"] x11 = ["tao/x11", "wry/x11"] +macos-private-api-fullscreen = ["wry/fullscreen"] +macos-private-api-transparent = ["wry/transparent", "tauri-runtime/macos-private-api-transparent"] +# Legacy umbrella feature: enables both fullscreen and transparent capabilities. macos-private-api = [ - "wry/fullscreen", - "wry/transparent", - "tauri-runtime/macos-private-api", + "macos-private-api-fullscreen", + "macos-private-api-transparent", ] # TODO: Remove in v3 - wry does not have this feature anymore objc-exception = [] diff --git a/crates/tauri-runtime-wry/src/lib.rs b/crates/tauri-runtime-wry/src/lib.rs index 178ad2ce4905..e8cfdc6c138d 100644 --- a/crates/tauri-runtime-wry/src/lib.rs +++ b/crates/tauri-runtime-wry/src/lib.rs @@ -781,19 +781,19 @@ impl WindowBuilder for WindowBuilderWrapper { } } - #[cfg(any(not(target_os = "macos"), feature = "macos-private-api"))] + #[cfg(any(not(target_os = "macos"), feature = "macos-private-api-transparent"))] { window = window.transparent(config.transparent); } #[cfg(all( target_os = "macos", - not(feature = "macos-private-api"), + not(feature = "macos-private-api-transparent"), debug_assertions ))] if config.transparent { eprintln!( - "The window is set to be transparent but the `macos-private-api` is not enabled. - This can be enabled via the `tauri.macOSPrivateApi` configuration property + "The window is set to be transparent but the transparent background API is not enabled. + This can be enabled via the `app.privateApiTransparent` (or the legacy `app.macOSPrivateApi`) configuration property "); } @@ -1019,7 +1019,7 @@ impl WindowBuilder for WindowBuilderWrapper { self } - #[cfg(any(not(target_os = "macos"), feature = "macos-private-api"))] + #[cfg(any(not(target_os = "macos"), feature = "macos-private-api-transparent"))] fn transparent(mut self, transparent: bool) -> Self { self.inner = self.inner.with_transparent(transparent); self diff --git a/crates/tauri-runtime/Cargo.toml b/crates/tauri-runtime/Cargo.toml index c2c54cccc519..7cf1d4867130 100644 --- a/crates/tauri-runtime/Cargo.toml +++ b/crates/tauri-runtime/Cargo.toml @@ -69,4 +69,6 @@ objc2-web-kit = { version = "0.3", default-features = false, features = [ [features] devtools = [] -macos-private-api = [] +macos-private-api-transparent = [] +# Legacy umbrella feature: kept as an alias for the transparent capability this crate gates. +macos-private-api = ["macos-private-api-transparent"] diff --git a/crates/tauri-runtime/src/webview.rs b/crates/tauri-runtime/src/webview.rs index 61bc15d0366b..d098897026ad 100644 --- a/crates/tauri-runtime/src/webview.rs +++ b/crates/tauri-runtime/src/webview.rs @@ -465,7 +465,7 @@ impl From<&WindowConfig> for WebviewAttributes { .limit_navigations_to_app_bound_domains(config.limit_navigations_to_app_bound_domains) .general_autofill_enabled(config.general_autofill_enabled); - #[cfg(any(not(target_os = "macos"), feature = "macos-private-api"))] + #[cfg(any(not(target_os = "macos"), feature = "macos-private-api-transparent"))] { builder = builder.transparent(config.transparent); } @@ -672,7 +672,7 @@ impl WebviewAttributes { } /// Enable or disable transparency for the WebView. - #[cfg(any(not(target_os = "macos"), feature = "macos-private-api"))] + #[cfg(any(not(target_os = "macos"), feature = "macos-private-api-transparent"))] #[must_use] pub fn transparent(mut self, transparent: bool) -> Self { self.transparent = transparent; diff --git a/crates/tauri-runtime/src/window.rs b/crates/tauri-runtime/src/window.rs index 936280ca18c3..4fc42f140efe 100644 --- a/crates/tauri-runtime/src/window.rs +++ b/crates/tauri-runtime/src/window.rs @@ -366,10 +366,10 @@ pub trait WindowBuilder: WindowBuilderBase { /// /// On Windows, using `no_redirection_bitmap` can help avoid a white flash when /// creating a transparent window. - #[cfg(any(not(target_os = "macos"), feature = "macos-private-api"))] + #[cfg(any(not(target_os = "macos"), feature = "macos-private-api-transparent"))] #[cfg_attr( docsrs, - doc(cfg(any(not(target_os = "macos"), feature = "macos-private-api"))) + doc(cfg(any(not(target_os = "macos"), feature = "macos-private-api-transparent"))) )] #[must_use] fn transparent(self, transparent: bool) -> Self; diff --git a/crates/tauri-schema-generator/schemas/config.schema.json b/crates/tauri-schema-generator/schemas/config.schema.json index f62f28ee4ddd..87c4d744b2b4 100644 --- a/crates/tauri-schema-generator/schemas/config.schema.json +++ b/crates/tauri-schema-generator/schemas/config.schema.json @@ -46,6 +46,8 @@ "default": { "enableGTKAppId": false, "macOSPrivateApi": false, + "privateApiFullscreen": false, + "privateApiTransparent": false, "security": { "assetProtocol": { "enable": false, @@ -209,7 +211,18 @@ ] }, "macOSPrivateApi": { - "description": "MacOS private API configuration. Enables the transparent background API and sets the `fullScreenEnabled` preference to `true`.", + "description": "Deprecated: use [`AppConfig::private_api_fullscreen`] and/or [`AppConfig::private_api_transparent`] instead.\n\n MacOS private API configuration. Enables the transparent background API and sets the `fullScreenEnabled` preference to `true`.\n\n This is an umbrella that opts into both capabilities at once. Prefer the granular\n `privateApiFullscreen` / `privateApiTransparent` keys so you only enable what you need.", + "default": false, + "deprecated": true, + "type": "boolean" + }, + "privateApiFullscreen": { + "description": "Enables the WKWebView fullscreen JavaScript API by setting the `fullScreenEnabled` preference to `true`.\n\n This relies on a macOS private API and is only respected on macOS.", + "default": false, + "type": "boolean" + }, + "privateApiTransparent": { + "description": "Enables transparent webview backgrounds.\n\n This relies on a macOS private API and is only respected on macOS.", "default": false, "type": "boolean" }, diff --git a/crates/tauri-utils/src/config.rs b/crates/tauri-utils/src/config.rs index 4297760ae58b..7a2dc3a1baac 100644 --- a/crates/tauri-utils/src/config.rs +++ b/crates/tauri-utils/src/config.rs @@ -3148,9 +3148,28 @@ pub struct AppConfig { /// Configuration for app tray icon. #[serde(alias = "tray-icon")] pub tray_icon: Option, + /// Deprecated: use [`AppConfig::private_api_fullscreen`] and/or [`AppConfig::private_api_transparent`] instead. + /// /// MacOS private API configuration. Enables the transparent background API and sets the `fullScreenEnabled` preference to `true`. + /// + /// This is an umbrella that opts into both capabilities at once. Prefer the granular + /// `privateApiFullscreen` / `privateApiTransparent` keys so you only enable what you need. + #[deprecated( + since = "2.10.0", + note = "Use `private_api_fullscreen` and/or `private_api_transparent` instead." + )] #[serde(rename = "macOSPrivateApi", alias = "macos-private-api", default)] pub macos_private_api: bool, + /// Enables the WKWebView fullscreen JavaScript API by setting the `fullScreenEnabled` preference to `true`. + /// + /// This relies on a macOS private API and is only respected on macOS. + #[serde(default, alias = "private-api-fullscreen")] + pub private_api_fullscreen: bool, + /// Enables transparent webview backgrounds. + /// + /// This relies on a macOS private API and is only respected on macOS. + #[serde(default, alias = "private-api-transparent")] + pub private_api_transparent: bool, /// Whether we should inject the Tauri API on `window.__TAURI__` or not. #[serde(default, alias = "with-global-tauri")] pub with_global_tauri: bool, @@ -3165,6 +3184,8 @@ impl AppConfig { vec![ "tray-icon", "macos-private-api", + "macos-private-api-fullscreen", + "macos-private-api-transparent", "protocol-asset", "isolation", ] @@ -3176,8 +3197,14 @@ impl AppConfig { if self.tray_icon.is_some() { features.push("tray-icon"); } - if self.macos_private_api { - features.push("macos-private-api"); + // `macOSPrivateApi` is the legacy umbrella that enables both capabilities. + #[allow(deprecated)] + let macos_private_api = self.macos_private_api; + if macos_private_api || self.private_api_fullscreen { + features.push("macos-private-api-fullscreen"); + } + if macos_private_api || self.private_api_transparent { + features.push("macos-private-api-transparent"); } if self.security.asset_protocol.enable { features.push("protocol-asset"); @@ -4497,11 +4524,14 @@ mod build { } impl ToTokens for AppConfig { + #[allow(deprecated)] fn to_tokens(&self, tokens: &mut TokenStream) { let windows = vec_lit(&self.windows, identity); let security = &self.security; let tray_icon = opt_lit(self.tray_icon.as_ref()); let macos_private_api = self.macos_private_api; + let private_api_fullscreen = self.private_api_fullscreen; + let private_api_transparent = self.private_api_transparent; let with_global_tauri = self.with_global_tauri; let enable_gtk_app_id = self.enable_gtk_app_id; @@ -4512,6 +4542,8 @@ mod build { security, tray_icon, macos_private_api, + private_api_fullscreen, + private_api_transparent, with_global_tauri, enable_gtk_app_id ); @@ -4572,6 +4604,7 @@ mod test { #[test] // test all of the default functions + #[allow(deprecated)] fn test_defaults() { // get default app config let a_config = AppConfig::default(); @@ -4597,6 +4630,8 @@ mod test { }, tray_icon: None, macos_private_api: false, + private_api_fullscreen: false, + private_api_transparent: false, with_global_tauri: false, enable_gtk_app_id: false, }; diff --git a/crates/tauri/Cargo.toml b/crates/tauri/Cargo.toml index 3f1dd5f82e2d..c1e219204764 100644 --- a/crates/tauri/Cargo.toml +++ b/crates/tauri/Cargo.toml @@ -220,9 +220,15 @@ devtools = ["tauri-runtime/devtools", "tauri-runtime-wry?/devtools"] process-relaunch-dangerous-allow-symlink-macos = [ "tauri-utils/process-relaunch-dangerous-allow-symlink-macos", ] -macos-private-api = [ +macos-private-api-fullscreen = ["tauri-runtime-wry?/macos-private-api-fullscreen"] +macos-private-api-transparent = [ "tauri-runtime/macos-private-api", - "tauri-runtime-wry?/macos-private-api", + "tauri-runtime-wry?/macos-private-api-transparent", +] +# Legacy umbrella feature: enables both fullscreen and transparent capabilities. +macos-private-api = [ + "macos-private-api-fullscreen", + "macos-private-api-transparent", ] webview-data-url = ["data-url", "tauri-utils/html-manipulation-2"] protocol-asset = ["http-range"] diff --git a/crates/tauri/src/lib.rs b/crates/tauri/src/lib.rs index de6944ce24f2..4d2b99057233 100644 --- a/crates/tauri/src/lib.rs +++ b/crates/tauri/src/lib.rs @@ -28,7 +28,9 @@ //! - **rustls-tls**: Provides TLS support to connect over HTTPS using rustls. //! - **process-relaunch-dangerous-allow-symlink-macos**: Allows the [`process::current_binary`] function to allow symlinks on macOS (this is dangerous, see the Security section in the documentation website). //! - **tray-icon**: Enables application tray icon APIs. Enabled by default if the `trayIcon` config is defined on the `tauri.conf.json` file. -//! - **macos-private-api**: Enables features only available in **macOS**'s private APIs, currently the `transparent` window functionality and the `fullScreenEnabled` preference setting to `true`. Enabled by default if the `tauri > macosPrivateApi` config flag is set to `true` on the `tauri.conf.json` file. +//! - **macos-private-api**: Enables features only available in **macOS**'s private APIs, currently the `transparent` window functionality and the `fullScreenEnabled` preference setting to `true`. Enabled by default if the `tauri > macosPrivateApi` config flag is set to `true` on the `tauri.conf.json` file. This is an umbrella that enables both `macos-private-api-fullscreen` and `macos-private-api-transparent`. +//! - **macos-private-api-fullscreen**: Enables only the **macOS** `fullScreenEnabled` preference private API, without the transparent window functionality. Enabled by default if the `app > privateApiFullscreen` config flag is set to `true` on the `tauri.conf.json` file. +//! - **macos-private-api-transparent**: Enables only the **macOS** `transparent` window private API, without the `fullScreenEnabled` preference. Enabled by default if the `app > privateApiTransparent` config flag is set to `true` on the `tauri.conf.json` file. //! - **webview-data-url**: Enables usage of data URLs on the webview. //! - **compression** *(enabled by default): Enables asset compression. You should only disable this if you want faster compile times in release builds - it produces larger binaries. //! - **config-json5**: Adds support to JSON5 format for `tauri.conf.json`. diff --git a/crates/tauri/src/test/mock_runtime.rs b/crates/tauri/src/test/mock_runtime.rs index a1f4c88745c9..06e1cc151574 100644 --- a/crates/tauri/src/test/mock_runtime.rs +++ b/crates/tauri/src/test/mock_runtime.rs @@ -432,10 +432,10 @@ impl WindowBuilder for MockWindowBuilder { self } - #[cfg(any(not(target_os = "macos"), feature = "macos-private-api"))] + #[cfg(any(not(target_os = "macos"), feature = "macos-private-api-transparent"))] #[cfg_attr( docsrs, - doc(cfg(any(not(target_os = "macos"), feature = "macos-private-api"))) + doc(cfg(any(not(target_os = "macos"), feature = "macos-private-api-transparent"))) )] fn transparent(self, transparent: bool) -> Self { self diff --git a/crates/tauri/src/test/mod.rs b/crates/tauri/src/test/mod.rs index a1428c390127..e17b1376d5f8 100644 --- a/crates/tauri/src/test/mod.rs +++ b/crates/tauri/src/test/mod.rs @@ -106,6 +106,7 @@ pub fn noop_assets() -> NoopAsset { } /// Creates a new [`crate::Context`] for testing. +#[allow(deprecated)] pub fn mock_context>(assets: A) -> crate::Context { Context { config: Config { @@ -120,6 +121,8 @@ pub fn mock_context>(assets: A) -> crate::Context { security: Default::default(), tray_icon: None, macos_private_api: false, + private_api_fullscreen: false, + private_api_transparent: false, enable_gtk_app_id: false, }, bundle: Default::default(), diff --git a/crates/tauri/src/webview/mod.rs b/crates/tauri/src/webview/mod.rs index a56ba676371a..90e63116a130 100644 --- a/crates/tauri/src/webview/mod.rs +++ b/crates/tauri/src/webview/mod.rs @@ -1015,10 +1015,10 @@ fn main() { } /// Enable or disable transparency for the WebView. - #[cfg(any(not(target_os = "macos"), feature = "macos-private-api"))] + #[cfg(any(not(target_os = "macos"), feature = "macos-private-api-transparent"))] #[cfg_attr( docsrs, - doc(cfg(any(not(target_os = "macos"), feature = "macos-private-api"))) + doc(cfg(any(not(target_os = "macos"), feature = "macos-private-api-transparent"))) )] #[must_use] pub fn transparent(mut self, transparent: bool) -> Self { diff --git a/crates/tauri/src/webview/webview_window.rs b/crates/tauri/src/webview/webview_window.rs index dea14ad5e49f..8c3da294592d 100644 --- a/crates/tauri/src/webview/webview_window.rs +++ b/crates/tauri/src/webview/webview_window.rs @@ -1089,10 +1089,10 @@ impl> WebviewWindowBuilder<'_, R, M> { /// /// On Windows, using `no_redirection_bitmap` can help avoid a white flash when /// creating a transparent window. - #[cfg(any(not(target_os = "macos"), feature = "macos-private-api"))] + #[cfg(any(not(target_os = "macos"), feature = "macos-private-api-transparent"))] #[cfg_attr( docsrs, - doc(cfg(any(not(target_os = "macos"), feature = "macos-private-api"))) + doc(cfg(any(not(target_os = "macos"), feature = "macos-private-api-transparent"))) )] #[must_use] pub fn transparent(mut self, transparent: bool) -> Self { diff --git a/crates/tauri/src/window/mod.rs b/crates/tauri/src/window/mod.rs index 8d6309b20747..6471a20d1103 100644 --- a/crates/tauri/src/window/mod.rs +++ b/crates/tauri/src/window/mod.rs @@ -919,10 +919,10 @@ impl<'a, R: Runtime, M: Manager> WindowBuilder<'a, R, M> { /// /// On Windows, using `no_redirection_bitmap` can help avoid a white flash when /// creating a transparent window. - #[cfg(any(not(target_os = "macos"), feature = "macos-private-api"))] + #[cfg(any(not(target_os = "macos"), feature = "macos-private-api-transparent"))] #[cfg_attr( docsrs, - doc(cfg(any(not(target_os = "macos"), feature = "macos-private-api"))) + doc(cfg(any(not(target_os = "macos"), feature = "macos-private-api-transparent"))) )] #[must_use] pub fn transparent(mut self, transparent: bool) -> Self {