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" ))] |
6 | compile_error!("Using borrowed handles on Android requires the `std` feature to be enabled." ); |
7 | |
8 | use core::fmt; |
9 | use core::hash::{Hash, Hasher}; |
10 | use core::marker::PhantomData; |
11 | |
12 | use 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 |
63 | pub struct Active(imp::Active); |
64 | |
65 | impl 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)] |
80 | pub struct ActiveHandle<'a>(imp::ActiveHandle<'a>); |
81 | |
82 | impl<'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 | |
88 | impl 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 | |
171 | impl 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 |
227 | pub trait HasDisplayHandle { |
228 | /// Get a handle to the display controller of the windowing system. |
229 | fn display_handle(&self) -> Result<DisplayHandle<'_>, HandleError>; |
230 | } |
231 | |
232 | impl<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" )] |
239 | impl<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" )] |
246 | impl<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" )] |
253 | impl<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)] |
267 | pub struct DisplayHandle<'a> { |
268 | raw: RawDisplayHandle, |
269 | _marker: PhantomData<&'a *const ()>, |
270 | } |
271 | |
272 | impl 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 | |
278 | impl<'a> Clone for DisplayHandle<'a> { |
279 | fn clone(&self) -> Self { |
280 | Self { |
281 | raw: self.raw, |
282 | _marker: PhantomData, |
283 | } |
284 | } |
285 | } |
286 | |
287 | impl<'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 | |
301 | unsafe impl HasRawDisplayHandle for DisplayHandle<'_> { |
302 | fn raw_display_handle(&self) -> RawDisplayHandle { |
303 | self.raw |
304 | } |
305 | } |
306 | |
307 | impl<'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 |
359 | pub trait HasWindowHandle { |
360 | /// Get a handle to the window. |
361 | fn window_handle(&self) -> Result<WindowHandle<'_>, HandleError>; |
362 | } |
363 | |
364 | impl<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" )] |
371 | impl<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" )] |
378 | impl<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" )] |
385 | impl<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)] |
401 | pub struct WindowHandle<'a> { |
402 | raw: RawWindowHandle, |
403 | _active: ActiveHandle<'a>, |
404 | _marker: PhantomData<&'a *const ()>, |
405 | } |
406 | |
407 | impl 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 | |
413 | impl PartialEq for WindowHandle<'_> { |
414 | fn eq(&self, other: &Self) -> bool { |
415 | self.raw == other.raw |
416 | } |
417 | } |
418 | |
419 | impl Eq for WindowHandle<'_> {} |
420 | |
421 | impl Hash for WindowHandle<'_> { |
422 | fn hash<H: Hasher>(&self, state: &mut H) { |
423 | self.raw.hash(state); |
424 | } |
425 | } |
426 | |
427 | impl<'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 | |
444 | unsafe impl HasRawWindowHandle for WindowHandle<'_> { |
445 | fn raw_window_handle(&self) -> RawWindowHandle { |
446 | self.raw |
447 | } |
448 | } |
449 | |
450 | impl 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 ] |
459 | pub enum HandleError { |
460 | /// The handle is not currently active. |
461 | /// |
462 | /// See documentation on [`Active`] for more information. |
463 | Inactive, |
464 | } |
465 | |
466 | impl 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" )] |
475 | impl 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 | /// ``` |
484 | fn _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" ))))] |
488 | mod 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" ))))] |
551 | mod 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 | |