wl_proxy/protocols/wayland/
wl_registry.rs

1//! global registry object
2//!
3//! The singleton global registry object.  The server has a number of
4//! global objects that are available to all clients.  These objects
5//! typically represent an actual object in the server (for example,
6//! an input device) or they are singleton objects that provide
7//! extension functionality.
8//!
9//! When a client creates a registry object, the registry object
10//! will emit a global event for each global currently in the
11//! registry.  Globals come and go as a result of device or
12//! monitor hotplugs, reconfiguration or other events, and the
13//! registry will send out global and global_remove events to
14//! keep the client up to date with the changes.  To mark the end
15//! of the initial burst of events, the client can use the
16//! wl_display.sync request immediately after calling
17//! wl_display.get_registry.
18//!
19//! A client can bind to a global object by using the bind
20//! request.  This creates a client-side handle that lets the object
21//! emit events to the client and lets the client invoke requests on
22//! the object.
23
24use crate::protocol_helpers::prelude::*;
25use super::super::all_types::*;
26
27/// A wl_registry object.
28///
29/// See the documentation of [the module][self] for the interface description.
30pub struct WlRegistry {
31    core: ObjectCore,
32    handler: HandlerHolder<dyn WlRegistryHandler>,
33    names: RefCell<HashSet<u32>>,
34}
35
36struct DefaultHandler;
37
38impl WlRegistryHandler for DefaultHandler { }
39
40impl ConcreteObject for WlRegistry {
41    const XML_VERSION: u32 = 1;
42    const INTERFACE: ObjectInterface = ObjectInterface::WlRegistry;
43    const INTERFACE_NAME: &str = "wl_registry";
44}
45
46impl WlRegistry {
47    /// Sets a new handler.
48    pub fn set_handler(&self, handler: impl WlRegistryHandler) {
49        self.set_boxed_handler(Box::new(handler));
50    }
51
52    /// Sets a new, already boxed handler.
53    pub fn set_boxed_handler(&self, handler: Box<dyn WlRegistryHandler>) {
54        if self.core.state.destroyed.get() {
55            return;
56        }
57        self.handler.set(Some(handler));
58    }
59}
60
61impl Debug for WlRegistry {
62    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
63        f.debug_struct("WlRegistry")
64            .field("server_obj_id", &self.core.server_obj_id.get())
65            .field("client_id", &self.core.client_id.get())
66            .field("client_obj_id", &self.core.client_obj_id.get())
67            .finish()
68    }
69}
70
71impl WlRegistry {
72    /// Since when the bind message is available.
73    pub const MSG__BIND__SINCE: u32 = 1;
74
75    /// bind an object to the display
76    ///
77    /// Binds a new, client-created object to the server using the
78    /// specified name as the identifier.
79    ///
80    /// # Arguments
81    ///
82    /// - `name`: unique numeric name of the object
83    /// - `id`: bounded object
84    #[inline]
85    pub fn try_send_bind(
86        &self,
87        name: u32,
88        id: Rc<dyn Object>,
89    ) -> Result<(), ObjectError> {
90        let (
91            arg0,
92            arg1,
93        ) = (
94            name,
95            id,
96        );
97        let arg1_obj = arg1;
98        let arg1 = arg1_obj.core();
99        let core = self.core();
100        let Some(id) = core.server_obj_id.get() else {
101            return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
102        };
103        arg1.generate_server_id(arg1_obj.clone())
104            .map_err(|e| ObjectError(ObjectErrorKind::GenerateServerId("id", e)))?;
105        let arg1_id = arg1.server_obj_id.get().unwrap_or(0);
106        #[cfg(feature = "logging")]
107        if self.core.state.log {
108            #[cold]
109            fn log(state: &State, id: u32, arg0: u32, arg1_interface: &str, arg1_id: u32, arg1_version: u32) {
110                let (millis, micros) = time_since_epoch();
111                let prefix = &state.log_prefix;
112                let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      <= wl_registry#{}.bind(name: {}, id: {}#{} (version: {}))\n", id, arg0, arg1_interface, arg1_id, arg1_version);
113                state.log(args);
114            }
115            log(&self.core.state, id, arg0, arg1.interface.name(), arg1_id, arg1.version);
116        }
117        let Some(endpoint) = &self.core.state.server else {
118            return Ok(());
119        };
120        if !endpoint.flush_queued.replace(true) {
121            self.core.state.add_flushable_endpoint(endpoint, None);
122        }
123        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
124        let outgoing = &mut *outgoing_ref;
125        let mut fmt = outgoing.formatter();
126        fmt.words([
127            id,
128            0,
129            arg0,
130        ]);
131        fmt.string(arg1.interface.name());
132        fmt.words([
133            arg1.version,
134            arg1_id,
135        ]);
136        Ok(())
137    }
138
139    /// bind an object to the display
140    ///
141    /// Binds a new, client-created object to the server using the
142    /// specified name as the identifier.
143    ///
144    /// # Arguments
145    ///
146    /// - `name`: unique numeric name of the object
147    /// - `id`: bounded object
148    #[inline]
149    pub fn send_bind(
150        &self,
151        name: u32,
152        id: Rc<dyn Object>,
153    ) {
154        let res = self.try_send_bind(
155            name,
156            id,
157        );
158        if let Err(e) = res {
159            log_send("wl_registry.bind", &e);
160        }
161    }
162
163    /// Since when the global message is available.
164    pub const MSG__GLOBAL__SINCE: u32 = 1;
165
166    /// announce global object
167    ///
168    /// Notify the client of global objects.
169    ///
170    /// The event notifies the client that a global object with
171    /// the given name is now available, and it implements the
172    /// given version of the given interface.
173    ///
174    /// # Arguments
175    ///
176    /// - `name`: numeric name of the global object
177    /// - `interface`: interface implemented by the object
178    /// - `version`: interface version
179    #[inline]
180    pub fn try_send_global(
181        &self,
182        name: u32,
183        interface: ObjectInterface,
184        version: u32,
185    ) -> Result<(), ObjectError> {
186        let interface = interface.name();
187        let (
188            arg0,
189            arg1,
190            arg2,
191        ) = (
192            name,
193            interface,
194            version,
195        );
196        let core = self.core();
197        let client_ref = core.client.borrow();
198        let Some(client) = &*client_ref else {
199            return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
200        };
201        let id = core.client_obj_id.get().unwrap_or(0);
202        #[cfg(feature = "logging")]
203        if self.core.state.log {
204            #[cold]
205            fn log(state: &State, client_id: u64, id: u32, arg0: u32, arg1: &str, arg2: u32) {
206                let (millis, micros) = time_since_epoch();
207                let prefix = &state.log_prefix;
208                let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_registry#{}.global(name: {}, interface: {:?}, version: {})\n", client_id, id, arg0, arg1, arg2);
209                state.log(args);
210            }
211            log(&self.core.state, client.endpoint.id, id, arg0, arg1, arg2);
212        }
213        let endpoint = &client.endpoint;
214        if !endpoint.flush_queued.replace(true) {
215            self.core.state.add_flushable_endpoint(endpoint, Some(client));
216        }
217        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
218        let outgoing = &mut *outgoing_ref;
219        let mut fmt = outgoing.formatter();
220        fmt.words([
221            id,
222            0,
223            arg0,
224        ]);
225        fmt.string(arg1);
226        fmt.words([
227            arg2,
228        ]);
229        Ok(())
230    }
231
232    /// announce global object
233    ///
234    /// Notify the client of global objects.
235    ///
236    /// The event notifies the client that a global object with
237    /// the given name is now available, and it implements the
238    /// given version of the given interface.
239    ///
240    /// # Arguments
241    ///
242    /// - `name`: numeric name of the global object
243    /// - `interface`: interface implemented by the object
244    /// - `version`: interface version
245    #[inline]
246    pub fn send_global(
247        &self,
248        name: u32,
249        interface: ObjectInterface,
250        version: u32,
251    ) {
252        let res = self.try_send_global(
253            name,
254            interface,
255            version,
256        );
257        if let Err(e) = res {
258            log_send("wl_registry.global", &e);
259        }
260    }
261
262    /// Since when the global_remove message is available.
263    pub const MSG__GLOBAL_REMOVE__SINCE: u32 = 1;
264
265    /// announce removal of global object
266    ///
267    /// Notify the client of removed global objects.
268    ///
269    /// This event notifies the client that the global identified
270    /// by name is no longer available.  If the client bound to
271    /// the global using the bind request, the client should now
272    /// destroy that object.
273    ///
274    /// The object remains valid and requests to the object will be
275    /// ignored until the client destroys it, to avoid races between
276    /// the global going away and a client sending a request to it.
277    ///
278    /// # Arguments
279    ///
280    /// - `name`: numeric name of the global object
281    #[inline]
282    pub fn try_send_global_remove(
283        &self,
284        name: u32,
285    ) -> Result<(), ObjectError> {
286        let (
287            arg0,
288        ) = (
289            name,
290        );
291        let core = self.core();
292        let client_ref = core.client.borrow();
293        let Some(client) = &*client_ref else {
294            return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
295        };
296        let id = core.client_obj_id.get().unwrap_or(0);
297        #[cfg(feature = "logging")]
298        if self.core.state.log {
299            #[cold]
300            fn log(state: &State, client_id: u64, id: u32, arg0: u32) {
301                let (millis, micros) = time_since_epoch();
302                let prefix = &state.log_prefix;
303                let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_registry#{}.global_remove(name: {})\n", client_id, id, arg0);
304                state.log(args);
305            }
306            log(&self.core.state, client.endpoint.id, id, arg0);
307        }
308        let endpoint = &client.endpoint;
309        if !endpoint.flush_queued.replace(true) {
310            self.core.state.add_flushable_endpoint(endpoint, Some(client));
311        }
312        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
313        let outgoing = &mut *outgoing_ref;
314        let mut fmt = outgoing.formatter();
315        fmt.words([
316            id,
317            1,
318            arg0,
319        ]);
320        Ok(())
321    }
322
323    /// announce removal of global object
324    ///
325    /// Notify the client of removed global objects.
326    ///
327    /// This event notifies the client that the global identified
328    /// by name is no longer available.  If the client bound to
329    /// the global using the bind request, the client should now
330    /// destroy that object.
331    ///
332    /// The object remains valid and requests to the object will be
333    /// ignored until the client destroys it, to avoid races between
334    /// the global going away and a client sending a request to it.
335    ///
336    /// # Arguments
337    ///
338    /// - `name`: numeric name of the global object
339    #[inline]
340    pub fn send_global_remove(
341        &self,
342        name: u32,
343    ) {
344        let res = self.try_send_global_remove(
345            name,
346        );
347        if let Err(e) = res {
348            log_send("wl_registry.global_remove", &e);
349        }
350    }
351}
352
353/// A message handler for [`WlRegistry`] proxies.
354pub trait WlRegistryHandler: Any {
355    /// Event handler for wl_display.delete_id messages deleting the ID of this object.
356    ///
357    /// The default handler forwards the event to the client, if any.
358    #[inline]
359    fn delete_id(&mut self, slf: &Rc<WlRegistry>) {
360        slf.core.delete_id();
361    }
362
363    /// bind an object to the display
364    ///
365    /// Binds a new, client-created object to the server using the
366    /// specified name as the identifier.
367    ///
368    /// # Arguments
369    ///
370    /// - `name`: unique numeric name of the object
371    /// - `id`: bounded object
372    #[inline]
373    fn handle_bind(
374        &mut self,
375        slf: &Rc<WlRegistry>,
376        name: u32,
377        id: Rc<dyn Object>,
378    ) {
379        if !slf.core.forward_to_server.get() {
380            return;
381        }
382        let res = slf.try_send_bind(
383            name,
384            id,
385        );
386        if let Err(e) = res {
387            log_forward("wl_registry.bind", &e);
388        }
389    }
390
391    /// announce global object
392    ///
393    /// Notify the client of global objects.
394    ///
395    /// The event notifies the client that a global object with
396    /// the given name is now available, and it implements the
397    /// given version of the given interface.
398    ///
399    /// # Arguments
400    ///
401    /// - `name`: numeric name of the global object
402    /// - `interface`: interface implemented by the object
403    /// - `version`: interface version
404    #[inline]
405    fn handle_global(
406        &mut self,
407        slf: &Rc<WlRegistry>,
408        name: u32,
409        interface: ObjectInterface,
410        version: u32,
411    ) {
412        if !slf.core.forward_to_client.get() {
413            return;
414        }
415        let res = slf.try_send_global(
416            name,
417            interface,
418            version,
419        );
420        if let Err(e) = res {
421            log_forward("wl_registry.global", &e);
422        }
423    }
424
425    /// announce removal of global object
426    ///
427    /// Notify the client of removed global objects.
428    ///
429    /// This event notifies the client that the global identified
430    /// by name is no longer available.  If the client bound to
431    /// the global using the bind request, the client should now
432    /// destroy that object.
433    ///
434    /// The object remains valid and requests to the object will be
435    /// ignored until the client destroys it, to avoid races between
436    /// the global going away and a client sending a request to it.
437    ///
438    /// # Arguments
439    ///
440    /// - `name`: numeric name of the global object
441    #[inline]
442    fn handle_global_remove(
443        &mut self,
444        slf: &Rc<WlRegistry>,
445        name: u32,
446    ) {
447        if !slf.core.forward_to_client.get() {
448            return;
449        }
450        let res = slf.try_send_global_remove(
451            name,
452        );
453        if let Err(e) = res {
454            log_forward("wl_registry.global_remove", &e);
455        }
456    }
457}
458
459impl ObjectPrivate for WlRegistry {
460    fn new(state: &Rc<State>, version: u32) -> Rc<Self> {
461        Rc::<Self>::new_cyclic(|slf| Self {
462            core: ObjectCore::new(state, slf.clone(), ObjectInterface::WlRegistry, version),
463            handler: Default::default(),
464            names: Default::default(),
465        })
466    }
467
468    fn delete_id(self: Rc<Self>) -> Result<(), (ObjectError, Rc<dyn Object>)> {
469        let Some(mut handler) = self.handler.try_borrow_mut() else {
470            return Err((ObjectError(ObjectErrorKind::HandlerBorrowed), self));
471        };
472        if let Some(handler) = &mut *handler {
473            handler.delete_id(&self);
474        } else {
475            self.core.delete_id();
476        }
477        Ok(())
478    }
479
480    fn handle_request(self: Rc<Self>, client: &Rc<Client>, msg: &[u32], fds: &mut VecDeque<Rc<OwnedFd>>) -> Result<(), ObjectError> {
481        let Some(mut handler) = self.handler.try_borrow_mut() else {
482            return Err(ObjectError(ObjectErrorKind::HandlerBorrowed));
483        };
484        let handler = &mut *handler;
485        match msg[1] & 0xffff {
486            0 => {
487                let mut offset = 2;
488                let Some(&arg0) = msg.get(offset) else {
489                    return Err(ObjectError(ObjectErrorKind::MissingArgument("name")));
490                };
491                offset += 1;
492                let arg1_interface;
493                (arg1_interface, offset) = parse_string::<NonNullString>(msg, offset, "id")?;
494                let Some(&arg1_version) = msg.get(offset) else {
495                    return Err(ObjectError(ObjectErrorKind::MissingArgument("id")));
496                };
497                offset += 1;
498                let Some(&arg1) = msg.get(offset) else {
499                    return Err(ObjectError(ObjectErrorKind::MissingArgument("id")));
500                };
501                offset += 1;
502                if offset != msg.len() {
503                    return Err(ObjectError(ObjectErrorKind::TrailingBytes));
504                }
505                #[cfg(feature = "logging")]
506                if self.core.state.log {
507                    #[cold]
508                    fn log(state: &State, client_id: u64, id: u32, arg0: u32, arg1_interface: &str, arg1_id: u32, arg1_version: u32) {
509                        let (millis, micros) = time_since_epoch();
510                        let prefix = &state.log_prefix;
511                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_registry#{}.bind(name: {}, id: {}#{} (version: {}))\n", client_id, id, arg0, arg1_interface, arg1_id, arg1_version);
512                        state.log(args);
513                    }
514                    log(&self.core.state, client.endpoint.id, msg[0], arg0, arg1_interface, arg1, arg1_version);
515                }
516                let arg1_id = arg1;
517                let arg1 = create_object_for_interface(&self.core.state, arg1_interface, arg1_version)?;
518                arg1.core().set_client_id(client, arg1_id, arg1.clone())
519                    .map_err(|e| ObjectError(ObjectErrorKind::SetClientId(arg1_id, "id", e)))?;
520                if let Some(handler) = handler {
521                    (**handler).handle_bind(&self, arg0, arg1);
522                } else {
523                    DefaultHandler.handle_bind(&self, arg0, arg1);
524                }
525            }
526            n => {
527                let _ = client;
528                let _ = msg;
529                let _ = fds;
530                let _ = handler;
531                return Err(ObjectError(ObjectErrorKind::UnknownMessageId(n)));
532            }
533        }
534        Ok(())
535    }
536
537    fn handle_event(self: Rc<Self>, server: &Endpoint, msg: &[u32], fds: &mut VecDeque<Rc<OwnedFd>>) -> Result<(), ObjectError> {
538        let Some(mut handler) = self.handler.try_borrow_mut() else {
539            return Err(ObjectError(ObjectErrorKind::HandlerBorrowed));
540        };
541        let handler = &mut *handler;
542        match msg[1] & 0xffff {
543            0 => {
544                let mut offset = 2;
545                let Some(&arg0) = msg.get(offset) else {
546                    return Err(ObjectError(ObjectErrorKind::MissingArgument("name")));
547                };
548                offset += 1;
549                let arg1;
550                (arg1, offset) = parse_string::<NonNullString>(msg, offset, "interface")?;
551                let Some(&arg2) = msg.get(offset) else {
552                    return Err(ObjectError(ObjectErrorKind::MissingArgument("version")));
553                };
554                offset += 1;
555                if offset != msg.len() {
556                    return Err(ObjectError(ObjectErrorKind::TrailingBytes));
557                }
558                #[cfg(feature = "logging")]
559                if self.core.state.log {
560                    #[cold]
561                    fn log(state: &State, id: u32, arg0: u32, arg1: &str, arg2: u32) {
562                        let (millis, micros) = time_since_epoch();
563                        let prefix = &state.log_prefix;
564                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      -> wl_registry#{}.global(name: {}, interface: {:?}, version: {})\n", id, arg0, arg1, arg2);
565                        state.log(args);
566                    }
567                    log(&self.core.state, msg[0], arg0, arg1, arg2);
568                }
569                let Some(arg1) = ObjectInterface::from_str(arg1) else {
570                    return Ok(());
571                };
572                let max_version = self.core.state.baseline.1[arg1];
573                if max_version == 0 {
574                    return Ok(());
575                }
576                self.names.borrow_mut().insert(arg0);
577                let arg2 = max_version.min(arg2);
578                if let Some(handler) = handler {
579                    (**handler).handle_global(&self, arg0, arg1, arg2);
580                } else {
581                    DefaultHandler.handle_global(&self, arg0, arg1, arg2);
582                }
583            }
584            1 => {
585                let [
586                    arg0,
587                ] = msg[2..] else {
588                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 12)));
589                };
590                #[cfg(feature = "logging")]
591                if self.core.state.log {
592                    #[cold]
593                    fn log(state: &State, id: u32, arg0: u32) {
594                        let (millis, micros) = time_since_epoch();
595                        let prefix = &state.log_prefix;
596                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      -> wl_registry#{}.global_remove(name: {})\n", id, arg0);
597                        state.log(args);
598                    }
599                    log(&self.core.state, msg[0], arg0);
600                }
601                if !self.names.borrow_mut().remove(&arg0) {
602                    return Ok(());
603                }
604                if let Some(handler) = handler {
605                    (**handler).handle_global_remove(&self, arg0);
606                } else {
607                    DefaultHandler.handle_global_remove(&self, arg0);
608                }
609            }
610            n => {
611                let _ = server;
612                let _ = msg;
613                let _ = fds;
614                let _ = handler;
615                return Err(ObjectError(ObjectErrorKind::UnknownMessageId(n)));
616            }
617        }
618        Ok(())
619    }
620
621    fn get_request_name(&self, id: u32) -> Option<&'static str> {
622        let name = match id {
623            0 => "bind",
624            _ => return None,
625        };
626        Some(name)
627    }
628
629    fn get_event_name(&self, id: u32) -> Option<&'static str> {
630        let name = match id {
631            0 => "global",
632            1 => "global_remove",
633            _ => return None,
634        };
635        Some(name)
636    }
637}
638
639impl Object for WlRegistry {
640    fn core(&self) -> &ObjectCore {
641        &self.core
642    }
643
644    fn unset_handler(&self) {
645        self.handler.set(None);
646    }
647
648    fn get_handler_any_ref(&self) -> Result<HandlerRef<'_, dyn Any>, HandlerAccessError> {
649        let borrowed = self.handler.try_borrow().ok_or(HandlerAccessError::AlreadyBorrowed)?;
650        if borrowed.is_none() {
651            return Err(HandlerAccessError::NoHandler);
652        }
653        Ok(HandlerRef::map(borrowed, |handler| &**handler.as_ref().unwrap() as &dyn Any))
654    }
655
656    fn get_handler_any_mut(&self) -> Result<HandlerMut<'_, dyn Any>, HandlerAccessError> {
657        let borrowed = self.handler.try_borrow_mut().ok_or(HandlerAccessError::AlreadyBorrowed)?;
658        if borrowed.is_none() {
659            return Err(HandlerAccessError::NoHandler);
660        }
661        Ok(HandlerMut::map(borrowed, |handler| &mut **handler.as_mut().unwrap() as &mut dyn Any))
662    }
663}
664