raw_window_handle/
uikit.rs

1use core::ffi::c_void;
2use core::ptr::NonNull;
3
4use super::DisplayHandle;
5
6/// Raw display handle for UIKit.
7#[non_exhaustive]
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
9pub struct UiKitDisplayHandle {}
10
11impl UiKitDisplayHandle {
12    /// Create a new empty display handle.
13    ///
14    ///
15    /// # Example
16    ///
17    /// ```
18    /// # use raw_window_handle::UiKitDisplayHandle;
19    /// let handle = UiKitDisplayHandle::new();
20    /// ```
21    pub fn new() -> Self {
22        Self {}
23    }
24}
25
26impl DisplayHandle<'static> {
27    /// Create a UiKit-based display handle.
28    ///
29    /// As no data is borrowed by this handle, it is completely safe to create. This function
30    /// may be useful to windowing framework implementations that want to avoid unsafe code.
31    ///
32    /// # Example
33    ///
34    /// ```
35    /// # use raw_window_handle::{DisplayHandle, HasDisplayHandle};
36    /// # fn do_something(rwh: impl HasDisplayHandle) { let _ = rwh; }
37    /// let handle = DisplayHandle::uikit();
38    /// do_something(handle);
39    /// ```
40    pub fn uikit() -> Self {
41        // SAFETY: No data is borrowed.
42        unsafe { Self::borrow_raw(UiKitDisplayHandle::new().into()) }
43    }
44}
45
46/// Raw window handle for UIKit.
47///
48/// Note that `UIView` can only be accessed from the main thread of the
49/// application. This struct is `!Send` and `!Sync` to help with ensuring
50/// that.
51///
52/// # Example
53///
54/// Getting the view from a [`WindowHandle`][crate::WindowHandle].
55///
56/// ```no_run
57/// # fn inner() {
58/// #![cfg(any(target_os = "ios", target_os = "tvos", target_os = "watchos", target_os = "xros"))]
59/// # #[cfg(requires_objc2)]
60/// use objc2_foundation::is_main_thread;
61/// # #[cfg(requires_objc2)]
62/// use objc2::rc::Id;
63/// # #[cfg(requires_objc2)]
64/// use objc2_ui_kit::UIView;
65/// use raw_window_handle::{WindowHandle, RawWindowHandle};
66///
67/// let handle: WindowHandle<'_>; // Get the window handle from somewhere else
68/// # handle = unimplemented!();
69/// match handle.as_raw() {
70///     # #[cfg(requires_objc2)]
71///     RawWindowHandle::UIKit(handle) => {
72///         assert!(is_main_thread(), "can only access UIKit handles on the main thread");
73///         let ui_view = handle.ui_view.as_ptr();
74///         // SAFETY: The pointer came from `WindowHandle`, which ensures
75///         // that the `UiKitWindowHandle` contains a valid pointer to an
76///         // `UIView`.
77///         // Unwrap is fine, since the pointer came from `NonNull`.
78///         let ui_view: Id<UIView> = unsafe { Id::retain(ui_view.cast()) }.unwrap();
79///         // Do something with the UIView here.
80///     }
81///     handle => unreachable!("unknown handle {handle:?} for platform"),
82/// }
83/// # }
84/// ```
85#[non_exhaustive]
86#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
87pub struct UiKitWindowHandle {
88    /// A pointer to an `UIView` object.
89    pub ui_view: NonNull<c_void>,
90    /// A pointer to an `UIViewController` object, if the view has one.
91    pub ui_view_controller: Option<NonNull<c_void>>,
92}
93
94impl UiKitWindowHandle {
95    /// Create a new handle to a view.
96    ///
97    ///
98    /// # Example
99    ///
100    /// ```
101    /// # use core::ptr::NonNull;
102    /// # use raw_window_handle::UiKitWindowHandle;
103    /// # type UIView = ();
104    /// #
105    /// let view: &UIView;
106    /// # view = &();
107    /// let mut handle = UiKitWindowHandle::new(NonNull::from(view).cast());
108    /// // Optionally set the view controller.
109    /// handle.ui_view_controller = None;
110    /// ```
111    pub fn new(ui_view: NonNull<c_void>) -> Self {
112        Self {
113            ui_view,
114            ui_view_controller: None,
115        }
116    }
117}