wl_client/proxy/low_level.rs
1//! Low-level proxy APIs.
2//!
3//! This module contains low-level APIs that are usually only used by `wl-client-builder` in
4//! generated protocol bindings.
5
6pub(crate) use owned::{OwnedProxyRegistry, destruction::ProxyDataDestruction};
7use {
8 crate::{
9 ffi::wl_proxy,
10 proxy::{BorrowedProxy, OwnedProxy, get_owned},
11 },
12 std::{
13 mem::{self, ManuallyDrop},
14 ptr::NonNull,
15 },
16};
17pub use {
18 borrowed::{UntypedBorrowedProxy, UntypedBorrowedProxyWrapper},
19 owned::{EventHandler, UntypedOwnedProxy, UntypedOwnedProxyWrapper},
20};
21
22pub(super) mod borrowed;
23pub(crate) mod owned;
24#[cfg(test)]
25mod tests;
26
27/// A type that can create an event handler.
28///
29/// This type is usually implemented by [`OwnedProxy::Api`] to turn an object implementing
30/// safe event callbacks into an event handler that can handle raw libwayland events.
31///
32/// This type is usually implemented by bindings that are automatically generated with the
33/// `wl-client-builder` crate.
34pub trait CreateEventHandler<T> {
35 type EventHandler: EventHandler;
36
37 /// Creates a new event handler.
38 fn create_event_handler(handler: T) -> Self::EventHandler;
39}
40
41#[inline]
42pub(crate) fn check_dispatching_proxy(proxy: Option<NonNull<wl_proxy>>) -> NonNull<wl_proxy> {
43 match proxy {
44 None => {
45 #[cold]
46 fn not_null() -> ! {
47 panic!("Proxy has already been destroyed");
48 }
49 not_null();
50 }
51 Some(p) => p,
52 }
53}
54
55#[inline]
56pub(crate) fn check_new_proxy(proxy: *mut wl_proxy) -> NonNull<wl_proxy> {
57 if let Some(proxy) = NonNull::new(proxy) {
58 proxy
59 } else {
60 #[cold]
61 fn not_null() -> ! {
62 panic!("new wl_proxy is null");
63 }
64 not_null();
65 }
66}
67
68/// Returns the borrowed version of an owned proxy.
69///
70/// This is a low-level API that you probably don't have to use unless you are writing
71/// protocol wrappers by hand.
72///
73/// `wl-client-builder` uses this function to implement the `Deref` trait.
74///
75/// # Example
76///
77/// ```
78/// # use wl_client::{proxy, Libwayland};
79/// # use wl_client::test_protocols::core::wl_display::{WlDisplay, WlDisplayRef};
80/// #
81/// let lib = Libwayland::open().unwrap();
82/// let con = lib.connect_to_default_display().unwrap();
83/// let queue = con.create_queue(c"queue name");
84///
85/// let display: WlDisplay = queue.display();
86/// let display_ref: &WlDisplayRef = proxy::low_level::deref(&display);
87/// ```
88pub fn deref<P>(proxy: &P) -> &P::Borrowed
89where
90 P: OwnedProxy,
91{
92 let borrowed: &UntypedBorrowedProxy = get_owned(proxy);
93 // SAFETY: borrowed has the interface P:WL_INTERFACE = P::Borrowed::Owned::WL_INTERFACE
94 unsafe { from_untyped_borrowed(borrowed) }
95}
96
97/// Creates a well-typed, borrowed proxy.
98///
99/// This is a low-level API that you probably don't have to use unless you are writing
100/// protocol wrappers by hand.
101///
102/// # Safety
103///
104/// - The proxy must have an interface compatible with `P::Owned::WL_INTERFACE`.
105#[inline]
106pub unsafe fn from_untyped_borrowed<P>(proxy: &UntypedBorrowedProxy) -> &P
107where
108 P: BorrowedProxy,
109{
110 // SAFETY: - Since the interface of the proxy is compatible with
111 // P::Owned::WL_INTERFACE, BorrowedProxy requires that this transmute is
112 // safe.
113 unsafe { mem::transmute::<&UntypedBorrowedProxy, &P>(proxy) }
114}
115
116/// Creates a well-typed, owned proxy.
117///
118/// This is a low-level API that you probably don't have to use unless you are writing
119/// protocol wrappers by hand.
120///
121/// # Safety
122///
123/// - The proxy must have an interface compatible with `P::WL_INTERFACE`.
124#[inline]
125pub unsafe fn from_untyped_owned<P>(proxy: UntypedOwnedProxy) -> P
126where
127 P: OwnedProxy,
128{
129 let proxy = ManuallyDrop::new(proxy);
130 // SAFETY: - Since the interface of the proxy is compatible with P::WL_INTERFACE,
131 // OwnedProxy requires that this transmute is safe.
132 unsafe { mem::transmute_copy::<UntypedOwnedProxy, P>(&*proxy) }
133}