| 1 | use core::ffi::c_void; |
| 2 | use core::ptr::NonNull; |
| 3 | |
| 4 | use super::DisplayHandle; |
| 5 | |
| 6 | /// Raw display handle for the Web. |
| 7 | #[non_exhaustive ] |
| 8 | #[derive (Debug, Clone, Copy, PartialEq, Eq, Hash)] |
| 9 | pub struct WebDisplayHandle {} |
| 10 | |
| 11 | impl WebDisplayHandle { |
| 12 | /// Create a new empty display handle. |
| 13 | /// |
| 14 | /// |
| 15 | /// # Example |
| 16 | /// |
| 17 | /// ``` |
| 18 | /// # use raw_window_handle::WebDisplayHandle; |
| 19 | /// let handle = WebDisplayHandle::new(); |
| 20 | /// ``` |
| 21 | pub fn new() -> Self { |
| 22 | Self {} |
| 23 | } |
| 24 | } |
| 25 | |
| 26 | impl DisplayHandle<'static> { |
| 27 | /// Create a Web-based display handle. |
| 28 | /// |
| 29 | /// As no data is borrowed by this handle, it is completely safe to create. This function |
| 30 | /// may be useful to windowing framework implementations that want to avoid unsafe code. |
| 31 | /// |
| 32 | /// # Example |
| 33 | /// |
| 34 | /// ``` |
| 35 | /// # use raw_window_handle::{DisplayHandle, HasDisplayHandle}; |
| 36 | /// # fn do_something(rwh: impl HasDisplayHandle) { let _ = rwh; } |
| 37 | /// let handle = DisplayHandle::web(); |
| 38 | /// do_something(handle); |
| 39 | /// ``` |
| 40 | pub fn web() -> Self { |
| 41 | // SAFETY: No data is borrowed. |
| 42 | unsafe { Self::borrow_raw(WebDisplayHandle::new().into()) } |
| 43 | } |
| 44 | } |
| 45 | |
| 46 | /// Raw window handle for the Web. |
| 47 | #[non_exhaustive ] |
| 48 | #[derive (Debug, Clone, Copy, PartialEq, Eq, Hash)] |
| 49 | pub struct WebWindowHandle { |
| 50 | /// An ID value inserted into the [data attributes] of the canvas element as '`raw-handle`'. |
| 51 | /// |
| 52 | /// When accessing from JS, the attribute will automatically be called `rawHandle`. |
| 53 | /// |
| 54 | /// Each canvas created by the windowing system should be assigned their own unique ID. |
| 55 | /// |
| 56 | /// [data attributes]: https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/data-* |
| 57 | pub id: u32, |
| 58 | } |
| 59 | |
| 60 | impl WebWindowHandle { |
| 61 | /// Create a new handle to a canvas element. |
| 62 | /// |
| 63 | /// |
| 64 | /// # Example |
| 65 | /// |
| 66 | /// ``` |
| 67 | /// # use raw_window_handle::WebWindowHandle; |
| 68 | /// # |
| 69 | /// let id: u32 = 0; // canvas.rawHandle; |
| 70 | /// let handle = WebWindowHandle::new(id); |
| 71 | /// ``` |
| 72 | pub fn new(id: u32) -> Self { |
| 73 | Self { id } |
| 74 | } |
| 75 | } |
| 76 | |
| 77 | /// Raw window handle for a Web canvas registered via [`wasm-bindgen`]. |
| 78 | /// |
| 79 | /// [`wasm-bindgen`]: https://crates.io/crates/wasm-bindgen |
| 80 | #[non_exhaustive ] |
| 81 | #[derive (Debug, Clone, Copy, PartialEq, Eq, Hash)] |
| 82 | pub struct WebCanvasWindowHandle { |
| 83 | /// A pointer to the [`JsValue`] of an [`HtmlCanvasElement`]. |
| 84 | /// |
| 85 | /// Note: This uses [`c_void`] to avoid depending on `wasm-bindgen` |
| 86 | /// directly. |
| 87 | /// |
| 88 | /// [`JsValue`]: https://docs.rs/wasm-bindgen/latest/wasm_bindgen/struct.JsValue.html |
| 89 | /// [`HtmlCanvasElement`]: https://docs.rs/web-sys/latest/web_sys/struct.HtmlCanvasElement.html |
| 90 | // |
| 91 | // SAFETY: Not using `JsValue` is sound because `wasm-bindgen` guarantees |
| 92 | // that there's only one version of itself in any given binary, and hence |
| 93 | // we can't have a type-confusion where e.g. one library used `JsValue` |
| 94 | // from `v0.2` of `wasm-bindgen`, and another used `JsValue` from `v1.0`; |
| 95 | // the binary will simply fail to compile! |
| 96 | // |
| 97 | // Reference: TODO |
| 98 | pub obj: NonNull<c_void>, |
| 99 | } |
| 100 | |
| 101 | impl WebCanvasWindowHandle { |
| 102 | /// Create a new handle from a pointer to [`HtmlCanvasElement`]. |
| 103 | /// |
| 104 | /// [`HtmlCanvasElement`]: https://docs.rs/web-sys/latest/web_sys/struct.HtmlCanvasElement.html |
| 105 | /// |
| 106 | /// # Example |
| 107 | /// |
| 108 | /// ``` |
| 109 | /// # use core::ffi::c_void; |
| 110 | /// # use core::ptr::NonNull; |
| 111 | /// # use raw_window_handle::WebCanvasWindowHandle; |
| 112 | /// # type HtmlCanvasElement = (); |
| 113 | /// # type JsValue = (); |
| 114 | /// let canvas: &HtmlCanvasElement; |
| 115 | /// # canvas = &(); |
| 116 | /// let value: &JsValue = &canvas; // Deref to `JsValue` |
| 117 | /// let obj: NonNull<c_void> = NonNull::from(value).cast(); |
| 118 | /// let mut handle = WebCanvasWindowHandle::new(obj); |
| 119 | /// ``` |
| 120 | pub fn new(obj: NonNull<c_void>) -> Self { |
| 121 | Self { obj } |
| 122 | } |
| 123 | } |
| 124 | |
| 125 | #[cfg (all(target_family = "wasm" , feature = "wasm-bindgen-0-2" ))] |
| 126 | #[cfg_attr ( |
| 127 | docsrs, |
| 128 | doc(cfg(all(target_family = "wasm" , feature = "wasm-bindgen-0-2" ))) |
| 129 | )] |
| 130 | /// These implementations are only available when `wasm-bindgen-0-2` is enabled. |
| 131 | impl WebCanvasWindowHandle { |
| 132 | /// Create a new `WebCanvasWindowHandle` from a [`wasm_bindgen::JsValue`]. |
| 133 | /// |
| 134 | /// The `JsValue` should refer to a `HtmlCanvasElement`, and the lifetime |
| 135 | /// of the value should be at least as long as the lifetime of this. |
| 136 | pub fn from_wasm_bindgen_0_2(js_value: &wasm_bindgen::JsValue) -> Self { |
| 137 | Self::new(NonNull::from(js_value).cast()) |
| 138 | } |
| 139 | |
| 140 | /// Convert to the underlying [`wasm_bindgen::JsValue`]. |
| 141 | /// |
| 142 | /// # Safety |
| 143 | /// |
| 144 | /// The inner pointer must be valid. This is ensured if this handle was |
| 145 | /// borrowed from [`WindowHandle`][crate::WindowHandle]. |
| 146 | pub unsafe fn as_wasm_bindgen_0_2(&self) -> &wasm_bindgen::JsValue { |
| 147 | unsafe { self.obj.cast().as_ref() } |
| 148 | } |
| 149 | } |
| 150 | |
| 151 | /// Raw window handle for a Web offscreen canvas registered via |
| 152 | /// [`wasm-bindgen`]. |
| 153 | /// |
| 154 | /// [`wasm-bindgen`]: https://crates.io/crates/wasm-bindgen |
| 155 | #[non_exhaustive ] |
| 156 | #[derive (Debug, Clone, Copy, PartialEq, Eq, Hash)] |
| 157 | pub struct WebOffscreenCanvasWindowHandle { |
| 158 | /// A pointer to the [`JsValue`] of an [`OffscreenCanvas`]. |
| 159 | /// |
| 160 | /// Note: This uses [`c_void`] to avoid depending on `wasm-bindgen` |
| 161 | /// directly. |
| 162 | /// |
| 163 | /// [`JsValue`]: https://docs.rs/wasm-bindgen/latest/wasm_bindgen/struct.JsValue.html |
| 164 | /// [`OffscreenCanvas`]: https://docs.rs/web-sys/latest/web_sys/struct.OffscreenCanvas.html |
| 165 | // |
| 166 | // SAFETY: See WebCanvasWindowHandle. |
| 167 | pub obj: NonNull<c_void>, |
| 168 | } |
| 169 | |
| 170 | impl WebOffscreenCanvasWindowHandle { |
| 171 | /// Create a new handle from a pointer to an [`OffscreenCanvas`]. |
| 172 | /// |
| 173 | /// [`OffscreenCanvas`]: https://docs.rs/web-sys/latest/web_sys/struct.OffscreenCanvas.html |
| 174 | /// |
| 175 | /// # Example |
| 176 | /// |
| 177 | /// ``` |
| 178 | /// # use core::ffi::c_void; |
| 179 | /// # use core::ptr::NonNull; |
| 180 | /// # use raw_window_handle::WebOffscreenCanvasWindowHandle; |
| 181 | /// # type OffscreenCanvas = (); |
| 182 | /// # type JsValue = (); |
| 183 | /// let canvas: &OffscreenCanvas; |
| 184 | /// # canvas = &(); |
| 185 | /// let value: &JsValue = &canvas; // Deref to `JsValue` |
| 186 | /// let obj: NonNull<c_void> = NonNull::from(value).cast(); |
| 187 | /// let mut handle = WebOffscreenCanvasWindowHandle::new(obj); |
| 188 | /// ``` |
| 189 | pub fn new(obj: NonNull<c_void>) -> Self { |
| 190 | Self { obj } |
| 191 | } |
| 192 | } |
| 193 | |
| 194 | #[cfg (all(target_family = "wasm" , feature = "wasm-bindgen-0-2" ))] |
| 195 | #[cfg_attr ( |
| 196 | docsrs, |
| 197 | doc(cfg(all(target_family = "wasm" , feature = "wasm-bindgen-0-2" ))) |
| 198 | )] |
| 199 | /// These implementations are only available when `wasm-bindgen-0-2` is enabled. |
| 200 | impl WebOffscreenCanvasWindowHandle { |
| 201 | /// Create a new `WebOffscreenCanvasWindowHandle` from a |
| 202 | /// [`wasm_bindgen::JsValue`]. |
| 203 | /// |
| 204 | /// The `JsValue` should refer to a `HtmlCanvasElement`, and the lifetime |
| 205 | /// of the value should be at least as long as the lifetime of this. |
| 206 | pub fn from_wasm_bindgen_0_2(js_value: &wasm_bindgen::JsValue) -> Self { |
| 207 | Self::new(NonNull::from(js_value).cast()) |
| 208 | } |
| 209 | |
| 210 | /// Convert to the underlying [`wasm_bindgen::JsValue`]. |
| 211 | /// |
| 212 | /// # Safety |
| 213 | /// |
| 214 | /// The inner pointer must be valid. This is ensured if this handle was |
| 215 | /// borrowed from [`WindowHandle`][crate::WindowHandle]. |
| 216 | pub unsafe fn as_wasm_bindgen_0_2(&self) -> &wasm_bindgen::JsValue { |
| 217 | unsafe { self.obj.cast().as_ref() } |
| 218 | } |
| 219 | } |
| 220 | |