winio_handle/
container.rs

1cfg_if::cfg_if! {
2    if #[cfg(windows)] {
3        use std::marker::PhantomData;
4
5        #[derive(Clone, Copy)]
6        enum BorrowedContainerInner<'a> {
7            #[cfg(feature = "win32")]
8            Win32(windows_sys::Win32::Foundation::HWND, PhantomData<&'a ()>),
9            #[cfg(feature = "winui")]
10            WinUI(&'a winui3::Microsoft::UI::Xaml::Controls::Canvas),
11            #[cfg(not(any(feature = "win32", feature = "winui")))]
12            Dummy(std::convert::Infallible, PhantomData<&'a ()>),
13        }
14    } else if #[cfg(target_os = "macos")] {
15        use objc2::rc::Retained;
16
17        type BorrowedContainerInner<'a> = &'a Retained<objc2_app_kit::NSView>;
18    } else {
19        use std::marker::PhantomData;
20
21        #[derive(Clone, Copy)]
22        enum BorrowedContainerInner<'a> {
23            #[cfg(feature = "qt")]
24            Qt(*mut core::ffi::c_void, PhantomData<&'a ()>),
25            #[cfg(feature = "gtk")]
26            Gtk(&'a gtk4::Fixed),
27            #[cfg(not(any(feature = "qt", feature = "gtk")))]
28            Dummy(std::convert::Infallible, PhantomData<&'a ()>),
29        }
30    }
31}
32
33/// Raw container handle.
34#[derive(Clone, Copy)]
35pub struct BorrowedContainer<'a>(BorrowedContainerInner<'a>);
36
37#[allow(unreachable_patterns)]
38#[cfg(windows)]
39impl<'a> BorrowedContainer<'a> {
40    /// Create from Win32 `HWND`.
41    ///
42    /// # Safety
43    ///
44    /// * The caller must ensure that `hwnd` is a valid handle for the lifetime
45    ///   `'a`.
46    /// * `hwnd` must not be null.
47    #[cfg(feature = "win32")]
48    pub unsafe fn win32(hwnd: windows_sys::Win32::Foundation::HWND) -> Self {
49        Self(BorrowedContainerInner::Win32(hwnd, PhantomData))
50    }
51
52    /// Create from WinUI `Canvas`.
53    #[cfg(feature = "winui")]
54    pub fn winui(container: &'a winui3::Microsoft::UI::Xaml::Controls::Canvas) -> Self {
55        Self(BorrowedContainerInner::WinUI(container))
56    }
57
58    /// Get Win32 `HWND`.
59    #[cfg(feature = "win32")]
60    pub fn as_win32(&self) -> windows_sys::Win32::Foundation::HWND {
61        match &self.0 {
62            BorrowedContainerInner::Win32(hwnd, ..) => *hwnd,
63            _ => panic!("unsupported handle type"),
64        }
65    }
66
67    /// Get WinUI `Canvas`.
68    #[cfg(feature = "winui")]
69    pub fn as_winui(&self) -> &winui3::Microsoft::UI::Xaml::Controls::Canvas {
70        match &self.0 {
71            BorrowedContainerInner::WinUI(container) => container,
72            _ => panic!("unsupported handle type"),
73        }
74    }
75}
76
77#[cfg(target_os = "macos")]
78impl<'a> BorrowedContainer<'a> {
79    /// Create from `NSView`.
80    pub fn app_kit(view: &'a Retained<objc2_app_kit::NSView>) -> Self {
81        Self(view)
82    }
83
84    /// Get `NSView`.
85    pub fn as_app_kit(&self) -> &'a Retained<objc2_app_kit::NSView> {
86        self.0
87    }
88}
89
90#[allow(unreachable_patterns)]
91#[cfg(not(any(windows, target_os = "macos")))]
92impl<'a> BorrowedContainer<'a> {
93    /// Create from Qt `QWidget`.
94    ///
95    /// # Safety
96    /// The caller must ensure that `widget` is a valid pointer for the lifetime
97    /// `'a`.
98    #[cfg(feature = "qt")]
99    pub unsafe fn qt<T>(widget: *mut T) -> Self {
100        Self(BorrowedContainerInner::Qt(widget.cast(), PhantomData))
101    }
102
103    /// Create from Gtk `Fixed`.
104    #[cfg(feature = "gtk")]
105    pub fn gtk(fixed: &'a gtk4::Fixed) -> Self {
106        Self(BorrowedContainerInner::Gtk(fixed))
107    }
108
109    /// Get Qt `QWidget`.
110    #[cfg(feature = "qt")]
111    pub fn as_qt<T>(&self) -> *mut T {
112        match &self.0 {
113            BorrowedContainerInner::Qt(w, ..) => (*w).cast(),
114            _ => panic!("unsupported handle type"),
115        }
116    }
117
118    /// Get Gtk `Fixed`.
119    #[cfg(feature = "gtk")]
120    pub fn to_gtk(&self) -> &'a gtk4::Fixed {
121        match &self.0 {
122            BorrowedContainerInner::Gtk(w) => w,
123            _ => panic!("unsupported handle type"),
124        }
125    }
126}
127
128/// Trait to borrow the container handle.
129pub trait AsContainer {
130    /// Get the container handle.
131    fn as_container(&self) -> BorrowedContainer<'_>;
132}
133
134impl AsContainer for BorrowedContainer<'_> {
135    fn as_container(&self) -> BorrowedContainer<'_> {
136        *self
137    }
138}
139
140impl<T: AsContainer + ?Sized> AsContainer for &T {
141    #[inline]
142    fn as_container(&self) -> BorrowedContainer<'_> {
143        T::as_container(self)
144    }
145}
146
147impl<'a, T: AsContainer + ?Sized> From<&'a T> for BorrowedContainer<'a> {
148    fn from(value: &'a T) -> Self {
149        value.as_container()
150    }
151}
152
153#[doc(hidden)]
154pub struct MaybeBorrowedContainer<'a>(pub Option<BorrowedContainer<'a>>);
155
156impl<'a, T: Into<BorrowedContainer<'a>>> From<T> for MaybeBorrowedContainer<'a> {
157    fn from(value: T) -> Self {
158        Self(Some(value.into()))
159    }
160}
161
162impl<'a, T: Into<BorrowedContainer<'a>>> From<Option<T>> for MaybeBorrowedContainer<'a> {
163    fn from(value: Option<T>) -> Self {
164        Self(value.map(|v| v.into()))
165    }
166}
167
168impl From<()> for MaybeBorrowedContainer<'_> {
169    fn from(_: ()) -> Self {
170        Self(None)
171    }
172}
173
174#[doc(hidden)]
175#[macro_export]
176macro_rules! impl_as_container {
177    ($t:ty, $inner:ident) => {
178        impl $crate::AsContainer for $t {
179            fn as_container(&self) -> $crate::BorrowedContainer<'_> {
180                self.$inner.as_container()
181            }
182        }
183    };
184}