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