1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
//! Various handlers for touch events.

use sctk::reexports::client::protocol::wl_touch::Event as TouchEvent;

use crate::dpi::LogicalPosition;
use crate::event::{TouchPhase, WindowEvent};

use crate::platform_impl::wayland::event_loop::WinitState;
use crate::platform_impl::wayland::{self, DeviceId};

use super::{TouchInner, TouchPoint};

/// Handle WlTouch events.
#[inline]
pub(super) fn handle_touch(
    event: TouchEvent,
    inner: &mut TouchInner,
    winit_state: &mut WinitState,
) {
    let event_sink = &mut winit_state.event_sink;

    match event {
        TouchEvent::Down {
            surface, id, x, y, ..
        } => {
            let window_id = wayland::make_wid(&surface);
            let window_handle = match winit_state.window_map.get(&window_id) {
                Some(w) => w,
                _ => return,
            };

            let scale_factor = window_handle.scale_factor();
            let position = LogicalPosition::new(x, y);

            event_sink.push_window_event(
                WindowEvent::Touch(crate::event::Touch {
                    device_id: crate::event::DeviceId(crate::platform_impl::DeviceId::Wayland(
                        DeviceId,
                    )),
                    phase: TouchPhase::Started,
                    location: position.to_physical(scale_factor),
                    force: None, // TODO
                    id: id as u64,
                }),
                window_id,
            );

            // For `TouchEvent::Up` we don't receive a position, so we're tracking active
            // touch points. Update either a known touch id or register a new one.
            if let Some(i) = inner.touch_points.iter().position(|p| p.id == id) {
                inner.touch_points[i].position = position;
            } else {
                inner
                    .touch_points
                    .push(TouchPoint::new(surface, position, id));
            }
        }
        TouchEvent::Up { id, .. } => {
            let touch_point = match inner.touch_points.iter().find(|p| p.id == id) {
                Some(touch_point) => touch_point,
                None => return,
            };

            let window_id = wayland::make_wid(&touch_point.surface);
            let window_handle = match winit_state.window_map.get(&window_id) {
                Some(w) => w,
                _ => return,
            };
            let scale_factor = window_handle.scale_factor();
            let location = touch_point.position.to_physical(scale_factor);
            let window_id = wayland::make_wid(&touch_point.surface);

            event_sink.push_window_event(
                WindowEvent::Touch(crate::event::Touch {
                    device_id: crate::event::DeviceId(crate::platform_impl::DeviceId::Wayland(
                        DeviceId,
                    )),
                    phase: TouchPhase::Ended,
                    location,
                    force: None, // TODO
                    id: id as u64,
                }),
                window_id,
            );
        }
        TouchEvent::Motion { id, x, y, .. } => {
            let touch_point = match inner.touch_points.iter_mut().find(|p| p.id == id) {
                Some(touch_point) => touch_point,
                None => return,
            };
            let window_id = wayland::make_wid(&touch_point.surface);
            let window_handle = match winit_state.window_map.get(&window_id) {
                Some(w) => w,
                _ => return,
            };

            touch_point.position = LogicalPosition::new(x, y);

            let scale_factor = window_handle.scale_factor();
            let location = touch_point.position.to_physical(scale_factor);
            let window_id = wayland::make_wid(&touch_point.surface);

            event_sink.push_window_event(
                WindowEvent::Touch(crate::event::Touch {
                    device_id: crate::event::DeviceId(crate::platform_impl::DeviceId::Wayland(
                        DeviceId,
                    )),
                    phase: TouchPhase::Moved,
                    location,
                    force: None, // TODO
                    id: id as u64,
                }),
                window_id,
            );
        }
        TouchEvent::Frame => (),
        TouchEvent::Cancel => {
            for touch_point in inner.touch_points.drain(..) {
                let window_id = wayland::make_wid(&touch_point.surface);
                let window_handle = match winit_state.window_map.get(&window_id) {
                    Some(w) => w,
                    _ => return,
                };

                let scale_factor = window_handle.scale_factor();
                let location = touch_point.position.to_physical(scale_factor);

                event_sink.push_window_event(
                    WindowEvent::Touch(crate::event::Touch {
                        device_id: crate::event::DeviceId(crate::platform_impl::DeviceId::Wayland(
                            DeviceId,
                        )),
                        phase: TouchPhase::Cancelled,
                        location,
                        force: None, // TODO
                        id: touch_point.id as u64,
                    }),
                    window_id,
                );
            }
        }
        _ => (),
    }
}