wl_proxy/protocols/wayland/
wl_touch.rs

1//! touchscreen input device
2//!
3//! The wl_touch interface represents a touchscreen
4//! associated with a seat.
5//!
6//! Touch interactions can consist of one or more contacts.
7//! For each contact, a series of events is generated, starting
8//! with a down event, followed by zero or more motion events,
9//! and ending with an up event. Events relating to the same
10//! contact point can be identified by the ID of the sequence.
11
12use crate::protocol_helpers::prelude::*;
13use super::super::all_types::*;
14
15/// A wl_touch object.
16///
17/// See the documentation of [the module][self] for the interface description.
18pub struct WlTouch {
19    core: ObjectCore,
20    handler: HandlerHolder<dyn WlTouchHandler>,
21}
22
23struct DefaultHandler;
24
25impl WlTouchHandler for DefaultHandler { }
26
27impl ConcreteObject for WlTouch {
28    const XML_VERSION: u32 = 10;
29    const INTERFACE: ObjectInterface = ObjectInterface::WlTouch;
30    const INTERFACE_NAME: &str = "wl_touch";
31}
32
33impl WlTouch {
34    /// Sets a new handler.
35    pub fn set_handler(&self, handler: impl WlTouchHandler) {
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 WlTouchHandler>) {
41        if self.core.state.destroyed.get() {
42            return;
43        }
44        self.handler.set(Some(handler));
45    }
46}
47
48impl Debug for WlTouch {
49    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
50        f.debug_struct("WlTouch")
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 WlTouch {
59    /// Since when the down message is available.
60    pub const MSG__DOWN__SINCE: u32 = 1;
61
62    /// touch down event and beginning of a touch sequence
63    ///
64    /// A new touch point has appeared on the surface. This touch point is
65    /// assigned a unique ID. Future events from this touch point reference
66    /// this ID. The ID ceases to be valid after a touch up event and may be
67    /// reused in the future.
68    ///
69    /// # Arguments
70    ///
71    /// - `serial`: serial number of the touch down event
72    /// - `time`: timestamp with millisecond granularity
73    /// - `surface`: surface touched
74    /// - `id`: the unique ID of this touch point
75    /// - `x`: surface-local x coordinate
76    /// - `y`: surface-local y coordinate
77    #[inline]
78    pub fn try_send_down(
79        &self,
80        serial: u32,
81        time: u32,
82        surface: &Rc<WlSurface>,
83        id: i32,
84        x: Fixed,
85        y: Fixed,
86    ) -> Result<(), ObjectError> {
87        let (
88            arg0,
89            arg1,
90            arg2,
91            arg3,
92            arg4,
93            arg5,
94        ) = (
95            serial,
96            time,
97            surface,
98            id,
99            x,
100            y,
101        );
102        let arg2 = arg2.core();
103        let core = self.core();
104        let client_ref = core.client.borrow();
105        let Some(client) = &*client_ref else {
106            return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
107        };
108        let id = core.client_obj_id.get().unwrap_or(0);
109        if arg2.client_id.get() != Some(client.endpoint.id) {
110            return Err(ObjectError(ObjectErrorKind::ArgNoClientId("surface", client.endpoint.id)));
111        }
112        let arg2_id = arg2.client_obj_id.get().unwrap_or(0);
113        #[cfg(feature = "logging")]
114        if self.core.state.log {
115            #[cold]
116            fn log(state: &State, client_id: u64, id: u32, arg0: u32, arg1: u32, arg2: u32, arg3: i32, arg4: Fixed, arg5: Fixed) {
117                let (millis, micros) = time_since_epoch();
118                let prefix = &state.log_prefix;
119                let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_touch#{}.down(serial: {}, time: {}, surface: wl_surface#{}, id: {}, x: {}, y: {})\n", client_id, id, arg0, arg1, arg2, arg3, arg4, arg5);
120                state.log(args);
121            }
122            log(&self.core.state, client.endpoint.id, id, arg0, arg1, arg2_id, arg3, arg4, arg5);
123        }
124        let endpoint = &client.endpoint;
125        if !endpoint.flush_queued.replace(true) {
126            self.core.state.add_flushable_endpoint(endpoint, Some(client));
127        }
128        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
129        let outgoing = &mut *outgoing_ref;
130        let mut fmt = outgoing.formatter();
131        fmt.words([
132            id,
133            0,
134            arg0,
135            arg1,
136            arg2_id,
137            arg3 as u32,
138            arg4.to_wire() as u32,
139            arg5.to_wire() as u32,
140        ]);
141        Ok(())
142    }
143
144    /// touch down event and beginning of a touch sequence
145    ///
146    /// A new touch point has appeared on the surface. This touch point is
147    /// assigned a unique ID. Future events from this touch point reference
148    /// this ID. The ID ceases to be valid after a touch up event and may be
149    /// reused in the future.
150    ///
151    /// # Arguments
152    ///
153    /// - `serial`: serial number of the touch down event
154    /// - `time`: timestamp with millisecond granularity
155    /// - `surface`: surface touched
156    /// - `id`: the unique ID of this touch point
157    /// - `x`: surface-local x coordinate
158    /// - `y`: surface-local y coordinate
159    #[inline]
160    pub fn send_down(
161        &self,
162        serial: u32,
163        time: u32,
164        surface: &Rc<WlSurface>,
165        id: i32,
166        x: Fixed,
167        y: Fixed,
168    ) {
169        let res = self.try_send_down(
170            serial,
171            time,
172            surface,
173            id,
174            x,
175            y,
176        );
177        if let Err(e) = res {
178            log_send("wl_touch.down", &e);
179        }
180    }
181
182    /// Since when the up message is available.
183    pub const MSG__UP__SINCE: u32 = 1;
184
185    /// end of a touch event sequence
186    ///
187    /// The touch point has disappeared. No further events will be sent for
188    /// this touch point and the touch point's ID is released and may be
189    /// reused in a future touch down event.
190    ///
191    /// # Arguments
192    ///
193    /// - `serial`: serial number of the touch up event
194    /// - `time`: timestamp with millisecond granularity
195    /// - `id`: the unique ID of this touch point
196    #[inline]
197    pub fn try_send_up(
198        &self,
199        serial: u32,
200        time: u32,
201        id: i32,
202    ) -> Result<(), ObjectError> {
203        let (
204            arg0,
205            arg1,
206            arg2,
207        ) = (
208            serial,
209            time,
210            id,
211        );
212        let core = self.core();
213        let client_ref = core.client.borrow();
214        let Some(client) = &*client_ref else {
215            return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
216        };
217        let id = core.client_obj_id.get().unwrap_or(0);
218        #[cfg(feature = "logging")]
219        if self.core.state.log {
220            #[cold]
221            fn log(state: &State, client_id: u64, id: u32, arg0: u32, arg1: u32, arg2: i32) {
222                let (millis, micros) = time_since_epoch();
223                let prefix = &state.log_prefix;
224                let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_touch#{}.up(serial: {}, time: {}, id: {})\n", client_id, id, arg0, arg1, arg2);
225                state.log(args);
226            }
227            log(&self.core.state, client.endpoint.id, id, arg0, arg1, arg2);
228        }
229        let endpoint = &client.endpoint;
230        if !endpoint.flush_queued.replace(true) {
231            self.core.state.add_flushable_endpoint(endpoint, Some(client));
232        }
233        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
234        let outgoing = &mut *outgoing_ref;
235        let mut fmt = outgoing.formatter();
236        fmt.words([
237            id,
238            1,
239            arg0,
240            arg1,
241            arg2 as u32,
242        ]);
243        Ok(())
244    }
245
246    /// end of a touch event sequence
247    ///
248    /// The touch point has disappeared. No further events will be sent for
249    /// this touch point and the touch point's ID is released and may be
250    /// reused in a future touch down event.
251    ///
252    /// # Arguments
253    ///
254    /// - `serial`: serial number of the touch up event
255    /// - `time`: timestamp with millisecond granularity
256    /// - `id`: the unique ID of this touch point
257    #[inline]
258    pub fn send_up(
259        &self,
260        serial: u32,
261        time: u32,
262        id: i32,
263    ) {
264        let res = self.try_send_up(
265            serial,
266            time,
267            id,
268        );
269        if let Err(e) = res {
270            log_send("wl_touch.up", &e);
271        }
272    }
273
274    /// Since when the motion message is available.
275    pub const MSG__MOTION__SINCE: u32 = 1;
276
277    /// update of touch point coordinates
278    ///
279    /// A touch point has changed coordinates.
280    ///
281    /// # Arguments
282    ///
283    /// - `time`: timestamp with millisecond granularity
284    /// - `id`: the unique ID of this touch point
285    /// - `x`: surface-local x coordinate
286    /// - `y`: surface-local y coordinate
287    #[inline]
288    pub fn try_send_motion(
289        &self,
290        time: u32,
291        id: i32,
292        x: Fixed,
293        y: Fixed,
294    ) -> Result<(), ObjectError> {
295        let (
296            arg0,
297            arg1,
298            arg2,
299            arg3,
300        ) = (
301            time,
302            id,
303            x,
304            y,
305        );
306        let core = self.core();
307        let client_ref = core.client.borrow();
308        let Some(client) = &*client_ref else {
309            return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
310        };
311        let id = core.client_obj_id.get().unwrap_or(0);
312        #[cfg(feature = "logging")]
313        if self.core.state.log {
314            #[cold]
315            fn log(state: &State, client_id: u64, id: u32, arg0: u32, arg1: i32, arg2: Fixed, arg3: Fixed) {
316                let (millis, micros) = time_since_epoch();
317                let prefix = &state.log_prefix;
318                let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_touch#{}.motion(time: {}, id: {}, x: {}, y: {})\n", client_id, id, arg0, arg1, arg2, arg3);
319                state.log(args);
320            }
321            log(&self.core.state, client.endpoint.id, id, arg0, arg1, arg2, arg3);
322        }
323        let endpoint = &client.endpoint;
324        if !endpoint.flush_queued.replace(true) {
325            self.core.state.add_flushable_endpoint(endpoint, Some(client));
326        }
327        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
328        let outgoing = &mut *outgoing_ref;
329        let mut fmt = outgoing.formatter();
330        fmt.words([
331            id,
332            2,
333            arg0,
334            arg1 as u32,
335            arg2.to_wire() as u32,
336            arg3.to_wire() as u32,
337        ]);
338        Ok(())
339    }
340
341    /// update of touch point coordinates
342    ///
343    /// A touch point has changed coordinates.
344    ///
345    /// # Arguments
346    ///
347    /// - `time`: timestamp with millisecond granularity
348    /// - `id`: the unique ID of this touch point
349    /// - `x`: surface-local x coordinate
350    /// - `y`: surface-local y coordinate
351    #[inline]
352    pub fn send_motion(
353        &self,
354        time: u32,
355        id: i32,
356        x: Fixed,
357        y: Fixed,
358    ) {
359        let res = self.try_send_motion(
360            time,
361            id,
362            x,
363            y,
364        );
365        if let Err(e) = res {
366            log_send("wl_touch.motion", &e);
367        }
368    }
369
370    /// Since when the frame message is available.
371    pub const MSG__FRAME__SINCE: u32 = 1;
372
373    /// end of touch frame event
374    ///
375    /// Indicates the end of a set of events that logically belong together.
376    /// A client is expected to accumulate the data in all events within the
377    /// frame before proceeding.
378    ///
379    /// A wl_touch.frame terminates at least one event but otherwise no
380    /// guarantee is provided about the set of events within a frame. A client
381    /// must assume that any state not updated in a frame is unchanged from the
382    /// previously known state.
383    #[inline]
384    pub fn try_send_frame(
385        &self,
386    ) -> Result<(), ObjectError> {
387        let core = self.core();
388        let client_ref = core.client.borrow();
389        let Some(client) = &*client_ref else {
390            return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
391        };
392        let id = core.client_obj_id.get().unwrap_or(0);
393        #[cfg(feature = "logging")]
394        if self.core.state.log {
395            #[cold]
396            fn log(state: &State, client_id: u64, id: u32) {
397                let (millis, micros) = time_since_epoch();
398                let prefix = &state.log_prefix;
399                let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_touch#{}.frame()\n", client_id, id);
400                state.log(args);
401            }
402            log(&self.core.state, client.endpoint.id, id);
403        }
404        let endpoint = &client.endpoint;
405        if !endpoint.flush_queued.replace(true) {
406            self.core.state.add_flushable_endpoint(endpoint, Some(client));
407        }
408        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
409        let outgoing = &mut *outgoing_ref;
410        let mut fmt = outgoing.formatter();
411        fmt.words([
412            id,
413            3,
414        ]);
415        Ok(())
416    }
417
418    /// end of touch frame event
419    ///
420    /// Indicates the end of a set of events that logically belong together.
421    /// A client is expected to accumulate the data in all events within the
422    /// frame before proceeding.
423    ///
424    /// A wl_touch.frame terminates at least one event but otherwise no
425    /// guarantee is provided about the set of events within a frame. A client
426    /// must assume that any state not updated in a frame is unchanged from the
427    /// previously known state.
428    #[inline]
429    pub fn send_frame(
430        &self,
431    ) {
432        let res = self.try_send_frame(
433        );
434        if let Err(e) = res {
435            log_send("wl_touch.frame", &e);
436        }
437    }
438
439    /// Since when the cancel message is available.
440    pub const MSG__CANCEL__SINCE: u32 = 1;
441
442    /// touch session cancelled
443    ///
444    /// Sent if the compositor decides the touch stream is a global
445    /// gesture. No further events are sent to the clients from that
446    /// particular gesture. Touch cancellation applies to all touch points
447    /// currently active on this client's surface. The client is
448    /// responsible for finalizing the touch points, future touch points on
449    /// this surface may reuse the touch point ID.
450    ///
451    /// No frame event is required after the cancel event.
452    #[inline]
453    pub fn try_send_cancel(
454        &self,
455    ) -> Result<(), ObjectError> {
456        let core = self.core();
457        let client_ref = core.client.borrow();
458        let Some(client) = &*client_ref else {
459            return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
460        };
461        let id = core.client_obj_id.get().unwrap_or(0);
462        #[cfg(feature = "logging")]
463        if self.core.state.log {
464            #[cold]
465            fn log(state: &State, client_id: u64, id: u32) {
466                let (millis, micros) = time_since_epoch();
467                let prefix = &state.log_prefix;
468                let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_touch#{}.cancel()\n", client_id, id);
469                state.log(args);
470            }
471            log(&self.core.state, client.endpoint.id, id);
472        }
473        let endpoint = &client.endpoint;
474        if !endpoint.flush_queued.replace(true) {
475            self.core.state.add_flushable_endpoint(endpoint, Some(client));
476        }
477        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
478        let outgoing = &mut *outgoing_ref;
479        let mut fmt = outgoing.formatter();
480        fmt.words([
481            id,
482            4,
483        ]);
484        Ok(())
485    }
486
487    /// touch session cancelled
488    ///
489    /// Sent if the compositor decides the touch stream is a global
490    /// gesture. No further events are sent to the clients from that
491    /// particular gesture. Touch cancellation applies to all touch points
492    /// currently active on this client's surface. The client is
493    /// responsible for finalizing the touch points, future touch points on
494    /// this surface may reuse the touch point ID.
495    ///
496    /// No frame event is required after the cancel event.
497    #[inline]
498    pub fn send_cancel(
499        &self,
500    ) {
501        let res = self.try_send_cancel(
502        );
503        if let Err(e) = res {
504            log_send("wl_touch.cancel", &e);
505        }
506    }
507
508    /// Since when the release message is available.
509    pub const MSG__RELEASE__SINCE: u32 = 3;
510
511    /// release the touch object
512    #[inline]
513    pub fn try_send_release(
514        &self,
515    ) -> Result<(), ObjectError> {
516        let core = self.core();
517        let Some(id) = core.server_obj_id.get() else {
518            return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
519        };
520        #[cfg(feature = "logging")]
521        if self.core.state.log {
522            #[cold]
523            fn log(state: &State, id: u32) {
524                let (millis, micros) = time_since_epoch();
525                let prefix = &state.log_prefix;
526                let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      <= wl_touch#{}.release()\n", id);
527                state.log(args);
528            }
529            log(&self.core.state, id);
530        }
531        let Some(endpoint) = &self.core.state.server else {
532            return Ok(());
533        };
534        if !endpoint.flush_queued.replace(true) {
535            self.core.state.add_flushable_endpoint(endpoint, None);
536        }
537        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
538        let outgoing = &mut *outgoing_ref;
539        let mut fmt = outgoing.formatter();
540        fmt.words([
541            id,
542            0,
543        ]);
544        self.core.handle_server_destroy();
545        Ok(())
546    }
547
548    /// release the touch object
549    #[inline]
550    pub fn send_release(
551        &self,
552    ) {
553        let res = self.try_send_release(
554        );
555        if let Err(e) = res {
556            log_send("wl_touch.release", &e);
557        }
558    }
559
560    /// Since when the shape message is available.
561    pub const MSG__SHAPE__SINCE: u32 = 6;
562
563    /// update shape of touch point
564    ///
565    /// Sent when a touchpoint has changed its shape.
566    ///
567    /// This event does not occur on its own. It is sent before a
568    /// wl_touch.frame event and carries the new shape information for
569    /// any previously reported, or new touch points of that frame.
570    ///
571    /// Other events describing the touch point such as wl_touch.down,
572    /// wl_touch.motion or wl_touch.orientation may be sent within the
573    /// same wl_touch.frame. A client should treat these events as a single
574    /// logical touch point update. The order of wl_touch.shape,
575    /// wl_touch.orientation and wl_touch.motion is not guaranteed.
576    /// A wl_touch.down event is guaranteed to occur before the first
577    /// wl_touch.shape event for this touch ID but both events may occur within
578    /// the same wl_touch.frame.
579    ///
580    /// A touchpoint shape is approximated by an ellipse through the major and
581    /// minor axis length. The major axis length describes the longer diameter
582    /// of the ellipse, while the minor axis length describes the shorter
583    /// diameter. Major and minor are orthogonal and both are specified in
584    /// surface-local coordinates. The center of the ellipse is always at the
585    /// touchpoint location as reported by wl_touch.down or wl_touch.move.
586    ///
587    /// This event is only sent by the compositor if the touch device supports
588    /// shape reports. The client has to make reasonable assumptions about the
589    /// shape if it did not receive this event.
590    ///
591    /// # Arguments
592    ///
593    /// - `id`: the unique ID of this touch point
594    /// - `major`: length of the major axis in surface-local coordinates
595    /// - `minor`: length of the minor axis in surface-local coordinates
596    #[inline]
597    pub fn try_send_shape(
598        &self,
599        id: i32,
600        major: Fixed,
601        minor: Fixed,
602    ) -> Result<(), ObjectError> {
603        let (
604            arg0,
605            arg1,
606            arg2,
607        ) = (
608            id,
609            major,
610            minor,
611        );
612        let core = self.core();
613        let client_ref = core.client.borrow();
614        let Some(client) = &*client_ref else {
615            return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
616        };
617        let id = core.client_obj_id.get().unwrap_or(0);
618        #[cfg(feature = "logging")]
619        if self.core.state.log {
620            #[cold]
621            fn log(state: &State, client_id: u64, id: u32, arg0: i32, arg1: Fixed, arg2: Fixed) {
622                let (millis, micros) = time_since_epoch();
623                let prefix = &state.log_prefix;
624                let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_touch#{}.shape(id: {}, major: {}, minor: {})\n", client_id, id, arg0, arg1, arg2);
625                state.log(args);
626            }
627            log(&self.core.state, client.endpoint.id, id, arg0, arg1, arg2);
628        }
629        let endpoint = &client.endpoint;
630        if !endpoint.flush_queued.replace(true) {
631            self.core.state.add_flushable_endpoint(endpoint, Some(client));
632        }
633        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
634        let outgoing = &mut *outgoing_ref;
635        let mut fmt = outgoing.formatter();
636        fmt.words([
637            id,
638            5,
639            arg0 as u32,
640            arg1.to_wire() as u32,
641            arg2.to_wire() as u32,
642        ]);
643        Ok(())
644    }
645
646    /// update shape of touch point
647    ///
648    /// Sent when a touchpoint has changed its shape.
649    ///
650    /// This event does not occur on its own. It is sent before a
651    /// wl_touch.frame event and carries the new shape information for
652    /// any previously reported, or new touch points of that frame.
653    ///
654    /// Other events describing the touch point such as wl_touch.down,
655    /// wl_touch.motion or wl_touch.orientation may be sent within the
656    /// same wl_touch.frame. A client should treat these events as a single
657    /// logical touch point update. The order of wl_touch.shape,
658    /// wl_touch.orientation and wl_touch.motion is not guaranteed.
659    /// A wl_touch.down event is guaranteed to occur before the first
660    /// wl_touch.shape event for this touch ID but both events may occur within
661    /// the same wl_touch.frame.
662    ///
663    /// A touchpoint shape is approximated by an ellipse through the major and
664    /// minor axis length. The major axis length describes the longer diameter
665    /// of the ellipse, while the minor axis length describes the shorter
666    /// diameter. Major and minor are orthogonal and both are specified in
667    /// surface-local coordinates. The center of the ellipse is always at the
668    /// touchpoint location as reported by wl_touch.down or wl_touch.move.
669    ///
670    /// This event is only sent by the compositor if the touch device supports
671    /// shape reports. The client has to make reasonable assumptions about the
672    /// shape if it did not receive this event.
673    ///
674    /// # Arguments
675    ///
676    /// - `id`: the unique ID of this touch point
677    /// - `major`: length of the major axis in surface-local coordinates
678    /// - `minor`: length of the minor axis in surface-local coordinates
679    #[inline]
680    pub fn send_shape(
681        &self,
682        id: i32,
683        major: Fixed,
684        minor: Fixed,
685    ) {
686        let res = self.try_send_shape(
687            id,
688            major,
689            minor,
690        );
691        if let Err(e) = res {
692            log_send("wl_touch.shape", &e);
693        }
694    }
695
696    /// Since when the orientation message is available.
697    pub const MSG__ORIENTATION__SINCE: u32 = 6;
698
699    /// update orientation of touch point
700    ///
701    /// Sent when a touchpoint has changed its orientation.
702    ///
703    /// This event does not occur on its own. It is sent before a
704    /// wl_touch.frame event and carries the new shape information for
705    /// any previously reported, or new touch points of that frame.
706    ///
707    /// Other events describing the touch point such as wl_touch.down,
708    /// wl_touch.motion or wl_touch.shape may be sent within the
709    /// same wl_touch.frame. A client should treat these events as a single
710    /// logical touch point update. The order of wl_touch.shape,
711    /// wl_touch.orientation and wl_touch.motion is not guaranteed.
712    /// A wl_touch.down event is guaranteed to occur before the first
713    /// wl_touch.orientation event for this touch ID but both events may occur
714    /// within the same wl_touch.frame.
715    ///
716    /// The orientation describes the clockwise angle of a touchpoint's major
717    /// axis to the positive surface y-axis and is normalized to the -180 to
718    /// +180 degree range. The granularity of orientation depends on the touch
719    /// device, some devices only support binary rotation values between 0 and
720    /// 90 degrees.
721    ///
722    /// This event is only sent by the compositor if the touch device supports
723    /// orientation reports.
724    ///
725    /// # Arguments
726    ///
727    /// - `id`: the unique ID of this touch point
728    /// - `orientation`: angle between major axis and positive surface y-axis in degrees
729    #[inline]
730    pub fn try_send_orientation(
731        &self,
732        id: i32,
733        orientation: Fixed,
734    ) -> Result<(), ObjectError> {
735        let (
736            arg0,
737            arg1,
738        ) = (
739            id,
740            orientation,
741        );
742        let core = self.core();
743        let client_ref = core.client.borrow();
744        let Some(client) = &*client_ref else {
745            return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
746        };
747        let id = core.client_obj_id.get().unwrap_or(0);
748        #[cfg(feature = "logging")]
749        if self.core.state.log {
750            #[cold]
751            fn log(state: &State, client_id: u64, id: u32, arg0: i32, arg1: Fixed) {
752                let (millis, micros) = time_since_epoch();
753                let prefix = &state.log_prefix;
754                let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_touch#{}.orientation(id: {}, orientation: {})\n", client_id, id, arg0, arg1);
755                state.log(args);
756            }
757            log(&self.core.state, client.endpoint.id, id, arg0, arg1);
758        }
759        let endpoint = &client.endpoint;
760        if !endpoint.flush_queued.replace(true) {
761            self.core.state.add_flushable_endpoint(endpoint, Some(client));
762        }
763        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
764        let outgoing = &mut *outgoing_ref;
765        let mut fmt = outgoing.formatter();
766        fmt.words([
767            id,
768            6,
769            arg0 as u32,
770            arg1.to_wire() as u32,
771        ]);
772        Ok(())
773    }
774
775    /// update orientation of touch point
776    ///
777    /// Sent when a touchpoint has changed its orientation.
778    ///
779    /// This event does not occur on its own. It is sent before a
780    /// wl_touch.frame event and carries the new shape information for
781    /// any previously reported, or new touch points of that frame.
782    ///
783    /// Other events describing the touch point such as wl_touch.down,
784    /// wl_touch.motion or wl_touch.shape may be sent within the
785    /// same wl_touch.frame. A client should treat these events as a single
786    /// logical touch point update. The order of wl_touch.shape,
787    /// wl_touch.orientation and wl_touch.motion is not guaranteed.
788    /// A wl_touch.down event is guaranteed to occur before the first
789    /// wl_touch.orientation event for this touch ID but both events may occur
790    /// within the same wl_touch.frame.
791    ///
792    /// The orientation describes the clockwise angle of a touchpoint's major
793    /// axis to the positive surface y-axis and is normalized to the -180 to
794    /// +180 degree range. The granularity of orientation depends on the touch
795    /// device, some devices only support binary rotation values between 0 and
796    /// 90 degrees.
797    ///
798    /// This event is only sent by the compositor if the touch device supports
799    /// orientation reports.
800    ///
801    /// # Arguments
802    ///
803    /// - `id`: the unique ID of this touch point
804    /// - `orientation`: angle between major axis and positive surface y-axis in degrees
805    #[inline]
806    pub fn send_orientation(
807        &self,
808        id: i32,
809        orientation: Fixed,
810    ) {
811        let res = self.try_send_orientation(
812            id,
813            orientation,
814        );
815        if let Err(e) = res {
816            log_send("wl_touch.orientation", &e);
817        }
818    }
819}
820
821/// A message handler for [`WlTouch`] proxies.
822pub trait WlTouchHandler: Any {
823    /// Event handler for wl_display.delete_id messages deleting the ID of this object.
824    ///
825    /// The default handler forwards the event to the client, if any.
826    #[inline]
827    fn delete_id(&mut self, slf: &Rc<WlTouch>) {
828        slf.core.delete_id();
829    }
830
831    /// touch down event and beginning of a touch sequence
832    ///
833    /// A new touch point has appeared on the surface. This touch point is
834    /// assigned a unique ID. Future events from this touch point reference
835    /// this ID. The ID ceases to be valid after a touch up event and may be
836    /// reused in the future.
837    ///
838    /// # Arguments
839    ///
840    /// - `serial`: serial number of the touch down event
841    /// - `time`: timestamp with millisecond granularity
842    /// - `surface`: surface touched
843    /// - `id`: the unique ID of this touch point
844    /// - `x`: surface-local x coordinate
845    /// - `y`: surface-local y coordinate
846    ///
847    /// All borrowed proxies passed to this function are guaranteed to be
848    /// immutable and non-null.
849    #[inline]
850    fn handle_down(
851        &mut self,
852        slf: &Rc<WlTouch>,
853        serial: u32,
854        time: u32,
855        surface: &Rc<WlSurface>,
856        id: i32,
857        x: Fixed,
858        y: Fixed,
859    ) {
860        if !slf.core.forward_to_client.get() {
861            return;
862        }
863        if let Some(client_id) = slf.core.client_id.get() {
864            if let Some(client_id_2) = surface.core().client_id.get() {
865                if client_id != client_id_2 {
866                    return;
867                }
868            }
869        }
870        let res = slf.try_send_down(
871            serial,
872            time,
873            surface,
874            id,
875            x,
876            y,
877        );
878        if let Err(e) = res {
879            log_forward("wl_touch.down", &e);
880        }
881    }
882
883    /// end of a touch event sequence
884    ///
885    /// The touch point has disappeared. No further events will be sent for
886    /// this touch point and the touch point's ID is released and may be
887    /// reused in a future touch down event.
888    ///
889    /// # Arguments
890    ///
891    /// - `serial`: serial number of the touch up event
892    /// - `time`: timestamp with millisecond granularity
893    /// - `id`: the unique ID of this touch point
894    #[inline]
895    fn handle_up(
896        &mut self,
897        slf: &Rc<WlTouch>,
898        serial: u32,
899        time: u32,
900        id: i32,
901    ) {
902        if !slf.core.forward_to_client.get() {
903            return;
904        }
905        let res = slf.try_send_up(
906            serial,
907            time,
908            id,
909        );
910        if let Err(e) = res {
911            log_forward("wl_touch.up", &e);
912        }
913    }
914
915    /// update of touch point coordinates
916    ///
917    /// A touch point has changed coordinates.
918    ///
919    /// # Arguments
920    ///
921    /// - `time`: timestamp with millisecond granularity
922    /// - `id`: the unique ID of this touch point
923    /// - `x`: surface-local x coordinate
924    /// - `y`: surface-local y coordinate
925    #[inline]
926    fn handle_motion(
927        &mut self,
928        slf: &Rc<WlTouch>,
929        time: u32,
930        id: i32,
931        x: Fixed,
932        y: Fixed,
933    ) {
934        if !slf.core.forward_to_client.get() {
935            return;
936        }
937        let res = slf.try_send_motion(
938            time,
939            id,
940            x,
941            y,
942        );
943        if let Err(e) = res {
944            log_forward("wl_touch.motion", &e);
945        }
946    }
947
948    /// end of touch frame event
949    ///
950    /// Indicates the end of a set of events that logically belong together.
951    /// A client is expected to accumulate the data in all events within the
952    /// frame before proceeding.
953    ///
954    /// A wl_touch.frame terminates at least one event but otherwise no
955    /// guarantee is provided about the set of events within a frame. A client
956    /// must assume that any state not updated in a frame is unchanged from the
957    /// previously known state.
958    #[inline]
959    fn handle_frame(
960        &mut self,
961        slf: &Rc<WlTouch>,
962    ) {
963        if !slf.core.forward_to_client.get() {
964            return;
965        }
966        let res = slf.try_send_frame(
967        );
968        if let Err(e) = res {
969            log_forward("wl_touch.frame", &e);
970        }
971    }
972
973    /// touch session cancelled
974    ///
975    /// Sent if the compositor decides the touch stream is a global
976    /// gesture. No further events are sent to the clients from that
977    /// particular gesture. Touch cancellation applies to all touch points
978    /// currently active on this client's surface. The client is
979    /// responsible for finalizing the touch points, future touch points on
980    /// this surface may reuse the touch point ID.
981    ///
982    /// No frame event is required after the cancel event.
983    #[inline]
984    fn handle_cancel(
985        &mut self,
986        slf: &Rc<WlTouch>,
987    ) {
988        if !slf.core.forward_to_client.get() {
989            return;
990        }
991        let res = slf.try_send_cancel(
992        );
993        if let Err(e) = res {
994            log_forward("wl_touch.cancel", &e);
995        }
996    }
997
998    /// release the touch object
999    #[inline]
1000    fn handle_release(
1001        &mut self,
1002        slf: &Rc<WlTouch>,
1003    ) {
1004        if !slf.core.forward_to_server.get() {
1005            return;
1006        }
1007        let res = slf.try_send_release(
1008        );
1009        if let Err(e) = res {
1010            log_forward("wl_touch.release", &e);
1011        }
1012    }
1013
1014    /// update shape of touch point
1015    ///
1016    /// Sent when a touchpoint has changed its shape.
1017    ///
1018    /// This event does not occur on its own. It is sent before a
1019    /// wl_touch.frame event and carries the new shape information for
1020    /// any previously reported, or new touch points of that frame.
1021    ///
1022    /// Other events describing the touch point such as wl_touch.down,
1023    /// wl_touch.motion or wl_touch.orientation may be sent within the
1024    /// same wl_touch.frame. A client should treat these events as a single
1025    /// logical touch point update. The order of wl_touch.shape,
1026    /// wl_touch.orientation and wl_touch.motion is not guaranteed.
1027    /// A wl_touch.down event is guaranteed to occur before the first
1028    /// wl_touch.shape event for this touch ID but both events may occur within
1029    /// the same wl_touch.frame.
1030    ///
1031    /// A touchpoint shape is approximated by an ellipse through the major and
1032    /// minor axis length. The major axis length describes the longer diameter
1033    /// of the ellipse, while the minor axis length describes the shorter
1034    /// diameter. Major and minor are orthogonal and both are specified in
1035    /// surface-local coordinates. The center of the ellipse is always at the
1036    /// touchpoint location as reported by wl_touch.down or wl_touch.move.
1037    ///
1038    /// This event is only sent by the compositor if the touch device supports
1039    /// shape reports. The client has to make reasonable assumptions about the
1040    /// shape if it did not receive this event.
1041    ///
1042    /// # Arguments
1043    ///
1044    /// - `id`: the unique ID of this touch point
1045    /// - `major`: length of the major axis in surface-local coordinates
1046    /// - `minor`: length of the minor axis in surface-local coordinates
1047    #[inline]
1048    fn handle_shape(
1049        &mut self,
1050        slf: &Rc<WlTouch>,
1051        id: i32,
1052        major: Fixed,
1053        minor: Fixed,
1054    ) {
1055        if !slf.core.forward_to_client.get() {
1056            return;
1057        }
1058        let res = slf.try_send_shape(
1059            id,
1060            major,
1061            minor,
1062        );
1063        if let Err(e) = res {
1064            log_forward("wl_touch.shape", &e);
1065        }
1066    }
1067
1068    /// update orientation of touch point
1069    ///
1070    /// Sent when a touchpoint has changed its orientation.
1071    ///
1072    /// This event does not occur on its own. It is sent before a
1073    /// wl_touch.frame event and carries the new shape information for
1074    /// any previously reported, or new touch points of that frame.
1075    ///
1076    /// Other events describing the touch point such as wl_touch.down,
1077    /// wl_touch.motion or wl_touch.shape may be sent within the
1078    /// same wl_touch.frame. A client should treat these events as a single
1079    /// logical touch point update. The order of wl_touch.shape,
1080    /// wl_touch.orientation and wl_touch.motion is not guaranteed.
1081    /// A wl_touch.down event is guaranteed to occur before the first
1082    /// wl_touch.orientation event for this touch ID but both events may occur
1083    /// within the same wl_touch.frame.
1084    ///
1085    /// The orientation describes the clockwise angle of a touchpoint's major
1086    /// axis to the positive surface y-axis and is normalized to the -180 to
1087    /// +180 degree range. The granularity of orientation depends on the touch
1088    /// device, some devices only support binary rotation values between 0 and
1089    /// 90 degrees.
1090    ///
1091    /// This event is only sent by the compositor if the touch device supports
1092    /// orientation reports.
1093    ///
1094    /// # Arguments
1095    ///
1096    /// - `id`: the unique ID of this touch point
1097    /// - `orientation`: angle between major axis and positive surface y-axis in degrees
1098    #[inline]
1099    fn handle_orientation(
1100        &mut self,
1101        slf: &Rc<WlTouch>,
1102        id: i32,
1103        orientation: Fixed,
1104    ) {
1105        if !slf.core.forward_to_client.get() {
1106            return;
1107        }
1108        let res = slf.try_send_orientation(
1109            id,
1110            orientation,
1111        );
1112        if let Err(e) = res {
1113            log_forward("wl_touch.orientation", &e);
1114        }
1115    }
1116}
1117
1118impl ObjectPrivate for WlTouch {
1119    fn new(state: &Rc<State>, version: u32) -> Rc<Self> {
1120        Rc::<Self>::new_cyclic(|slf| Self {
1121            core: ObjectCore::new(state, slf.clone(), ObjectInterface::WlTouch, version),
1122            handler: Default::default(),
1123        })
1124    }
1125
1126    fn delete_id(self: Rc<Self>) -> Result<(), (ObjectError, Rc<dyn Object>)> {
1127        let Some(mut handler) = self.handler.try_borrow_mut() else {
1128            return Err((ObjectError(ObjectErrorKind::HandlerBorrowed), self));
1129        };
1130        if let Some(handler) = &mut *handler {
1131            handler.delete_id(&self);
1132        } else {
1133            self.core.delete_id();
1134        }
1135        Ok(())
1136    }
1137
1138    fn handle_request(self: Rc<Self>, client: &Rc<Client>, msg: &[u32], fds: &mut VecDeque<Rc<OwnedFd>>) -> Result<(), ObjectError> {
1139        let Some(mut handler) = self.handler.try_borrow_mut() else {
1140            return Err(ObjectError(ObjectErrorKind::HandlerBorrowed));
1141        };
1142        let handler = &mut *handler;
1143        match msg[1] & 0xffff {
1144            0 => {
1145                if msg.len() != 2 {
1146                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 8)));
1147                }
1148                #[cfg(feature = "logging")]
1149                if self.core.state.log {
1150                    #[cold]
1151                    fn log(state: &State, client_id: u64, id: u32) {
1152                        let (millis, micros) = time_since_epoch();
1153                        let prefix = &state.log_prefix;
1154                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_touch#{}.release()\n", client_id, id);
1155                        state.log(args);
1156                    }
1157                    log(&self.core.state, client.endpoint.id, msg[0]);
1158                }
1159                self.core.handle_client_destroy();
1160                if let Some(handler) = handler {
1161                    (**handler).handle_release(&self);
1162                } else {
1163                    DefaultHandler.handle_release(&self);
1164                }
1165            }
1166            n => {
1167                let _ = client;
1168                let _ = msg;
1169                let _ = fds;
1170                let _ = handler;
1171                return Err(ObjectError(ObjectErrorKind::UnknownMessageId(n)));
1172            }
1173        }
1174        Ok(())
1175    }
1176
1177    fn handle_event(self: Rc<Self>, server: &Endpoint, msg: &[u32], fds: &mut VecDeque<Rc<OwnedFd>>) -> Result<(), ObjectError> {
1178        let Some(mut handler) = self.handler.try_borrow_mut() else {
1179            return Err(ObjectError(ObjectErrorKind::HandlerBorrowed));
1180        };
1181        let handler = &mut *handler;
1182        match msg[1] & 0xffff {
1183            0 => {
1184                let [
1185                    arg0,
1186                    arg1,
1187                    arg2,
1188                    arg3,
1189                    arg4,
1190                    arg5,
1191                ] = msg[2..] else {
1192                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 32)));
1193                };
1194                let arg3 = arg3 as i32;
1195                let arg4 = Fixed::from_wire(arg4 as i32);
1196                let arg5 = Fixed::from_wire(arg5 as i32);
1197                #[cfg(feature = "logging")]
1198                if self.core.state.log {
1199                    #[cold]
1200                    fn log(state: &State, id: u32, arg0: u32, arg1: u32, arg2: u32, arg3: i32, arg4: Fixed, arg5: Fixed) {
1201                        let (millis, micros) = time_since_epoch();
1202                        let prefix = &state.log_prefix;
1203                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      -> wl_touch#{}.down(serial: {}, time: {}, surface: wl_surface#{}, id: {}, x: {}, y: {})\n", id, arg0, arg1, arg2, arg3, arg4, arg5);
1204                        state.log(args);
1205                    }
1206                    log(&self.core.state, msg[0], arg0, arg1, arg2, arg3, arg4, arg5);
1207                }
1208                let arg2_id = arg2;
1209                let Some(arg2) = server.lookup(arg2_id) else {
1210                    return Err(ObjectError(ObjectErrorKind::NoServerObject(arg2_id)));
1211                };
1212                let Ok(arg2) = (arg2 as Rc<dyn Any>).downcast::<WlSurface>() else {
1213                    let o = server.lookup(arg2_id).unwrap();
1214                    return Err(ObjectError(ObjectErrorKind::WrongObjectType("surface", o.core().interface, ObjectInterface::WlSurface)));
1215                };
1216                let arg2 = &arg2;
1217                if let Some(handler) = handler {
1218                    (**handler).handle_down(&self, arg0, arg1, arg2, arg3, arg4, arg5);
1219                } else {
1220                    DefaultHandler.handle_down(&self, arg0, arg1, arg2, arg3, arg4, arg5);
1221                }
1222            }
1223            1 => {
1224                let [
1225                    arg0,
1226                    arg1,
1227                    arg2,
1228                ] = msg[2..] else {
1229                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 20)));
1230                };
1231                let arg2 = arg2 as i32;
1232                #[cfg(feature = "logging")]
1233                if self.core.state.log {
1234                    #[cold]
1235                    fn log(state: &State, id: u32, arg0: u32, arg1: u32, arg2: i32) {
1236                        let (millis, micros) = time_since_epoch();
1237                        let prefix = &state.log_prefix;
1238                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      -> wl_touch#{}.up(serial: {}, time: {}, id: {})\n", id, arg0, arg1, arg2);
1239                        state.log(args);
1240                    }
1241                    log(&self.core.state, msg[0], arg0, arg1, arg2);
1242                }
1243                if let Some(handler) = handler {
1244                    (**handler).handle_up(&self, arg0, arg1, arg2);
1245                } else {
1246                    DefaultHandler.handle_up(&self, arg0, arg1, arg2);
1247                }
1248            }
1249            2 => {
1250                let [
1251                    arg0,
1252                    arg1,
1253                    arg2,
1254                    arg3,
1255                ] = msg[2..] else {
1256                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 24)));
1257                };
1258                let arg1 = arg1 as i32;
1259                let arg2 = Fixed::from_wire(arg2 as i32);
1260                let arg3 = Fixed::from_wire(arg3 as i32);
1261                #[cfg(feature = "logging")]
1262                if self.core.state.log {
1263                    #[cold]
1264                    fn log(state: &State, id: u32, arg0: u32, arg1: i32, arg2: Fixed, arg3: Fixed) {
1265                        let (millis, micros) = time_since_epoch();
1266                        let prefix = &state.log_prefix;
1267                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      -> wl_touch#{}.motion(time: {}, id: {}, x: {}, y: {})\n", id, arg0, arg1, arg2, arg3);
1268                        state.log(args);
1269                    }
1270                    log(&self.core.state, msg[0], arg0, arg1, arg2, arg3);
1271                }
1272                if let Some(handler) = handler {
1273                    (**handler).handle_motion(&self, arg0, arg1, arg2, arg3);
1274                } else {
1275                    DefaultHandler.handle_motion(&self, arg0, arg1, arg2, arg3);
1276                }
1277            }
1278            3 => {
1279                if msg.len() != 2 {
1280                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 8)));
1281                }
1282                #[cfg(feature = "logging")]
1283                if self.core.state.log {
1284                    #[cold]
1285                    fn log(state: &State, id: u32) {
1286                        let (millis, micros) = time_since_epoch();
1287                        let prefix = &state.log_prefix;
1288                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      -> wl_touch#{}.frame()\n", id);
1289                        state.log(args);
1290                    }
1291                    log(&self.core.state, msg[0]);
1292                }
1293                if let Some(handler) = handler {
1294                    (**handler).handle_frame(&self);
1295                } else {
1296                    DefaultHandler.handle_frame(&self);
1297                }
1298            }
1299            4 => {
1300                if msg.len() != 2 {
1301                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 8)));
1302                }
1303                #[cfg(feature = "logging")]
1304                if self.core.state.log {
1305                    #[cold]
1306                    fn log(state: &State, id: u32) {
1307                        let (millis, micros) = time_since_epoch();
1308                        let prefix = &state.log_prefix;
1309                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      -> wl_touch#{}.cancel()\n", id);
1310                        state.log(args);
1311                    }
1312                    log(&self.core.state, msg[0]);
1313                }
1314                if let Some(handler) = handler {
1315                    (**handler).handle_cancel(&self);
1316                } else {
1317                    DefaultHandler.handle_cancel(&self);
1318                }
1319            }
1320            5 => {
1321                let [
1322                    arg0,
1323                    arg1,
1324                    arg2,
1325                ] = msg[2..] else {
1326                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 20)));
1327                };
1328                let arg0 = arg0 as i32;
1329                let arg1 = Fixed::from_wire(arg1 as i32);
1330                let arg2 = Fixed::from_wire(arg2 as i32);
1331                #[cfg(feature = "logging")]
1332                if self.core.state.log {
1333                    #[cold]
1334                    fn log(state: &State, id: u32, arg0: i32, arg1: Fixed, arg2: Fixed) {
1335                        let (millis, micros) = time_since_epoch();
1336                        let prefix = &state.log_prefix;
1337                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      -> wl_touch#{}.shape(id: {}, major: {}, minor: {})\n", id, arg0, arg1, arg2);
1338                        state.log(args);
1339                    }
1340                    log(&self.core.state, msg[0], arg0, arg1, arg2);
1341                }
1342                if let Some(handler) = handler {
1343                    (**handler).handle_shape(&self, arg0, arg1, arg2);
1344                } else {
1345                    DefaultHandler.handle_shape(&self, arg0, arg1, arg2);
1346                }
1347            }
1348            6 => {
1349                let [
1350                    arg0,
1351                    arg1,
1352                ] = msg[2..] else {
1353                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 16)));
1354                };
1355                let arg0 = arg0 as i32;
1356                let arg1 = Fixed::from_wire(arg1 as i32);
1357                #[cfg(feature = "logging")]
1358                if self.core.state.log {
1359                    #[cold]
1360                    fn log(state: &State, id: u32, arg0: i32, arg1: Fixed) {
1361                        let (millis, micros) = time_since_epoch();
1362                        let prefix = &state.log_prefix;
1363                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      -> wl_touch#{}.orientation(id: {}, orientation: {})\n", id, arg0, arg1);
1364                        state.log(args);
1365                    }
1366                    log(&self.core.state, msg[0], arg0, arg1);
1367                }
1368                if let Some(handler) = handler {
1369                    (**handler).handle_orientation(&self, arg0, arg1);
1370                } else {
1371                    DefaultHandler.handle_orientation(&self, arg0, arg1);
1372                }
1373            }
1374            n => {
1375                let _ = server;
1376                let _ = msg;
1377                let _ = fds;
1378                let _ = handler;
1379                return Err(ObjectError(ObjectErrorKind::UnknownMessageId(n)));
1380            }
1381        }
1382        Ok(())
1383    }
1384
1385    fn get_request_name(&self, id: u32) -> Option<&'static str> {
1386        let name = match id {
1387            0 => "release",
1388            _ => return None,
1389        };
1390        Some(name)
1391    }
1392
1393    fn get_event_name(&self, id: u32) -> Option<&'static str> {
1394        let name = match id {
1395            0 => "down",
1396            1 => "up",
1397            2 => "motion",
1398            3 => "frame",
1399            4 => "cancel",
1400            5 => "shape",
1401            6 => "orientation",
1402            _ => return None,
1403        };
1404        Some(name)
1405    }
1406}
1407
1408impl Object for WlTouch {
1409    fn core(&self) -> &ObjectCore {
1410        &self.core
1411    }
1412
1413    fn unset_handler(&self) {
1414        self.handler.set(None);
1415    }
1416
1417    fn get_handler_any_ref(&self) -> Result<HandlerRef<'_, dyn Any>, HandlerAccessError> {
1418        let borrowed = self.handler.try_borrow().ok_or(HandlerAccessError::AlreadyBorrowed)?;
1419        if borrowed.is_none() {
1420            return Err(HandlerAccessError::NoHandler);
1421        }
1422        Ok(HandlerRef::map(borrowed, |handler| &**handler.as_ref().unwrap() as &dyn Any))
1423    }
1424
1425    fn get_handler_any_mut(&self) -> Result<HandlerMut<'_, dyn Any>, HandlerAccessError> {
1426        let borrowed = self.handler.try_borrow_mut().ok_or(HandlerAccessError::AlreadyBorrowed)?;
1427        if borrowed.is_none() {
1428            return Err(HandlerAccessError::NoHandler);
1429        }
1430        Ok(HandlerMut::map(borrowed, |handler| &mut **handler.as_mut().unwrap() as &mut dyn Any))
1431    }
1432}
1433