winio_handle/
widget.rs

1cfg_if::cfg_if! {
2    if #[cfg(windows)] {
3        use std::marker::PhantomData;
4
5        #[derive(Clone, Copy)]
6        enum BorrowedWidgetInner<'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::FrameworkElement),
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 BorrowedWidgetInner<'a> = &'a Retained<objc2_app_kit::NSView>;
18    } else {
19        use std::marker::PhantomData;
20
21        #[derive(Clone, Copy)]
22        enum BorrowedWidgetInner<'a> {
23            #[cfg(feature = "qt")]
24            Qt(*mut core::ffi::c_void, PhantomData<&'a ()>),
25            #[cfg(feature = "gtk")]
26            Gtk(&'a gtk4::Widget),
27            #[cfg(not(any(feature = "qt", feature = "gtk")))]
28            Dummy(std::convert::Infallible, PhantomData<&'a ()>),
29        }
30    }
31}
32
33/// Raw widget handle.
34#[derive(Clone, Copy)]
35pub struct BorrowedWidget<'a>(BorrowedWidgetInner<'a>);
36
37#[allow(unreachable_patterns)]
38#[cfg(windows)]
39impl<'a> BorrowedWidget<'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(BorrowedWidgetInner::Win32(hwnd, PhantomData))
50    }
51
52    /// Create from WinUI `FrameworkElement`.
53    #[cfg(feature = "winui")]
54    pub fn winui(element: &'a winui3::Microsoft::UI::Xaml::FrameworkElement) -> Self {
55        Self(BorrowedWidgetInner::WinUI(element))
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            BorrowedWidgetInner::Win32(hwnd, ..) => *hwnd,
63            _ => panic!("unsupported handle type"),
64        }
65    }
66
67    /// Get WinUI `FrameworkElement`.
68    #[cfg(feature = "winui")]
69    pub fn as_winui(&self) -> &winui3::Microsoft::UI::Xaml::FrameworkElement {
70        match &self.0 {
71            BorrowedWidgetInner::WinUI(e) => e,
72            _ => panic!("unsupported handle type"),
73        }
74    }
75}
76
77#[cfg(target_os = "macos")]
78impl<'a> BorrowedWidget<'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> BorrowedWidget<'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(BorrowedWidgetInner::Qt(widget.cast(), PhantomData))
101    }
102
103    /// Create from Gtk `Widget`.
104    #[cfg(feature = "gtk")]
105    pub fn gtk(widget: &'a gtk4::Widget) -> Self {
106        Self(BorrowedWidgetInner::Gtk(widget))
107    }
108
109    /// Get Qt `QWidget`.
110    #[cfg(feature = "qt")]
111    pub fn as_qt<T>(&self) -> *mut T {
112        match &self.0 {
113            BorrowedWidgetInner::Qt(w, ..) => (*w).cast(),
114            _ => panic!("unsupported handle type"),
115        }
116    }
117
118    /// Get Gtk `Widget`.
119    #[cfg(feature = "gtk")]
120    pub fn to_gtk(&self) -> &'a gtk4::Widget {
121        match &self.0 {
122            BorrowedWidgetInner::Gtk(w) => w,
123            _ => panic!("unsupported handle type"),
124        }
125    }
126}
127
128/// Trait to borrow the widget handle.
129pub trait AsWidget {
130    /// Get the widget handle.
131    fn as_widget(&self) -> BorrowedWidget<'_>;
132}
133
134impl AsWidget for BorrowedWidget<'_> {
135    fn as_widget(&self) -> BorrowedWidget<'_> {
136        *self
137    }
138}
139
140impl<T: AsWidget + ?Sized> AsWidget for &T {
141    #[inline]
142    fn as_widget(&self) -> BorrowedWidget<'_> {
143        T::as_widget(self)
144    }
145}
146
147impl<'a, T: AsWidget + ?Sized> From<&'a T> for BorrowedWidget<'a> {
148    fn from(value: &'a T) -> Self {
149        value.as_widget()
150    }
151}
152
153#[doc(hidden)]
154#[macro_export]
155macro_rules! impl_as_widget {
156    ($t:ty, $inner:ident) => {
157        impl $crate::AsWidget for $t {
158            fn as_widget(&self) -> $crate::BorrowedWidget<'_> {
159                self.$inner.as_widget()
160            }
161        }
162    };
163}