1//! Touch handling.
2
3use sctk::reexports::client::protocol::wl_seat::WlSeat;
4use sctk::reexports::client::protocol::wl_surface::WlSurface;
5use sctk::reexports::client::protocol::wl_touch::WlTouch;
6use sctk::reexports::client::{Connection, Proxy, QueueHandle};
7
8use sctk::seat::touch::{TouchData, TouchHandler};
9
10use crate::dpi::LogicalPosition;
11use crate::event::{Touch, TouchPhase, WindowEvent};
12
13use crate::platform_impl::wayland::state::WinitState;
14use crate::platform_impl::wayland::{self, DeviceId};
15
16impl TouchHandler for WinitState {
17 fn down(
18 &mut self,
19 _: &Connection,
20 _: &QueueHandle<Self>,
21 touch: &WlTouch,
22 _: u32,
23 _: u32,
24 surface: WlSurface,
25 id: i32,
26 position: (f64, f64),
27 ) {
28 let window_id = wayland::make_wid(&surface);
29 let scale_factor = match self.windows.get_mut().get(&window_id) {
30 Some(window) => window.lock().unwrap().scale_factor(),
31 None => return,
32 };
33
34 let location = LogicalPosition::<f64>::from(position);
35
36 let seat_state = self.seats.get_mut(&touch.seat().id()).unwrap();
37
38 // Update the state of the point.
39 seat_state
40 .touch_map
41 .insert(id, TouchPoint { surface, location });
42
43 self.events_sink.push_window_event(
44 WindowEvent::Touch(Touch {
45 device_id: crate::event::DeviceId(crate::platform_impl::DeviceId::Wayland(
46 DeviceId,
47 )),
48 phase: TouchPhase::Started,
49 location: location.to_physical(scale_factor),
50 force: None,
51 id: id as u64,
52 }),
53 window_id,
54 );
55 }
56
57 fn up(
58 &mut self,
59 _: &Connection,
60 _: &QueueHandle<Self>,
61 touch: &WlTouch,
62 _: u32,
63 _: u32,
64 id: i32,
65 ) {
66 let seat_state = self.seats.get_mut(&touch.seat().id()).unwrap();
67
68 // Remove the touch point.
69 let touch_point = match seat_state.touch_map.remove(&id) {
70 Some(touch_point) => touch_point,
71 None => return,
72 };
73
74 let window_id = wayland::make_wid(&touch_point.surface);
75 let scale_factor = match self.windows.get_mut().get(&window_id) {
76 Some(window) => window.lock().unwrap().scale_factor(),
77 None => return,
78 };
79
80 self.events_sink.push_window_event(
81 WindowEvent::Touch(Touch {
82 device_id: crate::event::DeviceId(crate::platform_impl::DeviceId::Wayland(
83 DeviceId,
84 )),
85 phase: TouchPhase::Ended,
86 location: touch_point.location.to_physical(scale_factor),
87 force: None,
88 id: id as u64,
89 }),
90 window_id,
91 );
92 }
93
94 fn motion(
95 &mut self,
96 _: &Connection,
97 _: &QueueHandle<Self>,
98 touch: &WlTouch,
99 _: u32,
100 id: i32,
101 position: (f64, f64),
102 ) {
103 let seat_state = self.seats.get_mut(&touch.seat().id()).unwrap();
104
105 // Remove the touch point.
106 let touch_point = match seat_state.touch_map.get_mut(&id) {
107 Some(touch_point) => touch_point,
108 None => return,
109 };
110
111 let window_id = wayland::make_wid(&touch_point.surface);
112 let scale_factor = match self.windows.get_mut().get(&window_id) {
113 Some(window) => window.lock().unwrap().scale_factor(),
114 None => return,
115 };
116
117 touch_point.location = LogicalPosition::<f64>::from(position);
118
119 self.events_sink.push_window_event(
120 WindowEvent::Touch(Touch {
121 device_id: crate::event::DeviceId(crate::platform_impl::DeviceId::Wayland(
122 DeviceId,
123 )),
124 phase: TouchPhase::Moved,
125 location: touch_point.location.to_physical(scale_factor),
126 force: None,
127 id: id as u64,
128 }),
129 window_id,
130 );
131 }
132
133 fn cancel(&mut self, _: &Connection, _: &QueueHandle<Self>, touch: &WlTouch) {
134 let seat_state = self.seats.get_mut(&touch.seat().id()).unwrap();
135
136 for (id, touch_point) in seat_state.touch_map.drain() {
137 let window_id = wayland::make_wid(&touch_point.surface);
138 let scale_factor = match self.windows.get_mut().get(&window_id) {
139 Some(window) => window.lock().unwrap().scale_factor(),
140 None => return,
141 };
142
143 let location = touch_point.location.to_physical(scale_factor);
144
145 self.events_sink.push_window_event(
146 WindowEvent::Touch(Touch {
147 device_id: crate::event::DeviceId(crate::platform_impl::DeviceId::Wayland(
148 DeviceId,
149 )),
150 phase: TouchPhase::Cancelled,
151 location,
152 force: None,
153 id: id as u64,
154 }),
155 window_id,
156 );
157 }
158 }
159
160 fn shape(
161 &mut self,
162 _: &Connection,
163 _: &QueueHandle<Self>,
164 _: &WlTouch,
165 _: i32,
166 _: f64,
167 _: f64,
168 ) {
169 // Blank.
170 }
171
172 fn orientation(&mut self, _: &Connection, _: &QueueHandle<Self>, _: &WlTouch, _: i32, _: f64) {
173 // Blank.
174 }
175}
176
177/// The state of the touch point.
178#[derive(Debug)]
179pub struct TouchPoint {
180 /// The surface on which the point is present.
181 pub surface: WlSurface,
182
183 /// The location of the point on the surface.
184 pub location: LogicalPosition<f64>,
185}
186
187pub trait TouchDataExt {
188 fn seat(&self) -> &WlSeat;
189}
190
191impl TouchDataExt for WlTouch {
192 fn seat(&self) -> &WlSeat {
193 self.data::<TouchData>()
194 .expect(msg:"failed to get touch data.")
195 .seat()
196 }
197}
198
199sctk::delegate_touch!(WinitState);
200