wl_proxy/protocols/wayland/
wl_pointer.rs

1//! pointer input device
2//!
3//! The wl_pointer interface represents one or more input devices,
4//! such as mice, which control the pointer location and pointer_focus
5//! of a seat.
6//!
7//! The wl_pointer interface generates motion, enter and leave
8//! events for the surfaces that the pointer is located over,
9//! and button and axis events for button presses, button releases
10//! and scrolling.
11
12use crate::protocol_helpers::prelude::*;
13use super::super::all_types::*;
14
15/// A wl_pointer object.
16///
17/// See the documentation of [the module][self] for the interface description.
18pub struct WlPointer {
19    core: ObjectCore,
20    handler: HandlerHolder<dyn WlPointerHandler>,
21}
22
23struct DefaultHandler;
24
25impl WlPointerHandler for DefaultHandler { }
26
27impl ConcreteObject for WlPointer {
28    const XML_VERSION: u32 = 10;
29    const INTERFACE: ObjectInterface = ObjectInterface::WlPointer;
30    const INTERFACE_NAME: &str = "wl_pointer";
31}
32
33impl WlPointer {
34    /// Sets a new handler.
35    pub fn set_handler(&self, handler: impl WlPointerHandler) {
36        self.set_boxed_handler(Box::new(handler));
37    }
38
39    /// Sets a new, already boxed handler.
40    pub fn set_boxed_handler(&self, handler: Box<dyn WlPointerHandler>) {
41        if self.core.state.destroyed.get() {
42            return;
43        }
44        self.handler.set(Some(handler));
45    }
46}
47
48impl Debug for WlPointer {
49    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
50        f.debug_struct("WlPointer")
51            .field("server_obj_id", &self.core.server_obj_id.get())
52            .field("client_id", &self.core.client_id.get())
53            .field("client_obj_id", &self.core.client_obj_id.get())
54            .finish()
55    }
56}
57
58impl WlPointer {
59    /// Since when the set_cursor message is available.
60    pub const MSG__SET_CURSOR__SINCE: u32 = 1;
61
62    /// set the pointer surface
63    ///
64    /// Set the pointer surface, i.e., the surface that contains the
65    /// pointer image (cursor). This request gives the surface the role
66    /// of a cursor. If the surface already has another role, it raises
67    /// a protocol error.
68    ///
69    /// The cursor actually changes only if the pointer
70    /// focus for this device is one of the requesting client's surfaces
71    /// or the surface parameter is the current pointer surface. If
72    /// there was a previous surface set with this request it is
73    /// replaced. If surface is NULL, the pointer image is hidden.
74    ///
75    /// The parameters hotspot_x and hotspot_y define the position of
76    /// the pointer surface relative to the pointer location. Its
77    /// top-left corner is always at (x, y) - (hotspot_x, hotspot_y),
78    /// where (x, y) are the coordinates of the pointer location, in
79    /// surface-local coordinates.
80    ///
81    /// On wl_surface.offset requests to the pointer surface, hotspot_x
82    /// and hotspot_y are decremented by the x and y parameters
83    /// passed to the request. The offset must be applied by
84    /// wl_surface.commit as usual.
85    ///
86    /// The hotspot can also be updated by passing the currently set
87    /// pointer surface to this request with new values for hotspot_x
88    /// and hotspot_y.
89    ///
90    /// The input region is ignored for wl_surfaces with the role of
91    /// a cursor. When the use as a cursor ends, the wl_surface is
92    /// unmapped.
93    ///
94    /// The serial parameter must match the latest wl_pointer.enter
95    /// serial number sent to the client. Otherwise the request will be
96    /// ignored.
97    ///
98    /// # Arguments
99    ///
100    /// - `serial`: serial number of the enter event
101    /// - `surface`: pointer surface
102    /// - `hotspot_x`: surface-local x coordinate
103    /// - `hotspot_y`: surface-local y coordinate
104    #[inline]
105    pub fn try_send_set_cursor(
106        &self,
107        serial: u32,
108        surface: Option<&Rc<WlSurface>>,
109        hotspot_x: i32,
110        hotspot_y: i32,
111    ) -> Result<(), ObjectError> {
112        let (
113            arg0,
114            arg1,
115            arg2,
116            arg3,
117        ) = (
118            serial,
119            surface,
120            hotspot_x,
121            hotspot_y,
122        );
123        let arg1 = arg1.map(|a| a.core());
124        let core = self.core();
125        let Some(id) = core.server_obj_id.get() else {
126            return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
127        };
128        let arg1_id = match arg1 {
129            None => 0,
130            Some(arg1) => match arg1.server_obj_id.get() {
131                None => return Err(ObjectError(ObjectErrorKind::ArgNoServerId("surface"))),
132                Some(id) => id,
133            },
134        };
135        #[cfg(feature = "logging")]
136        if self.core.state.log {
137            #[cold]
138            fn log(state: &State, id: u32, arg0: u32, arg1: u32, arg2: i32, arg3: i32) {
139                let (millis, micros) = time_since_epoch();
140                let prefix = &state.log_prefix;
141                let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      <= wl_pointer#{}.set_cursor(serial: {}, surface: wl_surface#{}, hotspot_x: {}, hotspot_y: {})\n", id, arg0, arg1, arg2, arg3);
142                state.log(args);
143            }
144            log(&self.core.state, id, arg0, arg1_id, arg2, arg3);
145        }
146        let Some(endpoint) = &self.core.state.server else {
147            return Ok(());
148        };
149        if !endpoint.flush_queued.replace(true) {
150            self.core.state.add_flushable_endpoint(endpoint, None);
151        }
152        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
153        let outgoing = &mut *outgoing_ref;
154        let mut fmt = outgoing.formatter();
155        fmt.words([
156            id,
157            0,
158            arg0,
159            arg1_id,
160            arg2 as u32,
161            arg3 as u32,
162        ]);
163        Ok(())
164    }
165
166    /// set the pointer surface
167    ///
168    /// Set the pointer surface, i.e., the surface that contains the
169    /// pointer image (cursor). This request gives the surface the role
170    /// of a cursor. If the surface already has another role, it raises
171    /// a protocol error.
172    ///
173    /// The cursor actually changes only if the pointer
174    /// focus for this device is one of the requesting client's surfaces
175    /// or the surface parameter is the current pointer surface. If
176    /// there was a previous surface set with this request it is
177    /// replaced. If surface is NULL, the pointer image is hidden.
178    ///
179    /// The parameters hotspot_x and hotspot_y define the position of
180    /// the pointer surface relative to the pointer location. Its
181    /// top-left corner is always at (x, y) - (hotspot_x, hotspot_y),
182    /// where (x, y) are the coordinates of the pointer location, in
183    /// surface-local coordinates.
184    ///
185    /// On wl_surface.offset requests to the pointer surface, hotspot_x
186    /// and hotspot_y are decremented by the x and y parameters
187    /// passed to the request. The offset must be applied by
188    /// wl_surface.commit as usual.
189    ///
190    /// The hotspot can also be updated by passing the currently set
191    /// pointer surface to this request with new values for hotspot_x
192    /// and hotspot_y.
193    ///
194    /// The input region is ignored for wl_surfaces with the role of
195    /// a cursor. When the use as a cursor ends, the wl_surface is
196    /// unmapped.
197    ///
198    /// The serial parameter must match the latest wl_pointer.enter
199    /// serial number sent to the client. Otherwise the request will be
200    /// ignored.
201    ///
202    /// # Arguments
203    ///
204    /// - `serial`: serial number of the enter event
205    /// - `surface`: pointer surface
206    /// - `hotspot_x`: surface-local x coordinate
207    /// - `hotspot_y`: surface-local y coordinate
208    #[inline]
209    pub fn send_set_cursor(
210        &self,
211        serial: u32,
212        surface: Option<&Rc<WlSurface>>,
213        hotspot_x: i32,
214        hotspot_y: i32,
215    ) {
216        let res = self.try_send_set_cursor(
217            serial,
218            surface,
219            hotspot_x,
220            hotspot_y,
221        );
222        if let Err(e) = res {
223            log_send("wl_pointer.set_cursor", &e);
224        }
225    }
226
227    /// Since when the enter message is available.
228    pub const MSG__ENTER__SINCE: u32 = 1;
229
230    /// enter event
231    ///
232    /// Notification that this seat's pointer is focused on a certain
233    /// surface.
234    ///
235    /// When a seat's focus enters a surface, the pointer image
236    /// is undefined and a client should respond to this event by setting
237    /// an appropriate pointer image with the set_cursor request.
238    ///
239    /// # Arguments
240    ///
241    /// - `serial`: serial number of the enter event
242    /// - `surface`: surface entered by the pointer
243    /// - `surface_x`: surface-local x coordinate
244    /// - `surface_y`: surface-local y coordinate
245    #[inline]
246    pub fn try_send_enter(
247        &self,
248        serial: u32,
249        surface: &Rc<WlSurface>,
250        surface_x: Fixed,
251        surface_y: Fixed,
252    ) -> Result<(), ObjectError> {
253        let (
254            arg0,
255            arg1,
256            arg2,
257            arg3,
258        ) = (
259            serial,
260            surface,
261            surface_x,
262            surface_y,
263        );
264        let arg1 = arg1.core();
265        let core = self.core();
266        let client_ref = core.client.borrow();
267        let Some(client) = &*client_ref else {
268            return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
269        };
270        let id = core.client_obj_id.get().unwrap_or(0);
271        if arg1.client_id.get() != Some(client.endpoint.id) {
272            return Err(ObjectError(ObjectErrorKind::ArgNoClientId("surface", client.endpoint.id)));
273        }
274        let arg1_id = arg1.client_obj_id.get().unwrap_or(0);
275        #[cfg(feature = "logging")]
276        if self.core.state.log {
277            #[cold]
278            fn log(state: &State, client_id: u64, id: u32, arg0: u32, arg1: u32, arg2: Fixed, arg3: Fixed) {
279                let (millis, micros) = time_since_epoch();
280                let prefix = &state.log_prefix;
281                let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_pointer#{}.enter(serial: {}, surface: wl_surface#{}, surface_x: {}, surface_y: {})\n", client_id, id, arg0, arg1, arg2, arg3);
282                state.log(args);
283            }
284            log(&self.core.state, client.endpoint.id, id, arg0, arg1_id, arg2, arg3);
285        }
286        let endpoint = &client.endpoint;
287        if !endpoint.flush_queued.replace(true) {
288            self.core.state.add_flushable_endpoint(endpoint, Some(client));
289        }
290        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
291        let outgoing = &mut *outgoing_ref;
292        let mut fmt = outgoing.formatter();
293        fmt.words([
294            id,
295            0,
296            arg0,
297            arg1_id,
298            arg2.to_wire() as u32,
299            arg3.to_wire() as u32,
300        ]);
301        Ok(())
302    }
303
304    /// enter event
305    ///
306    /// Notification that this seat's pointer is focused on a certain
307    /// surface.
308    ///
309    /// When a seat's focus enters a surface, the pointer image
310    /// is undefined and a client should respond to this event by setting
311    /// an appropriate pointer image with the set_cursor request.
312    ///
313    /// # Arguments
314    ///
315    /// - `serial`: serial number of the enter event
316    /// - `surface`: surface entered by the pointer
317    /// - `surface_x`: surface-local x coordinate
318    /// - `surface_y`: surface-local y coordinate
319    #[inline]
320    pub fn send_enter(
321        &self,
322        serial: u32,
323        surface: &Rc<WlSurface>,
324        surface_x: Fixed,
325        surface_y: Fixed,
326    ) {
327        let res = self.try_send_enter(
328            serial,
329            surface,
330            surface_x,
331            surface_y,
332        );
333        if let Err(e) = res {
334            log_send("wl_pointer.enter", &e);
335        }
336    }
337
338    /// Since when the leave message is available.
339    pub const MSG__LEAVE__SINCE: u32 = 1;
340
341    /// leave event
342    ///
343    /// Notification that this seat's pointer is no longer focused on
344    /// a certain surface.
345    ///
346    /// The leave notification is sent before the enter notification
347    /// for the new focus.
348    ///
349    /// # Arguments
350    ///
351    /// - `serial`: serial number of the leave event
352    /// - `surface`: surface left by the pointer
353    #[inline]
354    pub fn try_send_leave(
355        &self,
356        serial: u32,
357        surface: &Rc<WlSurface>,
358    ) -> Result<(), ObjectError> {
359        let (
360            arg0,
361            arg1,
362        ) = (
363            serial,
364            surface,
365        );
366        let arg1 = arg1.core();
367        let core = self.core();
368        let client_ref = core.client.borrow();
369        let Some(client) = &*client_ref else {
370            return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
371        };
372        let id = core.client_obj_id.get().unwrap_or(0);
373        if arg1.client_id.get() != Some(client.endpoint.id) {
374            return Err(ObjectError(ObjectErrorKind::ArgNoClientId("surface", client.endpoint.id)));
375        }
376        let arg1_id = arg1.client_obj_id.get().unwrap_or(0);
377        #[cfg(feature = "logging")]
378        if self.core.state.log {
379            #[cold]
380            fn log(state: &State, client_id: u64, id: u32, arg0: u32, arg1: u32) {
381                let (millis, micros) = time_since_epoch();
382                let prefix = &state.log_prefix;
383                let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_pointer#{}.leave(serial: {}, surface: wl_surface#{})\n", client_id, id, arg0, arg1);
384                state.log(args);
385            }
386            log(&self.core.state, client.endpoint.id, id, arg0, arg1_id);
387        }
388        let endpoint = &client.endpoint;
389        if !endpoint.flush_queued.replace(true) {
390            self.core.state.add_flushable_endpoint(endpoint, Some(client));
391        }
392        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
393        let outgoing = &mut *outgoing_ref;
394        let mut fmt = outgoing.formatter();
395        fmt.words([
396            id,
397            1,
398            arg0,
399            arg1_id,
400        ]);
401        Ok(())
402    }
403
404    /// leave event
405    ///
406    /// Notification that this seat's pointer is no longer focused on
407    /// a certain surface.
408    ///
409    /// The leave notification is sent before the enter notification
410    /// for the new focus.
411    ///
412    /// # Arguments
413    ///
414    /// - `serial`: serial number of the leave event
415    /// - `surface`: surface left by the pointer
416    #[inline]
417    pub fn send_leave(
418        &self,
419        serial: u32,
420        surface: &Rc<WlSurface>,
421    ) {
422        let res = self.try_send_leave(
423            serial,
424            surface,
425        );
426        if let Err(e) = res {
427            log_send("wl_pointer.leave", &e);
428        }
429    }
430
431    /// Since when the motion message is available.
432    pub const MSG__MOTION__SINCE: u32 = 1;
433
434    /// pointer motion event
435    ///
436    /// Notification of pointer location change. The arguments
437    /// surface_x and surface_y are the location relative to the
438    /// focused surface.
439    ///
440    /// # Arguments
441    ///
442    /// - `time`: timestamp with millisecond granularity
443    /// - `surface_x`: surface-local x coordinate
444    /// - `surface_y`: surface-local y coordinate
445    #[inline]
446    pub fn try_send_motion(
447        &self,
448        time: u32,
449        surface_x: Fixed,
450        surface_y: Fixed,
451    ) -> Result<(), ObjectError> {
452        let (
453            arg0,
454            arg1,
455            arg2,
456        ) = (
457            time,
458            surface_x,
459            surface_y,
460        );
461        let core = self.core();
462        let client_ref = core.client.borrow();
463        let Some(client) = &*client_ref else {
464            return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
465        };
466        let id = core.client_obj_id.get().unwrap_or(0);
467        #[cfg(feature = "logging")]
468        if self.core.state.log {
469            #[cold]
470            fn log(state: &State, client_id: u64, id: u32, arg0: u32, arg1: Fixed, arg2: Fixed) {
471                let (millis, micros) = time_since_epoch();
472                let prefix = &state.log_prefix;
473                let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_pointer#{}.motion(time: {}, surface_x: {}, surface_y: {})\n", client_id, id, arg0, arg1, arg2);
474                state.log(args);
475            }
476            log(&self.core.state, client.endpoint.id, id, arg0, arg1, arg2);
477        }
478        let endpoint = &client.endpoint;
479        if !endpoint.flush_queued.replace(true) {
480            self.core.state.add_flushable_endpoint(endpoint, Some(client));
481        }
482        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
483        let outgoing = &mut *outgoing_ref;
484        let mut fmt = outgoing.formatter();
485        fmt.words([
486            id,
487            2,
488            arg0,
489            arg1.to_wire() as u32,
490            arg2.to_wire() as u32,
491        ]);
492        Ok(())
493    }
494
495    /// pointer motion event
496    ///
497    /// Notification of pointer location change. The arguments
498    /// surface_x and surface_y are the location relative to the
499    /// focused surface.
500    ///
501    /// # Arguments
502    ///
503    /// - `time`: timestamp with millisecond granularity
504    /// - `surface_x`: surface-local x coordinate
505    /// - `surface_y`: surface-local y coordinate
506    #[inline]
507    pub fn send_motion(
508        &self,
509        time: u32,
510        surface_x: Fixed,
511        surface_y: Fixed,
512    ) {
513        let res = self.try_send_motion(
514            time,
515            surface_x,
516            surface_y,
517        );
518        if let Err(e) = res {
519            log_send("wl_pointer.motion", &e);
520        }
521    }
522
523    /// Since when the button message is available.
524    pub const MSG__BUTTON__SINCE: u32 = 1;
525
526    /// pointer button event
527    ///
528    /// Mouse button click and release notifications.
529    ///
530    /// The location of the click is given by the last motion or
531    /// enter event.
532    /// The time argument is a timestamp with millisecond
533    /// granularity, with an undefined base.
534    ///
535    /// The button is a button code as defined in the Linux kernel's
536    /// linux/input-event-codes.h header file, e.g. BTN_LEFT.
537    ///
538    /// Any 16-bit button code value is reserved for future additions to the
539    /// kernel's event code list. All other button codes above 0xFFFF are
540    /// currently undefined but may be used in future versions of this
541    /// protocol.
542    ///
543    /// # Arguments
544    ///
545    /// - `serial`: serial number of the button event
546    /// - `time`: timestamp with millisecond granularity
547    /// - `button`: button that produced the event
548    /// - `state`: physical state of the button
549    #[inline]
550    pub fn try_send_button(
551        &self,
552        serial: u32,
553        time: u32,
554        button: u32,
555        state: WlPointerButtonState,
556    ) -> Result<(), ObjectError> {
557        let (
558            arg0,
559            arg1,
560            arg2,
561            arg3,
562        ) = (
563            serial,
564            time,
565            button,
566            state,
567        );
568        let core = self.core();
569        let client_ref = core.client.borrow();
570        let Some(client) = &*client_ref else {
571            return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
572        };
573        let id = core.client_obj_id.get().unwrap_or(0);
574        #[cfg(feature = "logging")]
575        if self.core.state.log {
576            #[cold]
577            fn log(state: &State, client_id: u64, id: u32, arg0: u32, arg1: u32, arg2: u32, arg3: WlPointerButtonState) {
578                let (millis, micros) = time_since_epoch();
579                let prefix = &state.log_prefix;
580                let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_pointer#{}.button(serial: {}, time: {}, button: {}, state: {:?})\n", client_id, id, arg0, arg1, arg2, arg3);
581                state.log(args);
582            }
583            log(&self.core.state, client.endpoint.id, id, arg0, arg1, arg2, arg3);
584        }
585        let endpoint = &client.endpoint;
586        if !endpoint.flush_queued.replace(true) {
587            self.core.state.add_flushable_endpoint(endpoint, Some(client));
588        }
589        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
590        let outgoing = &mut *outgoing_ref;
591        let mut fmt = outgoing.formatter();
592        fmt.words([
593            id,
594            3,
595            arg0,
596            arg1,
597            arg2,
598            arg3.0,
599        ]);
600        Ok(())
601    }
602
603    /// pointer button event
604    ///
605    /// Mouse button click and release notifications.
606    ///
607    /// The location of the click is given by the last motion or
608    /// enter event.
609    /// The time argument is a timestamp with millisecond
610    /// granularity, with an undefined base.
611    ///
612    /// The button is a button code as defined in the Linux kernel's
613    /// linux/input-event-codes.h header file, e.g. BTN_LEFT.
614    ///
615    /// Any 16-bit button code value is reserved for future additions to the
616    /// kernel's event code list. All other button codes above 0xFFFF are
617    /// currently undefined but may be used in future versions of this
618    /// protocol.
619    ///
620    /// # Arguments
621    ///
622    /// - `serial`: serial number of the button event
623    /// - `time`: timestamp with millisecond granularity
624    /// - `button`: button that produced the event
625    /// - `state`: physical state of the button
626    #[inline]
627    pub fn send_button(
628        &self,
629        serial: u32,
630        time: u32,
631        button: u32,
632        state: WlPointerButtonState,
633    ) {
634        let res = self.try_send_button(
635            serial,
636            time,
637            button,
638            state,
639        );
640        if let Err(e) = res {
641            log_send("wl_pointer.button", &e);
642        }
643    }
644
645    /// Since when the axis message is available.
646    pub const MSG__AXIS__SINCE: u32 = 1;
647
648    /// axis event
649    ///
650    /// Scroll and other axis notifications.
651    ///
652    /// For scroll events (vertical and horizontal scroll axes), the
653    /// value parameter is the length of a vector along the specified
654    /// axis in a coordinate space identical to those of motion events,
655    /// representing a relative movement along the specified axis.
656    ///
657    /// For devices that support movements non-parallel to axes multiple
658    /// axis events will be emitted.
659    ///
660    /// When applicable, for example for touch pads, the server can
661    /// choose to emit scroll events where the motion vector is
662    /// equivalent to a motion event vector.
663    ///
664    /// When applicable, a client can transform its content relative to the
665    /// scroll distance.
666    ///
667    /// # Arguments
668    ///
669    /// - `time`: timestamp with millisecond granularity
670    /// - `axis`: axis type
671    /// - `value`: length of vector in surface-local coordinate space
672    #[inline]
673    pub fn try_send_axis(
674        &self,
675        time: u32,
676        axis: WlPointerAxis,
677        value: Fixed,
678    ) -> Result<(), ObjectError> {
679        let (
680            arg0,
681            arg1,
682            arg2,
683        ) = (
684            time,
685            axis,
686            value,
687        );
688        let core = self.core();
689        let client_ref = core.client.borrow();
690        let Some(client) = &*client_ref else {
691            return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
692        };
693        let id = core.client_obj_id.get().unwrap_or(0);
694        #[cfg(feature = "logging")]
695        if self.core.state.log {
696            #[cold]
697            fn log(state: &State, client_id: u64, id: u32, arg0: u32, arg1: WlPointerAxis, arg2: Fixed) {
698                let (millis, micros) = time_since_epoch();
699                let prefix = &state.log_prefix;
700                let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_pointer#{}.axis(time: {}, axis: {:?}, value: {})\n", client_id, id, arg0, arg1, arg2);
701                state.log(args);
702            }
703            log(&self.core.state, client.endpoint.id, id, arg0, arg1, arg2);
704        }
705        let endpoint = &client.endpoint;
706        if !endpoint.flush_queued.replace(true) {
707            self.core.state.add_flushable_endpoint(endpoint, Some(client));
708        }
709        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
710        let outgoing = &mut *outgoing_ref;
711        let mut fmt = outgoing.formatter();
712        fmt.words([
713            id,
714            4,
715            arg0,
716            arg1.0,
717            arg2.to_wire() as u32,
718        ]);
719        Ok(())
720    }
721
722    /// axis event
723    ///
724    /// Scroll and other axis notifications.
725    ///
726    /// For scroll events (vertical and horizontal scroll axes), the
727    /// value parameter is the length of a vector along the specified
728    /// axis in a coordinate space identical to those of motion events,
729    /// representing a relative movement along the specified axis.
730    ///
731    /// For devices that support movements non-parallel to axes multiple
732    /// axis events will be emitted.
733    ///
734    /// When applicable, for example for touch pads, the server can
735    /// choose to emit scroll events where the motion vector is
736    /// equivalent to a motion event vector.
737    ///
738    /// When applicable, a client can transform its content relative to the
739    /// scroll distance.
740    ///
741    /// # Arguments
742    ///
743    /// - `time`: timestamp with millisecond granularity
744    /// - `axis`: axis type
745    /// - `value`: length of vector in surface-local coordinate space
746    #[inline]
747    pub fn send_axis(
748        &self,
749        time: u32,
750        axis: WlPointerAxis,
751        value: Fixed,
752    ) {
753        let res = self.try_send_axis(
754            time,
755            axis,
756            value,
757        );
758        if let Err(e) = res {
759            log_send("wl_pointer.axis", &e);
760        }
761    }
762
763    /// Since when the release message is available.
764    pub const MSG__RELEASE__SINCE: u32 = 3;
765
766    /// release the pointer object
767    ///
768    /// Using this request a client can tell the server that it is not going to
769    /// use the pointer object anymore.
770    ///
771    /// This request destroys the pointer proxy object, so clients must not call
772    /// wl_pointer_destroy() after using this request.
773    #[inline]
774    pub fn try_send_release(
775        &self,
776    ) -> Result<(), ObjectError> {
777        let core = self.core();
778        let Some(id) = core.server_obj_id.get() else {
779            return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
780        };
781        #[cfg(feature = "logging")]
782        if self.core.state.log {
783            #[cold]
784            fn log(state: &State, id: u32) {
785                let (millis, micros) = time_since_epoch();
786                let prefix = &state.log_prefix;
787                let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      <= wl_pointer#{}.release()\n", id);
788                state.log(args);
789            }
790            log(&self.core.state, id);
791        }
792        let Some(endpoint) = &self.core.state.server else {
793            return Ok(());
794        };
795        if !endpoint.flush_queued.replace(true) {
796            self.core.state.add_flushable_endpoint(endpoint, None);
797        }
798        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
799        let outgoing = &mut *outgoing_ref;
800        let mut fmt = outgoing.formatter();
801        fmt.words([
802            id,
803            1,
804        ]);
805        self.core.handle_server_destroy();
806        Ok(())
807    }
808
809    /// release the pointer object
810    ///
811    /// Using this request a client can tell the server that it is not going to
812    /// use the pointer object anymore.
813    ///
814    /// This request destroys the pointer proxy object, so clients must not call
815    /// wl_pointer_destroy() after using this request.
816    #[inline]
817    pub fn send_release(
818        &self,
819    ) {
820        let res = self.try_send_release(
821        );
822        if let Err(e) = res {
823            log_send("wl_pointer.release", &e);
824        }
825    }
826
827    /// Since when the frame message is available.
828    pub const MSG__FRAME__SINCE: u32 = 5;
829
830    /// end of a pointer event sequence
831    ///
832    /// Indicates the end of a set of events that logically belong together.
833    /// A client is expected to accumulate the data in all events within the
834    /// frame before proceeding.
835    ///
836    /// All wl_pointer events before a wl_pointer.frame event belong
837    /// logically together. For example, in a diagonal scroll motion the
838    /// compositor will send an optional wl_pointer.axis_source event, two
839    /// wl_pointer.axis events (horizontal and vertical) and finally a
840    /// wl_pointer.frame event. The client may use this information to
841    /// calculate a diagonal vector for scrolling.
842    ///
843    /// When multiple wl_pointer.axis events occur within the same frame,
844    /// the motion vector is the combined motion of all events.
845    /// When a wl_pointer.axis and a wl_pointer.axis_stop event occur within
846    /// the same frame, this indicates that axis movement in one axis has
847    /// stopped but continues in the other axis.
848    /// When multiple wl_pointer.axis_stop events occur within the same
849    /// frame, this indicates that these axes stopped in the same instance.
850    ///
851    /// A wl_pointer.frame event is sent for every logical event group,
852    /// even if the group only contains a single wl_pointer event.
853    /// Specifically, a client may get a sequence: motion, frame, button,
854    /// frame, axis, frame, axis_stop, frame.
855    ///
856    /// The wl_pointer.enter and wl_pointer.leave events are logical events
857    /// generated by the compositor and not the hardware. These events are
858    /// also grouped by a wl_pointer.frame. When a pointer moves from one
859    /// surface to another, a compositor should group the
860    /// wl_pointer.leave event within the same wl_pointer.frame.
861    /// However, a client must not rely on wl_pointer.leave and
862    /// wl_pointer.enter being in the same wl_pointer.frame.
863    /// Compositor-specific policies may require the wl_pointer.leave and
864    /// wl_pointer.enter event being split across multiple wl_pointer.frame
865    /// groups.
866    #[inline]
867    pub fn try_send_frame(
868        &self,
869    ) -> Result<(), ObjectError> {
870        let core = self.core();
871        let client_ref = core.client.borrow();
872        let Some(client) = &*client_ref else {
873            return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
874        };
875        let id = core.client_obj_id.get().unwrap_or(0);
876        #[cfg(feature = "logging")]
877        if self.core.state.log {
878            #[cold]
879            fn log(state: &State, client_id: u64, id: u32) {
880                let (millis, micros) = time_since_epoch();
881                let prefix = &state.log_prefix;
882                let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_pointer#{}.frame()\n", client_id, id);
883                state.log(args);
884            }
885            log(&self.core.state, client.endpoint.id, id);
886        }
887        let endpoint = &client.endpoint;
888        if !endpoint.flush_queued.replace(true) {
889            self.core.state.add_flushable_endpoint(endpoint, Some(client));
890        }
891        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
892        let outgoing = &mut *outgoing_ref;
893        let mut fmt = outgoing.formatter();
894        fmt.words([
895            id,
896            5,
897        ]);
898        Ok(())
899    }
900
901    /// end of a pointer event sequence
902    ///
903    /// Indicates the end of a set of events that logically belong together.
904    /// A client is expected to accumulate the data in all events within the
905    /// frame before proceeding.
906    ///
907    /// All wl_pointer events before a wl_pointer.frame event belong
908    /// logically together. For example, in a diagonal scroll motion the
909    /// compositor will send an optional wl_pointer.axis_source event, two
910    /// wl_pointer.axis events (horizontal and vertical) and finally a
911    /// wl_pointer.frame event. The client may use this information to
912    /// calculate a diagonal vector for scrolling.
913    ///
914    /// When multiple wl_pointer.axis events occur within the same frame,
915    /// the motion vector is the combined motion of all events.
916    /// When a wl_pointer.axis and a wl_pointer.axis_stop event occur within
917    /// the same frame, this indicates that axis movement in one axis has
918    /// stopped but continues in the other axis.
919    /// When multiple wl_pointer.axis_stop events occur within the same
920    /// frame, this indicates that these axes stopped in the same instance.
921    ///
922    /// A wl_pointer.frame event is sent for every logical event group,
923    /// even if the group only contains a single wl_pointer event.
924    /// Specifically, a client may get a sequence: motion, frame, button,
925    /// frame, axis, frame, axis_stop, frame.
926    ///
927    /// The wl_pointer.enter and wl_pointer.leave events are logical events
928    /// generated by the compositor and not the hardware. These events are
929    /// also grouped by a wl_pointer.frame. When a pointer moves from one
930    /// surface to another, a compositor should group the
931    /// wl_pointer.leave event within the same wl_pointer.frame.
932    /// However, a client must not rely on wl_pointer.leave and
933    /// wl_pointer.enter being in the same wl_pointer.frame.
934    /// Compositor-specific policies may require the wl_pointer.leave and
935    /// wl_pointer.enter event being split across multiple wl_pointer.frame
936    /// groups.
937    #[inline]
938    pub fn send_frame(
939        &self,
940    ) {
941        let res = self.try_send_frame(
942        );
943        if let Err(e) = res {
944            log_send("wl_pointer.frame", &e);
945        }
946    }
947
948    /// Since when the axis_source message is available.
949    pub const MSG__AXIS_SOURCE__SINCE: u32 = 5;
950
951    /// axis source event
952    ///
953    /// Source information for scroll and other axes.
954    ///
955    /// This event does not occur on its own. It is sent before a
956    /// wl_pointer.frame event and carries the source information for
957    /// all events within that frame.
958    ///
959    /// The source specifies how this event was generated. If the source is
960    /// wl_pointer.axis_source.finger, a wl_pointer.axis_stop event will be
961    /// sent when the user lifts the finger off the device.
962    ///
963    /// If the source is wl_pointer.axis_source.wheel,
964    /// wl_pointer.axis_source.wheel_tilt or
965    /// wl_pointer.axis_source.continuous, a wl_pointer.axis_stop event may
966    /// or may not be sent. Whether a compositor sends an axis_stop event
967    /// for these sources is hardware-specific and implementation-dependent;
968    /// clients must not rely on receiving an axis_stop event for these
969    /// scroll sources and should treat scroll sequences from these scroll
970    /// sources as unterminated by default.
971    ///
972    /// This event is optional. If the source is unknown for a particular
973    /// axis event sequence, no event is sent.
974    /// Only one wl_pointer.axis_source event is permitted per frame.
975    ///
976    /// The order of wl_pointer.axis_discrete and wl_pointer.axis_source is
977    /// not guaranteed.
978    ///
979    /// # Arguments
980    ///
981    /// - `axis_source`: source of the axis event
982    #[inline]
983    pub fn try_send_axis_source(
984        &self,
985        axis_source: WlPointerAxisSource,
986    ) -> Result<(), ObjectError> {
987        let (
988            arg0,
989        ) = (
990            axis_source,
991        );
992        let core = self.core();
993        let client_ref = core.client.borrow();
994        let Some(client) = &*client_ref else {
995            return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
996        };
997        let id = core.client_obj_id.get().unwrap_or(0);
998        #[cfg(feature = "logging")]
999        if self.core.state.log {
1000            #[cold]
1001            fn log(state: &State, client_id: u64, id: u32, arg0: WlPointerAxisSource) {
1002                let (millis, micros) = time_since_epoch();
1003                let prefix = &state.log_prefix;
1004                let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_pointer#{}.axis_source(axis_source: {:?})\n", client_id, id, arg0);
1005                state.log(args);
1006            }
1007            log(&self.core.state, client.endpoint.id, id, arg0);
1008        }
1009        let endpoint = &client.endpoint;
1010        if !endpoint.flush_queued.replace(true) {
1011            self.core.state.add_flushable_endpoint(endpoint, Some(client));
1012        }
1013        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
1014        let outgoing = &mut *outgoing_ref;
1015        let mut fmt = outgoing.formatter();
1016        fmt.words([
1017            id,
1018            6,
1019            arg0.0,
1020        ]);
1021        Ok(())
1022    }
1023
1024    /// axis source event
1025    ///
1026    /// Source information for scroll and other axes.
1027    ///
1028    /// This event does not occur on its own. It is sent before a
1029    /// wl_pointer.frame event and carries the source information for
1030    /// all events within that frame.
1031    ///
1032    /// The source specifies how this event was generated. If the source is
1033    /// wl_pointer.axis_source.finger, a wl_pointer.axis_stop event will be
1034    /// sent when the user lifts the finger off the device.
1035    ///
1036    /// If the source is wl_pointer.axis_source.wheel,
1037    /// wl_pointer.axis_source.wheel_tilt or
1038    /// wl_pointer.axis_source.continuous, a wl_pointer.axis_stop event may
1039    /// or may not be sent. Whether a compositor sends an axis_stop event
1040    /// for these sources is hardware-specific and implementation-dependent;
1041    /// clients must not rely on receiving an axis_stop event for these
1042    /// scroll sources and should treat scroll sequences from these scroll
1043    /// sources as unterminated by default.
1044    ///
1045    /// This event is optional. If the source is unknown for a particular
1046    /// axis event sequence, no event is sent.
1047    /// Only one wl_pointer.axis_source event is permitted per frame.
1048    ///
1049    /// The order of wl_pointer.axis_discrete and wl_pointer.axis_source is
1050    /// not guaranteed.
1051    ///
1052    /// # Arguments
1053    ///
1054    /// - `axis_source`: source of the axis event
1055    #[inline]
1056    pub fn send_axis_source(
1057        &self,
1058        axis_source: WlPointerAxisSource,
1059    ) {
1060        let res = self.try_send_axis_source(
1061            axis_source,
1062        );
1063        if let Err(e) = res {
1064            log_send("wl_pointer.axis_source", &e);
1065        }
1066    }
1067
1068    /// Since when the axis_stop message is available.
1069    pub const MSG__AXIS_STOP__SINCE: u32 = 5;
1070
1071    /// axis stop event
1072    ///
1073    /// Stop notification for scroll and other axes.
1074    ///
1075    /// For some wl_pointer.axis_source types, a wl_pointer.axis_stop event
1076    /// is sent to notify a client that the axis sequence has terminated.
1077    /// This enables the client to implement kinetic scrolling.
1078    /// See the wl_pointer.axis_source documentation for information on when
1079    /// this event may be generated.
1080    ///
1081    /// Any wl_pointer.axis events with the same axis_source after this
1082    /// event should be considered as the start of a new axis motion.
1083    ///
1084    /// The timestamp is to be interpreted identical to the timestamp in the
1085    /// wl_pointer.axis event. The timestamp value may be the same as a
1086    /// preceding wl_pointer.axis event.
1087    ///
1088    /// # Arguments
1089    ///
1090    /// - `time`: timestamp with millisecond granularity
1091    /// - `axis`: the axis stopped with this event
1092    #[inline]
1093    pub fn try_send_axis_stop(
1094        &self,
1095        time: u32,
1096        axis: WlPointerAxis,
1097    ) -> Result<(), ObjectError> {
1098        let (
1099            arg0,
1100            arg1,
1101        ) = (
1102            time,
1103            axis,
1104        );
1105        let core = self.core();
1106        let client_ref = core.client.borrow();
1107        let Some(client) = &*client_ref else {
1108            return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
1109        };
1110        let id = core.client_obj_id.get().unwrap_or(0);
1111        #[cfg(feature = "logging")]
1112        if self.core.state.log {
1113            #[cold]
1114            fn log(state: &State, client_id: u64, id: u32, arg0: u32, arg1: WlPointerAxis) {
1115                let (millis, micros) = time_since_epoch();
1116                let prefix = &state.log_prefix;
1117                let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_pointer#{}.axis_stop(time: {}, axis: {:?})\n", client_id, id, arg0, arg1);
1118                state.log(args);
1119            }
1120            log(&self.core.state, client.endpoint.id, id, arg0, arg1);
1121        }
1122        let endpoint = &client.endpoint;
1123        if !endpoint.flush_queued.replace(true) {
1124            self.core.state.add_flushable_endpoint(endpoint, Some(client));
1125        }
1126        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
1127        let outgoing = &mut *outgoing_ref;
1128        let mut fmt = outgoing.formatter();
1129        fmt.words([
1130            id,
1131            7,
1132            arg0,
1133            arg1.0,
1134        ]);
1135        Ok(())
1136    }
1137
1138    /// axis stop event
1139    ///
1140    /// Stop notification for scroll and other axes.
1141    ///
1142    /// For some wl_pointer.axis_source types, a wl_pointer.axis_stop event
1143    /// is sent to notify a client that the axis sequence has terminated.
1144    /// This enables the client to implement kinetic scrolling.
1145    /// See the wl_pointer.axis_source documentation for information on when
1146    /// this event may be generated.
1147    ///
1148    /// Any wl_pointer.axis events with the same axis_source after this
1149    /// event should be considered as the start of a new axis motion.
1150    ///
1151    /// The timestamp is to be interpreted identical to the timestamp in the
1152    /// wl_pointer.axis event. The timestamp value may be the same as a
1153    /// preceding wl_pointer.axis event.
1154    ///
1155    /// # Arguments
1156    ///
1157    /// - `time`: timestamp with millisecond granularity
1158    /// - `axis`: the axis stopped with this event
1159    #[inline]
1160    pub fn send_axis_stop(
1161        &self,
1162        time: u32,
1163        axis: WlPointerAxis,
1164    ) {
1165        let res = self.try_send_axis_stop(
1166            time,
1167            axis,
1168        );
1169        if let Err(e) = res {
1170            log_send("wl_pointer.axis_stop", &e);
1171        }
1172    }
1173
1174    /// Since when the axis_discrete message is available.
1175    pub const MSG__AXIS_DISCRETE__SINCE: u32 = 5;
1176
1177    /// Since when the axis_discrete message is deprecated.
1178    pub const MSG__AXIS_DISCRETE__DEPRECATED_SINCE: u32 = 8;
1179
1180    /// axis click event
1181    ///
1182    /// Discrete step information for scroll and other axes.
1183    ///
1184    /// This event carries the axis value of the wl_pointer.axis event in
1185    /// discrete steps (e.g. mouse wheel clicks).
1186    ///
1187    /// This event is deprecated with wl_pointer version 8 - this event is not
1188    /// sent to clients supporting version 8 or later.
1189    ///
1190    /// This event does not occur on its own, it is coupled with a
1191    /// wl_pointer.axis event that represents this axis value on a
1192    /// continuous scale. The protocol guarantees that each axis_discrete
1193    /// event is always followed by exactly one axis event with the same
1194    /// axis number within the same wl_pointer.frame. Note that the protocol
1195    /// allows for other events to occur between the axis_discrete and
1196    /// its coupled axis event, including other axis_discrete or axis
1197    /// events. A wl_pointer.frame must not contain more than one axis_discrete
1198    /// event per axis type.
1199    ///
1200    /// This event is optional; continuous scrolling devices
1201    /// like two-finger scrolling on touchpads do not have discrete
1202    /// steps and do not generate this event.
1203    ///
1204    /// The discrete value carries the directional information. e.g. a value
1205    /// of -2 is two steps towards the negative direction of this axis.
1206    ///
1207    /// The axis number is identical to the axis number in the associated
1208    /// axis event.
1209    ///
1210    /// The order of wl_pointer.axis_discrete and wl_pointer.axis_source is
1211    /// not guaranteed.
1212    ///
1213    /// # Arguments
1214    ///
1215    /// - `axis`: axis type
1216    /// - `discrete`: number of steps
1217    #[inline]
1218    pub fn try_send_axis_discrete(
1219        &self,
1220        axis: WlPointerAxis,
1221        discrete: i32,
1222    ) -> Result<(), ObjectError> {
1223        let (
1224            arg0,
1225            arg1,
1226        ) = (
1227            axis,
1228            discrete,
1229        );
1230        let core = self.core();
1231        let client_ref = core.client.borrow();
1232        let Some(client) = &*client_ref else {
1233            return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
1234        };
1235        let id = core.client_obj_id.get().unwrap_or(0);
1236        #[cfg(feature = "logging")]
1237        if self.core.state.log {
1238            #[cold]
1239            fn log(state: &State, client_id: u64, id: u32, arg0: WlPointerAxis, arg1: i32) {
1240                let (millis, micros) = time_since_epoch();
1241                let prefix = &state.log_prefix;
1242                let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_pointer#{}.axis_discrete(axis: {:?}, discrete: {})\n", client_id, id, arg0, arg1);
1243                state.log(args);
1244            }
1245            log(&self.core.state, client.endpoint.id, id, arg0, arg1);
1246        }
1247        let endpoint = &client.endpoint;
1248        if !endpoint.flush_queued.replace(true) {
1249            self.core.state.add_flushable_endpoint(endpoint, Some(client));
1250        }
1251        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
1252        let outgoing = &mut *outgoing_ref;
1253        let mut fmt = outgoing.formatter();
1254        fmt.words([
1255            id,
1256            8,
1257            arg0.0,
1258            arg1 as u32,
1259        ]);
1260        Ok(())
1261    }
1262
1263    /// axis click event
1264    ///
1265    /// Discrete step information for scroll and other axes.
1266    ///
1267    /// This event carries the axis value of the wl_pointer.axis event in
1268    /// discrete steps (e.g. mouse wheel clicks).
1269    ///
1270    /// This event is deprecated with wl_pointer version 8 - this event is not
1271    /// sent to clients supporting version 8 or later.
1272    ///
1273    /// This event does not occur on its own, it is coupled with a
1274    /// wl_pointer.axis event that represents this axis value on a
1275    /// continuous scale. The protocol guarantees that each axis_discrete
1276    /// event is always followed by exactly one axis event with the same
1277    /// axis number within the same wl_pointer.frame. Note that the protocol
1278    /// allows for other events to occur between the axis_discrete and
1279    /// its coupled axis event, including other axis_discrete or axis
1280    /// events. A wl_pointer.frame must not contain more than one axis_discrete
1281    /// event per axis type.
1282    ///
1283    /// This event is optional; continuous scrolling devices
1284    /// like two-finger scrolling on touchpads do not have discrete
1285    /// steps and do not generate this event.
1286    ///
1287    /// The discrete value carries the directional information. e.g. a value
1288    /// of -2 is two steps towards the negative direction of this axis.
1289    ///
1290    /// The axis number is identical to the axis number in the associated
1291    /// axis event.
1292    ///
1293    /// The order of wl_pointer.axis_discrete and wl_pointer.axis_source is
1294    /// not guaranteed.
1295    ///
1296    /// # Arguments
1297    ///
1298    /// - `axis`: axis type
1299    /// - `discrete`: number of steps
1300    #[inline]
1301    pub fn send_axis_discrete(
1302        &self,
1303        axis: WlPointerAxis,
1304        discrete: i32,
1305    ) {
1306        let res = self.try_send_axis_discrete(
1307            axis,
1308            discrete,
1309        );
1310        if let Err(e) = res {
1311            log_send("wl_pointer.axis_discrete", &e);
1312        }
1313    }
1314
1315    /// Since when the axis_value120 message is available.
1316    pub const MSG__AXIS_VALUE120__SINCE: u32 = 8;
1317
1318    /// axis high-resolution scroll event
1319    ///
1320    /// Discrete high-resolution scroll information.
1321    ///
1322    /// This event carries high-resolution wheel scroll information,
1323    /// with each multiple of 120 representing one logical scroll step
1324    /// (a wheel detent). For example, an axis_value120 of 30 is one quarter of
1325    /// a logical scroll step in the positive direction, a value120 of
1326    /// -240 are two logical scroll steps in the negative direction within the
1327    /// same hardware event.
1328    /// Clients that rely on discrete scrolling should accumulate the
1329    /// value120 to multiples of 120 before processing the event.
1330    ///
1331    /// The value120 must not be zero.
1332    ///
1333    /// This event replaces the wl_pointer.axis_discrete event in clients
1334    /// supporting wl_pointer version 8 or later.
1335    ///
1336    /// Where a wl_pointer.axis_source event occurs in the same
1337    /// wl_pointer.frame, the axis source applies to this event.
1338    ///
1339    /// The order of wl_pointer.axis_value120 and wl_pointer.axis_source is
1340    /// not guaranteed.
1341    ///
1342    /// # Arguments
1343    ///
1344    /// - `axis`: axis type
1345    /// - `value120`: scroll distance as fraction of 120
1346    #[inline]
1347    pub fn try_send_axis_value120(
1348        &self,
1349        axis: WlPointerAxis,
1350        value120: i32,
1351    ) -> Result<(), ObjectError> {
1352        let (
1353            arg0,
1354            arg1,
1355        ) = (
1356            axis,
1357            value120,
1358        );
1359        let core = self.core();
1360        let client_ref = core.client.borrow();
1361        let Some(client) = &*client_ref else {
1362            return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
1363        };
1364        let id = core.client_obj_id.get().unwrap_or(0);
1365        #[cfg(feature = "logging")]
1366        if self.core.state.log {
1367            #[cold]
1368            fn log(state: &State, client_id: u64, id: u32, arg0: WlPointerAxis, arg1: i32) {
1369                let (millis, micros) = time_since_epoch();
1370                let prefix = &state.log_prefix;
1371                let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_pointer#{}.axis_value120(axis: {:?}, value120: {})\n", client_id, id, arg0, arg1);
1372                state.log(args);
1373            }
1374            log(&self.core.state, client.endpoint.id, id, arg0, arg1);
1375        }
1376        let endpoint = &client.endpoint;
1377        if !endpoint.flush_queued.replace(true) {
1378            self.core.state.add_flushable_endpoint(endpoint, Some(client));
1379        }
1380        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
1381        let outgoing = &mut *outgoing_ref;
1382        let mut fmt = outgoing.formatter();
1383        fmt.words([
1384            id,
1385            9,
1386            arg0.0,
1387            arg1 as u32,
1388        ]);
1389        Ok(())
1390    }
1391
1392    /// axis high-resolution scroll event
1393    ///
1394    /// Discrete high-resolution scroll information.
1395    ///
1396    /// This event carries high-resolution wheel scroll information,
1397    /// with each multiple of 120 representing one logical scroll step
1398    /// (a wheel detent). For example, an axis_value120 of 30 is one quarter of
1399    /// a logical scroll step in the positive direction, a value120 of
1400    /// -240 are two logical scroll steps in the negative direction within the
1401    /// same hardware event.
1402    /// Clients that rely on discrete scrolling should accumulate the
1403    /// value120 to multiples of 120 before processing the event.
1404    ///
1405    /// The value120 must not be zero.
1406    ///
1407    /// This event replaces the wl_pointer.axis_discrete event in clients
1408    /// supporting wl_pointer version 8 or later.
1409    ///
1410    /// Where a wl_pointer.axis_source event occurs in the same
1411    /// wl_pointer.frame, the axis source applies to this event.
1412    ///
1413    /// The order of wl_pointer.axis_value120 and wl_pointer.axis_source is
1414    /// not guaranteed.
1415    ///
1416    /// # Arguments
1417    ///
1418    /// - `axis`: axis type
1419    /// - `value120`: scroll distance as fraction of 120
1420    #[inline]
1421    pub fn send_axis_value120(
1422        &self,
1423        axis: WlPointerAxis,
1424        value120: i32,
1425    ) {
1426        let res = self.try_send_axis_value120(
1427            axis,
1428            value120,
1429        );
1430        if let Err(e) = res {
1431            log_send("wl_pointer.axis_value120", &e);
1432        }
1433    }
1434
1435    /// Since when the axis_relative_direction message is available.
1436    pub const MSG__AXIS_RELATIVE_DIRECTION__SINCE: u32 = 9;
1437
1438    /// axis relative physical direction event
1439    ///
1440    /// Relative directional information of the entity causing the axis
1441    /// motion.
1442    ///
1443    /// For a wl_pointer.axis event, the wl_pointer.axis_relative_direction
1444    /// event specifies the movement direction of the entity causing the
1445    /// wl_pointer.axis event. For example:
1446    /// - if a user's fingers on a touchpad move down and this
1447    ///   causes a wl_pointer.axis vertical_scroll down event, the physical
1448    ///   direction is 'identical'
1449    /// - if a user's fingers on a touchpad move down and this causes a
1450    ///   wl_pointer.axis vertical_scroll up scroll up event ('natural
1451    ///   scrolling'), the physical direction is 'inverted'.
1452    ///
1453    /// A client may use this information to adjust scroll motion of
1454    /// components. Specifically, enabling natural scrolling causes the
1455    /// content to change direction compared to traditional scrolling.
1456    /// Some widgets like volume control sliders should usually match the
1457    /// physical direction regardless of whether natural scrolling is
1458    /// active. This event enables clients to match the scroll direction of
1459    /// a widget to the physical direction.
1460    ///
1461    /// This event does not occur on its own, it is coupled with a
1462    /// wl_pointer.axis event that represents this axis value.
1463    /// The protocol guarantees that each axis_relative_direction event is
1464    /// always followed by exactly one axis event with the same
1465    /// axis number within the same wl_pointer.frame. Note that the protocol
1466    /// allows for other events to occur between the axis_relative_direction
1467    /// and its coupled axis event.
1468    ///
1469    /// The axis number is identical to the axis number in the associated
1470    /// axis event.
1471    ///
1472    /// The order of wl_pointer.axis_relative_direction,
1473    /// wl_pointer.axis_discrete and wl_pointer.axis_source is not
1474    /// guaranteed.
1475    ///
1476    /// # Arguments
1477    ///
1478    /// - `axis`: axis type
1479    /// - `direction`: physical direction relative to axis motion
1480    #[inline]
1481    pub fn try_send_axis_relative_direction(
1482        &self,
1483        axis: WlPointerAxis,
1484        direction: WlPointerAxisRelativeDirection,
1485    ) -> Result<(), ObjectError> {
1486        let (
1487            arg0,
1488            arg1,
1489        ) = (
1490            axis,
1491            direction,
1492        );
1493        let core = self.core();
1494        let client_ref = core.client.borrow();
1495        let Some(client) = &*client_ref else {
1496            return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
1497        };
1498        let id = core.client_obj_id.get().unwrap_or(0);
1499        #[cfg(feature = "logging")]
1500        if self.core.state.log {
1501            #[cold]
1502            fn log(state: &State, client_id: u64, id: u32, arg0: WlPointerAxis, arg1: WlPointerAxisRelativeDirection) {
1503                let (millis, micros) = time_since_epoch();
1504                let prefix = &state.log_prefix;
1505                let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_pointer#{}.axis_relative_direction(axis: {:?}, direction: {:?})\n", client_id, id, arg0, arg1);
1506                state.log(args);
1507            }
1508            log(&self.core.state, client.endpoint.id, id, arg0, arg1);
1509        }
1510        let endpoint = &client.endpoint;
1511        if !endpoint.flush_queued.replace(true) {
1512            self.core.state.add_flushable_endpoint(endpoint, Some(client));
1513        }
1514        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
1515        let outgoing = &mut *outgoing_ref;
1516        let mut fmt = outgoing.formatter();
1517        fmt.words([
1518            id,
1519            10,
1520            arg0.0,
1521            arg1.0,
1522        ]);
1523        Ok(())
1524    }
1525
1526    /// axis relative physical direction event
1527    ///
1528    /// Relative directional information of the entity causing the axis
1529    /// motion.
1530    ///
1531    /// For a wl_pointer.axis event, the wl_pointer.axis_relative_direction
1532    /// event specifies the movement direction of the entity causing the
1533    /// wl_pointer.axis event. For example:
1534    /// - if a user's fingers on a touchpad move down and this
1535    ///   causes a wl_pointer.axis vertical_scroll down event, the physical
1536    ///   direction is 'identical'
1537    /// - if a user's fingers on a touchpad move down and this causes a
1538    ///   wl_pointer.axis vertical_scroll up scroll up event ('natural
1539    ///   scrolling'), the physical direction is 'inverted'.
1540    ///
1541    /// A client may use this information to adjust scroll motion of
1542    /// components. Specifically, enabling natural scrolling causes the
1543    /// content to change direction compared to traditional scrolling.
1544    /// Some widgets like volume control sliders should usually match the
1545    /// physical direction regardless of whether natural scrolling is
1546    /// active. This event enables clients to match the scroll direction of
1547    /// a widget to the physical direction.
1548    ///
1549    /// This event does not occur on its own, it is coupled with a
1550    /// wl_pointer.axis event that represents this axis value.
1551    /// The protocol guarantees that each axis_relative_direction event is
1552    /// always followed by exactly one axis event with the same
1553    /// axis number within the same wl_pointer.frame. Note that the protocol
1554    /// allows for other events to occur between the axis_relative_direction
1555    /// and its coupled axis event.
1556    ///
1557    /// The axis number is identical to the axis number in the associated
1558    /// axis event.
1559    ///
1560    /// The order of wl_pointer.axis_relative_direction,
1561    /// wl_pointer.axis_discrete and wl_pointer.axis_source is not
1562    /// guaranteed.
1563    ///
1564    /// # Arguments
1565    ///
1566    /// - `axis`: axis type
1567    /// - `direction`: physical direction relative to axis motion
1568    #[inline]
1569    pub fn send_axis_relative_direction(
1570        &self,
1571        axis: WlPointerAxis,
1572        direction: WlPointerAxisRelativeDirection,
1573    ) {
1574        let res = self.try_send_axis_relative_direction(
1575            axis,
1576            direction,
1577        );
1578        if let Err(e) = res {
1579            log_send("wl_pointer.axis_relative_direction", &e);
1580        }
1581    }
1582}
1583
1584/// A message handler for [`WlPointer`] proxies.
1585pub trait WlPointerHandler: Any {
1586    /// Event handler for wl_display.delete_id messages deleting the ID of this object.
1587    ///
1588    /// The default handler forwards the event to the client, if any.
1589    #[inline]
1590    fn delete_id(&mut self, slf: &Rc<WlPointer>) {
1591        slf.core.delete_id();
1592    }
1593
1594    /// set the pointer surface
1595    ///
1596    /// Set the pointer surface, i.e., the surface that contains the
1597    /// pointer image (cursor). This request gives the surface the role
1598    /// of a cursor. If the surface already has another role, it raises
1599    /// a protocol error.
1600    ///
1601    /// The cursor actually changes only if the pointer
1602    /// focus for this device is one of the requesting client's surfaces
1603    /// or the surface parameter is the current pointer surface. If
1604    /// there was a previous surface set with this request it is
1605    /// replaced. If surface is NULL, the pointer image is hidden.
1606    ///
1607    /// The parameters hotspot_x and hotspot_y define the position of
1608    /// the pointer surface relative to the pointer location. Its
1609    /// top-left corner is always at (x, y) - (hotspot_x, hotspot_y),
1610    /// where (x, y) are the coordinates of the pointer location, in
1611    /// surface-local coordinates.
1612    ///
1613    /// On wl_surface.offset requests to the pointer surface, hotspot_x
1614    /// and hotspot_y are decremented by the x and y parameters
1615    /// passed to the request. The offset must be applied by
1616    /// wl_surface.commit as usual.
1617    ///
1618    /// The hotspot can also be updated by passing the currently set
1619    /// pointer surface to this request with new values for hotspot_x
1620    /// and hotspot_y.
1621    ///
1622    /// The input region is ignored for wl_surfaces with the role of
1623    /// a cursor. When the use as a cursor ends, the wl_surface is
1624    /// unmapped.
1625    ///
1626    /// The serial parameter must match the latest wl_pointer.enter
1627    /// serial number sent to the client. Otherwise the request will be
1628    /// ignored.
1629    ///
1630    /// # Arguments
1631    ///
1632    /// - `serial`: serial number of the enter event
1633    /// - `surface`: pointer surface
1634    /// - `hotspot_x`: surface-local x coordinate
1635    /// - `hotspot_y`: surface-local y coordinate
1636    ///
1637    /// All borrowed proxies passed to this function are guaranteed to be
1638    /// immutable and non-null.
1639    #[inline]
1640    fn handle_set_cursor(
1641        &mut self,
1642        slf: &Rc<WlPointer>,
1643        serial: u32,
1644        surface: Option<&Rc<WlSurface>>,
1645        hotspot_x: i32,
1646        hotspot_y: i32,
1647    ) {
1648        if !slf.core.forward_to_server.get() {
1649            return;
1650        }
1651        let res = slf.try_send_set_cursor(
1652            serial,
1653            surface,
1654            hotspot_x,
1655            hotspot_y,
1656        );
1657        if let Err(e) = res {
1658            log_forward("wl_pointer.set_cursor", &e);
1659        }
1660    }
1661
1662    /// enter event
1663    ///
1664    /// Notification that this seat's pointer is focused on a certain
1665    /// surface.
1666    ///
1667    /// When a seat's focus enters a surface, the pointer image
1668    /// is undefined and a client should respond to this event by setting
1669    /// an appropriate pointer image with the set_cursor request.
1670    ///
1671    /// # Arguments
1672    ///
1673    /// - `serial`: serial number of the enter event
1674    /// - `surface`: surface entered by the pointer
1675    /// - `surface_x`: surface-local x coordinate
1676    /// - `surface_y`: surface-local y coordinate
1677    ///
1678    /// All borrowed proxies passed to this function are guaranteed to be
1679    /// immutable and non-null.
1680    #[inline]
1681    fn handle_enter(
1682        &mut self,
1683        slf: &Rc<WlPointer>,
1684        serial: u32,
1685        surface: &Rc<WlSurface>,
1686        surface_x: Fixed,
1687        surface_y: Fixed,
1688    ) {
1689        if !slf.core.forward_to_client.get() {
1690            return;
1691        }
1692        if let Some(client_id) = slf.core.client_id.get() {
1693            if let Some(client_id_2) = surface.core().client_id.get() {
1694                if client_id != client_id_2 {
1695                    return;
1696                }
1697            }
1698        }
1699        let res = slf.try_send_enter(
1700            serial,
1701            surface,
1702            surface_x,
1703            surface_y,
1704        );
1705        if let Err(e) = res {
1706            log_forward("wl_pointer.enter", &e);
1707        }
1708    }
1709
1710    /// leave event
1711    ///
1712    /// Notification that this seat's pointer is no longer focused on
1713    /// a certain surface.
1714    ///
1715    /// The leave notification is sent before the enter notification
1716    /// for the new focus.
1717    ///
1718    /// # Arguments
1719    ///
1720    /// - `serial`: serial number of the leave event
1721    /// - `surface`: surface left by the pointer
1722    ///
1723    /// All borrowed proxies passed to this function are guaranteed to be
1724    /// immutable and non-null.
1725    #[inline]
1726    fn handle_leave(
1727        &mut self,
1728        slf: &Rc<WlPointer>,
1729        serial: u32,
1730        surface: &Rc<WlSurface>,
1731    ) {
1732        if !slf.core.forward_to_client.get() {
1733            return;
1734        }
1735        if let Some(client_id) = slf.core.client_id.get() {
1736            if let Some(client_id_2) = surface.core().client_id.get() {
1737                if client_id != client_id_2 {
1738                    return;
1739                }
1740            }
1741        }
1742        let res = slf.try_send_leave(
1743            serial,
1744            surface,
1745        );
1746        if let Err(e) = res {
1747            log_forward("wl_pointer.leave", &e);
1748        }
1749    }
1750
1751    /// pointer motion event
1752    ///
1753    /// Notification of pointer location change. The arguments
1754    /// surface_x and surface_y are the location relative to the
1755    /// focused surface.
1756    ///
1757    /// # Arguments
1758    ///
1759    /// - `time`: timestamp with millisecond granularity
1760    /// - `surface_x`: surface-local x coordinate
1761    /// - `surface_y`: surface-local y coordinate
1762    #[inline]
1763    fn handle_motion(
1764        &mut self,
1765        slf: &Rc<WlPointer>,
1766        time: u32,
1767        surface_x: Fixed,
1768        surface_y: Fixed,
1769    ) {
1770        if !slf.core.forward_to_client.get() {
1771            return;
1772        }
1773        let res = slf.try_send_motion(
1774            time,
1775            surface_x,
1776            surface_y,
1777        );
1778        if let Err(e) = res {
1779            log_forward("wl_pointer.motion", &e);
1780        }
1781    }
1782
1783    /// pointer button event
1784    ///
1785    /// Mouse button click and release notifications.
1786    ///
1787    /// The location of the click is given by the last motion or
1788    /// enter event.
1789    /// The time argument is a timestamp with millisecond
1790    /// granularity, with an undefined base.
1791    ///
1792    /// The button is a button code as defined in the Linux kernel's
1793    /// linux/input-event-codes.h header file, e.g. BTN_LEFT.
1794    ///
1795    /// Any 16-bit button code value is reserved for future additions to the
1796    /// kernel's event code list. All other button codes above 0xFFFF are
1797    /// currently undefined but may be used in future versions of this
1798    /// protocol.
1799    ///
1800    /// # Arguments
1801    ///
1802    /// - `serial`: serial number of the button event
1803    /// - `time`: timestamp with millisecond granularity
1804    /// - `button`: button that produced the event
1805    /// - `state`: physical state of the button
1806    #[inline]
1807    fn handle_button(
1808        &mut self,
1809        slf: &Rc<WlPointer>,
1810        serial: u32,
1811        time: u32,
1812        button: u32,
1813        state: WlPointerButtonState,
1814    ) {
1815        if !slf.core.forward_to_client.get() {
1816            return;
1817        }
1818        let res = slf.try_send_button(
1819            serial,
1820            time,
1821            button,
1822            state,
1823        );
1824        if let Err(e) = res {
1825            log_forward("wl_pointer.button", &e);
1826        }
1827    }
1828
1829    /// axis event
1830    ///
1831    /// Scroll and other axis notifications.
1832    ///
1833    /// For scroll events (vertical and horizontal scroll axes), the
1834    /// value parameter is the length of a vector along the specified
1835    /// axis in a coordinate space identical to those of motion events,
1836    /// representing a relative movement along the specified axis.
1837    ///
1838    /// For devices that support movements non-parallel to axes multiple
1839    /// axis events will be emitted.
1840    ///
1841    /// When applicable, for example for touch pads, the server can
1842    /// choose to emit scroll events where the motion vector is
1843    /// equivalent to a motion event vector.
1844    ///
1845    /// When applicable, a client can transform its content relative to the
1846    /// scroll distance.
1847    ///
1848    /// # Arguments
1849    ///
1850    /// - `time`: timestamp with millisecond granularity
1851    /// - `axis`: axis type
1852    /// - `value`: length of vector in surface-local coordinate space
1853    #[inline]
1854    fn handle_axis(
1855        &mut self,
1856        slf: &Rc<WlPointer>,
1857        time: u32,
1858        axis: WlPointerAxis,
1859        value: Fixed,
1860    ) {
1861        if !slf.core.forward_to_client.get() {
1862            return;
1863        }
1864        let res = slf.try_send_axis(
1865            time,
1866            axis,
1867            value,
1868        );
1869        if let Err(e) = res {
1870            log_forward("wl_pointer.axis", &e);
1871        }
1872    }
1873
1874    /// release the pointer object
1875    ///
1876    /// Using this request a client can tell the server that it is not going to
1877    /// use the pointer object anymore.
1878    ///
1879    /// This request destroys the pointer proxy object, so clients must not call
1880    /// wl_pointer_destroy() after using this request.
1881    #[inline]
1882    fn handle_release(
1883        &mut self,
1884        slf: &Rc<WlPointer>,
1885    ) {
1886        if !slf.core.forward_to_server.get() {
1887            return;
1888        }
1889        let res = slf.try_send_release(
1890        );
1891        if let Err(e) = res {
1892            log_forward("wl_pointer.release", &e);
1893        }
1894    }
1895
1896    /// end of a pointer event sequence
1897    ///
1898    /// Indicates the end of a set of events that logically belong together.
1899    /// A client is expected to accumulate the data in all events within the
1900    /// frame before proceeding.
1901    ///
1902    /// All wl_pointer events before a wl_pointer.frame event belong
1903    /// logically together. For example, in a diagonal scroll motion the
1904    /// compositor will send an optional wl_pointer.axis_source event, two
1905    /// wl_pointer.axis events (horizontal and vertical) and finally a
1906    /// wl_pointer.frame event. The client may use this information to
1907    /// calculate a diagonal vector for scrolling.
1908    ///
1909    /// When multiple wl_pointer.axis events occur within the same frame,
1910    /// the motion vector is the combined motion of all events.
1911    /// When a wl_pointer.axis and a wl_pointer.axis_stop event occur within
1912    /// the same frame, this indicates that axis movement in one axis has
1913    /// stopped but continues in the other axis.
1914    /// When multiple wl_pointer.axis_stop events occur within the same
1915    /// frame, this indicates that these axes stopped in the same instance.
1916    ///
1917    /// A wl_pointer.frame event is sent for every logical event group,
1918    /// even if the group only contains a single wl_pointer event.
1919    /// Specifically, a client may get a sequence: motion, frame, button,
1920    /// frame, axis, frame, axis_stop, frame.
1921    ///
1922    /// The wl_pointer.enter and wl_pointer.leave events are logical events
1923    /// generated by the compositor and not the hardware. These events are
1924    /// also grouped by a wl_pointer.frame. When a pointer moves from one
1925    /// surface to another, a compositor should group the
1926    /// wl_pointer.leave event within the same wl_pointer.frame.
1927    /// However, a client must not rely on wl_pointer.leave and
1928    /// wl_pointer.enter being in the same wl_pointer.frame.
1929    /// Compositor-specific policies may require the wl_pointer.leave and
1930    /// wl_pointer.enter event being split across multiple wl_pointer.frame
1931    /// groups.
1932    #[inline]
1933    fn handle_frame(
1934        &mut self,
1935        slf: &Rc<WlPointer>,
1936    ) {
1937        if !slf.core.forward_to_client.get() {
1938            return;
1939        }
1940        let res = slf.try_send_frame(
1941        );
1942        if let Err(e) = res {
1943            log_forward("wl_pointer.frame", &e);
1944        }
1945    }
1946
1947    /// axis source event
1948    ///
1949    /// Source information for scroll and other axes.
1950    ///
1951    /// This event does not occur on its own. It is sent before a
1952    /// wl_pointer.frame event and carries the source information for
1953    /// all events within that frame.
1954    ///
1955    /// The source specifies how this event was generated. If the source is
1956    /// wl_pointer.axis_source.finger, a wl_pointer.axis_stop event will be
1957    /// sent when the user lifts the finger off the device.
1958    ///
1959    /// If the source is wl_pointer.axis_source.wheel,
1960    /// wl_pointer.axis_source.wheel_tilt or
1961    /// wl_pointer.axis_source.continuous, a wl_pointer.axis_stop event may
1962    /// or may not be sent. Whether a compositor sends an axis_stop event
1963    /// for these sources is hardware-specific and implementation-dependent;
1964    /// clients must not rely on receiving an axis_stop event for these
1965    /// scroll sources and should treat scroll sequences from these scroll
1966    /// sources as unterminated by default.
1967    ///
1968    /// This event is optional. If the source is unknown for a particular
1969    /// axis event sequence, no event is sent.
1970    /// Only one wl_pointer.axis_source event is permitted per frame.
1971    ///
1972    /// The order of wl_pointer.axis_discrete and wl_pointer.axis_source is
1973    /// not guaranteed.
1974    ///
1975    /// # Arguments
1976    ///
1977    /// - `axis_source`: source of the axis event
1978    #[inline]
1979    fn handle_axis_source(
1980        &mut self,
1981        slf: &Rc<WlPointer>,
1982        axis_source: WlPointerAxisSource,
1983    ) {
1984        if !slf.core.forward_to_client.get() {
1985            return;
1986        }
1987        let res = slf.try_send_axis_source(
1988            axis_source,
1989        );
1990        if let Err(e) = res {
1991            log_forward("wl_pointer.axis_source", &e);
1992        }
1993    }
1994
1995    /// axis stop event
1996    ///
1997    /// Stop notification for scroll and other axes.
1998    ///
1999    /// For some wl_pointer.axis_source types, a wl_pointer.axis_stop event
2000    /// is sent to notify a client that the axis sequence has terminated.
2001    /// This enables the client to implement kinetic scrolling.
2002    /// See the wl_pointer.axis_source documentation for information on when
2003    /// this event may be generated.
2004    ///
2005    /// Any wl_pointer.axis events with the same axis_source after this
2006    /// event should be considered as the start of a new axis motion.
2007    ///
2008    /// The timestamp is to be interpreted identical to the timestamp in the
2009    /// wl_pointer.axis event. The timestamp value may be the same as a
2010    /// preceding wl_pointer.axis event.
2011    ///
2012    /// # Arguments
2013    ///
2014    /// - `time`: timestamp with millisecond granularity
2015    /// - `axis`: the axis stopped with this event
2016    #[inline]
2017    fn handle_axis_stop(
2018        &mut self,
2019        slf: &Rc<WlPointer>,
2020        time: u32,
2021        axis: WlPointerAxis,
2022    ) {
2023        if !slf.core.forward_to_client.get() {
2024            return;
2025        }
2026        let res = slf.try_send_axis_stop(
2027            time,
2028            axis,
2029        );
2030        if let Err(e) = res {
2031            log_forward("wl_pointer.axis_stop", &e);
2032        }
2033    }
2034
2035    /// axis click event
2036    ///
2037    /// Discrete step information for scroll and other axes.
2038    ///
2039    /// This event carries the axis value of the wl_pointer.axis event in
2040    /// discrete steps (e.g. mouse wheel clicks).
2041    ///
2042    /// This event is deprecated with wl_pointer version 8 - this event is not
2043    /// sent to clients supporting version 8 or later.
2044    ///
2045    /// This event does not occur on its own, it is coupled with a
2046    /// wl_pointer.axis event that represents this axis value on a
2047    /// continuous scale. The protocol guarantees that each axis_discrete
2048    /// event is always followed by exactly one axis event with the same
2049    /// axis number within the same wl_pointer.frame. Note that the protocol
2050    /// allows for other events to occur between the axis_discrete and
2051    /// its coupled axis event, including other axis_discrete or axis
2052    /// events. A wl_pointer.frame must not contain more than one axis_discrete
2053    /// event per axis type.
2054    ///
2055    /// This event is optional; continuous scrolling devices
2056    /// like two-finger scrolling on touchpads do not have discrete
2057    /// steps and do not generate this event.
2058    ///
2059    /// The discrete value carries the directional information. e.g. a value
2060    /// of -2 is two steps towards the negative direction of this axis.
2061    ///
2062    /// The axis number is identical to the axis number in the associated
2063    /// axis event.
2064    ///
2065    /// The order of wl_pointer.axis_discrete and wl_pointer.axis_source is
2066    /// not guaranteed.
2067    ///
2068    /// # Arguments
2069    ///
2070    /// - `axis`: axis type
2071    /// - `discrete`: number of steps
2072    #[inline]
2073    fn handle_axis_discrete(
2074        &mut self,
2075        slf: &Rc<WlPointer>,
2076        axis: WlPointerAxis,
2077        discrete: i32,
2078    ) {
2079        if !slf.core.forward_to_client.get() {
2080            return;
2081        }
2082        let res = slf.try_send_axis_discrete(
2083            axis,
2084            discrete,
2085        );
2086        if let Err(e) = res {
2087            log_forward("wl_pointer.axis_discrete", &e);
2088        }
2089    }
2090
2091    /// axis high-resolution scroll event
2092    ///
2093    /// Discrete high-resolution scroll information.
2094    ///
2095    /// This event carries high-resolution wheel scroll information,
2096    /// with each multiple of 120 representing one logical scroll step
2097    /// (a wheel detent). For example, an axis_value120 of 30 is one quarter of
2098    /// a logical scroll step in the positive direction, a value120 of
2099    /// -240 are two logical scroll steps in the negative direction within the
2100    /// same hardware event.
2101    /// Clients that rely on discrete scrolling should accumulate the
2102    /// value120 to multiples of 120 before processing the event.
2103    ///
2104    /// The value120 must not be zero.
2105    ///
2106    /// This event replaces the wl_pointer.axis_discrete event in clients
2107    /// supporting wl_pointer version 8 or later.
2108    ///
2109    /// Where a wl_pointer.axis_source event occurs in the same
2110    /// wl_pointer.frame, the axis source applies to this event.
2111    ///
2112    /// The order of wl_pointer.axis_value120 and wl_pointer.axis_source is
2113    /// not guaranteed.
2114    ///
2115    /// # Arguments
2116    ///
2117    /// - `axis`: axis type
2118    /// - `value120`: scroll distance as fraction of 120
2119    #[inline]
2120    fn handle_axis_value120(
2121        &mut self,
2122        slf: &Rc<WlPointer>,
2123        axis: WlPointerAxis,
2124        value120: i32,
2125    ) {
2126        if !slf.core.forward_to_client.get() {
2127            return;
2128        }
2129        let res = slf.try_send_axis_value120(
2130            axis,
2131            value120,
2132        );
2133        if let Err(e) = res {
2134            log_forward("wl_pointer.axis_value120", &e);
2135        }
2136    }
2137
2138    /// axis relative physical direction event
2139    ///
2140    /// Relative directional information of the entity causing the axis
2141    /// motion.
2142    ///
2143    /// For a wl_pointer.axis event, the wl_pointer.axis_relative_direction
2144    /// event specifies the movement direction of the entity causing the
2145    /// wl_pointer.axis event. For example:
2146    /// - if a user's fingers on a touchpad move down and this
2147    ///   causes a wl_pointer.axis vertical_scroll down event, the physical
2148    ///   direction is 'identical'
2149    /// - if a user's fingers on a touchpad move down and this causes a
2150    ///   wl_pointer.axis vertical_scroll up scroll up event ('natural
2151    ///   scrolling'), the physical direction is 'inverted'.
2152    ///
2153    /// A client may use this information to adjust scroll motion of
2154    /// components. Specifically, enabling natural scrolling causes the
2155    /// content to change direction compared to traditional scrolling.
2156    /// Some widgets like volume control sliders should usually match the
2157    /// physical direction regardless of whether natural scrolling is
2158    /// active. This event enables clients to match the scroll direction of
2159    /// a widget to the physical direction.
2160    ///
2161    /// This event does not occur on its own, it is coupled with a
2162    /// wl_pointer.axis event that represents this axis value.
2163    /// The protocol guarantees that each axis_relative_direction event is
2164    /// always followed by exactly one axis event with the same
2165    /// axis number within the same wl_pointer.frame. Note that the protocol
2166    /// allows for other events to occur between the axis_relative_direction
2167    /// and its coupled axis event.
2168    ///
2169    /// The axis number is identical to the axis number in the associated
2170    /// axis event.
2171    ///
2172    /// The order of wl_pointer.axis_relative_direction,
2173    /// wl_pointer.axis_discrete and wl_pointer.axis_source is not
2174    /// guaranteed.
2175    ///
2176    /// # Arguments
2177    ///
2178    /// - `axis`: axis type
2179    /// - `direction`: physical direction relative to axis motion
2180    #[inline]
2181    fn handle_axis_relative_direction(
2182        &mut self,
2183        slf: &Rc<WlPointer>,
2184        axis: WlPointerAxis,
2185        direction: WlPointerAxisRelativeDirection,
2186    ) {
2187        if !slf.core.forward_to_client.get() {
2188            return;
2189        }
2190        let res = slf.try_send_axis_relative_direction(
2191            axis,
2192            direction,
2193        );
2194        if let Err(e) = res {
2195            log_forward("wl_pointer.axis_relative_direction", &e);
2196        }
2197    }
2198}
2199
2200impl ObjectPrivate for WlPointer {
2201    fn new(state: &Rc<State>, version: u32) -> Rc<Self> {
2202        Rc::<Self>::new_cyclic(|slf| Self {
2203            core: ObjectCore::new(state, slf.clone(), ObjectInterface::WlPointer, version),
2204            handler: Default::default(),
2205        })
2206    }
2207
2208    fn delete_id(self: Rc<Self>) -> Result<(), (ObjectError, Rc<dyn Object>)> {
2209        let Some(mut handler) = self.handler.try_borrow_mut() else {
2210            return Err((ObjectError(ObjectErrorKind::HandlerBorrowed), self));
2211        };
2212        if let Some(handler) = &mut *handler {
2213            handler.delete_id(&self);
2214        } else {
2215            self.core.delete_id();
2216        }
2217        Ok(())
2218    }
2219
2220    fn handle_request(self: Rc<Self>, client: &Rc<Client>, msg: &[u32], fds: &mut VecDeque<Rc<OwnedFd>>) -> Result<(), ObjectError> {
2221        let Some(mut handler) = self.handler.try_borrow_mut() else {
2222            return Err(ObjectError(ObjectErrorKind::HandlerBorrowed));
2223        };
2224        let handler = &mut *handler;
2225        match msg[1] & 0xffff {
2226            0 => {
2227                let [
2228                    arg0,
2229                    arg1,
2230                    arg2,
2231                    arg3,
2232                ] = msg[2..] else {
2233                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 24)));
2234                };
2235                let arg2 = arg2 as i32;
2236                let arg3 = arg3 as i32;
2237                #[cfg(feature = "logging")]
2238                if self.core.state.log {
2239                    #[cold]
2240                    fn log(state: &State, client_id: u64, id: u32, arg0: u32, arg1: u32, arg2: i32, arg3: i32) {
2241                        let (millis, micros) = time_since_epoch();
2242                        let prefix = &state.log_prefix;
2243                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_pointer#{}.set_cursor(serial: {}, surface: wl_surface#{}, hotspot_x: {}, hotspot_y: {})\n", client_id, id, arg0, arg1, arg2, arg3);
2244                        state.log(args);
2245                    }
2246                    log(&self.core.state, client.endpoint.id, msg[0], arg0, arg1, arg2, arg3);
2247                }
2248                let arg1 = if arg1 == 0 {
2249                    None
2250                } else {
2251                    let arg1_id = arg1;
2252                    let Some(arg1) = client.endpoint.lookup(arg1_id) else {
2253                        return Err(ObjectError(ObjectErrorKind::NoClientObject(client.endpoint.id, arg1_id)));
2254                    };
2255                    let Ok(arg1) = (arg1 as Rc<dyn Any>).downcast::<WlSurface>() else {
2256                        let o = client.endpoint.lookup(arg1_id).unwrap();
2257                        return Err(ObjectError(ObjectErrorKind::WrongObjectType("surface", o.core().interface, ObjectInterface::WlSurface)));
2258                    };
2259                    Some(arg1)
2260                };
2261                let arg1 = arg1.as_ref();
2262                if let Some(handler) = handler {
2263                    (**handler).handle_set_cursor(&self, arg0, arg1, arg2, arg3);
2264                } else {
2265                    DefaultHandler.handle_set_cursor(&self, arg0, arg1, arg2, arg3);
2266                }
2267            }
2268            1 => {
2269                if msg.len() != 2 {
2270                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 8)));
2271                }
2272                #[cfg(feature = "logging")]
2273                if self.core.state.log {
2274                    #[cold]
2275                    fn log(state: &State, client_id: u64, id: u32) {
2276                        let (millis, micros) = time_since_epoch();
2277                        let prefix = &state.log_prefix;
2278                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_pointer#{}.release()\n", client_id, id);
2279                        state.log(args);
2280                    }
2281                    log(&self.core.state, client.endpoint.id, msg[0]);
2282                }
2283                self.core.handle_client_destroy();
2284                if let Some(handler) = handler {
2285                    (**handler).handle_release(&self);
2286                } else {
2287                    DefaultHandler.handle_release(&self);
2288                }
2289            }
2290            n => {
2291                let _ = client;
2292                let _ = msg;
2293                let _ = fds;
2294                let _ = handler;
2295                return Err(ObjectError(ObjectErrorKind::UnknownMessageId(n)));
2296            }
2297        }
2298        Ok(())
2299    }
2300
2301    fn handle_event(self: Rc<Self>, server: &Endpoint, msg: &[u32], fds: &mut VecDeque<Rc<OwnedFd>>) -> Result<(), ObjectError> {
2302        let Some(mut handler) = self.handler.try_borrow_mut() else {
2303            return Err(ObjectError(ObjectErrorKind::HandlerBorrowed));
2304        };
2305        let handler = &mut *handler;
2306        match msg[1] & 0xffff {
2307            0 => {
2308                let [
2309                    arg0,
2310                    arg1,
2311                    arg2,
2312                    arg3,
2313                ] = msg[2..] else {
2314                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 24)));
2315                };
2316                let arg2 = Fixed::from_wire(arg2 as i32);
2317                let arg3 = Fixed::from_wire(arg3 as i32);
2318                #[cfg(feature = "logging")]
2319                if self.core.state.log {
2320                    #[cold]
2321                    fn log(state: &State, id: u32, arg0: u32, arg1: u32, arg2: Fixed, arg3: Fixed) {
2322                        let (millis, micros) = time_since_epoch();
2323                        let prefix = &state.log_prefix;
2324                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      -> wl_pointer#{}.enter(serial: {}, surface: wl_surface#{}, surface_x: {}, surface_y: {})\n", id, arg0, arg1, arg2, arg3);
2325                        state.log(args);
2326                    }
2327                    log(&self.core.state, msg[0], arg0, arg1, arg2, arg3);
2328                }
2329                let arg1_id = arg1;
2330                let Some(arg1) = server.lookup(arg1_id) else {
2331                    return Err(ObjectError(ObjectErrorKind::NoServerObject(arg1_id)));
2332                };
2333                let Ok(arg1) = (arg1 as Rc<dyn Any>).downcast::<WlSurface>() else {
2334                    let o = server.lookup(arg1_id).unwrap();
2335                    return Err(ObjectError(ObjectErrorKind::WrongObjectType("surface", o.core().interface, ObjectInterface::WlSurface)));
2336                };
2337                let arg1 = &arg1;
2338                if let Some(handler) = handler {
2339                    (**handler).handle_enter(&self, arg0, arg1, arg2, arg3);
2340                } else {
2341                    DefaultHandler.handle_enter(&self, arg0, arg1, arg2, arg3);
2342                }
2343            }
2344            1 => {
2345                let [
2346                    arg0,
2347                    arg1,
2348                ] = msg[2..] else {
2349                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 16)));
2350                };
2351                #[cfg(feature = "logging")]
2352                if self.core.state.log {
2353                    #[cold]
2354                    fn log(state: &State, id: u32, arg0: u32, arg1: u32) {
2355                        let (millis, micros) = time_since_epoch();
2356                        let prefix = &state.log_prefix;
2357                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      -> wl_pointer#{}.leave(serial: {}, surface: wl_surface#{})\n", id, arg0, arg1);
2358                        state.log(args);
2359                    }
2360                    log(&self.core.state, msg[0], arg0, arg1);
2361                }
2362                let arg1_id = arg1;
2363                let Some(arg1) = server.lookup(arg1_id) else {
2364                    return Err(ObjectError(ObjectErrorKind::NoServerObject(arg1_id)));
2365                };
2366                let Ok(arg1) = (arg1 as Rc<dyn Any>).downcast::<WlSurface>() else {
2367                    let o = server.lookup(arg1_id).unwrap();
2368                    return Err(ObjectError(ObjectErrorKind::WrongObjectType("surface", o.core().interface, ObjectInterface::WlSurface)));
2369                };
2370                let arg1 = &arg1;
2371                if let Some(handler) = handler {
2372                    (**handler).handle_leave(&self, arg0, arg1);
2373                } else {
2374                    DefaultHandler.handle_leave(&self, arg0, arg1);
2375                }
2376            }
2377            2 => {
2378                let [
2379                    arg0,
2380                    arg1,
2381                    arg2,
2382                ] = msg[2..] else {
2383                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 20)));
2384                };
2385                let arg1 = Fixed::from_wire(arg1 as i32);
2386                let arg2 = Fixed::from_wire(arg2 as i32);
2387                #[cfg(feature = "logging")]
2388                if self.core.state.log {
2389                    #[cold]
2390                    fn log(state: &State, id: u32, arg0: u32, arg1: Fixed, arg2: Fixed) {
2391                        let (millis, micros) = time_since_epoch();
2392                        let prefix = &state.log_prefix;
2393                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      -> wl_pointer#{}.motion(time: {}, surface_x: {}, surface_y: {})\n", id, arg0, arg1, arg2);
2394                        state.log(args);
2395                    }
2396                    log(&self.core.state, msg[0], arg0, arg1, arg2);
2397                }
2398                if let Some(handler) = handler {
2399                    (**handler).handle_motion(&self, arg0, arg1, arg2);
2400                } else {
2401                    DefaultHandler.handle_motion(&self, arg0, arg1, arg2);
2402                }
2403            }
2404            3 => {
2405                let [
2406                    arg0,
2407                    arg1,
2408                    arg2,
2409                    arg3,
2410                ] = msg[2..] else {
2411                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 24)));
2412                };
2413                let arg3 = WlPointerButtonState(arg3);
2414                #[cfg(feature = "logging")]
2415                if self.core.state.log {
2416                    #[cold]
2417                    fn log(state: &State, id: u32, arg0: u32, arg1: u32, arg2: u32, arg3: WlPointerButtonState) {
2418                        let (millis, micros) = time_since_epoch();
2419                        let prefix = &state.log_prefix;
2420                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      -> wl_pointer#{}.button(serial: {}, time: {}, button: {}, state: {:?})\n", id, arg0, arg1, arg2, arg3);
2421                        state.log(args);
2422                    }
2423                    log(&self.core.state, msg[0], arg0, arg1, arg2, arg3);
2424                }
2425                if let Some(handler) = handler {
2426                    (**handler).handle_button(&self, arg0, arg1, arg2, arg3);
2427                } else {
2428                    DefaultHandler.handle_button(&self, arg0, arg1, arg2, arg3);
2429                }
2430            }
2431            4 => {
2432                let [
2433                    arg0,
2434                    arg1,
2435                    arg2,
2436                ] = msg[2..] else {
2437                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 20)));
2438                };
2439                let arg1 = WlPointerAxis(arg1);
2440                let arg2 = Fixed::from_wire(arg2 as i32);
2441                #[cfg(feature = "logging")]
2442                if self.core.state.log {
2443                    #[cold]
2444                    fn log(state: &State, id: u32, arg0: u32, arg1: WlPointerAxis, arg2: Fixed) {
2445                        let (millis, micros) = time_since_epoch();
2446                        let prefix = &state.log_prefix;
2447                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      -> wl_pointer#{}.axis(time: {}, axis: {:?}, value: {})\n", id, arg0, arg1, arg2);
2448                        state.log(args);
2449                    }
2450                    log(&self.core.state, msg[0], arg0, arg1, arg2);
2451                }
2452                if let Some(handler) = handler {
2453                    (**handler).handle_axis(&self, arg0, arg1, arg2);
2454                } else {
2455                    DefaultHandler.handle_axis(&self, arg0, arg1, arg2);
2456                }
2457            }
2458            5 => {
2459                if msg.len() != 2 {
2460                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 8)));
2461                }
2462                #[cfg(feature = "logging")]
2463                if self.core.state.log {
2464                    #[cold]
2465                    fn log(state: &State, id: u32) {
2466                        let (millis, micros) = time_since_epoch();
2467                        let prefix = &state.log_prefix;
2468                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      -> wl_pointer#{}.frame()\n", id);
2469                        state.log(args);
2470                    }
2471                    log(&self.core.state, msg[0]);
2472                }
2473                if let Some(handler) = handler {
2474                    (**handler).handle_frame(&self);
2475                } else {
2476                    DefaultHandler.handle_frame(&self);
2477                }
2478            }
2479            6 => {
2480                let [
2481                    arg0,
2482                ] = msg[2..] else {
2483                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 12)));
2484                };
2485                let arg0 = WlPointerAxisSource(arg0);
2486                #[cfg(feature = "logging")]
2487                if self.core.state.log {
2488                    #[cold]
2489                    fn log(state: &State, id: u32, arg0: WlPointerAxisSource) {
2490                        let (millis, micros) = time_since_epoch();
2491                        let prefix = &state.log_prefix;
2492                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      -> wl_pointer#{}.axis_source(axis_source: {:?})\n", id, arg0);
2493                        state.log(args);
2494                    }
2495                    log(&self.core.state, msg[0], arg0);
2496                }
2497                if let Some(handler) = handler {
2498                    (**handler).handle_axis_source(&self, arg0);
2499                } else {
2500                    DefaultHandler.handle_axis_source(&self, arg0);
2501                }
2502            }
2503            7 => {
2504                let [
2505                    arg0,
2506                    arg1,
2507                ] = msg[2..] else {
2508                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 16)));
2509                };
2510                let arg1 = WlPointerAxis(arg1);
2511                #[cfg(feature = "logging")]
2512                if self.core.state.log {
2513                    #[cold]
2514                    fn log(state: &State, id: u32, arg0: u32, arg1: WlPointerAxis) {
2515                        let (millis, micros) = time_since_epoch();
2516                        let prefix = &state.log_prefix;
2517                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      -> wl_pointer#{}.axis_stop(time: {}, axis: {:?})\n", id, arg0, arg1);
2518                        state.log(args);
2519                    }
2520                    log(&self.core.state, msg[0], arg0, arg1);
2521                }
2522                if let Some(handler) = handler {
2523                    (**handler).handle_axis_stop(&self, arg0, arg1);
2524                } else {
2525                    DefaultHandler.handle_axis_stop(&self, arg0, arg1);
2526                }
2527            }
2528            8 => {
2529                let [
2530                    arg0,
2531                    arg1,
2532                ] = msg[2..] else {
2533                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 16)));
2534                };
2535                let arg0 = WlPointerAxis(arg0);
2536                let arg1 = arg1 as i32;
2537                #[cfg(feature = "logging")]
2538                if self.core.state.log {
2539                    #[cold]
2540                    fn log(state: &State, id: u32, arg0: WlPointerAxis, arg1: i32) {
2541                        let (millis, micros) = time_since_epoch();
2542                        let prefix = &state.log_prefix;
2543                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      -> wl_pointer#{}.axis_discrete(axis: {:?}, discrete: {})\n", id, arg0, arg1);
2544                        state.log(args);
2545                    }
2546                    log(&self.core.state, msg[0], arg0, arg1);
2547                }
2548                if let Some(handler) = handler {
2549                    (**handler).handle_axis_discrete(&self, arg0, arg1);
2550                } else {
2551                    DefaultHandler.handle_axis_discrete(&self, arg0, arg1);
2552                }
2553            }
2554            9 => {
2555                let [
2556                    arg0,
2557                    arg1,
2558                ] = msg[2..] else {
2559                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 16)));
2560                };
2561                let arg0 = WlPointerAxis(arg0);
2562                let arg1 = arg1 as i32;
2563                #[cfg(feature = "logging")]
2564                if self.core.state.log {
2565                    #[cold]
2566                    fn log(state: &State, id: u32, arg0: WlPointerAxis, arg1: i32) {
2567                        let (millis, micros) = time_since_epoch();
2568                        let prefix = &state.log_prefix;
2569                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      -> wl_pointer#{}.axis_value120(axis: {:?}, value120: {})\n", id, arg0, arg1);
2570                        state.log(args);
2571                    }
2572                    log(&self.core.state, msg[0], arg0, arg1);
2573                }
2574                if let Some(handler) = handler {
2575                    (**handler).handle_axis_value120(&self, arg0, arg1);
2576                } else {
2577                    DefaultHandler.handle_axis_value120(&self, arg0, arg1);
2578                }
2579            }
2580            10 => {
2581                let [
2582                    arg0,
2583                    arg1,
2584                ] = msg[2..] else {
2585                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 16)));
2586                };
2587                let arg0 = WlPointerAxis(arg0);
2588                let arg1 = WlPointerAxisRelativeDirection(arg1);
2589                #[cfg(feature = "logging")]
2590                if self.core.state.log {
2591                    #[cold]
2592                    fn log(state: &State, id: u32, arg0: WlPointerAxis, arg1: WlPointerAxisRelativeDirection) {
2593                        let (millis, micros) = time_since_epoch();
2594                        let prefix = &state.log_prefix;
2595                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      -> wl_pointer#{}.axis_relative_direction(axis: {:?}, direction: {:?})\n", id, arg0, arg1);
2596                        state.log(args);
2597                    }
2598                    log(&self.core.state, msg[0], arg0, arg1);
2599                }
2600                if let Some(handler) = handler {
2601                    (**handler).handle_axis_relative_direction(&self, arg0, arg1);
2602                } else {
2603                    DefaultHandler.handle_axis_relative_direction(&self, arg0, arg1);
2604                }
2605            }
2606            n => {
2607                let _ = server;
2608                let _ = msg;
2609                let _ = fds;
2610                let _ = handler;
2611                return Err(ObjectError(ObjectErrorKind::UnknownMessageId(n)));
2612            }
2613        }
2614        Ok(())
2615    }
2616
2617    fn get_request_name(&self, id: u32) -> Option<&'static str> {
2618        let name = match id {
2619            0 => "set_cursor",
2620            1 => "release",
2621            _ => return None,
2622        };
2623        Some(name)
2624    }
2625
2626    fn get_event_name(&self, id: u32) -> Option<&'static str> {
2627        let name = match id {
2628            0 => "enter",
2629            1 => "leave",
2630            2 => "motion",
2631            3 => "button",
2632            4 => "axis",
2633            5 => "frame",
2634            6 => "axis_source",
2635            7 => "axis_stop",
2636            8 => "axis_discrete",
2637            9 => "axis_value120",
2638            10 => "axis_relative_direction",
2639            _ => return None,
2640        };
2641        Some(name)
2642    }
2643}
2644
2645impl Object for WlPointer {
2646    fn core(&self) -> &ObjectCore {
2647        &self.core
2648    }
2649
2650    fn unset_handler(&self) {
2651        self.handler.set(None);
2652    }
2653
2654    fn get_handler_any_ref(&self) -> Result<HandlerRef<'_, dyn Any>, HandlerAccessError> {
2655        let borrowed = self.handler.try_borrow().ok_or(HandlerAccessError::AlreadyBorrowed)?;
2656        if borrowed.is_none() {
2657            return Err(HandlerAccessError::NoHandler);
2658        }
2659        Ok(HandlerRef::map(borrowed, |handler| &**handler.as_ref().unwrap() as &dyn Any))
2660    }
2661
2662    fn get_handler_any_mut(&self) -> Result<HandlerMut<'_, dyn Any>, HandlerAccessError> {
2663        let borrowed = self.handler.try_borrow_mut().ok_or(HandlerAccessError::AlreadyBorrowed)?;
2664        if borrowed.is_none() {
2665            return Err(HandlerAccessError::NoHandler);
2666        }
2667        Ok(HandlerMut::map(borrowed, |handler| &mut **handler.as_mut().unwrap() as &mut dyn Any))
2668    }
2669}
2670
2671impl WlPointer {
2672    /// Since when the error.role enum variant is available.
2673    pub const ENM__ERROR_ROLE__SINCE: u32 = 1;
2674
2675    /// Since when the button_state.released enum variant is available.
2676    pub const ENM__BUTTON_STATE_RELEASED__SINCE: u32 = 1;
2677    /// Since when the button_state.pressed enum variant is available.
2678    pub const ENM__BUTTON_STATE_PRESSED__SINCE: u32 = 1;
2679
2680    /// Since when the axis.vertical_scroll enum variant is available.
2681    pub const ENM__AXIS_VERTICAL_SCROLL__SINCE: u32 = 1;
2682    /// Since when the axis.horizontal_scroll enum variant is available.
2683    pub const ENM__AXIS_HORIZONTAL_SCROLL__SINCE: u32 = 1;
2684
2685    /// Since when the axis_source.wheel enum variant is available.
2686    pub const ENM__AXIS_SOURCE_WHEEL__SINCE: u32 = 1;
2687    /// Since when the axis_source.finger enum variant is available.
2688    pub const ENM__AXIS_SOURCE_FINGER__SINCE: u32 = 1;
2689    /// Since when the axis_source.continuous enum variant is available.
2690    pub const ENM__AXIS_SOURCE_CONTINUOUS__SINCE: u32 = 1;
2691    /// Since when the axis_source.wheel_tilt enum variant is available.
2692    pub const ENM__AXIS_SOURCE_WHEEL_TILT__SINCE: u32 = 6;
2693
2694    /// Since when the axis_relative_direction.identical enum variant is available.
2695    pub const ENM__AXIS_RELATIVE_DIRECTION_IDENTICAL__SINCE: u32 = 1;
2696    /// Since when the axis_relative_direction.inverted enum variant is available.
2697    pub const ENM__AXIS_RELATIVE_DIRECTION_INVERTED__SINCE: u32 = 1;
2698}
2699
2700#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
2701pub struct WlPointerError(pub u32);
2702
2703impl WlPointerError {
2704    /// given wl_surface has another role
2705    pub const ROLE: Self = Self(0);
2706}
2707
2708impl Debug for WlPointerError {
2709    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
2710        let name = match *self {
2711            Self::ROLE => "ROLE",
2712            _ => return Debug::fmt(&self.0, f),
2713        };
2714        f.write_str(name)
2715    }
2716}
2717
2718/// physical button state
2719///
2720/// Describes the physical state of a button that produced the button
2721/// event.
2722#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
2723pub struct WlPointerButtonState(pub u32);
2724
2725impl WlPointerButtonState {
2726    /// the button is not pressed
2727    pub const RELEASED: Self = Self(0);
2728
2729    /// the button is pressed
2730    pub const PRESSED: Self = Self(1);
2731}
2732
2733impl Debug for WlPointerButtonState {
2734    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
2735        let name = match *self {
2736            Self::RELEASED => "RELEASED",
2737            Self::PRESSED => "PRESSED",
2738            _ => return Debug::fmt(&self.0, f),
2739        };
2740        f.write_str(name)
2741    }
2742}
2743
2744/// axis types
2745///
2746/// Describes the axis types of scroll events.
2747#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
2748pub struct WlPointerAxis(pub u32);
2749
2750impl WlPointerAxis {
2751    /// vertical axis
2752    pub const VERTICAL_SCROLL: Self = Self(0);
2753
2754    /// horizontal axis
2755    pub const HORIZONTAL_SCROLL: Self = Self(1);
2756}
2757
2758impl Debug for WlPointerAxis {
2759    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
2760        let name = match *self {
2761            Self::VERTICAL_SCROLL => "VERTICAL_SCROLL",
2762            Self::HORIZONTAL_SCROLL => "HORIZONTAL_SCROLL",
2763            _ => return Debug::fmt(&self.0, f),
2764        };
2765        f.write_str(name)
2766    }
2767}
2768
2769/// axis source types
2770///
2771/// Describes the source types for axis events. This indicates to the
2772/// client how an axis event was physically generated; a client may
2773/// adjust the user interface accordingly. For example, scroll events
2774/// from a "finger" source may be in a smooth coordinate space with
2775/// kinetic scrolling whereas a "wheel" source may be in discrete steps
2776/// of a number of lines.
2777///
2778/// The "continuous" axis source is a device generating events in a
2779/// continuous coordinate space, but using something other than a
2780/// finger. One example for this source is button-based scrolling where
2781/// the vertical motion of a device is converted to scroll events while
2782/// a button is held down.
2783///
2784/// The "wheel tilt" axis source indicates that the actual device is a
2785/// wheel but the scroll event is not caused by a rotation but a
2786/// (usually sideways) tilt of the wheel.
2787#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
2788pub struct WlPointerAxisSource(pub u32);
2789
2790impl WlPointerAxisSource {
2791    /// a physical wheel rotation
2792    pub const WHEEL: Self = Self(0);
2793
2794    /// finger on a touch surface
2795    pub const FINGER: Self = Self(1);
2796
2797    /// continuous coordinate space
2798    pub const CONTINUOUS: Self = Self(2);
2799
2800    /// a physical wheel tilt
2801    pub const WHEEL_TILT: Self = Self(3);
2802}
2803
2804impl Debug for WlPointerAxisSource {
2805    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
2806        let name = match *self {
2807            Self::WHEEL => "WHEEL",
2808            Self::FINGER => "FINGER",
2809            Self::CONTINUOUS => "CONTINUOUS",
2810            Self::WHEEL_TILT => "WHEEL_TILT",
2811            _ => return Debug::fmt(&self.0, f),
2812        };
2813        f.write_str(name)
2814    }
2815}
2816
2817/// axis relative direction
2818///
2819/// This specifies the direction of the physical motion that caused a
2820/// wl_pointer.axis event, relative to the wl_pointer.axis direction.
2821#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
2822pub struct WlPointerAxisRelativeDirection(pub u32);
2823
2824impl WlPointerAxisRelativeDirection {
2825    /// physical motion matches axis direction
2826    pub const IDENTICAL: Self = Self(0);
2827
2828    /// physical motion is the inverse of the axis direction
2829    pub const INVERTED: Self = Self(1);
2830}
2831
2832impl Debug for WlPointerAxisRelativeDirection {
2833    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
2834        let name = match *self {
2835            Self::IDENTICAL => "IDENTICAL",
2836            Self::INVERTED => "INVERTED",
2837            _ => return Debug::fmt(&self.0, f),
2838        };
2839        f.write_str(name)
2840    }
2841}