smithay_client_toolkit/seat/
touch.rs1use std::sync::Mutex;
2
3use wayland_client::protocol::wl_seat::WlSeat;
4
5use wayland_client::protocol::wl_surface::WlSurface;
6use wayland_client::protocol::wl_touch::{Event as TouchEvent, WlTouch};
7use wayland_client::{Connection, Dispatch, QueueHandle};
8
9use crate::dispatch2::Dispatch2;
10
11#[derive(Debug)]
12pub struct TouchData<U> {
13 seat: WlSeat,
14 inner: Mutex<TouchDataInner>,
15 udata: U,
16}
17
18impl<U> TouchData<U> {
19 pub fn new(seat: WlSeat, udata: U) -> Self {
21 Self { seat, inner: Default::default(), udata }
22 }
23
24 pub fn data(&self) -> &U {
25 &self.udata
26 }
27
28 pub fn data_mut(&mut self) -> &mut U {
29 &mut self.udata
30 }
31
32 pub fn seat(&self) -> &WlSeat {
34 &self.seat
35 }
36
37 pub fn latest_down_serial(&self) -> Option<u32> {
39 self.inner.lock().unwrap().latest_down
40 }
41}
42
43#[derive(Debug, Default)]
44pub(crate) struct TouchDataInner {
45 events: Vec<TouchEvent>,
46 active_touch_points: Vec<i32>,
47
48 latest_down: Option<u32>,
50}
51
52pub trait TouchHandler: Sized {
53 #[allow(clippy::too_many_arguments)]
64 fn down(
65 &mut self,
66 conn: &Connection,
67 qh: &QueueHandle<Self>,
68 touch: &WlTouch,
69 serial: u32,
70 time: u32,
71 surface: WlSurface,
72 id: i32,
73 position: (f64, f64),
74 );
75
76 fn up(
78 &mut self,
79 conn: &Connection,
80 qh: &QueueHandle<Self>,
81 touch: &WlTouch,
82 serial: u32,
83 time: u32,
84 id: i32,
85 );
86
87 fn motion(
91 &mut self,
92 conn: &Connection,
93 qh: &QueueHandle<Self>,
94 touch: &WlTouch,
95 time: u32,
96 id: i32,
97 position: (f64, f64),
98 );
99
100 fn shape(
108 &mut self,
109 conn: &Connection,
110 qh: &QueueHandle<Self>,
111 touch: &WlTouch,
112 id: i32,
113 major: f64,
114 minor: f64,
115 );
116
117 fn orientation(
122 &mut self,
123 conn: &Connection,
124 qh: &QueueHandle<Self>,
125 touch: &WlTouch,
126 id: i32,
127 orientation: f64,
128 );
129
130 fn cancel(&mut self, conn: &Connection, qh: &QueueHandle<Self>, touch: &WlTouch);
135}
136
137impl<D, U> Dispatch2<WlTouch, D> for TouchData<U>
138where
139 D: Dispatch<WlTouch, TouchData<U>> + TouchHandler,
140{
141 fn event(
142 &self,
143 data: &mut D,
144 touch: &WlTouch,
145 event: TouchEvent,
146 conn: &Connection,
147 qh: &QueueHandle<D>,
148 ) {
149 let mut guard: std::sync::MutexGuard<'_, TouchDataInner> = self.inner.lock().unwrap();
150
151 let mut save_event = false;
152 let mut process_events = false;
153
154 match &event {
155 TouchEvent::Down { serial, id, .. } => {
157 guard.latest_down = Some(*serial);
158 save_event = true;
159 if let Err(insert_pos) = guard.active_touch_points.binary_search(id) {
160 guard.active_touch_points.insert(insert_pos, *id);
161 }
162 }
163 TouchEvent::Up { id, .. } => {
164 save_event = true;
165 if let Ok(remove_pos) = guard.active_touch_points.binary_search(id) {
166 guard.active_touch_points.remove(remove_pos);
167 }
168
169 if guard.active_touch_points.is_empty() {
174 process_events = true;
175 }
176 }
177 TouchEvent::Motion { .. }
178 | TouchEvent::Shape { .. }
179 | TouchEvent::Orientation { .. } => {
180 save_event = true;
181 }
182 TouchEvent::Frame => {
184 process_events = true;
185 }
186 TouchEvent::Cancel => {
187 guard.events.clear();
188 guard.active_touch_points.clear();
189
190 data.cancel(conn, qh, touch);
191 }
192 _ => unreachable!(),
193 }
194
195 if save_event {
196 guard.events.push(event);
197 }
198
199 if process_events {
200 for event in guard.events.drain(..) {
201 process_framed_event(data, touch, conn, qh, event);
202 }
203 }
204 }
205}
206
207fn process_framed_event<D>(
209 data: &mut D,
210 touch: &WlTouch,
211 conn: &Connection,
212 qh: &QueueHandle<D>,
213 event: TouchEvent,
214) where
215 D: TouchHandler,
216{
217 match event {
218 TouchEvent::Down { serial, time, surface, id, x, y } => {
219 data.down(conn, qh, touch, serial, time, surface, id, (x, y));
220 }
221 TouchEvent::Up { serial, time, id } => {
222 data.up(conn, qh, touch, serial, time, id);
223 }
224 TouchEvent::Motion { time, id, x, y } => {
225 data.motion(conn, qh, touch, time, id, (x, y));
226 }
227 TouchEvent::Shape { id, major, minor } => {
228 data.shape(conn, qh, touch, id, major, minor);
229 }
230 TouchEvent::Orientation { id, orientation } => {
231 data.orientation(conn, qh, touch, id, orientation);
232 }
233 _ => unreachable!(),
235 }
236}