winit/platform_impl/linux/wayland/seat/touch/
mod.rs

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