wl_proxy/protocols/wayland/
wl_callback.rs

1//! callback object
2//!
3//! Clients can handle the 'done' event to get notified when
4//! the related request is done.
5//!
6//! Note, because wl_callback objects are created from multiple independent
7//! factory interfaces, the wl_callback interface is frozen at version 1.
8
9use crate::protocol_helpers::prelude::*;
10use super::super::all_types::*;
11
12/// A wl_callback object.
13///
14/// See the documentation of [the module][self] for the interface description.
15pub struct WlCallback {
16    core: ObjectCore,
17    handler: HandlerHolder<dyn WlCallbackHandler>,
18}
19
20struct DefaultHandler;
21
22impl WlCallbackHandler for DefaultHandler { }
23
24impl ConcreteObject for WlCallback {
25    const XML_VERSION: u32 = 1;
26    const INTERFACE: ObjectInterface = ObjectInterface::WlCallback;
27    const INTERFACE_NAME: &str = "wl_callback";
28}
29
30impl WlCallback {
31    /// Sets a new handler.
32    pub fn set_handler(&self, handler: impl WlCallbackHandler) {
33        self.set_boxed_handler(Box::new(handler));
34    }
35
36    /// Sets a new, already boxed handler.
37    pub fn set_boxed_handler(&self, handler: Box<dyn WlCallbackHandler>) {
38        if self.core.state.destroyed.get() {
39            return;
40        }
41        self.handler.set(Some(handler));
42    }
43}
44
45impl Debug for WlCallback {
46    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
47        f.debug_struct("WlCallback")
48            .field("server_obj_id", &self.core.server_obj_id.get())
49            .field("client_id", &self.core.client_id.get())
50            .field("client_obj_id", &self.core.client_obj_id.get())
51            .finish()
52    }
53}
54
55impl WlCallback {
56    /// Since when the done message is available.
57    pub const MSG__DONE__SINCE: u32 = 1;
58
59    /// done event
60    ///
61    /// Notify the client when the related request is done.
62    ///
63    /// # Arguments
64    ///
65    /// - `callback_data`: request-specific data for the callback
66    #[inline]
67    pub fn try_send_done(
68        &self,
69        callback_data: u32,
70    ) -> Result<(), ObjectError> {
71        let (
72            arg0,
73        ) = (
74            callback_data,
75        );
76        let core = self.core();
77        let client_ref = core.client.borrow();
78        let Some(client) = &*client_ref else {
79            return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
80        };
81        let id = core.client_obj_id.get().unwrap_or(0);
82        #[cfg(feature = "logging")]
83        if self.core.state.log {
84            #[cold]
85            fn log(state: &State, client_id: u64, id: u32, arg0: u32) {
86                let (millis, micros) = time_since_epoch();
87                let prefix = &state.log_prefix;
88                let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_callback#{}.done(callback_data: {})\n", client_id, id, arg0);
89                state.log(args);
90            }
91            log(&self.core.state, client.endpoint.id, id, arg0);
92        }
93        let endpoint = &client.endpoint;
94        if !endpoint.flush_queued.replace(true) {
95            self.core.state.add_flushable_endpoint(endpoint, Some(client));
96        }
97        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
98        let outgoing = &mut *outgoing_ref;
99        let mut fmt = outgoing.formatter();
100        fmt.words([
101            id,
102            0,
103            arg0,
104        ]);
105        drop(fmt);
106        drop(outgoing_ref);
107        drop(client_ref);
108        self.core.handle_client_destroy();
109        Ok(())
110    }
111
112    /// done event
113    ///
114    /// Notify the client when the related request is done.
115    ///
116    /// # Arguments
117    ///
118    /// - `callback_data`: request-specific data for the callback
119    #[inline]
120    pub fn send_done(
121        &self,
122        callback_data: u32,
123    ) {
124        let res = self.try_send_done(
125            callback_data,
126        );
127        if let Err(e) = res {
128            log_send("wl_callback.done", &e);
129        }
130    }
131}
132
133/// A message handler for [`WlCallback`] proxies.
134pub trait WlCallbackHandler: Any {
135    /// Event handler for wl_display.delete_id messages deleting the ID of this object.
136    ///
137    /// The default handler forwards the event to the client, if any.
138    #[inline]
139    fn delete_id(&mut self, slf: &Rc<WlCallback>) {
140        slf.core.delete_id();
141    }
142
143    /// done event
144    ///
145    /// Notify the client when the related request is done.
146    ///
147    /// # Arguments
148    ///
149    /// - `callback_data`: request-specific data for the callback
150    #[inline]
151    fn handle_done(
152        &mut self,
153        slf: &Rc<WlCallback>,
154        callback_data: u32,
155    ) {
156        if !slf.core.forward_to_client.get() {
157            return;
158        }
159        let res = slf.try_send_done(
160            callback_data,
161        );
162        if let Err(e) = res {
163            log_forward("wl_callback.done", &e);
164        }
165    }
166}
167
168impl ObjectPrivate for WlCallback {
169    fn new(state: &Rc<State>, version: u32) -> Rc<Self> {
170        Rc::<Self>::new_cyclic(|slf| Self {
171            core: ObjectCore::new(state, slf.clone(), ObjectInterface::WlCallback, version),
172            handler: Default::default(),
173        })
174    }
175
176    fn delete_id(self: Rc<Self>) -> Result<(), (ObjectError, Rc<dyn Object>)> {
177        let Some(mut handler) = self.handler.try_borrow_mut() else {
178            return Err((ObjectError(ObjectErrorKind::HandlerBorrowed), self));
179        };
180        if let Some(handler) = &mut *handler {
181            handler.delete_id(&self);
182        } else {
183            self.core.delete_id();
184        }
185        Ok(())
186    }
187
188    fn handle_request(self: Rc<Self>, client: &Rc<Client>, msg: &[u32], fds: &mut VecDeque<Rc<OwnedFd>>) -> Result<(), ObjectError> {
189        let Some(mut handler) = self.handler.try_borrow_mut() else {
190            return Err(ObjectError(ObjectErrorKind::HandlerBorrowed));
191        };
192        let handler = &mut *handler;
193        match msg[1] & 0xffff {
194            n => {
195                let _ = client;
196                let _ = msg;
197                let _ = fds;
198                let _ = handler;
199                return Err(ObjectError(ObjectErrorKind::UnknownMessageId(n)));
200            }
201        }
202    }
203
204    fn handle_event(self: Rc<Self>, server: &Endpoint, msg: &[u32], fds: &mut VecDeque<Rc<OwnedFd>>) -> Result<(), ObjectError> {
205        let Some(mut handler) = self.handler.try_borrow_mut() else {
206            return Err(ObjectError(ObjectErrorKind::HandlerBorrowed));
207        };
208        let handler = &mut *handler;
209        match msg[1] & 0xffff {
210            0 => {
211                let [
212                    arg0,
213                ] = msg[2..] else {
214                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 12)));
215                };
216                #[cfg(feature = "logging")]
217                if self.core.state.log {
218                    #[cold]
219                    fn log(state: &State, id: u32, arg0: u32) {
220                        let (millis, micros) = time_since_epoch();
221                        let prefix = &state.log_prefix;
222                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      -> wl_callback#{}.done(callback_data: {})\n", id, arg0);
223                        state.log(args);
224                    }
225                    log(&self.core.state, msg[0], arg0);
226                }
227                self.core.handle_server_destroy();
228                if let Some(handler) = handler {
229                    (**handler).handle_done(&self, arg0);
230                } else {
231                    DefaultHandler.handle_done(&self, arg0);
232                }
233            }
234            n => {
235                let _ = server;
236                let _ = msg;
237                let _ = fds;
238                let _ = handler;
239                return Err(ObjectError(ObjectErrorKind::UnknownMessageId(n)));
240            }
241        }
242        Ok(())
243    }
244
245    fn get_request_name(&self, id: u32) -> Option<&'static str> {
246        let _ = id;
247        None
248    }
249
250    fn get_event_name(&self, id: u32) -> Option<&'static str> {
251        let name = match id {
252            0 => "done",
253            _ => return None,
254        };
255        Some(name)
256    }
257}
258
259impl Object for WlCallback {
260    fn core(&self) -> &ObjectCore {
261        &self.core
262    }
263
264    fn unset_handler(&self) {
265        self.handler.set(None);
266    }
267
268    fn get_handler_any_ref(&self) -> Result<HandlerRef<'_, dyn Any>, HandlerAccessError> {
269        let borrowed = self.handler.try_borrow().ok_or(HandlerAccessError::AlreadyBorrowed)?;
270        if borrowed.is_none() {
271            return Err(HandlerAccessError::NoHandler);
272        }
273        Ok(HandlerRef::map(borrowed, |handler| &**handler.as_ref().unwrap() as &dyn Any))
274    }
275
276    fn get_handler_any_mut(&self) -> Result<HandlerMut<'_, dyn Any>, HandlerAccessError> {
277        let borrowed = self.handler.try_borrow_mut().ok_or(HandlerAccessError::AlreadyBorrowed)?;
278        if borrowed.is_none() {
279            return Err(HandlerAccessError::NoHandler);
280        }
281        Ok(HandlerMut::map(borrowed, |handler| &mut **handler.as_mut().unwrap() as &mut dyn Any))
282    }
283}
284