| 1 | //! Borrowable window handles based on the ones in this crate. |
| 2 | //! |
| 3 | //! These should be 100% safe to pass around and use, no possibility of dangling or invalidity. |
| 4 | |
| 5 | use core::borrow::Borrow; |
| 6 | use core::fmt; |
| 7 | use core::marker::PhantomData; |
| 8 | |
| 9 | use crate::{HandleError, RawDisplayHandle, RawWindowHandle}; |
| 10 | |
| 11 | /// A display that acts as a wrapper around a display handle. |
| 12 | /// |
| 13 | /// Objects that implement this trait should be able to return a [`DisplayHandle`] for the display |
| 14 | /// that they are associated with. This handle should last for the lifetime of the object, and should |
| 15 | /// return an error if the application is inactive. |
| 16 | /// |
| 17 | /// Implementors of this trait will be windowing systems, like [`winit`] and [`sdl2`]. These windowing |
| 18 | /// systems should implement this trait on types that represent the top-level display server. It |
| 19 | /// should be implemented by tying the lifetime of the [`DisplayHandle`] to the lifetime of the |
| 20 | /// display object. |
| 21 | /// |
| 22 | /// Users of this trait will include graphics libraries, like [`wgpu`] and [`glutin`]. These APIs |
| 23 | /// should be generic over a type that implements `HasDisplayHandle`, and should use the |
| 24 | /// [`DisplayHandle`] type to access the display handle. |
| 25 | /// |
| 26 | /// Note that these requirements are not enforced on `HasDisplayHandle`, rather, they are enforced on the |
| 27 | /// constructors of [`DisplayHandle`]. This is because the `HasDisplayHandle` trait is safe to implement. |
| 28 | /// |
| 29 | /// [`winit`]: https://crates.io/crates/winit |
| 30 | /// [`sdl2`]: https://crates.io/crates/sdl2 |
| 31 | /// [`wgpu`]: https://crates.io/crates/wgpu |
| 32 | /// [`glutin`]: https://crates.io/crates/glutin |
| 33 | pub trait HasDisplayHandle { |
| 34 | /// Get a handle to the display controller of the windowing system. |
| 35 | fn display_handle(&self) -> Result<DisplayHandle<'_>, HandleError>; |
| 36 | } |
| 37 | |
| 38 | impl<H: HasDisplayHandle + ?Sized> HasDisplayHandle for &H { |
| 39 | fn display_handle(&self) -> Result<DisplayHandle<'_>, HandleError> { |
| 40 | (**self).display_handle() |
| 41 | } |
| 42 | } |
| 43 | |
| 44 | impl<H: HasDisplayHandle + ?Sized> HasDisplayHandle for &mut H { |
| 45 | fn display_handle(&self) -> Result<DisplayHandle<'_>, HandleError> { |
| 46 | (**self).display_handle() |
| 47 | } |
| 48 | } |
| 49 | |
| 50 | #[cfg (feature = "alloc" )] |
| 51 | #[cfg_attr (docsrs, doc(cfg(feature = "alloc" )))] |
| 52 | impl<H: HasDisplayHandle + ?Sized> HasDisplayHandle for alloc::boxed::Box<H> { |
| 53 | fn display_handle(&self) -> Result<DisplayHandle<'_>, HandleError> { |
| 54 | (**self).display_handle() |
| 55 | } |
| 56 | } |
| 57 | |
| 58 | #[cfg (feature = "alloc" )] |
| 59 | #[cfg_attr (docsrs, doc(cfg(feature = "alloc" )))] |
| 60 | impl<H: HasDisplayHandle + ?Sized> HasDisplayHandle for alloc::rc::Rc<H> { |
| 61 | fn display_handle(&self) -> Result<DisplayHandle<'_>, HandleError> { |
| 62 | (**self).display_handle() |
| 63 | } |
| 64 | } |
| 65 | |
| 66 | #[cfg (feature = "alloc" )] |
| 67 | #[cfg_attr (docsrs, doc(cfg(feature = "alloc" )))] |
| 68 | impl<H: HasDisplayHandle + ?Sized> HasDisplayHandle for alloc::sync::Arc<H> { |
| 69 | fn display_handle(&self) -> Result<DisplayHandle<'_>, HandleError> { |
| 70 | (**self).display_handle() |
| 71 | } |
| 72 | } |
| 73 | |
| 74 | /// The handle to the display controller of the windowing system. |
| 75 | /// |
| 76 | /// This is the primary return type of the [`HasDisplayHandle`] trait. It is guaranteed to contain |
| 77 | /// a valid platform-specific display handle for its lifetime. |
| 78 | #[repr (transparent)] |
| 79 | #[derive (PartialEq, Eq, Hash, Copy, Clone)] |
| 80 | pub struct DisplayHandle<'a> { |
| 81 | raw: RawDisplayHandle, |
| 82 | _marker: PhantomData<&'a ()>, |
| 83 | } |
| 84 | |
| 85 | impl fmt::Debug for DisplayHandle<'_> { |
| 86 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 87 | f.debug_tuple(name:"DisplayHandle" ).field(&self.raw).finish() |
| 88 | } |
| 89 | } |
| 90 | |
| 91 | impl<'a> DisplayHandle<'a> { |
| 92 | /// Create a `DisplayHandle` from a [`RawDisplayHandle`]. |
| 93 | /// |
| 94 | /// # Safety |
| 95 | /// |
| 96 | /// Users can safely assume that non-`null`/`0` fields are valid handles, and it is up to the |
| 97 | /// implementer of this trait to ensure that condition is upheld. |
| 98 | /// |
| 99 | /// Despite that qualification, implementors should still make a best-effort attempt to fill in all |
| 100 | /// available fields. If an implementation doesn't, and a downstream user needs the field, it should |
| 101 | /// try to derive the field from other fields the implementer *does* provide via whatever methods the |
| 102 | /// platform provides. |
| 103 | /// |
| 104 | /// It is not possible to invalidate a [`DisplayHandle`] on any platform without additional unsafe code. |
| 105 | pub unsafe fn borrow_raw(raw: RawDisplayHandle) -> Self { |
| 106 | Self { |
| 107 | raw, |
| 108 | _marker: PhantomData, |
| 109 | } |
| 110 | } |
| 111 | |
| 112 | /// Get the underlying raw display handle. |
| 113 | pub fn as_raw(&self) -> RawDisplayHandle { |
| 114 | self.raw |
| 115 | } |
| 116 | } |
| 117 | |
| 118 | impl AsRef<RawDisplayHandle> for DisplayHandle<'_> { |
| 119 | fn as_ref(&self) -> &RawDisplayHandle { |
| 120 | &self.raw |
| 121 | } |
| 122 | } |
| 123 | |
| 124 | impl Borrow<RawDisplayHandle> for DisplayHandle<'_> { |
| 125 | fn borrow(&self) -> &RawDisplayHandle { |
| 126 | &self.raw |
| 127 | } |
| 128 | } |
| 129 | |
| 130 | impl From<DisplayHandle<'_>> for RawDisplayHandle { |
| 131 | fn from(handle: DisplayHandle<'_>) -> Self { |
| 132 | handle.raw |
| 133 | } |
| 134 | } |
| 135 | |
| 136 | impl<'a> HasDisplayHandle for DisplayHandle<'a> { |
| 137 | fn display_handle(&self) -> Result<DisplayHandle<'_>, HandleError> { |
| 138 | Ok(*self) |
| 139 | } |
| 140 | } |
| 141 | |
| 142 | /// A handle to a window. |
| 143 | /// |
| 144 | /// Objects that implement this trait should be able to return a [`WindowHandle`] for the window |
| 145 | /// that they are associated with. This handle should last for the lifetime of the object, and should |
| 146 | /// return an error if the application is inactive. |
| 147 | /// |
| 148 | /// Implementors of this trait will be windowing systems, like [`winit`] and [`sdl2`]. These windowing |
| 149 | /// systems should implement this trait on types that represent windows. |
| 150 | /// |
| 151 | /// Users of this trait will include graphics libraries, like [`wgpu`] and [`glutin`]. These APIs |
| 152 | /// should be generic over a type that implements `HasWindowHandle`, and should use the |
| 153 | /// [`WindowHandle`] type to access the window handle. The window handle should be acquired and held |
| 154 | /// while the window is being used, in order to ensure that the window is not deleted while it is in |
| 155 | /// use. |
| 156 | /// |
| 157 | /// [`winit`]: https://crates.io/crates/winit |
| 158 | /// [`sdl2`]: https://crates.io/crates/sdl2 |
| 159 | /// [`wgpu`]: https://crates.io/crates/wgpu |
| 160 | /// [`glutin`]: https://crates.io/crates/glutin |
| 161 | pub trait HasWindowHandle { |
| 162 | /// Get a handle to the window. |
| 163 | fn window_handle(&self) -> Result<WindowHandle<'_>, HandleError>; |
| 164 | } |
| 165 | |
| 166 | impl<H: HasWindowHandle + ?Sized> HasWindowHandle for &H { |
| 167 | fn window_handle(&self) -> Result<WindowHandle<'_>, HandleError> { |
| 168 | (**self).window_handle() |
| 169 | } |
| 170 | } |
| 171 | |
| 172 | impl<H: HasWindowHandle + ?Sized> HasWindowHandle for &mut H { |
| 173 | fn window_handle(&self) -> Result<WindowHandle<'_>, HandleError> { |
| 174 | (**self).window_handle() |
| 175 | } |
| 176 | } |
| 177 | |
| 178 | #[cfg (feature = "alloc" )] |
| 179 | #[cfg_attr (docsrs, doc(cfg(feature = "alloc" )))] |
| 180 | impl<H: HasWindowHandle + ?Sized> HasWindowHandle for alloc::boxed::Box<H> { |
| 181 | fn window_handle(&self) -> Result<WindowHandle<'_>, HandleError> { |
| 182 | (**self).window_handle() |
| 183 | } |
| 184 | } |
| 185 | |
| 186 | #[cfg (feature = "alloc" )] |
| 187 | #[cfg_attr (docsrs, doc(cfg(feature = "alloc" )))] |
| 188 | impl<H: HasWindowHandle + ?Sized> HasWindowHandle for alloc::rc::Rc<H> { |
| 189 | fn window_handle(&self) -> Result<WindowHandle<'_>, HandleError> { |
| 190 | (**self).window_handle() |
| 191 | } |
| 192 | } |
| 193 | |
| 194 | #[cfg (feature = "alloc" )] |
| 195 | #[cfg_attr (docsrs, doc(cfg(feature = "alloc" )))] |
| 196 | impl<H: HasWindowHandle + ?Sized> HasWindowHandle for alloc::sync::Arc<H> { |
| 197 | fn window_handle(&self) -> Result<WindowHandle<'_>, HandleError> { |
| 198 | (**self).window_handle() |
| 199 | } |
| 200 | } |
| 201 | |
| 202 | /// The handle to a window. |
| 203 | /// |
| 204 | /// This is the primary return type of the [`HasWindowHandle`] trait. All *pointers* within this type |
| 205 | /// are guaranteed to be valid and not dangling for the lifetime of the handle. This excludes window IDs |
| 206 | /// like XIDs and the window ID for web platforms. See the documentation on the [`HasWindowHandle`] |
| 207 | /// trait for more information about these safety requirements. |
| 208 | /// |
| 209 | /// This handle is guaranteed to be safe and valid. |
| 210 | #[derive (PartialEq, Eq, Hash, Copy, Clone)] |
| 211 | pub struct WindowHandle<'a> { |
| 212 | raw: RawWindowHandle, |
| 213 | _marker: PhantomData<&'a ()>, |
| 214 | } |
| 215 | |
| 216 | impl fmt::Debug for WindowHandle<'_> { |
| 217 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 218 | f.debug_tuple(name:"WindowHandle" ).field(&self.raw).finish() |
| 219 | } |
| 220 | } |
| 221 | |
| 222 | impl<'a> WindowHandle<'a> { |
| 223 | /// Borrow a `WindowHandle` from a [`RawWindowHandle`]. |
| 224 | /// |
| 225 | /// # Safety |
| 226 | /// |
| 227 | /// Users can safely assume that non-`null`/`0` fields are valid handles, and it is up to the |
| 228 | /// implementer of this trait to ensure that condition is upheld. |
| 229 | /// |
| 230 | /// Despite that qualification, implementers should still make a best-effort attempt to fill in all |
| 231 | /// available fields. If an implementation doesn't, and a downstream user needs the field, it should |
| 232 | /// try to derive the field from other fields the implementer *does* provide via whatever methods the |
| 233 | /// platform provides. |
| 234 | /// |
| 235 | /// Note that this guarantee only applies to *pointers*, and not any window ID types in the handle. |
| 236 | /// This includes Window IDs (XIDs) from X11 and the window ID for web platforms. There is no way for |
| 237 | /// Rust to enforce any kind of invariant on these types, since: |
| 238 | /// |
| 239 | /// - For all three listed platforms, it is possible for safe code in the same process to delete |
| 240 | /// the window. |
| 241 | /// - For X11, it is possible for code in a different process to delete the window. In fact, it is |
| 242 | /// possible for code on a different *machine* to delete the window. |
| 243 | /// |
| 244 | /// It is *also* possible for the window to be replaced with another, valid-but-different window. User |
| 245 | /// code should be aware of this possibility, and should be ready to soundly handle the possible error |
| 246 | /// conditions that can arise from this. |
| 247 | pub unsafe fn borrow_raw(raw: RawWindowHandle) -> Self { |
| 248 | Self { |
| 249 | raw, |
| 250 | _marker: PhantomData, |
| 251 | } |
| 252 | } |
| 253 | |
| 254 | /// Get the underlying raw window handle. |
| 255 | pub fn as_raw(&self) -> RawWindowHandle { |
| 256 | self.raw.clone() |
| 257 | } |
| 258 | } |
| 259 | |
| 260 | impl AsRef<RawWindowHandle> for WindowHandle<'_> { |
| 261 | fn as_ref(&self) -> &RawWindowHandle { |
| 262 | &self.raw |
| 263 | } |
| 264 | } |
| 265 | |
| 266 | impl Borrow<RawWindowHandle> for WindowHandle<'_> { |
| 267 | fn borrow(&self) -> &RawWindowHandle { |
| 268 | &self.raw |
| 269 | } |
| 270 | } |
| 271 | |
| 272 | impl From<WindowHandle<'_>> for RawWindowHandle { |
| 273 | fn from(handle: WindowHandle<'_>) -> Self { |
| 274 | handle.raw |
| 275 | } |
| 276 | } |
| 277 | |
| 278 | impl HasWindowHandle for WindowHandle<'_> { |
| 279 | fn window_handle(&self) -> Result<Self, HandleError> { |
| 280 | Ok(*self) |
| 281 | } |
| 282 | } |
| 283 | |