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}