Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add wasm-bindgen v0.2 handles for web_sys::HtmlCanvasElement and web_sys::OffscreenCanvas #134

Merged
merged 14 commits into from
Sep 3, 2023
16 changes: 6 additions & 10 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,19 +40,15 @@ jobs:
with:
rust-version: ${{ matrix.rust_version }}

- run: rustup target add x86_64-linux-android
- run: rustup target add wasm32-unknown-unknown

- name: Check documentation
run: cargo doc --no-deps --document-private-items

- name: Run tests
run: cargo test --verbose

- name: Run tests with std
run: cargo test --verbose --features std
- uses: taiki-e/install-action@cargo-hack

- name: Check on Android
run: cargo check --verbose --target x86_64-linux-android
- name: Run tests
run: cargo hack test --feature-powerset

- name: Check on Android with std
run: cargo check --verbose --target x86_64-linux-android --features std
- name: Run tests for wasm32-unknown-unknown
run: cargo hack check --target wasm32-unknown-unknown --feature-powerset
15 changes: 15 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,21 @@ rust-version = "1.64"
alloc = []
std = ["alloc"]

# Unstable feature to allow the use of `wasm-bindgen` in the `wasm` target.
#
# This is radioactive semver-wise. Do not rely on this in stable code. Any code enabled by this
# feature can be changed or removed in a breaking way at any time. In fact, this feature could
# be removed entirely tomorrow.
#
# The point being: rely on this at your own peril.
madsmtm marked this conversation as resolved.
Show resolved Hide resolved
unstable_web_handles_wbg_02 = ["wasm-bindgen", "std"]
notgull marked this conversation as resolved.
Show resolved Hide resolved

[target.'cfg(target_family = "wasm")'.dependencies.wasm-bindgen]
version = "0.2.87"
default-features = false
features = ["std"]
notgull marked this conversation as resolved.
Show resolved Hide resolved
optional = true

[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]
6 changes: 3 additions & 3 deletions src/borrowed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ impl<H: HasDisplayHandle + ?Sized> HasDisplayHandle for alloc::sync::Arc<H> {
///
/// Get the underlying raw display handle with the [`HasRawDisplayHandle`] trait.
#[repr(transparent)]
#[derive(PartialEq, Eq, Hash, Copy, Clone)]
madsmtm marked this conversation as resolved.
Show resolved Hide resolved
#[derive(PartialEq, Eq, Hash, Clone)]
pub struct DisplayHandle<'a> {
raw: RawDisplayHandle,
_marker: PhantomData<&'a *const ()>,
Expand Down Expand Up @@ -118,7 +118,7 @@ unsafe impl HasRawDisplayHandle for DisplayHandle<'_> {

impl<'a> HasDisplayHandle for DisplayHandle<'a> {
fn display_handle(&self) -> Result<DisplayHandle<'_>, HandleError> {
Ok(*self)
Ok(self.clone())
}
}

Expand Down Expand Up @@ -237,7 +237,7 @@ impl<'a> WindowHandle<'a> {

unsafe impl HasRawWindowHandle for WindowHandle<'_> {
fn raw_window_handle(&self) -> Result<RawWindowHandle, HandleError> {
Ok(self.raw.clone())
Ok(self.raw)
}
}

Expand Down
21 changes: 19 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#![no_std]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![allow(clippy::new_without_default)]

//! Interoperability library for Rust Windowing applications.
//!
Expand Down Expand Up @@ -51,7 +52,9 @@ pub use unix::{
DrmDisplayHandle, DrmWindowHandle, GbmDisplayHandle, GbmWindowHandle, WaylandDisplayHandle,
WaylandWindowHandle, XcbDisplayHandle, XcbWindowHandle, XlibDisplayHandle, XlibWindowHandle,
};
pub use web::{WebDisplayHandle, WebWindowHandle};
pub use web::{
Wbg02CanvasWindowHandle, Wbg02OffscreenCanvasWindowHandle, WebDisplayHandle, WebWindowHandle,
};
pub use windows::{Win32WindowHandle, WinRtWindowHandle, WindowsDisplayHandle};

use core::fmt;
Expand Down Expand Up @@ -120,7 +123,7 @@ unsafe impl<T: HasRawWindowHandle + ?Sized> HasRawWindowHandle for alloc::sync::
/// [`RawWindowHandle::Xlib`] on macOS, it would just be weird, and probably
/// requires something like XQuartz be used).
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum RawWindowHandle {
/// A raw window handle for UIKit (Apple's non-macOS windowing library).
///
Expand Down Expand Up @@ -189,6 +192,20 @@ pub enum RawWindowHandle {
/// ## Availability Hints
/// This variant is used on Wasm or asm.js targets when targeting the Web/HTML5.
Web(WebWindowHandle),
/// A raw window handle for a Web canvas registered via [`wasm-bindgen`].
///
/// ## Availability Hints
/// This variant is used on Wasm or asm.js targets when targeting the Web/HTML5.
///
/// [`wasm-bindgen`]: https://crates.io/crates/wasm-bindgen
Wgb02Canvas(Wbg02CanvasWindowHandle),
/// A raw window handle for a Web offscreen canvas registered via [`wasm-bindgen`].
///
/// ## Availability Hints
/// This variant is used on Wasm or asm.js targets when targeting the Web/HTML5.
///
/// [`wasm-bindgen`]: https://crates.io/crates/wasm-bindgen
Wgb02OffscreenCanvas(Wbg02OffscreenCanvasWindowHandle),
/// A raw window handle for Android NDK.
///
/// ## Availability Hints
Expand Down
145 changes: 145 additions & 0 deletions src/web.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
use core::ffi::c_void;
use core::ptr::NonNull;

/// Raw display handle for the Web.
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
Expand Down Expand Up @@ -48,3 +51,145 @@ impl WebWindowHandle {
Self { id }
}
}

/// Raw window handle for a Web canvas registered via [`wasm-bindgen`].
///
/// [`wasm-bindgen`]: https://crates.io/crates/wasm-bindgen
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Wbg02CanvasWindowHandle {
madsmtm marked this conversation as resolved.
Show resolved Hide resolved
/// The pointer to the [`JsValue`] of an [`HtmlCanvasElement`].
///
/// [`HtmlCanvasElement`]: https://docs.rs/web-sys/latest/web_sys/struct.HtmlCanvasElement.html
/// [`wasm-bindgen`]: https://crates.io/crates/wasm-bindgen
/// [`JsValue`]: https://docs.rs/wasm-bindgen/latest/wasm_bindgen/struct.JsValue.html
pub obj: NonNull<c_void>,
}

impl Wbg02CanvasWindowHandle {
/// Create a new handle to a pointer to [`HtmlCanvasElement`].
///
/// [`HtmlCanvasElement`]: https://docs.rs/web-sys/latest/web_sys/struct.HtmlCanvasElement.html
///
/// ## Example
/// ```no_run
/// # use raw_window_handle::Wbg02CanvasWindowHandle;
/// # use core::{ffi::c_void, ptr::NonNull};
/// # fn get_canvas() -> NonNull<c_void> { unimplemented!() }
/// let obj: NonNull<c_void> = get_canvas();
/// let mut window_handle = Wbg02CanvasWindowHandle::new(obj);
/// /* set fields */
/// ```
madsmtm marked this conversation as resolved.
Show resolved Hide resolved
pub fn new(obj: NonNull<c_void>) -> Self {
Self { obj }
}
}

#[cfg(all(target_family = "wasm", feature = "unstable-wasm-bindgen-0-2"))]
#[cfg_attr(
docsrs,
doc(cfg(all(target_family = "wasm", feature = "unstable-wasm-bindgen-0-2")))
)]
/// These implementations are only available when `unstable-wasm-bindgen-0-2` is enabled.
impl Wbg02CanvasWindowHandle {
/// Create a new `Wbg02CanvasWindowHandle` from a [`wasm-bindgen`] object.
///
/// This function is unstable. Its signature may be changed or even removed outright without a
/// breaking version change.
///
/// # Safety
madsmtm marked this conversation as resolved.
Show resolved Hide resolved
///
/// The [`JsValue`] must refer to an [`HtmlCanvasElement`], and the lifetime must be longer than
/// the `Wbg02CanvasWindowHandle` lives for.
///
/// [`wasm-bindgen`]: https://crates.io/crates/wasm-bindgen
pub fn from_wasm_bindgen_0_2(js_value: &wasm_bindgen::JsValue) -> Self {
Self::new(NonNull::from(js_value).cast())
}

/// Convert to the underlying [`wasm-bindgen`] index.
///
/// This function is unstable. Its signature may be changed or even removed outright without a
/// breaking version change.
///
/// # Safety
///
/// The lifetime from the `from_wasm_bindgen_0_2` function must still be valid, and the
/// underlying pointer must still be a [`wasm_bindgen`] object.
///
/// [`wasm-bindgen`]: https://crates.io/crates/wasm-bindgen
pub unsafe fn as_wasm_bindgen_0_2(&self) -> &wasm_bindgen::JsValue {
self.obj.cast().as_ref()
}
}

/// Raw window handle for a Web offscreen canvas registered via [`wasm-bindgen`].
///
/// [`wasm-bindgen`]: https://crates.io/crates/wasm-bindgen
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Wbg02OffscreenCanvasWindowHandle {
/// The pointer to the [`JsValue`] of an [`OffscreenElement`].
///
/// [`OffscreenElement`]: https://docs.rs/web-sys/latest/web_sys/struct.OffscreenElement.html
/// [`wasm-bindgen`]: https://crates.io/crates/wasm-bindgen
/// [`JsValue`]: https://docs.rs/wasm-bindgen/latest/wasm_bindgen/struct.JsValue.html
pub obj: NonNull<c_void>,
}

impl Wbg02OffscreenCanvasWindowHandle {
/// Create a new handle to a pointer to an [`OffscreenCanvas`].
///
/// ## Construction
/// ```no_run
/// # use raw_window_handle::Wbg02OffscreenCanvasWindowHandle;
/// # use core::{ffi::c_void, ptr::NonNull};
/// # fn get_offscreen_canvas() -> NonNull<c_void> { unimplemented!() }
/// let obj: NonNull<c_void> = get_offscreen_canvas();
/// let mut window_handle = Wbg02OffscreenCanvasWindowHandle::new(obj);
/// /* set fields */
/// ```
///
/// [`OffscreenCanvas`]: https://docs.rs/web-sys/latest/web_sys/struct.OffscreenCanvas.html
pub fn new(obj: NonNull<c_void>) -> Self {
Self { obj }
}
}

#[cfg(all(target_family = "wasm", feature = "unstable-wasm-bindgen-0-2"))]
#[cfg_attr(
docsrs,
doc(cfg(all(target_family = "wasm", feature = "unstable-wasm-bindgen-0-2")))
)]
/// These implementations are only available when `unstable-wasm-bindgen-0-2` is enabled.
impl Wbg02OffscreenCanvasWindowHandle {
/// Create a new `Wbg02OffscreenCanvasWindowHandle` from a [`wasm-bindgen`] object.
///
/// This function is unstable. Its signature may be changed or even removed outright without a
/// breaking version change.
///
/// # Safety
///
/// The [`JsValue`] must refer to an [`OffscreenCanvas`], and the lifetime must be longer than
/// the `Wbg02OffscreenCanvasWindowHandle` lives for.
///
/// [`wasm-bindgen`]: https://crates.io/crates/wasm-bindgen
pub fn from_wasm_bindgen_0_2(js_value: &wasm_bindgen::JsValue) -> Self {
Self::new(NonNull::from(js_value).cast())
}

/// Convert to the underlying [`wasm-bindgen`] index.
///
/// This function is unstable. Its signature may be changed or even removed outright without a
/// breaking version change.
///
/// # Safety
///
/// The lifetime from the `from_wasm_bindgen_0_2` function must still be valid, and the
/// underlying pointer must still be a [`wasm_bindgen`] object.
///
/// [`wasm-bindgen`]: https://crates.io/crates/wasm-bindgen
pub unsafe fn as_wasm_bindgen_0_2(&self) -> &wasm_bindgen::JsValue {
self.obj.cast().as_ref()
}
}
Loading