wl_proxy/protocols/wayland/
wl_region.rs

1//! region interface
2//!
3//! A region object describes an area.
4//!
5//! Region objects are used to describe the opaque and input
6//! regions of a surface.
7
8use crate::protocol_helpers::prelude::*;
9use super::super::all_types::*;
10
11/// A wl_region object.
12///
13/// See the documentation of [the module][self] for the interface description.
14pub struct WlRegion {
15    core: ObjectCore,
16    handler: HandlerHolder<dyn WlRegionHandler>,
17}
18
19struct DefaultHandler;
20
21impl WlRegionHandler for DefaultHandler { }
22
23impl ConcreteObject for WlRegion {
24    const XML_VERSION: u32 = 1;
25    const INTERFACE: ObjectInterface = ObjectInterface::WlRegion;
26    const INTERFACE_NAME: &str = "wl_region";
27}
28
29impl WlRegion {
30    /// Sets a new handler.
31    pub fn set_handler(&self, handler: impl WlRegionHandler) {
32        self.set_boxed_handler(Box::new(handler));
33    }
34
35    /// Sets a new, already boxed handler.
36    pub fn set_boxed_handler(&self, handler: Box<dyn WlRegionHandler>) {
37        if self.core.state.destroyed.get() {
38            return;
39        }
40        self.handler.set(Some(handler));
41    }
42}
43
44impl Debug for WlRegion {
45    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
46        f.debug_struct("WlRegion")
47            .field("server_obj_id", &self.core.server_obj_id.get())
48            .field("client_id", &self.core.client_id.get())
49            .field("client_obj_id", &self.core.client_obj_id.get())
50            .finish()
51    }
52}
53
54impl WlRegion {
55    /// Since when the destroy message is available.
56    pub const MSG__DESTROY__SINCE: u32 = 1;
57
58    /// destroy region
59    ///
60    /// Destroy the region.  This will invalidate the object ID.
61    #[inline]
62    pub fn try_send_destroy(
63        &self,
64    ) -> Result<(), ObjectError> {
65        let core = self.core();
66        let Some(id) = core.server_obj_id.get() else {
67            return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
68        };
69        #[cfg(feature = "logging")]
70        if self.core.state.log {
71            #[cold]
72            fn log(state: &State, id: u32) {
73                let (millis, micros) = time_since_epoch();
74                let prefix = &state.log_prefix;
75                let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      <= wl_region#{}.destroy()\n", id);
76                state.log(args);
77            }
78            log(&self.core.state, id);
79        }
80        let Some(endpoint) = &self.core.state.server else {
81            return Ok(());
82        };
83        if !endpoint.flush_queued.replace(true) {
84            self.core.state.add_flushable_endpoint(endpoint, None);
85        }
86        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
87        let outgoing = &mut *outgoing_ref;
88        let mut fmt = outgoing.formatter();
89        fmt.words([
90            id,
91            0,
92        ]);
93        self.core.handle_server_destroy();
94        Ok(())
95    }
96
97    /// destroy region
98    ///
99    /// Destroy the region.  This will invalidate the object ID.
100    #[inline]
101    pub fn send_destroy(
102        &self,
103    ) {
104        let res = self.try_send_destroy(
105        );
106        if let Err(e) = res {
107            log_send("wl_region.destroy", &e);
108        }
109    }
110
111    /// Since when the add message is available.
112    pub const MSG__ADD__SINCE: u32 = 1;
113
114    /// add rectangle to region
115    ///
116    /// Add the specified rectangle to the region.
117    ///
118    /// # Arguments
119    ///
120    /// - `x`: region-local x coordinate
121    /// - `y`: region-local y coordinate
122    /// - `width`: rectangle width
123    /// - `height`: rectangle height
124    #[inline]
125    pub fn try_send_add(
126        &self,
127        x: i32,
128        y: i32,
129        width: i32,
130        height: i32,
131    ) -> Result<(), ObjectError> {
132        let (
133            arg0,
134            arg1,
135            arg2,
136            arg3,
137        ) = (
138            x,
139            y,
140            width,
141            height,
142        );
143        let core = self.core();
144        let Some(id) = core.server_obj_id.get() else {
145            return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
146        };
147        #[cfg(feature = "logging")]
148        if self.core.state.log {
149            #[cold]
150            fn log(state: &State, id: u32, arg0: i32, arg1: i32, arg2: i32, arg3: i32) {
151                let (millis, micros) = time_since_epoch();
152                let prefix = &state.log_prefix;
153                let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      <= wl_region#{}.add(x: {}, y: {}, width: {}, height: {})\n", id, arg0, arg1, arg2, arg3);
154                state.log(args);
155            }
156            log(&self.core.state, id, arg0, arg1, arg2, arg3);
157        }
158        let Some(endpoint) = &self.core.state.server else {
159            return Ok(());
160        };
161        if !endpoint.flush_queued.replace(true) {
162            self.core.state.add_flushable_endpoint(endpoint, None);
163        }
164        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
165        let outgoing = &mut *outgoing_ref;
166        let mut fmt = outgoing.formatter();
167        fmt.words([
168            id,
169            1,
170            arg0 as u32,
171            arg1 as u32,
172            arg2 as u32,
173            arg3 as u32,
174        ]);
175        Ok(())
176    }
177
178    /// add rectangle to region
179    ///
180    /// Add the specified rectangle to the region.
181    ///
182    /// # Arguments
183    ///
184    /// - `x`: region-local x coordinate
185    /// - `y`: region-local y coordinate
186    /// - `width`: rectangle width
187    /// - `height`: rectangle height
188    #[inline]
189    pub fn send_add(
190        &self,
191        x: i32,
192        y: i32,
193        width: i32,
194        height: i32,
195    ) {
196        let res = self.try_send_add(
197            x,
198            y,
199            width,
200            height,
201        );
202        if let Err(e) = res {
203            log_send("wl_region.add", &e);
204        }
205    }
206
207    /// Since when the subtract message is available.
208    pub const MSG__SUBTRACT__SINCE: u32 = 1;
209
210    /// subtract rectangle from region
211    ///
212    /// Subtract the specified rectangle from the region.
213    ///
214    /// # Arguments
215    ///
216    /// - `x`: region-local x coordinate
217    /// - `y`: region-local y coordinate
218    /// - `width`: rectangle width
219    /// - `height`: rectangle height
220    #[inline]
221    pub fn try_send_subtract(
222        &self,
223        x: i32,
224        y: i32,
225        width: i32,
226        height: i32,
227    ) -> Result<(), ObjectError> {
228        let (
229            arg0,
230            arg1,
231            arg2,
232            arg3,
233        ) = (
234            x,
235            y,
236            width,
237            height,
238        );
239        let core = self.core();
240        let Some(id) = core.server_obj_id.get() else {
241            return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
242        };
243        #[cfg(feature = "logging")]
244        if self.core.state.log {
245            #[cold]
246            fn log(state: &State, id: u32, arg0: i32, arg1: i32, arg2: i32, arg3: i32) {
247                let (millis, micros) = time_since_epoch();
248                let prefix = &state.log_prefix;
249                let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      <= wl_region#{}.subtract(x: {}, y: {}, width: {}, height: {})\n", id, arg0, arg1, arg2, arg3);
250                state.log(args);
251            }
252            log(&self.core.state, id, arg0, arg1, arg2, arg3);
253        }
254        let Some(endpoint) = &self.core.state.server else {
255            return Ok(());
256        };
257        if !endpoint.flush_queued.replace(true) {
258            self.core.state.add_flushable_endpoint(endpoint, None);
259        }
260        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
261        let outgoing = &mut *outgoing_ref;
262        let mut fmt = outgoing.formatter();
263        fmt.words([
264            id,
265            2,
266            arg0 as u32,
267            arg1 as u32,
268            arg2 as u32,
269            arg3 as u32,
270        ]);
271        Ok(())
272    }
273
274    /// subtract rectangle from region
275    ///
276    /// Subtract the specified rectangle from the region.
277    ///
278    /// # Arguments
279    ///
280    /// - `x`: region-local x coordinate
281    /// - `y`: region-local y coordinate
282    /// - `width`: rectangle width
283    /// - `height`: rectangle height
284    #[inline]
285    pub fn send_subtract(
286        &self,
287        x: i32,
288        y: i32,
289        width: i32,
290        height: i32,
291    ) {
292        let res = self.try_send_subtract(
293            x,
294            y,
295            width,
296            height,
297        );
298        if let Err(e) = res {
299            log_send("wl_region.subtract", &e);
300        }
301    }
302}
303
304/// A message handler for [`WlRegion`] proxies.
305pub trait WlRegionHandler: Any {
306    /// Event handler for wl_display.delete_id messages deleting the ID of this object.
307    ///
308    /// The default handler forwards the event to the client, if any.
309    #[inline]
310    fn delete_id(&mut self, slf: &Rc<WlRegion>) {
311        slf.core.delete_id();
312    }
313
314    /// destroy region
315    ///
316    /// Destroy the region.  This will invalidate the object ID.
317    #[inline]
318    fn handle_destroy(
319        &mut self,
320        slf: &Rc<WlRegion>,
321    ) {
322        if !slf.core.forward_to_server.get() {
323            return;
324        }
325        let res = slf.try_send_destroy(
326        );
327        if let Err(e) = res {
328            log_forward("wl_region.destroy", &e);
329        }
330    }
331
332    /// add rectangle to region
333    ///
334    /// Add the specified rectangle to the region.
335    ///
336    /// # Arguments
337    ///
338    /// - `x`: region-local x coordinate
339    /// - `y`: region-local y coordinate
340    /// - `width`: rectangle width
341    /// - `height`: rectangle height
342    #[inline]
343    fn handle_add(
344        &mut self,
345        slf: &Rc<WlRegion>,
346        x: i32,
347        y: i32,
348        width: i32,
349        height: i32,
350    ) {
351        if !slf.core.forward_to_server.get() {
352            return;
353        }
354        let res = slf.try_send_add(
355            x,
356            y,
357            width,
358            height,
359        );
360        if let Err(e) = res {
361            log_forward("wl_region.add", &e);
362        }
363    }
364
365    /// subtract rectangle from region
366    ///
367    /// Subtract the specified rectangle from the region.
368    ///
369    /// # Arguments
370    ///
371    /// - `x`: region-local x coordinate
372    /// - `y`: region-local y coordinate
373    /// - `width`: rectangle width
374    /// - `height`: rectangle height
375    #[inline]
376    fn handle_subtract(
377        &mut self,
378        slf: &Rc<WlRegion>,
379        x: i32,
380        y: i32,
381        width: i32,
382        height: i32,
383    ) {
384        if !slf.core.forward_to_server.get() {
385            return;
386        }
387        let res = slf.try_send_subtract(
388            x,
389            y,
390            width,
391            height,
392        );
393        if let Err(e) = res {
394            log_forward("wl_region.subtract", &e);
395        }
396    }
397}
398
399impl ObjectPrivate for WlRegion {
400    fn new(state: &Rc<State>, version: u32) -> Rc<Self> {
401        Rc::<Self>::new_cyclic(|slf| Self {
402            core: ObjectCore::new(state, slf.clone(), ObjectInterface::WlRegion, version),
403            handler: Default::default(),
404        })
405    }
406
407    fn delete_id(self: Rc<Self>) -> Result<(), (ObjectError, Rc<dyn Object>)> {
408        let Some(mut handler) = self.handler.try_borrow_mut() else {
409            return Err((ObjectError(ObjectErrorKind::HandlerBorrowed), self));
410        };
411        if let Some(handler) = &mut *handler {
412            handler.delete_id(&self);
413        } else {
414            self.core.delete_id();
415        }
416        Ok(())
417    }
418
419    fn handle_request(self: Rc<Self>, client: &Rc<Client>, msg: &[u32], fds: &mut VecDeque<Rc<OwnedFd>>) -> Result<(), ObjectError> {
420        let Some(mut handler) = self.handler.try_borrow_mut() else {
421            return Err(ObjectError(ObjectErrorKind::HandlerBorrowed));
422        };
423        let handler = &mut *handler;
424        match msg[1] & 0xffff {
425            0 => {
426                if msg.len() != 2 {
427                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 8)));
428                }
429                #[cfg(feature = "logging")]
430                if self.core.state.log {
431                    #[cold]
432                    fn log(state: &State, client_id: u64, id: u32) {
433                        let (millis, micros) = time_since_epoch();
434                        let prefix = &state.log_prefix;
435                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_region#{}.destroy()\n", client_id, id);
436                        state.log(args);
437                    }
438                    log(&self.core.state, client.endpoint.id, msg[0]);
439                }
440                self.core.handle_client_destroy();
441                if let Some(handler) = handler {
442                    (**handler).handle_destroy(&self);
443                } else {
444                    DefaultHandler.handle_destroy(&self);
445                }
446            }
447            1 => {
448                let [
449                    arg0,
450                    arg1,
451                    arg2,
452                    arg3,
453                ] = msg[2..] else {
454                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 24)));
455                };
456                let arg0 = arg0 as i32;
457                let arg1 = arg1 as i32;
458                let arg2 = arg2 as i32;
459                let arg3 = arg3 as i32;
460                #[cfg(feature = "logging")]
461                if self.core.state.log {
462                    #[cold]
463                    fn log(state: &State, client_id: u64, id: u32, arg0: i32, arg1: i32, arg2: i32, arg3: i32) {
464                        let (millis, micros) = time_since_epoch();
465                        let prefix = &state.log_prefix;
466                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_region#{}.add(x: {}, y: {}, width: {}, height: {})\n", client_id, id, arg0, arg1, arg2, arg3);
467                        state.log(args);
468                    }
469                    log(&self.core.state, client.endpoint.id, msg[0], arg0, arg1, arg2, arg3);
470                }
471                if let Some(handler) = handler {
472                    (**handler).handle_add(&self, arg0, arg1, arg2, arg3);
473                } else {
474                    DefaultHandler.handle_add(&self, arg0, arg1, arg2, arg3);
475                }
476            }
477            2 => {
478                let [
479                    arg0,
480                    arg1,
481                    arg2,
482                    arg3,
483                ] = msg[2..] else {
484                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 24)));
485                };
486                let arg0 = arg0 as i32;
487                let arg1 = arg1 as i32;
488                let arg2 = arg2 as i32;
489                let arg3 = arg3 as i32;
490                #[cfg(feature = "logging")]
491                if self.core.state.log {
492                    #[cold]
493                    fn log(state: &State, client_id: u64, id: u32, arg0: i32, arg1: i32, arg2: i32, arg3: i32) {
494                        let (millis, micros) = time_since_epoch();
495                        let prefix = &state.log_prefix;
496                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_region#{}.subtract(x: {}, y: {}, width: {}, height: {})\n", client_id, id, arg0, arg1, arg2, arg3);
497                        state.log(args);
498                    }
499                    log(&self.core.state, client.endpoint.id, msg[0], arg0, arg1, arg2, arg3);
500                }
501                if let Some(handler) = handler {
502                    (**handler).handle_subtract(&self, arg0, arg1, arg2, arg3);
503                } else {
504                    DefaultHandler.handle_subtract(&self, arg0, arg1, arg2, arg3);
505                }
506            }
507            n => {
508                let _ = client;
509                let _ = msg;
510                let _ = fds;
511                let _ = handler;
512                return Err(ObjectError(ObjectErrorKind::UnknownMessageId(n)));
513            }
514        }
515        Ok(())
516    }
517
518    fn handle_event(self: Rc<Self>, server: &Endpoint, msg: &[u32], fds: &mut VecDeque<Rc<OwnedFd>>) -> Result<(), ObjectError> {
519        let Some(mut handler) = self.handler.try_borrow_mut() else {
520            return Err(ObjectError(ObjectErrorKind::HandlerBorrowed));
521        };
522        let handler = &mut *handler;
523        match msg[1] & 0xffff {
524            n => {
525                let _ = server;
526                let _ = msg;
527                let _ = fds;
528                let _ = handler;
529                return Err(ObjectError(ObjectErrorKind::UnknownMessageId(n)));
530            }
531        }
532    }
533
534    fn get_request_name(&self, id: u32) -> Option<&'static str> {
535        let name = match id {
536            0 => "destroy",
537            1 => "add",
538            2 => "subtract",
539            _ => return None,
540        };
541        Some(name)
542    }
543
544    fn get_event_name(&self, id: u32) -> Option<&'static str> {
545        let _ = id;
546        None
547    }
548}
549
550impl Object for WlRegion {
551    fn core(&self) -> &ObjectCore {
552        &self.core
553    }
554
555    fn unset_handler(&self) {
556        self.handler.set(None);
557    }
558
559    fn get_handler_any_ref(&self) -> Result<HandlerRef<'_, dyn Any>, HandlerAccessError> {
560        let borrowed = self.handler.try_borrow().ok_or(HandlerAccessError::AlreadyBorrowed)?;
561        if borrowed.is_none() {
562            return Err(HandlerAccessError::NoHandler);
563        }
564        Ok(HandlerRef::map(borrowed, |handler| &**handler.as_ref().unwrap() as &dyn Any))
565    }
566
567    fn get_handler_any_mut(&self) -> Result<HandlerMut<'_, dyn Any>, HandlerAccessError> {
568        let borrowed = self.handler.try_borrow_mut().ok_or(HandlerAccessError::AlreadyBorrowed)?;
569        if borrowed.is_none() {
570            return Err(HandlerAccessError::NoHandler);
571        }
572        Ok(HandlerMut::map(borrowed, |handler| &mut **handler.as_mut().unwrap() as &mut dyn Any))
573    }
574}
575