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
5use core::borrow::Borrow;
6use core::fmt;
7use core::marker::PhantomData;
8
9use 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
33pub trait HasDisplayHandle {
34 /// Get a handle to the display controller of the windowing system.
35 fn display_handle(&self) -> Result<DisplayHandle<'_>, HandleError>;
36}
37
38impl<H: HasDisplayHandle + ?Sized> HasDisplayHandle for &H {
39 fn display_handle(&self) -> Result<DisplayHandle<'_>, HandleError> {
40 (**self).display_handle()
41 }
42}
43
44impl<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")))]
52impl<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")))]
60impl<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")))]
68impl<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)]
80pub struct DisplayHandle<'a> {
81 raw: RawDisplayHandle,
82 _marker: PhantomData<&'a *const ()>,
83}
84
85impl 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
91impl<'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
118impl AsRef<RawDisplayHandle> for DisplayHandle<'_> {
119 fn as_ref(&self) -> &RawDisplayHandle {
120 &self.raw
121 }
122}
123
124impl Borrow<RawDisplayHandle> for DisplayHandle<'_> {
125 fn borrow(&self) -> &RawDisplayHandle {
126 &self.raw
127 }
128}
129
130impl From<DisplayHandle<'_>> for RawDisplayHandle {
131 fn from(handle: DisplayHandle<'_>) -> Self {
132 handle.raw
133 }
134}
135
136impl<'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
161pub trait HasWindowHandle {
162 /// Get a handle to the window.
163 fn window_handle(&self) -> Result<WindowHandle<'_>, HandleError>;
164}
165
166impl<H: HasWindowHandle + ?Sized> HasWindowHandle for &H {
167 fn window_handle(&self) -> Result<WindowHandle<'_>, HandleError> {
168 (**self).window_handle()
169 }
170}
171
172impl<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")))]
180impl<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")))]
188impl<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")))]
196impl<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)]
211pub struct WindowHandle<'a> {
212 raw: RawWindowHandle,
213 _marker: PhantomData<&'a *const ()>,
214}
215
216impl 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
222impl<'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
260impl AsRef<RawWindowHandle> for WindowHandle<'_> {
261 fn as_ref(&self) -> &RawWindowHandle {
262 &self.raw
263 }
264}
265
266impl Borrow<RawWindowHandle> for WindowHandle<'_> {
267 fn borrow(&self) -> &RawWindowHandle {
268 &self.raw
269 }
270}
271
272impl From<WindowHandle<'_>> for RawWindowHandle {
273 fn from(handle: WindowHandle<'_>) -> Self {
274 handle.raw
275 }
276}
277
278impl HasWindowHandle for WindowHandle<'_> {
279 fn window_handle(&self) -> Result<Self, HandleError> {
280 Ok(*self)
281 }
282}
283
284/// ```compile_fail
285/// use raw_window_handle::{DisplayHandle, WindowHandle};
286/// fn _assert<T: Send + Sync>() {}
287/// _assert::<DisplayHandle<'static>>();
288/// _assert::<WindowHandle<'static>>();
289/// ```
290fn _not_send_or_sync() {}
291