diff --git a/.github/workflows/build_docs.yaml b/.github/workflows/build_docs.yaml index 870ced6f666..ebeaea52630 100644 --- a/.github/workflows/build_docs.yaml +++ b/.github/workflows/build_docs.yaml @@ -22,7 +22,7 @@ jobs: - name: Set up rgb crate rustdoc link run: | rgb_version=`grep 'rgb = ' internal/core/Cargo.toml | sed 's/^.*"\(.*\)"/\1/'` - echo "RUSTDOCFLAGS=$RUSTDOCFLAGS --extern-html-root-url rgb=https://docs.rs/rgb/$rgb_version/ --extern-html-root-url android_activity=https://docs.rs/android-activity/0.5/ -Z unstable-options" >> $GITHUB_ENV + echo "RUSTDOCFLAGS=$RUSTDOCFLAGS --extern-html-root-url rgb=https://docs.rs/rgb/$rgb_version/ --extern-html-root-url android_activity=https://docs.rs/android-activity/0.5/ --extern-html-root-url raw_window_handle=https://docs.rs/raw_window_handle/0.6 -Z unstable-options" >> $GITHUB_ENV - uses: ./.github/actions/install-nodejs - name: Cache mdbook and mdbook-linkcheck uses: actions/cache@v4 diff --git a/Cargo.toml b/Cargo.toml index 3b1da5e706b..b2a3d9c3301 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -140,6 +140,8 @@ strum = { version = "0.26.1", default-features = false, features = ["derive"] } toml_edit = { version = "0.22.7" } cfg_aliases = { version = "0.2.0" } +raw-window-handle-06 = { package = "raw-window-handle", version = "0.6", features = ["alloc"] } + [profile.release] lto = true panic = "abort" diff --git a/api/rs/slint/Cargo.toml b/api/rs/slint/Cargo.toml index 18507ce9bf7..d1553ad4309 100644 --- a/api/rs/slint/Cargo.toml +++ b/api/rs/slint/Cargo.toml @@ -78,6 +78,12 @@ unsafe-single-threaded = ["i-slint-core/unsafe-single-threaded"] ## APIs to support screen readers and other assistive technologies. accessibility = ["i-slint-backend-selector/accessibility"] +## Enable integration with [raw-window-handle](raw_window_handle_06) version 0.6. This provides a +## [`Window::window_handle()`] function that returns a struct that implements +## [HasWindowHandle](raw_window_handle_06::HasWindowHandle) and +## [HasDisplayHandle](raw_window_handle_06::HasDisplayHandle) implementation. +raw-window-handle-06 = ["dep:raw-window-handle-06", "i-slint-backend-selector/raw-window-handle-06"] + #! ### Backends #! Slint needs a backend that will act as liaison between Slint and the OS. @@ -175,6 +181,8 @@ num-traits = { version = "0.2", default-features = false } log = { version = "0.4.17", optional = true } +raw-window-handle-06 = { workspace = true, optional = true } + [target.'cfg(not(target_os = "android"))'.dependencies] # FemtoVG is disabled on android because it doesn't compile without setting RUST_FONTCONFIG_DLOPEN=on # end even then wouldn't work because it can't load fonts @@ -200,4 +208,4 @@ rustdoc-args = [ "--html-in-header", "docs/resources/slint-docs-highlight.html", ] -features = ["document-features", "log", "gettext", "renderer-software", "renderer-femtovg"] +features = ["document-features", "log", "gettext", "renderer-software", "renderer-femtovg", "raw-window-handle-06"] diff --git a/internal/backends/selector/Cargo.toml b/internal/backends/selector/Cargo.toml index c0ed65bca98..e067be6ef99 100644 --- a/internal/backends/selector/Cargo.toml +++ b/internal/backends/selector/Cargo.toml @@ -32,6 +32,8 @@ renderer-software = ["i-slint-backend-winit?/renderer-software", "i-slint-core/s rtti = ["i-slint-core/rtti", "i-slint-backend-qt?/rtti"] accessibility = ["i-slint-backend-winit?/accessibility"] +raw-window-handle-06 = ["i-slint-core/raw-window-handle-06", "i-slint-backend-winit?/raw-window-handle-06"] + # note that default enable the i-slint-backend-qt, but not its enable feature default = ["i-slint-backend-qt", "backend-winit"] diff --git a/internal/backends/winit/Cargo.toml b/internal/backends/winit/Cargo.toml index 0507198f35c..08ee04ec519 100644 --- a/internal/backends/winit/Cargo.toml +++ b/internal/backends/winit/Cargo.toml @@ -27,6 +27,7 @@ renderer-skia-opengl = ["renderer-skia", "i-slint-renderer-skia/opengl"] renderer-skia-vulkan = ["renderer-skia", "i-slint-renderer-skia/vulkan"] renderer-software = ["dep:softbuffer", "dep:imgref", "dep:rgb", "i-slint-core/software-renderer-systemfonts", "dep:bytemuck", "winit/rwh_05"] accessibility = ["dep:accesskit", "dep:accesskit_winit"] +raw-window-handle-06 = ["dep:raw-window-handle-06", "winit/rwh_06"] default = [] [dependencies] @@ -58,6 +59,8 @@ imgref = { version = "1.6.1", optional = true } rgb = { version = "0.8.27", optional = true } bytemuck = { workspace = true, optional = true, features = ["derive"] } +raw-window-handle-06 = { workspace = true, optional = true } + [target.'cfg(target_arch = "wasm32")'.dependencies] web-sys = { version = "0.3", features=["HtmlInputElement", "HtmlCanvasElement", "Window", "Document", "Event", "KeyboardEvent", "InputEvent", "CompositionEvent", "DomStringMap", "ClipboardEvent", "DataTransfer"] } wasm-bindgen = { version = "0.2" } @@ -77,7 +80,7 @@ cocoa = { version = "0.25.0" } cfg_aliases = { workspace = true } [dev-dependencies] -slint = { path = "../../../api/rs/slint", default-features = false, features = ["std", "compat-1-2", "backend-winit", "renderer-software"] } +slint = { path = "../../../api/rs/slint", default-features = false, features = ["std", "compat-1-2", "backend-winit", "renderer-software", "raw-window-handle-06"] } [package.metadata.docs.rs] features = ["wayland", "renderer-software"] diff --git a/internal/backends/winit/lib.rs b/internal/backends/winit/lib.rs index cacfa5c5c69..b8a9173f8a5 100644 --- a/internal/backends/winit/lib.rs +++ b/internal/backends/winit/lib.rs @@ -408,11 +408,15 @@ mod testui { // Sorry, can't test with rust test harness and multiple threads. #[cfg(not(any(target_arch = "wasm32", target_os = "macos", target_os = "ios")))] #[test] -fn test_window_accessor() { +fn test_window_accessor_and_rwh() { slint::platform::set_platform(Box::new(crate::Backend::new().unwrap())).unwrap(); use testui::*; let app = App::new().unwrap(); let slint_window = app.window(); assert!(slint_window.has_winit_window()); + let handle = slint_window.window_handle(); + use raw_window_handle_06::{HasDisplayHandle, HasWindowHandle}; + assert!(handle.window_handle().is_ok()); + assert!(handle.display_handle().is_ok()); } diff --git a/internal/backends/winit/winitwindowadapter.rs b/internal/backends/winit/winitwindowadapter.rs index 819b337e562..86e8915655f 100644 --- a/internal/backends/winit/winitwindowadapter.rs +++ b/internal/backends/winit/winitwindowadapter.rs @@ -617,6 +617,20 @@ impl WindowAdapter for WinitWindowAdapter { fn internal(&self, _: corelib::InternalToken) -> Option<&dyn WindowAdapterInternal> { Some(self) } + + #[cfg(feature = "raw-window-handle-06")] + fn window_handle_06( + &self, + ) -> Result, raw_window_handle_06::HandleError> { + raw_window_handle_06::HasWindowHandle::window_handle(&self.winit_window) + } + + #[cfg(feature = "raw-window-handle-06")] + fn display_handle_06( + &self, + ) -> Result, raw_window_handle_06::HandleError> { + raw_window_handle_06::HasDisplayHandle::display_handle(&self.winit_window) + } } impl WindowAdapterInternal for WinitWindowAdapter { diff --git a/internal/core/Cargo.toml b/internal/core/Cargo.toml index 9b97560f3c9..4068ddcafc1 100644 --- a/internal/core/Cargo.toml +++ b/internal/core/Cargo.toml @@ -24,7 +24,7 @@ libm = ["num-traits/libm", "euclid/libm"] # Allow the viewer to query at runtime information about item types rtti = [] # Use the standard library -std = ["euclid/std", "once_cell/std", "scoped-tls-hkt", "lyon_path", "lyon_algorithms", "lyon_geom", "lyon_extra", "dep:web-time", "image-decoders", "svg"] +std = ["euclid/std", "once_cell/std", "scoped-tls-hkt", "lyon_path", "lyon_algorithms", "lyon_geom", "lyon_extra", "dep:web-time", "image-decoders", "svg", "raw-window-handle-06?/std"] # Unsafe feature meaning that there is only one core running and all thread_local are static. # You can only enable this feature if you are sure that any API of this crate is only called # from a single core, and not in a interrupt or signal handler. @@ -44,6 +44,8 @@ box-shadow-cache = [] shared-fontdb = ["i-slint-common/shared-fontdb"] +raw-window-handle-06 = ["dep:raw-window-handle-06"] + default = ["std", "unicode"] [dependencies] @@ -86,6 +88,8 @@ resvg = { workspace = true, optional = true } fontdb = { workspace = true, optional = true } serde = { version = "1.0.163", features = ["derive"], optional = true } +raw-window-handle-06 = { workspace = true, optional = true } + [target.'cfg(target_family = "unix")'.dependencies] gettext-rs = { version = "0.7", optional = true, features = ["gettext-system"] } @@ -107,4 +111,4 @@ ttf-parser = "0.20.0" fontdb = { workspace = true, default-features = true } serde_json = "1.0.96" tiny-skia = "0.11.0" -tokio = { version = "1.35", features = ["rt-multi-thread"] } \ No newline at end of file +tokio = { version = "1.35", features = ["rt-multi-thread"] } diff --git a/internal/core/api.rs b/internal/core/api.rs index 4aef11de405..5127c089e35 100644 --- a/internal/core/api.rs +++ b/internal/core/api.rs @@ -324,6 +324,34 @@ pub enum SetRenderingNotifierError { AlreadySet, } +/// This struct represents a persistent handle to a window and implements the +/// [`raw_window_handle_06::HasWindowHandle`] and [`raw_window_handle_06::HasDisplayHandle`] +/// traits for accessing exposing raw window and display handles. +/// Obtain an instance of this by calling [`Window::window_handle()`]. +#[cfg(feature = "raw-window-handle-06")] +#[derive(Clone)] +pub struct WindowHandle { + adapter: alloc::rc::Rc, +} + +#[cfg(feature = "raw-window-handle-06")] +impl raw_window_handle_06::HasWindowHandle for WindowHandle { + fn window_handle<'a>( + &'a self, + ) -> Result, raw_window_handle_06::HandleError> { + self.adapter.window_handle_06() + } +} + +#[cfg(feature = "raw-window-handle-06")] +impl raw_window_handle_06::HasDisplayHandle for WindowHandle { + fn display_handle<'a>( + &'a self, + ) -> Result, raw_window_handle_06::HandleError> { + self.adapter.display_handle_06() + } +} + /// This type represents a window towards the windowing system, that's used to render the /// scene of a component. It provides API to control windowing system specific aspects such /// as the position on the screen. @@ -571,6 +599,13 @@ impl Window { pub fn is_visible(&self) -> bool { self.0.is_visible() } + + /// Returns a struct that implements the raw window handle traits to access the windowing system specific window + /// and display handles. This function is only accessible if you enable the `raw-window-handle-06` crate feature. + #[cfg(feature = "raw-window-handle-06")] + pub fn window_handle(&self) -> WindowHandle { + WindowHandle { adapter: self.0.window_adapter() } + } } pub use crate::SharedString; diff --git a/internal/core/window.rs b/internal/core/window.rs index 7488cb1a980..651718f3bbf 100644 --- a/internal/core/window.rs +++ b/internal/core/window.rs @@ -137,6 +137,22 @@ pub trait WindowAdapter { fn internal(&self, _: crate::InternalToken) -> Option<&dyn WindowAdapterInternal> { None } + + /// Re-implement this to support exposing raw window handles (version 0.6). + #[cfg(feature = "raw-window-handle-06")] + fn window_handle_06( + &self, + ) -> Result, raw_window_handle_06::HandleError> { + Err(raw_window_handle_06::HandleError::NotSupported) + } + + /// Re-implement this to support exposing raw display handles (version 0.6). + #[cfg(feature = "raw-window-handle-06")] + fn display_handle_06( + &self, + ) -> Result, raw_window_handle_06::HandleError> { + Err(raw_window_handle_06::HandleError::NotSupported) + } } /// Implementation details behind [`WindowAdapter`], but since this diff --git a/internal/interpreter/Cargo.toml b/internal/interpreter/Cargo.toml index 9ecdf227ee9..dcecc0287f7 100644 --- a/internal/interpreter/Cargo.toml +++ b/internal/interpreter/Cargo.toml @@ -107,6 +107,12 @@ renderer-winit-software = ["renderer-software"] ## APIs to support screen readers and other assistive technologies. accessibility = ["i-slint-backend-selector/accessibility"] +## Enable integration with [raw-window-handle](raw_window_handle_06) version 0.6. This provides a +## [`Window::window_handle()`] function that returns a struct that implements +## [HasWindowHandle](raw_window_handle_06::HasWindowHandle) and +## [HasDisplayHandle](raw_window_handle_06::HasDisplayHandle) implementation. +raw-window-handle-06 = ["dep:raw-window-handle-06", "i-slint-backend-selector/raw-window-handle-06"] + ## Features used internally by Slint tooling that are not stable and come without ## any stability guarantees whatsoever. internal = [] @@ -126,6 +132,7 @@ once_cell = "1.5" thiserror = "1" document-features = { version = "0.2.0", optional = true } spin_on = { version = "0.1", optional = true } +raw-window-handle-06 = { workspace = true, optional = true } [target.'cfg(target_arch = "wasm32")'.dependencies] i-slint-backend-winit = { workspace = true } @@ -140,4 +147,4 @@ i-slint-backend-testing = { path = "../../internal/backends/testing" } spin_on = "0.1" [package.metadata.docs.rs] -features = ["display-diagnostics", "document-features"] +features = ["display-diagnostics", "document-features", "raw-window-handle-06"]