raw_window_handle/
borrowed.rs

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 ()>,
83}
84
85impl fmt::Debug for DisplayHandle<'_> {
86    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
87        f.debug_tuple("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 ()>,
214}
215
216impl fmt::Debug for WindowHandle<'_> {
217    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
218        f.debug_tuple("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}