wl_proxy/protocols/wayland/
wl_seat.rs

1//! group of input devices
2//!
3//! A seat is a group of keyboards, pointer and touch devices. This
4//! object is published as a global during start up, or when such a
5//! device is hot plugged.  A seat typically has a pointer and
6//! maintains a keyboard focus and a pointer focus.
7
8use crate::protocol_helpers::prelude::*;
9use super::super::all_types::*;
10
11/// A wl_seat object.
12///
13/// See the documentation of [the module][self] for the interface description.
14pub struct WlSeat {
15    core: ObjectCore,
16    handler: HandlerHolder<dyn WlSeatHandler>,
17}
18
19struct DefaultHandler;
20
21impl WlSeatHandler for DefaultHandler { }
22
23impl ConcreteObject for WlSeat {
24    const XML_VERSION: u32 = 10;
25    const INTERFACE: ObjectInterface = ObjectInterface::WlSeat;
26    const INTERFACE_NAME: &str = "wl_seat";
27}
28
29impl WlSeat {
30    /// Sets a new handler.
31    pub fn set_handler(&self, handler: impl WlSeatHandler) {
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 WlSeatHandler>) {
37        if self.core.state.destroyed.get() {
38            return;
39        }
40        self.handler.set(Some(handler));
41    }
42}
43
44impl Debug for WlSeat {
45    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
46        f.debug_struct("WlSeat")
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 WlSeat {
55    /// Since when the capabilities message is available.
56    pub const MSG__CAPABILITIES__SINCE: u32 = 1;
57
58    /// seat capabilities changed
59    ///
60    /// This is sent on binding to the seat global or whenever a seat gains
61    /// or loses the pointer, keyboard or touch capabilities.
62    /// The argument is a capability enum containing the complete set of
63    /// capabilities this seat has.
64    ///
65    /// When the pointer capability is added, a client may create a
66    /// wl_pointer object using the wl_seat.get_pointer request. This object
67    /// will receive pointer events until the capability is removed in the
68    /// future.
69    ///
70    /// When the pointer capability is removed, a client should destroy the
71    /// wl_pointer objects associated with the seat where the capability was
72    /// removed, using the wl_pointer.release request. No further pointer
73    /// events will be received on these objects.
74    ///
75    /// In some compositors, if a seat regains the pointer capability and a
76    /// client has a previously obtained wl_pointer object of version 4 or
77    /// less, that object may start sending pointer events again. This
78    /// behavior is considered a misinterpretation of the intended behavior
79    /// and must not be relied upon by the client. wl_pointer objects of
80    /// version 5 or later must not send events if created before the most
81    /// recent event notifying the client of an added pointer capability.
82    ///
83    /// The above behavior also applies to wl_keyboard and wl_touch with the
84    /// keyboard and touch capabilities, respectively.
85    ///
86    /// # Arguments
87    ///
88    /// - `capabilities`: capabilities of the seat
89    #[inline]
90    pub fn try_send_capabilities(
91        &self,
92        capabilities: WlSeatCapability,
93    ) -> Result<(), ObjectError> {
94        let (
95            arg0,
96        ) = (
97            capabilities,
98        );
99        let core = self.core();
100        let client_ref = core.client.borrow();
101        let Some(client) = &*client_ref else {
102            return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
103        };
104        let id = core.client_obj_id.get().unwrap_or(0);
105        #[cfg(feature = "logging")]
106        if self.core.state.log {
107            #[cold]
108            fn log(state: &State, client_id: u64, id: u32, arg0: WlSeatCapability) {
109                let (millis, micros) = time_since_epoch();
110                let prefix = &state.log_prefix;
111                let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_seat#{}.capabilities(capabilities: {:?})\n", client_id, id, arg0);
112                state.log(args);
113            }
114            log(&self.core.state, client.endpoint.id, id, arg0);
115        }
116        let endpoint = &client.endpoint;
117        if !endpoint.flush_queued.replace(true) {
118            self.core.state.add_flushable_endpoint(endpoint, Some(client));
119        }
120        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
121        let outgoing = &mut *outgoing_ref;
122        let mut fmt = outgoing.formatter();
123        fmt.words([
124            id,
125            0,
126            arg0.0,
127        ]);
128        Ok(())
129    }
130
131    /// seat capabilities changed
132    ///
133    /// This is sent on binding to the seat global or whenever a seat gains
134    /// or loses the pointer, keyboard or touch capabilities.
135    /// The argument is a capability enum containing the complete set of
136    /// capabilities this seat has.
137    ///
138    /// When the pointer capability is added, a client may create a
139    /// wl_pointer object using the wl_seat.get_pointer request. This object
140    /// will receive pointer events until the capability is removed in the
141    /// future.
142    ///
143    /// When the pointer capability is removed, a client should destroy the
144    /// wl_pointer objects associated with the seat where the capability was
145    /// removed, using the wl_pointer.release request. No further pointer
146    /// events will be received on these objects.
147    ///
148    /// In some compositors, if a seat regains the pointer capability and a
149    /// client has a previously obtained wl_pointer object of version 4 or
150    /// less, that object may start sending pointer events again. This
151    /// behavior is considered a misinterpretation of the intended behavior
152    /// and must not be relied upon by the client. wl_pointer objects of
153    /// version 5 or later must not send events if created before the most
154    /// recent event notifying the client of an added pointer capability.
155    ///
156    /// The above behavior also applies to wl_keyboard and wl_touch with the
157    /// keyboard and touch capabilities, respectively.
158    ///
159    /// # Arguments
160    ///
161    /// - `capabilities`: capabilities of the seat
162    #[inline]
163    pub fn send_capabilities(
164        &self,
165        capabilities: WlSeatCapability,
166    ) {
167        let res = self.try_send_capabilities(
168            capabilities,
169        );
170        if let Err(e) = res {
171            log_send("wl_seat.capabilities", &e);
172        }
173    }
174
175    /// Since when the get_pointer message is available.
176    pub const MSG__GET_POINTER__SINCE: u32 = 1;
177
178    /// return pointer object
179    ///
180    /// The ID provided will be initialized to the wl_pointer interface
181    /// for this seat.
182    ///
183    /// This request only takes effect if the seat has the pointer
184    /// capability, or has had the pointer capability in the past.
185    /// It is a protocol violation to issue this request on a seat that has
186    /// never had the pointer capability. The missing_capability error will
187    /// be sent in this case.
188    ///
189    /// # Arguments
190    ///
191    /// - `id`: seat pointer
192    #[inline]
193    pub fn try_send_get_pointer(
194        &self,
195        id: &Rc<WlPointer>,
196    ) -> Result<(), ObjectError> {
197        let (
198            arg0,
199        ) = (
200            id,
201        );
202        let arg0_obj = arg0;
203        let arg0 = arg0_obj.core();
204        let core = self.core();
205        let Some(id) = core.server_obj_id.get() else {
206            return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
207        };
208        arg0.generate_server_id(arg0_obj.clone())
209            .map_err(|e| ObjectError(ObjectErrorKind::GenerateServerId("id", e)))?;
210        let arg0_id = arg0.server_obj_id.get().unwrap_or(0);
211        #[cfg(feature = "logging")]
212        if self.core.state.log {
213            #[cold]
214            fn log(state: &State, id: u32, arg0: u32) {
215                let (millis, micros) = time_since_epoch();
216                let prefix = &state.log_prefix;
217                let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      <= wl_seat#{}.get_pointer(id: wl_pointer#{})\n", id, arg0);
218                state.log(args);
219            }
220            log(&self.core.state, id, arg0_id);
221        }
222        let Some(endpoint) = &self.core.state.server else {
223            return Ok(());
224        };
225        if !endpoint.flush_queued.replace(true) {
226            self.core.state.add_flushable_endpoint(endpoint, None);
227        }
228        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
229        let outgoing = &mut *outgoing_ref;
230        let mut fmt = outgoing.formatter();
231        fmt.words([
232            id,
233            0,
234            arg0_id,
235        ]);
236        Ok(())
237    }
238
239    /// return pointer object
240    ///
241    /// The ID provided will be initialized to the wl_pointer interface
242    /// for this seat.
243    ///
244    /// This request only takes effect if the seat has the pointer
245    /// capability, or has had the pointer capability in the past.
246    /// It is a protocol violation to issue this request on a seat that has
247    /// never had the pointer capability. The missing_capability error will
248    /// be sent in this case.
249    ///
250    /// # Arguments
251    ///
252    /// - `id`: seat pointer
253    #[inline]
254    pub fn send_get_pointer(
255        &self,
256        id: &Rc<WlPointer>,
257    ) {
258        let res = self.try_send_get_pointer(
259            id,
260        );
261        if let Err(e) = res {
262            log_send("wl_seat.get_pointer", &e);
263        }
264    }
265
266    /// return pointer object
267    ///
268    /// The ID provided will be initialized to the wl_pointer interface
269    /// for this seat.
270    ///
271    /// This request only takes effect if the seat has the pointer
272    /// capability, or has had the pointer capability in the past.
273    /// It is a protocol violation to issue this request on a seat that has
274    /// never had the pointer capability. The missing_capability error will
275    /// be sent in this case.
276    #[inline]
277    pub fn new_try_send_get_pointer(
278        &self,
279    ) -> Result<Rc<WlPointer>, ObjectError> {
280        let id = self.core.create_child();
281        self.try_send_get_pointer(
282            &id,
283        )?;
284        Ok(id)
285    }
286
287    /// return pointer object
288    ///
289    /// The ID provided will be initialized to the wl_pointer interface
290    /// for this seat.
291    ///
292    /// This request only takes effect if the seat has the pointer
293    /// capability, or has had the pointer capability in the past.
294    /// It is a protocol violation to issue this request on a seat that has
295    /// never had the pointer capability. The missing_capability error will
296    /// be sent in this case.
297    #[inline]
298    pub fn new_send_get_pointer(
299        &self,
300    ) -> Rc<WlPointer> {
301        let id = self.core.create_child();
302        self.send_get_pointer(
303            &id,
304        );
305        id
306    }
307
308    /// Since when the get_keyboard message is available.
309    pub const MSG__GET_KEYBOARD__SINCE: u32 = 1;
310
311    /// return keyboard object
312    ///
313    /// The ID provided will be initialized to the wl_keyboard interface
314    /// for this seat.
315    ///
316    /// This request only takes effect if the seat has the keyboard
317    /// capability, or has had the keyboard capability in the past.
318    /// It is a protocol violation to issue this request on a seat that has
319    /// never had the keyboard capability. The missing_capability error will
320    /// be sent in this case.
321    ///
322    /// # Arguments
323    ///
324    /// - `id`: seat keyboard
325    #[inline]
326    pub fn try_send_get_keyboard(
327        &self,
328        id: &Rc<WlKeyboard>,
329    ) -> Result<(), ObjectError> {
330        let (
331            arg0,
332        ) = (
333            id,
334        );
335        let arg0_obj = arg0;
336        let arg0 = arg0_obj.core();
337        let core = self.core();
338        let Some(id) = core.server_obj_id.get() else {
339            return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
340        };
341        arg0.generate_server_id(arg0_obj.clone())
342            .map_err(|e| ObjectError(ObjectErrorKind::GenerateServerId("id", e)))?;
343        let arg0_id = arg0.server_obj_id.get().unwrap_or(0);
344        #[cfg(feature = "logging")]
345        if self.core.state.log {
346            #[cold]
347            fn log(state: &State, id: u32, arg0: u32) {
348                let (millis, micros) = time_since_epoch();
349                let prefix = &state.log_prefix;
350                let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      <= wl_seat#{}.get_keyboard(id: wl_keyboard#{})\n", id, arg0);
351                state.log(args);
352            }
353            log(&self.core.state, id, arg0_id);
354        }
355        let Some(endpoint) = &self.core.state.server else {
356            return Ok(());
357        };
358        if !endpoint.flush_queued.replace(true) {
359            self.core.state.add_flushable_endpoint(endpoint, None);
360        }
361        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
362        let outgoing = &mut *outgoing_ref;
363        let mut fmt = outgoing.formatter();
364        fmt.words([
365            id,
366            1,
367            arg0_id,
368        ]);
369        Ok(())
370    }
371
372    /// return keyboard object
373    ///
374    /// The ID provided will be initialized to the wl_keyboard interface
375    /// for this seat.
376    ///
377    /// This request only takes effect if the seat has the keyboard
378    /// capability, or has had the keyboard capability in the past.
379    /// It is a protocol violation to issue this request on a seat that has
380    /// never had the keyboard capability. The missing_capability error will
381    /// be sent in this case.
382    ///
383    /// # Arguments
384    ///
385    /// - `id`: seat keyboard
386    #[inline]
387    pub fn send_get_keyboard(
388        &self,
389        id: &Rc<WlKeyboard>,
390    ) {
391        let res = self.try_send_get_keyboard(
392            id,
393        );
394        if let Err(e) = res {
395            log_send("wl_seat.get_keyboard", &e);
396        }
397    }
398
399    /// return keyboard object
400    ///
401    /// The ID provided will be initialized to the wl_keyboard interface
402    /// for this seat.
403    ///
404    /// This request only takes effect if the seat has the keyboard
405    /// capability, or has had the keyboard capability in the past.
406    /// It is a protocol violation to issue this request on a seat that has
407    /// never had the keyboard capability. The missing_capability error will
408    /// be sent in this case.
409    #[inline]
410    pub fn new_try_send_get_keyboard(
411        &self,
412    ) -> Result<Rc<WlKeyboard>, ObjectError> {
413        let id = self.core.create_child();
414        self.try_send_get_keyboard(
415            &id,
416        )?;
417        Ok(id)
418    }
419
420    /// return keyboard object
421    ///
422    /// The ID provided will be initialized to the wl_keyboard interface
423    /// for this seat.
424    ///
425    /// This request only takes effect if the seat has the keyboard
426    /// capability, or has had the keyboard capability in the past.
427    /// It is a protocol violation to issue this request on a seat that has
428    /// never had the keyboard capability. The missing_capability error will
429    /// be sent in this case.
430    #[inline]
431    pub fn new_send_get_keyboard(
432        &self,
433    ) -> Rc<WlKeyboard> {
434        let id = self.core.create_child();
435        self.send_get_keyboard(
436            &id,
437        );
438        id
439    }
440
441    /// Since when the get_touch message is available.
442    pub const MSG__GET_TOUCH__SINCE: u32 = 1;
443
444    /// return touch object
445    ///
446    /// The ID provided will be initialized to the wl_touch interface
447    /// for this seat.
448    ///
449    /// This request only takes effect if the seat has the touch
450    /// capability, or has had the touch capability in the past.
451    /// It is a protocol violation to issue this request on a seat that has
452    /// never had the touch capability. The missing_capability error will
453    /// be sent in this case.
454    ///
455    /// # Arguments
456    ///
457    /// - `id`: seat touch interface
458    #[inline]
459    pub fn try_send_get_touch(
460        &self,
461        id: &Rc<WlTouch>,
462    ) -> Result<(), ObjectError> {
463        let (
464            arg0,
465        ) = (
466            id,
467        );
468        let arg0_obj = arg0;
469        let arg0 = arg0_obj.core();
470        let core = self.core();
471        let Some(id) = core.server_obj_id.get() else {
472            return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
473        };
474        arg0.generate_server_id(arg0_obj.clone())
475            .map_err(|e| ObjectError(ObjectErrorKind::GenerateServerId("id", e)))?;
476        let arg0_id = arg0.server_obj_id.get().unwrap_or(0);
477        #[cfg(feature = "logging")]
478        if self.core.state.log {
479            #[cold]
480            fn log(state: &State, id: u32, arg0: u32) {
481                let (millis, micros) = time_since_epoch();
482                let prefix = &state.log_prefix;
483                let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      <= wl_seat#{}.get_touch(id: wl_touch#{})\n", id, arg0);
484                state.log(args);
485            }
486            log(&self.core.state, id, arg0_id);
487        }
488        let Some(endpoint) = &self.core.state.server else {
489            return Ok(());
490        };
491        if !endpoint.flush_queued.replace(true) {
492            self.core.state.add_flushable_endpoint(endpoint, None);
493        }
494        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
495        let outgoing = &mut *outgoing_ref;
496        let mut fmt = outgoing.formatter();
497        fmt.words([
498            id,
499            2,
500            arg0_id,
501        ]);
502        Ok(())
503    }
504
505    /// return touch object
506    ///
507    /// The ID provided will be initialized to the wl_touch interface
508    /// for this seat.
509    ///
510    /// This request only takes effect if the seat has the touch
511    /// capability, or has had the touch capability in the past.
512    /// It is a protocol violation to issue this request on a seat that has
513    /// never had the touch capability. The missing_capability error will
514    /// be sent in this case.
515    ///
516    /// # Arguments
517    ///
518    /// - `id`: seat touch interface
519    #[inline]
520    pub fn send_get_touch(
521        &self,
522        id: &Rc<WlTouch>,
523    ) {
524        let res = self.try_send_get_touch(
525            id,
526        );
527        if let Err(e) = res {
528            log_send("wl_seat.get_touch", &e);
529        }
530    }
531
532    /// return touch object
533    ///
534    /// The ID provided will be initialized to the wl_touch interface
535    /// for this seat.
536    ///
537    /// This request only takes effect if the seat has the touch
538    /// capability, or has had the touch capability in the past.
539    /// It is a protocol violation to issue this request on a seat that has
540    /// never had the touch capability. The missing_capability error will
541    /// be sent in this case.
542    #[inline]
543    pub fn new_try_send_get_touch(
544        &self,
545    ) -> Result<Rc<WlTouch>, ObjectError> {
546        let id = self.core.create_child();
547        self.try_send_get_touch(
548            &id,
549        )?;
550        Ok(id)
551    }
552
553    /// return touch object
554    ///
555    /// The ID provided will be initialized to the wl_touch interface
556    /// for this seat.
557    ///
558    /// This request only takes effect if the seat has the touch
559    /// capability, or has had the touch capability in the past.
560    /// It is a protocol violation to issue this request on a seat that has
561    /// never had the touch capability. The missing_capability error will
562    /// be sent in this case.
563    #[inline]
564    pub fn new_send_get_touch(
565        &self,
566    ) -> Rc<WlTouch> {
567        let id = self.core.create_child();
568        self.send_get_touch(
569            &id,
570        );
571        id
572    }
573
574    /// Since when the name message is available.
575    pub const MSG__NAME__SINCE: u32 = 2;
576
577    /// unique identifier for this seat
578    ///
579    /// In a multi-seat configuration the seat name can be used by clients to
580    /// help identify which physical devices the seat represents.
581    ///
582    /// The seat name is a UTF-8 string with no convention defined for its
583    /// contents. Each name is unique among all wl_seat globals. The name is
584    /// only guaranteed to be unique for the current compositor instance.
585    ///
586    /// The same seat names are used for all clients. Thus, the name can be
587    /// shared across processes to refer to a specific wl_seat global.
588    ///
589    /// The name event is sent after binding to the seat global, and should be sent
590    /// before announcing capabilities. This event only sent once per seat object,
591    /// and the name does not change over the lifetime of the wl_seat global.
592    ///
593    /// Compositors may re-use the same seat name if the wl_seat global is
594    /// destroyed and re-created later.
595    ///
596    /// # Arguments
597    ///
598    /// - `name`: seat identifier
599    #[inline]
600    pub fn try_send_name(
601        &self,
602        name: &str,
603    ) -> Result<(), ObjectError> {
604        let (
605            arg0,
606        ) = (
607            name,
608        );
609        let core = self.core();
610        let client_ref = core.client.borrow();
611        let Some(client) = &*client_ref else {
612            return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
613        };
614        let id = core.client_obj_id.get().unwrap_or(0);
615        #[cfg(feature = "logging")]
616        if self.core.state.log {
617            #[cold]
618            fn log(state: &State, client_id: u64, id: u32, arg0: &str) {
619                let (millis, micros) = time_since_epoch();
620                let prefix = &state.log_prefix;
621                let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_seat#{}.name(name: {:?})\n", client_id, id, arg0);
622                state.log(args);
623            }
624            log(&self.core.state, client.endpoint.id, id, arg0);
625        }
626        let endpoint = &client.endpoint;
627        if !endpoint.flush_queued.replace(true) {
628            self.core.state.add_flushable_endpoint(endpoint, Some(client));
629        }
630        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
631        let outgoing = &mut *outgoing_ref;
632        let mut fmt = outgoing.formatter();
633        fmt.words([
634            id,
635            1,
636        ]);
637        fmt.string(arg0);
638        Ok(())
639    }
640
641    /// unique identifier for this seat
642    ///
643    /// In a multi-seat configuration the seat name can be used by clients to
644    /// help identify which physical devices the seat represents.
645    ///
646    /// The seat name is a UTF-8 string with no convention defined for its
647    /// contents. Each name is unique among all wl_seat globals. The name is
648    /// only guaranteed to be unique for the current compositor instance.
649    ///
650    /// The same seat names are used for all clients. Thus, the name can be
651    /// shared across processes to refer to a specific wl_seat global.
652    ///
653    /// The name event is sent after binding to the seat global, and should be sent
654    /// before announcing capabilities. This event only sent once per seat object,
655    /// and the name does not change over the lifetime of the wl_seat global.
656    ///
657    /// Compositors may re-use the same seat name if the wl_seat global is
658    /// destroyed and re-created later.
659    ///
660    /// # Arguments
661    ///
662    /// - `name`: seat identifier
663    #[inline]
664    pub fn send_name(
665        &self,
666        name: &str,
667    ) {
668        let res = self.try_send_name(
669            name,
670        );
671        if let Err(e) = res {
672            log_send("wl_seat.name", &e);
673        }
674    }
675
676    /// Since when the release message is available.
677    pub const MSG__RELEASE__SINCE: u32 = 5;
678
679    /// release the seat object
680    ///
681    /// Using this request a client can tell the server that it is not going to
682    /// use the seat object anymore.
683    #[inline]
684    pub fn try_send_release(
685        &self,
686    ) -> Result<(), ObjectError> {
687        let core = self.core();
688        let Some(id) = core.server_obj_id.get() else {
689            return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
690        };
691        #[cfg(feature = "logging")]
692        if self.core.state.log {
693            #[cold]
694            fn log(state: &State, id: u32) {
695                let (millis, micros) = time_since_epoch();
696                let prefix = &state.log_prefix;
697                let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      <= wl_seat#{}.release()\n", id);
698                state.log(args);
699            }
700            log(&self.core.state, id);
701        }
702        let Some(endpoint) = &self.core.state.server else {
703            return Ok(());
704        };
705        if !endpoint.flush_queued.replace(true) {
706            self.core.state.add_flushable_endpoint(endpoint, None);
707        }
708        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
709        let outgoing = &mut *outgoing_ref;
710        let mut fmt = outgoing.formatter();
711        fmt.words([
712            id,
713            3,
714        ]);
715        self.core.handle_server_destroy();
716        Ok(())
717    }
718
719    /// release the seat object
720    ///
721    /// Using this request a client can tell the server that it is not going to
722    /// use the seat object anymore.
723    #[inline]
724    pub fn send_release(
725        &self,
726    ) {
727        let res = self.try_send_release(
728        );
729        if let Err(e) = res {
730            log_send("wl_seat.release", &e);
731        }
732    }
733}
734
735/// A message handler for [`WlSeat`] proxies.
736pub trait WlSeatHandler: Any {
737    /// Event handler for wl_display.delete_id messages deleting the ID of this object.
738    ///
739    /// The default handler forwards the event to the client, if any.
740    #[inline]
741    fn delete_id(&mut self, slf: &Rc<WlSeat>) {
742        slf.core.delete_id();
743    }
744
745    /// seat capabilities changed
746    ///
747    /// This is sent on binding to the seat global or whenever a seat gains
748    /// or loses the pointer, keyboard or touch capabilities.
749    /// The argument is a capability enum containing the complete set of
750    /// capabilities this seat has.
751    ///
752    /// When the pointer capability is added, a client may create a
753    /// wl_pointer object using the wl_seat.get_pointer request. This object
754    /// will receive pointer events until the capability is removed in the
755    /// future.
756    ///
757    /// When the pointer capability is removed, a client should destroy the
758    /// wl_pointer objects associated with the seat where the capability was
759    /// removed, using the wl_pointer.release request. No further pointer
760    /// events will be received on these objects.
761    ///
762    /// In some compositors, if a seat regains the pointer capability and a
763    /// client has a previously obtained wl_pointer object of version 4 or
764    /// less, that object may start sending pointer events again. This
765    /// behavior is considered a misinterpretation of the intended behavior
766    /// and must not be relied upon by the client. wl_pointer objects of
767    /// version 5 or later must not send events if created before the most
768    /// recent event notifying the client of an added pointer capability.
769    ///
770    /// The above behavior also applies to wl_keyboard and wl_touch with the
771    /// keyboard and touch capabilities, respectively.
772    ///
773    /// # Arguments
774    ///
775    /// - `capabilities`: capabilities of the seat
776    #[inline]
777    fn handle_capabilities(
778        &mut self,
779        slf: &Rc<WlSeat>,
780        capabilities: WlSeatCapability,
781    ) {
782        if !slf.core.forward_to_client.get() {
783            return;
784        }
785        let res = slf.try_send_capabilities(
786            capabilities,
787        );
788        if let Err(e) = res {
789            log_forward("wl_seat.capabilities", &e);
790        }
791    }
792
793    /// return pointer object
794    ///
795    /// The ID provided will be initialized to the wl_pointer interface
796    /// for this seat.
797    ///
798    /// This request only takes effect if the seat has the pointer
799    /// capability, or has had the pointer capability in the past.
800    /// It is a protocol violation to issue this request on a seat that has
801    /// never had the pointer capability. The missing_capability error will
802    /// be sent in this case.
803    ///
804    /// # Arguments
805    ///
806    /// - `id`: seat pointer
807    #[inline]
808    fn handle_get_pointer(
809        &mut self,
810        slf: &Rc<WlSeat>,
811        id: &Rc<WlPointer>,
812    ) {
813        if !slf.core.forward_to_server.get() {
814            return;
815        }
816        let res = slf.try_send_get_pointer(
817            id,
818        );
819        if let Err(e) = res {
820            log_forward("wl_seat.get_pointer", &e);
821        }
822    }
823
824    /// return keyboard object
825    ///
826    /// The ID provided will be initialized to the wl_keyboard interface
827    /// for this seat.
828    ///
829    /// This request only takes effect if the seat has the keyboard
830    /// capability, or has had the keyboard capability in the past.
831    /// It is a protocol violation to issue this request on a seat that has
832    /// never had the keyboard capability. The missing_capability error will
833    /// be sent in this case.
834    ///
835    /// # Arguments
836    ///
837    /// - `id`: seat keyboard
838    #[inline]
839    fn handle_get_keyboard(
840        &mut self,
841        slf: &Rc<WlSeat>,
842        id: &Rc<WlKeyboard>,
843    ) {
844        if !slf.core.forward_to_server.get() {
845            return;
846        }
847        let res = slf.try_send_get_keyboard(
848            id,
849        );
850        if let Err(e) = res {
851            log_forward("wl_seat.get_keyboard", &e);
852        }
853    }
854
855    /// return touch object
856    ///
857    /// The ID provided will be initialized to the wl_touch interface
858    /// for this seat.
859    ///
860    /// This request only takes effect if the seat has the touch
861    /// capability, or has had the touch capability in the past.
862    /// It is a protocol violation to issue this request on a seat that has
863    /// never had the touch capability. The missing_capability error will
864    /// be sent in this case.
865    ///
866    /// # Arguments
867    ///
868    /// - `id`: seat touch interface
869    #[inline]
870    fn handle_get_touch(
871        &mut self,
872        slf: &Rc<WlSeat>,
873        id: &Rc<WlTouch>,
874    ) {
875        if !slf.core.forward_to_server.get() {
876            return;
877        }
878        let res = slf.try_send_get_touch(
879            id,
880        );
881        if let Err(e) = res {
882            log_forward("wl_seat.get_touch", &e);
883        }
884    }
885
886    /// unique identifier for this seat
887    ///
888    /// In a multi-seat configuration the seat name can be used by clients to
889    /// help identify which physical devices the seat represents.
890    ///
891    /// The seat name is a UTF-8 string with no convention defined for its
892    /// contents. Each name is unique among all wl_seat globals. The name is
893    /// only guaranteed to be unique for the current compositor instance.
894    ///
895    /// The same seat names are used for all clients. Thus, the name can be
896    /// shared across processes to refer to a specific wl_seat global.
897    ///
898    /// The name event is sent after binding to the seat global, and should be sent
899    /// before announcing capabilities. This event only sent once per seat object,
900    /// and the name does not change over the lifetime of the wl_seat global.
901    ///
902    /// Compositors may re-use the same seat name if the wl_seat global is
903    /// destroyed and re-created later.
904    ///
905    /// # Arguments
906    ///
907    /// - `name`: seat identifier
908    #[inline]
909    fn handle_name(
910        &mut self,
911        slf: &Rc<WlSeat>,
912        name: &str,
913    ) {
914        if !slf.core.forward_to_client.get() {
915            return;
916        }
917        let res = slf.try_send_name(
918            name,
919        );
920        if let Err(e) = res {
921            log_forward("wl_seat.name", &e);
922        }
923    }
924
925    /// release the seat object
926    ///
927    /// Using this request a client can tell the server that it is not going to
928    /// use the seat object anymore.
929    #[inline]
930    fn handle_release(
931        &mut self,
932        slf: &Rc<WlSeat>,
933    ) {
934        if !slf.core.forward_to_server.get() {
935            return;
936        }
937        let res = slf.try_send_release(
938        );
939        if let Err(e) = res {
940            log_forward("wl_seat.release", &e);
941        }
942    }
943}
944
945impl ObjectPrivate for WlSeat {
946    fn new(state: &Rc<State>, version: u32) -> Rc<Self> {
947        Rc::<Self>::new_cyclic(|slf| Self {
948            core: ObjectCore::new(state, slf.clone(), ObjectInterface::WlSeat, version),
949            handler: Default::default(),
950        })
951    }
952
953    fn delete_id(self: Rc<Self>) -> Result<(), (ObjectError, Rc<dyn Object>)> {
954        let Some(mut handler) = self.handler.try_borrow_mut() else {
955            return Err((ObjectError(ObjectErrorKind::HandlerBorrowed), self));
956        };
957        if let Some(handler) = &mut *handler {
958            handler.delete_id(&self);
959        } else {
960            self.core.delete_id();
961        }
962        Ok(())
963    }
964
965    fn handle_request(self: Rc<Self>, client: &Rc<Client>, msg: &[u32], fds: &mut VecDeque<Rc<OwnedFd>>) -> Result<(), ObjectError> {
966        let Some(mut handler) = self.handler.try_borrow_mut() else {
967            return Err(ObjectError(ObjectErrorKind::HandlerBorrowed));
968        };
969        let handler = &mut *handler;
970        match msg[1] & 0xffff {
971            0 => {
972                let [
973                    arg0,
974                ] = msg[2..] else {
975                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 12)));
976                };
977                #[cfg(feature = "logging")]
978                if self.core.state.log {
979                    #[cold]
980                    fn log(state: &State, client_id: u64, id: u32, arg0: u32) {
981                        let (millis, micros) = time_since_epoch();
982                        let prefix = &state.log_prefix;
983                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_seat#{}.get_pointer(id: wl_pointer#{})\n", client_id, id, arg0);
984                        state.log(args);
985                    }
986                    log(&self.core.state, client.endpoint.id, msg[0], arg0);
987                }
988                let arg0_id = arg0;
989                let arg0 = WlPointer::new(&self.core.state, self.core.version);
990                arg0.core().set_client_id(client, arg0_id, arg0.clone())
991                    .map_err(|e| ObjectError(ObjectErrorKind::SetClientId(arg0_id, "id", e)))?;
992                let arg0 = &arg0;
993                if let Some(handler) = handler {
994                    (**handler).handle_get_pointer(&self, arg0);
995                } else {
996                    DefaultHandler.handle_get_pointer(&self, arg0);
997                }
998            }
999            1 => {
1000                let [
1001                    arg0,
1002                ] = msg[2..] else {
1003                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 12)));
1004                };
1005                #[cfg(feature = "logging")]
1006                if self.core.state.log {
1007                    #[cold]
1008                    fn log(state: &State, client_id: u64, id: u32, arg0: u32) {
1009                        let (millis, micros) = time_since_epoch();
1010                        let prefix = &state.log_prefix;
1011                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_seat#{}.get_keyboard(id: wl_keyboard#{})\n", client_id, id, arg0);
1012                        state.log(args);
1013                    }
1014                    log(&self.core.state, client.endpoint.id, msg[0], arg0);
1015                }
1016                let arg0_id = arg0;
1017                let arg0 = WlKeyboard::new(&self.core.state, self.core.version);
1018                arg0.core().set_client_id(client, arg0_id, arg0.clone())
1019                    .map_err(|e| ObjectError(ObjectErrorKind::SetClientId(arg0_id, "id", e)))?;
1020                let arg0 = &arg0;
1021                if let Some(handler) = handler {
1022                    (**handler).handle_get_keyboard(&self, arg0);
1023                } else {
1024                    DefaultHandler.handle_get_keyboard(&self, arg0);
1025                }
1026            }
1027            2 => {
1028                let [
1029                    arg0,
1030                ] = msg[2..] else {
1031                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 12)));
1032                };
1033                #[cfg(feature = "logging")]
1034                if self.core.state.log {
1035                    #[cold]
1036                    fn log(state: &State, client_id: u64, id: u32, arg0: u32) {
1037                        let (millis, micros) = time_since_epoch();
1038                        let prefix = &state.log_prefix;
1039                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_seat#{}.get_touch(id: wl_touch#{})\n", client_id, id, arg0);
1040                        state.log(args);
1041                    }
1042                    log(&self.core.state, client.endpoint.id, msg[0], arg0);
1043                }
1044                let arg0_id = arg0;
1045                let arg0 = WlTouch::new(&self.core.state, self.core.version);
1046                arg0.core().set_client_id(client, arg0_id, arg0.clone())
1047                    .map_err(|e| ObjectError(ObjectErrorKind::SetClientId(arg0_id, "id", e)))?;
1048                let arg0 = &arg0;
1049                if let Some(handler) = handler {
1050                    (**handler).handle_get_touch(&self, arg0);
1051                } else {
1052                    DefaultHandler.handle_get_touch(&self, arg0);
1053                }
1054            }
1055            3 => {
1056                if msg.len() != 2 {
1057                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 8)));
1058                }
1059                #[cfg(feature = "logging")]
1060                if self.core.state.log {
1061                    #[cold]
1062                    fn log(state: &State, client_id: u64, id: u32) {
1063                        let (millis, micros) = time_since_epoch();
1064                        let prefix = &state.log_prefix;
1065                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_seat#{}.release()\n", client_id, id);
1066                        state.log(args);
1067                    }
1068                    log(&self.core.state, client.endpoint.id, msg[0]);
1069                }
1070                self.core.handle_client_destroy();
1071                if let Some(handler) = handler {
1072                    (**handler).handle_release(&self);
1073                } else {
1074                    DefaultHandler.handle_release(&self);
1075                }
1076            }
1077            n => {
1078                let _ = client;
1079                let _ = msg;
1080                let _ = fds;
1081                let _ = handler;
1082                return Err(ObjectError(ObjectErrorKind::UnknownMessageId(n)));
1083            }
1084        }
1085        Ok(())
1086    }
1087
1088    fn handle_event(self: Rc<Self>, server: &Endpoint, msg: &[u32], fds: &mut VecDeque<Rc<OwnedFd>>) -> Result<(), ObjectError> {
1089        let Some(mut handler) = self.handler.try_borrow_mut() else {
1090            return Err(ObjectError(ObjectErrorKind::HandlerBorrowed));
1091        };
1092        let handler = &mut *handler;
1093        match msg[1] & 0xffff {
1094            0 => {
1095                let [
1096                    arg0,
1097                ] = msg[2..] else {
1098                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 12)));
1099                };
1100                let arg0 = WlSeatCapability(arg0);
1101                #[cfg(feature = "logging")]
1102                if self.core.state.log {
1103                    #[cold]
1104                    fn log(state: &State, id: u32, arg0: WlSeatCapability) {
1105                        let (millis, micros) = time_since_epoch();
1106                        let prefix = &state.log_prefix;
1107                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      -> wl_seat#{}.capabilities(capabilities: {:?})\n", id, arg0);
1108                        state.log(args);
1109                    }
1110                    log(&self.core.state, msg[0], arg0);
1111                }
1112                if let Some(handler) = handler {
1113                    (**handler).handle_capabilities(&self, arg0);
1114                } else {
1115                    DefaultHandler.handle_capabilities(&self, arg0);
1116                }
1117            }
1118            1 => {
1119                let mut offset = 2;
1120                let arg0;
1121                (arg0, offset) = parse_string::<NonNullString>(msg, offset, "name")?;
1122                if offset != msg.len() {
1123                    return Err(ObjectError(ObjectErrorKind::TrailingBytes));
1124                }
1125                #[cfg(feature = "logging")]
1126                if self.core.state.log {
1127                    #[cold]
1128                    fn log(state: &State, id: u32, arg0: &str) {
1129                        let (millis, micros) = time_since_epoch();
1130                        let prefix = &state.log_prefix;
1131                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      -> wl_seat#{}.name(name: {:?})\n", id, arg0);
1132                        state.log(args);
1133                    }
1134                    log(&self.core.state, msg[0], arg0);
1135                }
1136                if let Some(handler) = handler {
1137                    (**handler).handle_name(&self, arg0);
1138                } else {
1139                    DefaultHandler.handle_name(&self, arg0);
1140                }
1141            }
1142            n => {
1143                let _ = server;
1144                let _ = msg;
1145                let _ = fds;
1146                let _ = handler;
1147                return Err(ObjectError(ObjectErrorKind::UnknownMessageId(n)));
1148            }
1149        }
1150        Ok(())
1151    }
1152
1153    fn get_request_name(&self, id: u32) -> Option<&'static str> {
1154        let name = match id {
1155            0 => "get_pointer",
1156            1 => "get_keyboard",
1157            2 => "get_touch",
1158            3 => "release",
1159            _ => return None,
1160        };
1161        Some(name)
1162    }
1163
1164    fn get_event_name(&self, id: u32) -> Option<&'static str> {
1165        let name = match id {
1166            0 => "capabilities",
1167            1 => "name",
1168            _ => return None,
1169        };
1170        Some(name)
1171    }
1172}
1173
1174impl Object for WlSeat {
1175    fn core(&self) -> &ObjectCore {
1176        &self.core
1177    }
1178
1179    fn unset_handler(&self) {
1180        self.handler.set(None);
1181    }
1182
1183    fn get_handler_any_ref(&self) -> Result<HandlerRef<'_, dyn Any>, HandlerAccessError> {
1184        let borrowed = self.handler.try_borrow().ok_or(HandlerAccessError::AlreadyBorrowed)?;
1185        if borrowed.is_none() {
1186            return Err(HandlerAccessError::NoHandler);
1187        }
1188        Ok(HandlerRef::map(borrowed, |handler| &**handler.as_ref().unwrap() as &dyn Any))
1189    }
1190
1191    fn get_handler_any_mut(&self) -> Result<HandlerMut<'_, dyn Any>, HandlerAccessError> {
1192        let borrowed = self.handler.try_borrow_mut().ok_or(HandlerAccessError::AlreadyBorrowed)?;
1193        if borrowed.is_none() {
1194            return Err(HandlerAccessError::NoHandler);
1195        }
1196        Ok(HandlerMut::map(borrowed, |handler| &mut **handler.as_mut().unwrap() as &mut dyn Any))
1197    }
1198}
1199
1200impl WlSeat {
1201    /// Since when the capability.pointer enum variant is available.
1202    pub const ENM__CAPABILITY_POINTER__SINCE: u32 = 1;
1203    /// Since when the capability.keyboard enum variant is available.
1204    pub const ENM__CAPABILITY_KEYBOARD__SINCE: u32 = 1;
1205    /// Since when the capability.touch enum variant is available.
1206    pub const ENM__CAPABILITY_TOUCH__SINCE: u32 = 1;
1207
1208    /// Since when the error.missing_capability enum variant is available.
1209    pub const ENM__ERROR_MISSING_CAPABILITY__SINCE: u32 = 1;
1210}
1211
1212/// seat capability bitmask
1213///
1214/// This is a bitmask of capabilities this seat has; if a member is
1215/// set, then it is present on the seat.
1216#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
1217#[derive(Default)]
1218pub struct WlSeatCapability(pub u32);
1219
1220/// An iterator over the set bits in a [`WlSeatCapability`].
1221///
1222/// You can construct this with the `IntoIterator` implementation of `WlSeatCapability`.
1223#[derive(Clone, Debug)]
1224pub struct WlSeatCapabilityIter(pub u32);
1225
1226impl WlSeatCapability {
1227    /// the seat has pointer devices
1228    pub const POINTER: Self = Self(1);
1229
1230    /// the seat has one or more keyboards
1231    pub const KEYBOARD: Self = Self(2);
1232
1233    /// the seat has touch devices
1234    pub const TOUCH: Self = Self(4);
1235}
1236
1237impl WlSeatCapability {
1238    #[inline]
1239    pub const fn empty() -> Self {
1240        Self(0)
1241    }
1242
1243    #[inline]
1244    #[must_use]
1245    pub const fn is_empty(self) -> bool {
1246        self.0 == 0
1247    }
1248
1249    #[inline]
1250    #[must_use]
1251    pub const fn contains(self, other: Self) -> bool {
1252        self.0 & other.0 == other.0
1253    }
1254
1255    #[inline]
1256    #[must_use]
1257    pub const fn intersects(self, other: Self) -> bool {
1258        self.0 & other.0 != 0
1259    }
1260
1261    #[inline]
1262    pub const fn insert(&mut self, other: Self) {
1263        *self = self.union(other);
1264    }
1265
1266    #[inline]
1267    pub const fn remove(&mut self, other: Self) {
1268        *self = self.difference(other);
1269    }
1270
1271    #[inline]
1272    pub const fn toggle(&mut self, other: Self) {
1273        *self = self.symmetric_difference(other);
1274    }
1275
1276    #[inline]
1277    pub const fn set(&mut self, other: Self, value: bool) {
1278        if value {
1279            self.insert(other);
1280        } else {
1281            self.remove(other);
1282        }
1283    }
1284
1285    #[inline]
1286    #[must_use]
1287    pub const fn intersection(self, other: Self) -> Self {
1288        Self(self.0 & other.0)
1289    }
1290
1291    #[inline]
1292    #[must_use]
1293    pub const fn union(self, other: Self) -> Self {
1294        Self(self.0 | other.0)
1295    }
1296
1297    #[inline]
1298    #[must_use]
1299    pub const fn difference(self, other: Self) -> Self {
1300        Self(self.0 & !other.0)
1301    }
1302
1303    #[inline]
1304    #[must_use]
1305    pub const fn complement(self) -> Self {
1306        Self(!self.0)
1307    }
1308
1309    #[inline]
1310    #[must_use]
1311    pub const fn symmetric_difference(self, other: Self) -> Self {
1312        Self(self.0 ^ other.0)
1313    }
1314
1315    #[inline]
1316    pub const fn all_known() -> Self {
1317        #[allow(clippy::eq_op, clippy::identity_op)]
1318        Self(0 | 1 | 2 | 4)
1319    }
1320}
1321
1322impl Iterator for WlSeatCapabilityIter {
1323    type Item = WlSeatCapability;
1324
1325    fn next(&mut self) -> Option<Self::Item> {
1326        if self.0 == 0 {
1327            return None;
1328        }
1329        let bit = 1 << self.0.trailing_zeros();
1330        self.0 &= !bit;
1331        Some(WlSeatCapability(bit))
1332    }
1333}
1334
1335impl IntoIterator for WlSeatCapability {
1336    type Item = WlSeatCapability;
1337    type IntoIter = WlSeatCapabilityIter;
1338
1339    fn into_iter(self) -> Self::IntoIter {
1340        WlSeatCapabilityIter(self.0)
1341    }
1342}
1343
1344impl BitAnd for WlSeatCapability {
1345    type Output = Self;
1346
1347    fn bitand(self, rhs: Self) -> Self::Output {
1348        self.intersection(rhs)
1349    }
1350}
1351
1352impl BitAndAssign for WlSeatCapability {
1353    fn bitand_assign(&mut self, rhs: Self) {
1354        *self = self.intersection(rhs);
1355    }
1356}
1357
1358impl BitOr for WlSeatCapability {
1359    type Output = Self;
1360
1361    fn bitor(self, rhs: Self) -> Self::Output {
1362        self.union(rhs)
1363    }
1364}
1365
1366impl BitOrAssign for WlSeatCapability {
1367    fn bitor_assign(&mut self, rhs: Self) {
1368        *self = self.union(rhs);
1369    }
1370}
1371
1372impl BitXor for WlSeatCapability {
1373    type Output = Self;
1374
1375    fn bitxor(self, rhs: Self) -> Self::Output {
1376        self.symmetric_difference(rhs)
1377    }
1378}
1379
1380impl BitXorAssign for WlSeatCapability {
1381    fn bitxor_assign(&mut self, rhs: Self) {
1382        *self = self.symmetric_difference(rhs);
1383    }
1384}
1385
1386impl Sub for WlSeatCapability {
1387    type Output = Self;
1388
1389    fn sub(self, rhs: Self) -> Self::Output {
1390        self.difference(rhs)
1391    }
1392}
1393
1394impl SubAssign for WlSeatCapability {
1395    fn sub_assign(&mut self, rhs: Self) {
1396        *self = self.difference(rhs);
1397    }
1398}
1399
1400impl Not for WlSeatCapability {
1401    type Output = Self;
1402
1403    fn not(self) -> Self::Output {
1404        self.complement()
1405    }
1406}
1407
1408impl Debug for WlSeatCapability {
1409    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1410        let mut v = self.0;
1411        let mut first = true;
1412        if v & 1 == 1 {
1413            v &= !1;
1414            if first {
1415                first = false;
1416            } else {
1417                f.write_str(" | ")?;
1418            }
1419            f.write_str("POINTER")?;
1420        }
1421        if v & 2 == 2 {
1422            v &= !2;
1423            if first {
1424                first = false;
1425            } else {
1426                f.write_str(" | ")?;
1427            }
1428            f.write_str("KEYBOARD")?;
1429        }
1430        if v & 4 == 4 {
1431            v &= !4;
1432            if first {
1433                first = false;
1434            } else {
1435                f.write_str(" | ")?;
1436            }
1437            f.write_str("TOUCH")?;
1438        }
1439        if v != 0 {
1440            if first {
1441                first = false;
1442            } else {
1443                f.write_str(" | ")?;
1444            }
1445            write!(f, "0x{v:032x}")?;
1446        }
1447        if first {
1448            f.write_str("0")?;
1449        }
1450        Ok(())
1451    }
1452}
1453
1454/// wl_seat error values
1455///
1456/// These errors can be emitted in response to wl_seat requests.
1457#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
1458pub struct WlSeatError(pub u32);
1459
1460impl WlSeatError {
1461    /// get_pointer, get_keyboard or get_touch called on seat without the matching capability
1462    pub const MISSING_CAPABILITY: Self = Self(0);
1463}
1464
1465impl Debug for WlSeatError {
1466    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1467        let name = match *self {
1468            Self::MISSING_CAPABILITY => "MISSING_CAPABILITY",
1469            _ => return Debug::fmt(&self.0, f),
1470        };
1471        f.write_str(name)
1472    }
1473}