Skip to content

Commit

Permalink
Add support for raw-window-handle
Browse files Browse the repository at this point in the history
Add a `rwh_06` feature to the Rust API crates, which adds support for version 0.6 of rwh to slint::Window, by delegation to the backend.

HasDisplayHandle could also be provided on the backend, but that can be
done separately if needed.

Fixes #877
  • Loading branch information
tronical committed Mar 22, 2024
1 parent e4d12ca commit 96c5a50
Show file tree
Hide file tree
Showing 10 changed files with 88 additions and 3 deletions.
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" }

rwh_06 = { package = "raw-window-handle", version = "0.6", features = ["alloc"] }

[profile.release]
lto = true
panic = "abort"
Expand Down
4 changes: 4 additions & 0 deletions api/rs/slint/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,10 @@ 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 version 0.6. This provides a HasWindowHandle implementation
### for slint::Window.
rwh_06 = ["i-slint-core/rwh_06", "i-slint-backend-selector/rwh_06"]

#! ### Backends

#! Slint needs a backend that will act as liaison between Slint and the OS.
Expand Down
2 changes: 2 additions & 0 deletions internal/backends/selector/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"]

rwh_06 = ["i-slint-backend-winit?/rwh_06"]

# note that default enable the i-slint-backend-qt, but not its enable feature
default = ["i-slint-backend-qt", "backend-winit"]

Expand Down
5 changes: 4 additions & 1 deletion internal/backends/winit/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
rwh_06 = ["dep:rwh_06", "winit/rwh_06"]
default = []

[dependencies]
Expand Down Expand Up @@ -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"] }

rwh_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" }
Expand All @@ -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", "rwh_06"] }

[package.metadata.docs.rs]
features = ["wayland", "renderer-software"]
14 changes: 14 additions & 0 deletions internal/backends/winit/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -416,3 +416,17 @@ fn test_window_accessor() {
let slint_window = app.window();
assert!(slint_window.has_winit_window());
}

// 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_rwh() {
slint::platform::set_platform(Box::new(crate::Backend::new().unwrap())).unwrap();

use testui::*;
let app = App::new().unwrap();
let slint_window = app.window();
use rwh_06::{HasDisplayHandle, HasWindowHandle};
assert!(slint_window.window_handle().is_ok());
assert!(slint_window.display_handle().is_ok());
}
10 changes: 10 additions & 0 deletions internal/backends/winit/winitwindowadapter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,16 @@ impl WindowAdapter for WinitWindowAdapter {
fn internal(&self, _: corelib::InternalToken) -> Option<&dyn WindowAdapterInternal> {
Some(self)
}

#[cfg(feature = "rwh_06")]
fn window_handle_06(&self) -> Result<rwh_06::WindowHandle<'_>, rwh_06::HandleError> {
rwh_06::HasWindowHandle::window_handle(&self.winit_window)
}

#[cfg(feature = "rwh_06")]
fn display_handle_06(&self) -> Result<rwh_06::DisplayHandle<'_>, rwh_06::HandleError> {
rwh_06::HasDisplayHandle::display_handle(&self.winit_window)
}
}

impl WindowAdapterInternal for WinitWindowAdapter {
Expand Down
8 changes: 6 additions & 2 deletions internal/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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", "rwh_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.
Expand All @@ -44,6 +44,8 @@ box-shadow-cache = []

shared-fontdb = ["i-slint-common/shared-fontdb"]

rwh_06 = ["dep:rwh_06"]

default = ["std", "unicode"]

[dependencies]
Expand Down Expand Up @@ -86,6 +88,8 @@ resvg = { workspace = true, optional = true }
fontdb = { workspace = true, optional = true }
serde = { version = "1.0.163", features = ["derive"], optional = true }

rwh_06 = { workspace = true, optional = true }

[target.'cfg(target_family = "unix")'.dependencies]
gettext-rs = { version = "0.7", optional = true, features = ["gettext-system"] }

Expand All @@ -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"] }
tokio = { version = "1.35", features = ["rt-multi-thread"] }
30 changes: 30 additions & 0 deletions internal/core/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,36 @@ impl Window {
}
}

#[cfg(feature = "rwh_06")]
impl rwh_06::HasWindowHandle for Window {
fn window_handle<'a>(&'a self) -> Result<rwh_06::WindowHandle<'a>, rwh_06::HandleError> {
let adapter = self.0.window_adapter();
let wh = adapter.window_handle_06()?;
// Safety: The Rc<dyn WindowAdapter> owns this slint::Window (&self). Therefore the caller of
// this function must also have a strong reference to the window adapter. The adapter above
// was created from a self weak and is the same as the Rc<dyn WindowAdapter> of the caller.
#[allow(unsafe_code)]
Ok(unsafe {
core::mem::transmute::<rwh_06::WindowHandle<'_>, rwh_06::WindowHandle<'a>>(wh)
})
}
}

#[cfg(feature = "rwh_06")]
impl rwh_06::HasDisplayHandle for Window {
fn display_handle<'a>(&'a self) -> Result<rwh_06::DisplayHandle<'a>, rwh_06::HandleError> {
let adapter = self.0.window_adapter();
let wh = adapter.display_handle_06()?;
// Safety: The Rc<dyn WindowAdapter> owns this slint::Window (&self). Therefore the caller of
// this function must also have a strong reference to the window adapter. The adapter above
// was created from a self weak and is the same as the Rc<dyn WindowAdapter> of the caller.
#[allow(unsafe_code)]
Ok(unsafe {
core::mem::transmute::<rwh_06::DisplayHandle<'_>, rwh_06::DisplayHandle<'a>>(wh)
})
}
}

pub use crate::SharedString;

/// This trait is used to obtain references to global singletons exported in `.slint`
Expand Down
12 changes: 12 additions & 0 deletions internal/core/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,18 @@ 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 = "rwh_06")]
fn window_handle_06(&self) -> Result<rwh_06::WindowHandle<'_>, rwh_06::HandleError> {
Err(rwh_06::HandleError::NotSupported)
}

/// Re-implement this to support exposing raw display handles (version 0.6).
#[cfg(feature = "rwh_06")]
fn display_handle_06(&self) -> Result<rwh_06::DisplayHandle<'_>, rwh_06::HandleError> {
Err(rwh_06::HandleError::NotSupported)
}
}

/// Implementation details behind [`WindowAdapter`], but since this
Expand Down
4 changes: 4 additions & 0 deletions internal/interpreter/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ 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 version 0.6. This provides a HasWindowHandle implementation
### for slint::Window.
rwh_06 = ["i-slint-core/rwh_06", "i-slint-backend-selector/rwh_06"]

## Features used internally by Slint tooling that are not stable and come without
## any stability guarantees whatsoever.
internal = []
Expand Down

0 comments on commit 96c5a50

Please sign in to comment.