diff --git a/.changes/visionos.md b/.changes/visionos.md new file mode 100644 index 000000000..b9427a2e8 --- /dev/null +++ b/.changes/visionos.md @@ -0,0 +1,5 @@ +--- +"wry": patch +--- + +Added visionOS support based on https://github.com/rust-lang/rust/pull/121419 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2bb62cf5c..1a46fb603 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -16,17 +16,25 @@ jobs: - { target: x86_64-unknown-linux-gnu, os: ubuntu-latest } - { target: x86_64-apple-darwin, os: macos-latest } - { target: aarch64-apple-ios, os: macos-latest } + - { target: aarch64-apple-visionos, os: macos-latest } - { target: aarch64-apple-darwin, os: macos-14 } - { target: aarch64-linux-android, os: ubuntu-latest } runs-on: ${{ matrix.platform.os }} steps: + # - uses: actions/checkout@v4 + # - name: install stable + # uses: dtolnay/rust-toolchain@stable + # with: + # targets: ${{ matrix.platform.target }} - uses: actions/checkout@v4 - - name: install stable - uses: dtolnay/rust-toolchain@stable + - name: install nightly + uses: dtolnay/rust-toolchain@nightly with: + profile: minimal targets: ${{ matrix.platform.target }} + # components: rust-src, miri - name: install webkit2gtk (ubuntu only) if: contains(matrix.platform.target, 'gnu') @@ -44,7 +52,7 @@ jobs: - uses: Swatinem/rust-cache@v2 - name: build wry - run: cargo build --target ${{ matrix.platform.target }} --all-features + run: cargo +nightly build -Z build-std=std,panic_abort --target ${{ matrix.platform.target }} --all-features - name: build tests and examples shell: bash @@ -55,15 +63,17 @@ jobs: if: (!contains(matrix.platform.target, 'android') && !contains(matrix.platform.target, 'ios')) run: cargo test --verbose --target ${{ matrix.platform.target }} --features linux-body - - name: install nightly - uses: dtolnay/rust-toolchain@nightly - with: - targets: ${{ matrix.platform.target }} - components: miri + # - name: install nightly + # uses: dtolnay/rust-toolchain@nightly + # with: + # targets: ${{ matrix.platform.target }} + # components: miri - name: Run tests with miri if: (!contains(matrix.platform.target, 'android') && !contains(matrix.platform.target, 'ios')) - run: cargo +nightly miri test --verbose --target ${{ matrix.platform.target }} --features linux-body + run: | + rustup +nightly component add miri + cargo +nightly -Z build-std=std,panic_abort miri test --verbose --target ${{ matrix.platform.target }} --features linux-body doc: runs-on: ubuntu-latest diff --git a/Cargo.toml b/Cargo.toml index 1e50bd2b2..307632611 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -90,7 +90,7 @@ dunce = "1" "Win32_UI_Input_KeyboardAndMouse" ] -[target."cfg(any(target_os = \"ios\", target_os = \"macos\"))".dependencies] +[target."cfg(any(target_os = \"ios\", target_os = \"visionos\", target_os = \"macos\"))".dependencies] block = "0.1" cocoa = "0.25" core-graphics = "0.23" diff --git a/bench/tests/src/cpu_intensive.rs b/bench/tests/src/cpu_intensive.rs index 6ddc79d9b..23700e3cc 100644 --- a/bench/tests/src/cpu_intensive.rs +++ b/bench/tests/src/cpu_intensive.rs @@ -28,6 +28,7 @@ fn main() -> wry::Result<()> { target_os = "windows", target_os = "macos", target_os = "ios", + target_os = "visionos", target_os = "android" ))] let builder = WebViewBuilder::new(&window); @@ -36,6 +37,7 @@ fn main() -> wry::Result<()> { target_os = "windows", target_os = "macos", target_os = "ios", + target_os = "visionos", target_os = "android" )))] let builder = { diff --git a/bench/tests/src/custom_protocol.rs b/bench/tests/src/custom_protocol.rs index b7c96db28..cd0bac73f 100644 --- a/bench/tests/src/custom_protocol.rs +++ b/bench/tests/src/custom_protocol.rs @@ -52,6 +52,7 @@ fn main() -> wry::Result<()> { target_os = "windows", target_os = "macos", target_os = "ios", + target_os = "visionos", target_os = "android" ))] let builder = WebViewBuilder::new(&window); @@ -60,6 +61,7 @@ fn main() -> wry::Result<()> { target_os = "windows", target_os = "macos", target_os = "ios", + target_os = "visionos", target_os = "android" )))] let builder = { diff --git a/bench/tests/src/hello_world.rs b/bench/tests/src/hello_world.rs index 452b6dc66..3693beae9 100644 --- a/bench/tests/src/hello_world.rs +++ b/bench/tests/src/hello_world.rs @@ -43,6 +43,7 @@ fn main() -> wry::Result<()> { target_os = "windows", target_os = "macos", target_os = "ios", + target_os = "visionos", target_os = "android" ))] let builder = WebViewBuilder::new(&window); @@ -51,6 +52,7 @@ fn main() -> wry::Result<()> { target_os = "windows", target_os = "macos", target_os = "ios", + target_os = "visionos", target_os = "android" )))] let builder = { diff --git a/build.rs b/build.rs index 712a9e7a9..236a5ce54 100644 --- a/build.rs +++ b/build.rs @@ -4,7 +4,7 @@ fn main() { let target_os = std::env::var("CARGO_CFG_TARGET_OS").unwrap_or_default(); - if target_os == "macos" || target_os == "ios" { + if target_os == "macos" || target_os == "ios" || target_os == "visionos" { println!("cargo:rustc-link-lib=framework=WebKit"); } diff --git a/examples/async_custom_protocol.rs b/examples/async_custom_protocol.rs index 757c5bbd9..fbd88b426 100644 --- a/examples/async_custom_protocol.rs +++ b/examples/async_custom_protocol.rs @@ -22,6 +22,7 @@ fn main() -> wry::Result<()> { target_os = "windows", target_os = "macos", target_os = "ios", + target_os = "visionos", target_os = "android" ))] let builder = WebViewBuilder::new(&window); @@ -30,6 +31,7 @@ fn main() -> wry::Result<()> { target_os = "windows", target_os = "macos", target_os = "ios", + target_os = "visionos", target_os = "android" )))] let builder = { diff --git a/examples/custom_protocol.rs b/examples/custom_protocol.rs index b24adc8a4..2364a6743 100644 --- a/examples/custom_protocol.rs +++ b/examples/custom_protocol.rs @@ -22,6 +22,7 @@ fn main() -> wry::Result<()> { target_os = "windows", target_os = "macos", target_os = "ios", + target_os = "visionos", target_os = "android" ))] let builder = WebViewBuilder::new(&window); @@ -30,6 +31,7 @@ fn main() -> wry::Result<()> { target_os = "windows", target_os = "macos", target_os = "ios", + target_os = "visionos", target_os = "android" )))] let builder = { diff --git a/examples/custom_titlebar.rs b/examples/custom_titlebar.rs index dd3ecbb95..7345659c1 100644 --- a/examples/custom_titlebar.rs +++ b/examples/custom_titlebar.rs @@ -245,6 +245,7 @@ fn main() -> wry::Result<()> { target_os = "windows", target_os = "macos", target_os = "ios", + target_os = "visionos", target_os = "android" ))] let builder = WebViewBuilder::new(&window); @@ -253,6 +254,7 @@ fn main() -> wry::Result<()> { target_os = "windows", target_os = "macos", target_os = "ios", + target_os = "visionos", target_os = "android" )))] let builder = { diff --git a/examples/gtk_multiwebview.rs b/examples/gtk_multiwebview.rs index 6e6533996..2d9cf40bf 100644 --- a/examples/gtk_multiwebview.rs +++ b/examples/gtk_multiwebview.rs @@ -20,6 +20,7 @@ fn main() -> wry::Result<()> { target_os = "windows", target_os = "macos", target_os = "ios", + target_os = "visionos", target_os = "android" )))] let fixed = { @@ -38,6 +39,7 @@ fn main() -> wry::Result<()> { target_os = "windows", target_os = "macos", target_os = "ios", + target_os = "visionos", target_os = "android" ))] return WebViewBuilder::new_as_child(&window); @@ -46,6 +48,7 @@ fn main() -> wry::Result<()> { target_os = "windows", target_os = "macos", target_os = "ios", + target_os = "visionos", target_os = "android" )))] { diff --git a/examples/multiwindow.rs b/examples/multiwindow.rs index 1a95c09a1..af4a06a0f 100644 --- a/examples/multiwindow.rs +++ b/examples/multiwindow.rs @@ -96,6 +96,7 @@ fn create_new_window( target_os = "windows", target_os = "macos", target_os = "ios", + target_os = "visionos", target_os = "android" ))] let builder = WebViewBuilder::new(&window); @@ -104,6 +105,7 @@ fn create_new_window( target_os = "windows", target_os = "macos", target_os = "ios", + target_os = "visionos", target_os = "android" )))] let builder = { diff --git a/examples/reparent.rs b/examples/reparent.rs index 3bb2649a9..f54127fc0 100644 --- a/examples/reparent.rs +++ b/examples/reparent.rs @@ -19,12 +19,14 @@ use {tao::platform::windows::WindowExtWindows, wry::WebViewExtWindows}; target_os = "windows", target_os = "macos", target_os = "ios", + target_os = "visionos", target_os = "android" )))] #[cfg(not(any( target_os = "windows", target_os = "macos", target_os = "ios", + target_os = "visionos", target_os = "android" )))] use { @@ -41,6 +43,7 @@ fn main() -> wry::Result<()> { target_os = "windows", target_os = "macos", target_os = "ios", + target_os = "visionos", target_os = "android" ))] let builder = WebViewBuilder::new(&window); @@ -49,6 +52,7 @@ fn main() -> wry::Result<()> { target_os = "windows", target_os = "macos", target_os = "ios", + target_os = "visionos", target_os = "android" )))] let builder = { @@ -97,6 +101,7 @@ fn main() -> wry::Result<()> { target_os = "windows", target_os = "macos", target_os = "ios", + target_os = "visionos", target_os = "android" )))] webview diff --git a/examples/simple.rs b/examples/simple.rs index 5528e41b9..791a8da91 100644 --- a/examples/simple.rs +++ b/examples/simple.rs @@ -17,6 +17,7 @@ fn main() -> wry::Result<()> { target_os = "windows", target_os = "macos", target_os = "ios", + target_os = "visionos", target_os = "android" ))] let builder = WebViewBuilder::new(&window); @@ -25,6 +26,7 @@ fn main() -> wry::Result<()> { target_os = "windows", target_os = "macos", target_os = "ios", + target_os = "visionos", target_os = "android" )))] let builder = { diff --git a/examples/streaming.rs b/examples/streaming.rs index 86a9a0dc2..0363a5029 100644 --- a/examples/streaming.rs +++ b/examples/streaming.rs @@ -27,6 +27,7 @@ fn main() -> wry::Result<()> { target_os = "windows", target_os = "macos", target_os = "ios", + target_os = "visionos", target_os = "android" ))] let builder = WebViewBuilder::new(&window); @@ -35,6 +36,7 @@ fn main() -> wry::Result<()> { target_os = "windows", target_os = "macos", target_os = "ios", + target_os = "visionos", target_os = "android" )))] let builder = { diff --git a/examples/transparent.rs b/examples/transparent.rs index 96b26ddcb..e1357ab7d 100644 --- a/examples/transparent.rs +++ b/examples/transparent.rs @@ -34,6 +34,7 @@ fn main() -> wry::Result<()> { target_os = "windows", target_os = "macos", target_os = "ios", + target_os = "visionos", target_os = "android" ))] let builder = WebViewBuilder::new(&window); @@ -42,6 +43,7 @@ fn main() -> wry::Result<()> { target_os = "windows", target_os = "macos", target_os = "ios", + target_os = "visionos", target_os = "android" )))] let builder = { diff --git a/src/lib.rs b/src/lib.rs index 244e514ec..356fdc41a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,7 +10,7 @@ //! //! ## Examples //! -//! This example leverages the [`HasWindowHandle`] and supports Windows, macOS, iOS, Android and Linux (X11 Only). +//! This example leverages the [`HasWindowHandle`] and supports Windows, macOS, iOS, visionOS, Android and Linux (X11 Only). //! See the following example using [`winit`]. //! //! ```no_run @@ -198,7 +198,7 @@ #![allow(clippy::type_complexity)] #![cfg_attr(docsrs, feature(doc_cfg))] -#[cfg(any(target_os = "macos", target_os = "ios"))] +#[cfg(any(target_os = "macos", target_os = "ios", target_os = "visionos"))] #[macro_use] extern crate objc; @@ -228,11 +228,11 @@ use raw_window_handle::HasWindowHandle; #[cfg(gtk)] use webkitgtk::*; -#[cfg(any(target_os = "macos", target_os = "ios"))] +#[cfg(any(target_os = "macos", target_os = "ios", target_os = "visionos"))] pub(crate) mod wkwebview; -#[cfg(any(target_os = "macos", target_os = "ios"))] +#[cfg(any(target_os = "macos", target_os = "ios", target_os = "visionos"))] use wkwebview::*; -#[cfg(any(target_os = "macos", target_os = "ios"))] +#[cfg(any(target_os = "macos", target_os = "ios", target_os = "visionos"))] pub use wkwebview::{PrintMargin, PrintOptions}; #[cfg(target_os = "windows")] @@ -1034,13 +1034,13 @@ impl<'a> WebViewBuilder<'a> { } } -#[cfg(any(target_os = "macos", target_os = "ios",))] +#[cfg(any(target_os = "macos", target_os = "ios", target_os = "visionos"))] #[derive(Clone)] pub(crate) struct PlatformSpecificWebViewAttributes { data_store_identifier: Option<[u8; 16]>, } -#[cfg(any(target_os = "macos", target_os = "ios",))] +#[cfg(any(target_os = "macos", target_os = "ios", target_os = "visionos"))] impl Default for PlatformSpecificWebViewAttributes { fn default() -> Self { Self { @@ -1049,7 +1049,7 @@ impl Default for PlatformSpecificWebViewAttributes { } } -#[cfg(any(target_os = "macos", target_os = "ios",))] +#[cfg(any(target_os = "macos", target_os = "ios", target_os = "visionos"))] pub trait WebViewBuilderExtDarwin { /// Initialize the WebView with a custom data store identifier. /// Can be used as a replacement for data_directory not being available in WKWebView. @@ -1058,7 +1058,7 @@ pub trait WebViewBuilderExtDarwin { fn with_data_store_identifier(self, identifier: [u8; 16]) -> Self; } -#[cfg(any(target_os = "macos", target_os = "ios",))] +#[cfg(any(target_os = "macos", target_os = "ios", target_os = "visionos"))] impl WebViewBuilderExtDarwin for WebViewBuilder<'_> { fn with_data_store_identifier(mut self, identifier: [u8; 16]) -> Self { self.platform_specific.data_store_identifier = Some(identifier); @@ -1639,6 +1639,15 @@ pub trait WebViewExtIOS { fn manager(&self) -> cocoa::base::id; } +/// Additional methods on `WebView` that are specific to visionOS. +#[cfg(target_os = "visionos")] +pub trait WebViewExtVisionOS { + /// Returns WKWebView handle + fn webview(&self) -> cocoa::base::id; + /// Returns WKWebView manager [(userContentController)](https://developer.apple.com/documentation/webkit/wkscriptmessagehandler/1396222-usercontentcontroller) handle + fn manager(&self) -> cocoa::base::id; +} + #[cfg(target_os = "ios")] impl WebViewExtIOS for WebView { fn webview(&self) -> cocoa::base::id { @@ -1650,6 +1659,17 @@ impl WebViewExtIOS for WebView { } } +#[cfg(target_os = "visionos")] +impl WebViewExtVisionOS for WebView { + fn webview(&self) -> cocoa::base::id { + self.webview.webview + } + + fn manager(&self) -> cocoa::base::id { + self.webview.manager + } +} + #[cfg(target_os = "android")] /// Additional methods on `WebView` that are specific to Android pub trait WebViewExtAndroid { diff --git a/src/wkwebview/mod.rs b/src/wkwebview/mod.rs index b61500de9..7aaf38726 100644 --- a/src/wkwebview/mod.rs +++ b/src/wkwebview/mod.rs @@ -124,7 +124,7 @@ impl InnerWebView { let ns_view = match window.window_handle()?.as_raw() { #[cfg(target_os = "macos")] RawWindowHandle::AppKit(w) => w.ns_view.as_ptr(), - #[cfg(target_os = "ios")] + #[cfg(any(target_os = "ios", target_os = "visionos"))] RawWindowHandle::UiKit(w) => w.ui_view.as_ptr(), _ => return Err(Error::UnsupportedWindowHandle), }; @@ -141,7 +141,7 @@ impl InnerWebView { let ns_view = match window.window_handle()?.as_raw() { #[cfg(target_os = "macos")] RawWindowHandle::AppKit(w) => w.ns_view.as_ptr(), - #[cfg(target_os = "ios")] + #[cfg(any(target_os = "ios", target_os = "visionos"))] RawWindowHandle::UiKit(w) => w.ui_view.as_ptr(), _ => return Err(Error::UnsupportedWindowHandle), }; @@ -359,6 +359,9 @@ impl InnerWebView { #[cfg(target_os = "ios")] let custom_data_store_available = os_version.0 >= 17; + #[cfg(target_os = "visionos")] + let custom_data_store_available = os_version.0 >= 1; + let data_store: id = match ( attributes.incognito, custom_data_store_available, @@ -475,7 +478,7 @@ impl InnerWebView { let _: id = msg_send![_preference, setValue:_yes forKey:NSString::new("allowsPictureInPictureMediaPlayback")]; - #[cfg(target_os = "ios")] + #[cfg(any(target_os = "ios", target_os = "visionos"))] let _: id = msg_send![config, setAllowsInlineMediaPlayback: YES]; if attributes.autoplay { @@ -541,7 +544,7 @@ impl InnerWebView { } } - #[cfg(target_os = "ios")] + #[cfg(any(target_os = "ios", target_os = "visionos"))] { let frame: CGRect = msg_send![ns_view, frame]; // set all autoresizingmasks @@ -1019,7 +1022,7 @@ r#"Object.defineProperty(window, 'ipc', { let _: () = msg_send![app, activateIgnoringOtherApps: YES]; } - #[cfg(target_os = "ios")] + #[cfg(any(target_os = "ios", target_os = "visionos"))] { let _: () = msg_send![ns_view, addSubview: webview]; }