1 | //! Touch handling. |
2 | |
3 | use sctk::reexports::client::protocol::wl_seat::WlSeat; |
4 | use sctk::reexports::client::protocol::wl_surface::WlSurface; |
5 | use sctk::reexports::client::protocol::wl_touch::WlTouch; |
6 | use sctk::reexports::client::{Connection, Proxy, QueueHandle}; |
7 | |
8 | use sctk::seat::touch::{TouchData, TouchHandler}; |
9 | |
10 | use crate::dpi::LogicalPosition; |
11 | use crate::event::{Touch, TouchPhase, WindowEvent}; |
12 | |
13 | use crate::platform_impl::wayland::state::WinitState; |
14 | use crate::platform_impl::wayland::{self, DeviceId}; |
15 | |
16 | impl 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)] |
179 | pub 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 | |
187 | pub trait TouchDataExt { |
188 | fn seat(&self) -> &WlSeat; |
189 | } |
190 | |
191 | impl 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 | |
199 | sctk::delegate_touch!(WinitState); |
200 | |