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#[cfg(all(not(feature = "std"), target_os = "android"))]
6compile_error!("Using borrowed handles on Android requires the `std` feature to be enabled.");
7
8use core::fmt;
9use core::hash::{Hash, Hasher};
10use core::marker::PhantomData;
11
12use crate::{HasRawDisplayHandle, HasRawWindowHandle, RawDisplayHandle, RawWindowHandle};
13
14/// Keeps track of whether the application is currently active.
15///
16/// On certain platforms (e.g. Android), it is possible for the application to enter a "suspended"
17/// state. While in this state, all previously valid window handles become invalid. Therefore, in
18/// order for window handles to be valid, the application must be active.
19///
20/// On platforms where the graphical user interface is always active, this type is a ZST and all
21/// of its methods are noops. On Android, this type acts as a reference counter that keeps track
22/// of all currently active window handles. Before the application enters the suspended state, it
23/// blocks until all of the currently active window handles are dropped.
24///
25/// ## Explanation
26///
27/// On Android, there is an [Activity]-global [`ANativeWindow`] object that is used for drawing. This
28/// handle is used [within the `RawWindowHandle` type] for Android NDK, since it is necessary for GFX
29/// APIs to draw to the screen.
30///
31/// However, the [`ANativeWindow`] type can be arbitrarily invalidated by the underlying Android runtime.
32/// The reasoning for this is complicated, but this idea is exposed to native code through the
33/// [`onNativeWindowCreated`] and [`onNativeWindowDestroyed`] callbacks. To save you a click, the
34/// conditions associated with these callbacks are:
35///
36/// - [`onNativeWindowCreated`] provides a valid [`ANativeWindow`] pointer that can be used for drawing.
37/// - [`onNativeWindowDestroyed`] indicates that the previous [`ANativeWindow`] pointer is no longer
38/// valid. The documentation clarifies that, *once the function returns*, the [`ANativeWindow`] pointer
39/// can no longer be used for drawing without resulting in undefined behavior.
40///
41/// In [`winit`], these are exposed via the [`Resumed`] and [`Suspended`] events, respectively. Therefore,
42/// between the last [`Suspended`] event and the next [`Resumed`] event, it is undefined behavior to use
43/// the raw window handle. This condition makes it tricky to define an API that safely wraps the raw
44/// window handles, since an existing window handle can be made invalid at any time.
45///
46/// The Android docs specifies that the [`ANativeWindow`] pointer is still valid while the application
47/// is still in the [`onNativeWindowDestroyed`] block, and suggests that synchronization needs to take
48/// place to ensure that the pointer has been invalidated before the function returns. `Active` aims
49/// to be the solution to this problem. It keeps track of all currently active window handles, and
50/// blocks until all of them are dropped before allowing the application to enter the suspended state.
51///
52/// [Activity]: https://developer.android.com/reference/android/app/Activity
53/// [`ANativeWindow`]: https://developer.android.com/ndk/reference/group/a-native-window
54/// [within the `RawWindowHandle` type]: struct.AndroidNdkWindowHandle.html#structfield.a_native_window
55/// [`onNativeWindowCreated`]: https://developer.android.com/ndk/reference/struct/a-native-activity-callbacks#onnativewindowcreated
56/// [`onNativeWindowDestroyed`]: https://developer.android.com/ndk/reference/struct/a-native-activity-callbacks#onnativewindowdestroyed
57/// [`Resumed`]: https://docs.rs/winit/latest/winit/event/enum.Event.html#variant.Resumed
58/// [`Suspended`]: https://docs.rs/winit/latest/winit/event/enum.Event.html#variant.Suspended
59/// [`sdl2`]: https://crates.io/crates/sdl2
60/// [`RawWindowHandle`]: https://docs.rs/raw-window-handle/latest/raw_window_handle/enum.RawWindowHandle.html
61/// [`HasRawWindowHandle`]: https://docs.rs/raw-window-handle/latest/raw_window_handle/trait.HasRawWindowHandle.html
62/// [`winit`]: https://crates.io/crates/winit
63pub struct Active(imp::Active);
64
65impl fmt::Debug for Active {
66 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67 f.write_str(data:"Active { .. }")
68 }
69}
70
71/// Represents a live window handle.
72///
73/// This is carried around by the [`Active`] type, and is used to ensure that the application doesn't
74/// enter the suspended state while there are still live window handles. See documentation on the
75/// [`Active`] type for more information.
76///
77/// On non-Android platforms, this is a ZST. On Android, this is a reference counted handle that
78/// keeps the application active while it is alive.
79#[derive(Clone)]
80pub struct ActiveHandle<'a>(imp::ActiveHandle<'a>);
81
82impl<'a> fmt::Debug for ActiveHandle<'a> {
83 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
84 f.write_str(data:"ActiveHandle { .. }")
85 }
86}
87
88impl Active {
89 /// Create a new `Active` tracker.
90 ///
91 /// Only one of these should exist per display connection.
92 ///
93 /// # Example
94 ///
95 /// ```
96 /// use raw_window_handle::Active;
97 /// let active = Active::new();
98 /// ```
99 pub const fn new() -> Self {
100 Self(imp::Active::new())
101 }
102
103 /// Get a live window handle.
104 ///
105 /// This function returns an active handle if the application is active, and `None` otherwise.
106 ///
107 /// # Example
108 ///
109 /// ```
110 /// use raw_window_handle::Active;
111 ///
112 /// // Set the application to be active.
113 /// let active = Active::new();
114 /// unsafe { active.set_active() };
115 ///
116 /// // Get a live window handle.
117 /// let handle = active.handle();
118 ///
119 /// // Drop it and set the application to be inactive.
120 /// drop(handle);
121 /// active.set_inactive();
122 /// ```
123 pub fn handle(&self) -> Option<ActiveHandle<'_>> {
124 self.0.handle().map(ActiveHandle)
125 }
126
127 /// Set the application to be inactive.
128 ///
129 /// This function may block until there are no more active handles.
130 ///
131 /// # Example
132 ///
133 /// ```
134 /// use raw_window_handle::Active;
135 ///
136 /// // Set the application to be active.
137 /// let active = Active::new();
138 /// unsafe { active.set_active() };
139 ///
140 /// // Set the application to be inactive.
141 /// active.set_inactive();
142 /// ```
143 pub fn set_inactive(&self) {
144 self.0.set_inactive()
145 }
146
147 /// Set the application to be active.
148 ///
149 /// # Safety
150 ///
151 /// The application must actually be active. Setting to active when the application is not active
152 /// will result in undefined behavior.
153 ///
154 /// # Example
155 ///
156 /// ```
157 /// use raw_window_handle::Active;
158 ///
159 /// // Set the application to be active.
160 /// let active = Active::new();
161 /// unsafe { active.set_active() };
162 ///
163 /// // Set the application to be inactive.
164 /// active.set_inactive();
165 /// ```
166 pub unsafe fn set_active(&self) {
167 self.0.set_active()
168 }
169}
170
171impl ActiveHandle<'_> {
172 /// Create a new freestanding active handle.
173 ///
174 /// This function acts as an "escape hatch" to allow the user to create a live window handle
175 /// without having to go through the [`Active`] type. This is useful if the user *knows* that the
176 /// application is active, and wants to create a live window handle without having to go through
177 /// the [`Active`] type.
178 ///
179 /// # Safety
180 ///
181 /// The application must actually be active.
182 ///
183 /// # Example
184 ///
185 /// ```
186 /// use raw_window_handle::ActiveHandle;
187 ///
188 /// // Create a freestanding active handle.
189 /// // SAFETY: The application must actually be active.
190 /// let handle = unsafe { ActiveHandle::new_unchecked() };
191 /// ```
192 pub unsafe fn new_unchecked() -> Self {
193 Self(imp::ActiveHandle::new_unchecked())
194 }
195}
196
197/// A display that acts as a wrapper around a display handle.
198///
199/// Objects that implement this trait should be able to return a [`DisplayHandle`] for the display
200/// that they are associated with. This handle should last for the lifetime of the object, and should
201/// return an error if the application is inactive.
202///
203/// Implementors of this trait will be windowing systems, like [`winit`] and [`sdl2`]. These windowing
204/// systems should implement this trait on types that already implement [`HasRawDisplayHandle`]. It
205/// should be implemented by tying the lifetime of the [`DisplayHandle`] to the lifetime of the
206/// display object.
207///
208/// Users of this trait will include graphics libraries, like [`wgpu`] and [`glutin`]. These APIs
209/// should be generic over a type that implements `HasDisplayHandle`, and should use the
210/// [`DisplayHandle`] type to access the display handle.
211///
212/// # Safety
213///
214/// The safety requirements of [`HasRawDisplayHandle`] apply here as well. To reiterate, the
215/// [`DisplayHandle`] must contain a valid window handle for its lifetime.
216///
217/// It is not possible to invalidate a [`DisplayHandle`] on any platform without additional unsafe code.
218///
219/// Note that these requirements are not enforced on `HasDisplayHandle`, rather, they are enforced on the
220/// constructors of [`DisplayHandle`]. This is because the `HasDisplayHandle` trait is safe to implement.
221///
222/// [`HasRawDisplayHandle`]: crate::HasRawDisplayHandle
223/// [`winit`]: https://crates.io/crates/winit
224/// [`sdl2`]: https://crates.io/crates/sdl2
225/// [`wgpu`]: https://crates.io/crates/wgpu
226/// [`glutin`]: https://crates.io/crates/glutin
227pub trait HasDisplayHandle {
228 /// Get a handle to the display controller of the windowing system.
229 fn display_handle(&self) -> Result<DisplayHandle<'_>, HandleError>;
230}
231
232impl<H: HasDisplayHandle + ?Sized> HasDisplayHandle for &H {
233 fn display_handle(&self) -> Result<DisplayHandle<'_>, HandleError> {
234 (**self).display_handle()
235 }
236}
237
238#[cfg(feature = "alloc")]
239impl<H: HasDisplayHandle + ?Sized> HasDisplayHandle for alloc::boxed::Box<H> {
240 fn display_handle(&self) -> Result<DisplayHandle<'_>, HandleError> {
241 (**self).display_handle()
242 }
243}
244
245#[cfg(feature = "alloc")]
246impl<H: HasDisplayHandle + ?Sized> HasDisplayHandle for alloc::rc::Rc<H> {
247 fn display_handle(&self) -> Result<DisplayHandle<'_>, HandleError> {
248 (**self).display_handle()
249 }
250}
251
252#[cfg(feature = "alloc")]
253impl<H: HasDisplayHandle + ?Sized> HasDisplayHandle for alloc::sync::Arc<H> {
254 fn display_handle(&self) -> Result<DisplayHandle<'_>, HandleError> {
255 (**self).display_handle()
256 }
257}
258
259/// The handle to the display controller of the windowing system.
260///
261/// This is the primary return type of the [`HasDisplayHandle`] trait. It is guaranteed to contain
262/// a valid platform-specific display handle for its lifetime.
263///
264/// Get the underlying raw display handle with the [`HasRawDisplayHandle`] trait.
265#[repr(transparent)]
266#[derive(PartialEq, Eq, Hash)]
267pub struct DisplayHandle<'a> {
268 raw: RawDisplayHandle,
269 _marker: PhantomData<&'a *const ()>,
270}
271
272impl fmt::Debug for DisplayHandle<'_> {
273 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
274 f.debug_tuple(name:"DisplayHandle").field(&self.raw).finish()
275 }
276}
277
278impl<'a> Clone for DisplayHandle<'a> {
279 fn clone(&self) -> Self {
280 Self {
281 raw: self.raw,
282 _marker: PhantomData,
283 }
284 }
285}
286
287impl<'a> DisplayHandle<'a> {
288 /// Create a `DisplayHandle` from a [`RawDisplayHandle`].
289 ///
290 /// # Safety
291 ///
292 /// The `RawDisplayHandle` must be valid for the lifetime.
293 pub unsafe fn borrow_raw(raw: RawDisplayHandle) -> Self {
294 Self {
295 raw,
296 _marker: PhantomData,
297 }
298 }
299}
300
301unsafe impl HasRawDisplayHandle for DisplayHandle<'_> {
302 fn raw_display_handle(&self) -> RawDisplayHandle {
303 self.raw
304 }
305}
306
307impl<'a> HasDisplayHandle for DisplayHandle<'a> {
308 fn display_handle(&self) -> Result<DisplayHandle<'_>, HandleError> {
309 Ok(self.clone())
310 }
311}
312
313/// A handle to a window.
314///
315/// Objects that implement this trait should be able to return a [`WindowHandle`] for the window
316/// that they are associated with. This handle should last for the lifetime of the object, and should
317/// return an error if the application is inactive.
318///
319/// Implementors of this trait will be windowing systems, like [`winit`] and [`sdl2`]. These windowing
320/// systems should implement this trait on types that already implement [`HasRawWindowHandle`]. First,
321/// it should be made sure that the display type contains a unique [`Active`] ref-counted handle.
322/// To create a [`WindowHandle`], the [`Active`] should be used to create an [`ActiveHandle`] that is
323/// then used to create a [`WindowHandle`]. Finally, the raw window handle should be retrieved from
324/// the type and used to create a [`WindowHandle`].
325///
326/// Users of this trait will include graphics libraries, like [`wgpu`] and [`glutin`]. These APIs
327/// should be generic over a type that implements `HasWindowHandle`, and should use the
328/// [`WindowHandle`] type to access the window handle. The window handle should be acquired and held
329/// while the window is being used, in order to ensure that the window is not deleted while it is in
330/// use.
331///
332/// # Safety
333///
334/// All pointers within the resulting [`WindowHandle`] must be valid and not dangling for the lifetime of
335/// the handle.
336///
337/// Note that this guarantee only applies to *pointers*, and not any window ID types in the handle.
338/// This includes Window IDs (XIDs) from X11 and the window ID for web platforms. There is no way for
339/// Rust to enforce any kind of invariant on these types, since:
340///
341/// - For all three listed platforms, it is possible for safe code in the same process to delete
342/// the window.
343/// - For X11, it is possible for code in a different process to delete the window. In fact, it is
344/// possible for code on a different *machine* to delete the window.
345///
346/// It is *also* possible for the window to be replaced with another, valid-but-different window. User
347/// code should be aware of this possibility, and should be ready to soundly handle the possible error
348/// conditions that can arise from this.
349///
350/// In addition, the window handle must not be invalidated for the duration of the [`ActiveHandle`] token.
351///
352/// Note that these requirements are not enforced on `HasWindowHandle`, rather, they are enforced on the
353/// constructors of [`WindowHandle`]. This is because the `HasWindowHandle` trait is safe to implement.
354///
355/// [`winit`]: https://crates.io/crates/winit
356/// [`sdl2`]: https://crates.io/crates/sdl2
357/// [`wgpu`]: https://crates.io/crates/wgpu
358/// [`glutin`]: https://crates.io/crates/glutin
359pub trait HasWindowHandle {
360 /// Get a handle to the window.
361 fn window_handle(&self) -> Result<WindowHandle<'_>, HandleError>;
362}
363
364impl<H: HasWindowHandle + ?Sized> HasWindowHandle for &H {
365 fn window_handle(&self) -> Result<WindowHandle<'_>, HandleError> {
366 (**self).window_handle()
367 }
368}
369
370#[cfg(feature = "alloc")]
371impl<H: HasWindowHandle + ?Sized> HasWindowHandle for alloc::boxed::Box<H> {
372 fn window_handle(&self) -> Result<WindowHandle<'_>, HandleError> {
373 (**self).window_handle()
374 }
375}
376
377#[cfg(feature = "alloc")]
378impl<H: HasWindowHandle + ?Sized> HasWindowHandle for alloc::rc::Rc<H> {
379 fn window_handle(&self) -> Result<WindowHandle<'_>, HandleError> {
380 (**self).window_handle()
381 }
382}
383
384#[cfg(feature = "alloc")]
385impl<H: HasWindowHandle + ?Sized> HasWindowHandle for alloc::sync::Arc<H> {
386 fn window_handle(&self) -> Result<WindowHandle<'_>, HandleError> {
387 (**self).window_handle()
388 }
389}
390
391/// The handle to a window.
392///
393/// This is the primary return type of the [`HasWindowHandle`] trait. All *pointers* within this type
394/// are guaranteed to be valid and not dangling for the lifetime of the handle. This excludes window IDs
395/// like XIDs and the window ID for web platforms. See the documentation on the [`HasWindowHandle`]
396/// trait for more information about these safety requirements.
397///
398/// This handle is guaranteed to be safe and valid. Get the underlying raw window handle with the
399/// [`HasRawWindowHandle`] trait.
400#[derive(Clone)]
401pub struct WindowHandle<'a> {
402 raw: RawWindowHandle,
403 _active: ActiveHandle<'a>,
404 _marker: PhantomData<&'a *const ()>,
405}
406
407impl fmt::Debug for WindowHandle<'_> {
408 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
409 f.debug_tuple(name:"WindowHandle").field(&self.raw).finish()
410 }
411}
412
413impl PartialEq for WindowHandle<'_> {
414 fn eq(&self, other: &Self) -> bool {
415 self.raw == other.raw
416 }
417}
418
419impl Eq for WindowHandle<'_> {}
420
421impl Hash for WindowHandle<'_> {
422 fn hash<H: Hasher>(&self, state: &mut H) {
423 self.raw.hash(state);
424 }
425}
426
427impl<'a> WindowHandle<'a> {
428 /// Borrow a `WindowHandle` from a [`RawWindowHandle`].
429 ///
430 /// # Safety
431 ///
432 /// The [`RawWindowHandle`] must be valid for the lifetime and the application must not be
433 /// suspended. The [`Active`] object that the [`ActiveHandle`] was created from must be
434 /// associated directly with the display that the window handle is associated with.
435 pub unsafe fn borrow_raw(raw: RawWindowHandle, active: ActiveHandle<'a>) -> Self {
436 Self {
437 raw,
438 _active: active,
439 _marker: PhantomData,
440 }
441 }
442}
443
444unsafe impl HasRawWindowHandle for WindowHandle<'_> {
445 fn raw_window_handle(&self) -> RawWindowHandle {
446 self.raw
447 }
448}
449
450impl HasWindowHandle for WindowHandle<'_> {
451 fn window_handle(&self) -> Result<Self, HandleError> {
452 Ok(self.clone())
453 }
454}
455
456/// The error type returned when a handle cannot be obtained.
457#[derive(Debug)]
458#[non_exhaustive]
459pub enum HandleError {
460 /// The handle is not currently active.
461 ///
462 /// See documentation on [`Active`] for more information.
463 Inactive,
464}
465
466impl fmt::Display for HandleError {
467 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
468 match self {
469 Self::Inactive => write!(f, "the handle is not currently active"),
470 }
471 }
472}
473
474#[cfg(feature = "std")]
475impl std::error::Error for HandleError {}
476
477/// ```compile_fail
478/// use raw_window_handle::{Active, DisplayHandle, WindowHandle};
479/// fn _assert<T: Send + Sync>() {}
480/// _assert::<Active<'static>>();
481/// _assert::<DisplayHandle<'static>>();
482/// _assert::<WindowHandle<'static>>();
483/// ```
484fn _not_send_or_sync() {}
485
486#[cfg(not(any(target_os = "android", raw_window_handle_force_refcount)))]
487#[cfg_attr(docsrs, doc(cfg(not(target_os = "android"))))]
488mod imp {
489 //! We don't need to refcount the handles, so we can just use no-ops.
490
491 use core::cell::UnsafeCell;
492 use core::marker::PhantomData;
493
494 pub(super) struct Active;
495
496 #[derive(Clone)]
497 pub(super) struct ActiveHandle<'a> {
498 _marker: PhantomData<&'a UnsafeCell<()>>,
499 }
500
501 impl Active {
502 pub(super) const fn new() -> Self {
503 Self
504 }
505
506 pub(super) fn handle(&self) -> Option<ActiveHandle<'_>> {
507 // SAFETY: The handle is always active.
508 Some(unsafe { ActiveHandle::new_unchecked() })
509 }
510
511 pub(super) unsafe fn set_active(&self) {}
512
513 pub(super) fn set_inactive(&self) {}
514 }
515
516 impl ActiveHandle<'_> {
517 pub(super) unsafe fn new_unchecked() -> Self {
518 Self {
519 _marker: PhantomData,
520 }
521 }
522 }
523
524 impl Drop for ActiveHandle<'_> {
525 fn drop(&mut self) {
526 // Done for consistency with the refcounted version.
527 }
528 }
529
530 impl super::ActiveHandle<'_> {
531 /// Create a new `ActiveHandle`.
532 ///
533 /// This is safe because the handle is always active.
534 ///
535 /// # Example
536 ///
537 /// ```
538 /// use raw_window_handle::ActiveHandle;
539 /// let handle = ActiveHandle::new();
540 /// ```
541 #[allow(clippy::new_without_default)]
542 pub fn new() -> Self {
543 // SAFETY: The handle is always active.
544 unsafe { super::ActiveHandle::new_unchecked() }
545 }
546 }
547}
548
549#[cfg(any(target_os = "android", raw_window_handle_force_refcount))]
550#[cfg_attr(docsrs, doc(cfg(any(target_os = "android"))))]
551mod imp {
552 //! We need to refcount the handles, so we use an `RwLock` to do so.
553
554 use std::sync::{RwLock, RwLockReadGuard};
555
556 pub(super) struct Active {
557 active: RwLock<bool>,
558 }
559
560 pub(super) struct ActiveHandle<'a> {
561 inner: Option<Inner<'a>>,
562 }
563
564 struct Inner<'a> {
565 _read_guard: RwLockReadGuard<'a, bool>,
566 active: &'a Active,
567 }
568
569 impl Clone for ActiveHandle<'_> {
570 fn clone(&self) -> Self {
571 Self {
572 inner: self.inner.as_ref().map(|inner| Inner {
573 _read_guard: inner.active.active.read().unwrap(),
574 active: inner.active,
575 }),
576 }
577 }
578 }
579
580 impl Active {
581 pub(super) const fn new() -> Self {
582 Self {
583 active: RwLock::new(false),
584 }
585 }
586
587 pub(super) fn handle(&self) -> Option<ActiveHandle<'_>> {
588 let active = self.active.read().ok()?;
589 if !*active {
590 return None;
591 }
592
593 Some(ActiveHandle {
594 inner: Some(Inner {
595 _read_guard: active,
596 active: self,
597 }),
598 })
599 }
600
601 pub(super) unsafe fn set_active(&self) {
602 *self.active.write().unwrap() = true;
603 }
604
605 pub(super) fn set_inactive(&self) {
606 *self.active.write().unwrap() = false;
607 }
608 }
609
610 impl ActiveHandle<'_> {
611 pub(super) unsafe fn new_unchecked() -> Self {
612 Self { inner: None }
613 }
614 }
615}
616