1#![allow(unused)]
6use crate::geometry::{IntPoint, IntSize};
7use crate::input::*;
8use fidl_fuchsia_input_report as hid_input_report;
9use std::collections::{BTreeMap, HashSet, VecDeque};
10use zx::MonotonicInstant;
11
12#[derive(Clone, Copy)]
13struct ContactDetails {
14 event_time: u64,
15 location: IntPoint,
16 size: IntSize,
17}
18
19struct DownContact {
20 last: ContactDetails,
21 next: ContactDetails,
22}
23
24struct TouchDevice {
25 down_contacts: BTreeMap<touch::ContactId, DownContact>,
26 buttons: HashSet<hid_input_report::TouchButton>,
27}
28
29pub(crate) struct TouchEventResampler {
30 events: VecDeque<Event>,
31 touch_devices: BTreeMap<DeviceId, TouchDevice>,
32}
33
34impl TouchEventResampler {
35 pub fn new() -> Self {
37 Self { events: VecDeque::new(), touch_devices: BTreeMap::new() }
38 }
39
40 pub fn enqueue(&mut self, event: Event) {
42 self.events.push_back(event);
43 }
44
45 pub fn dequeue_and_sample(&mut self, sample_time: MonotonicInstant) -> Vec<Event> {
48 let sample_time_ns = sample_time.into_nanos() as u64;
49
50 self.process_events(sample_time_ns);
52
53 let mut events = self.dequeue_events_until(sample_time_ns);
55
56 events.extend(self.touch_devices.iter().filter_map(|(device_id, device)| {
58 if device.down_contacts.is_empty() {
59 None
60 } else {
61 let contacts = device.down_contacts.iter().map(|(contact_id, contact)| {
62 let p = contact.last;
63 let n = contact.next;
64 touch::Contact {
65 contact_id: *contact_id,
66 phase: if n.event_time > sample_time_ns && n.event_time > p.event_time {
69 let interval = (n.event_time - p.event_time) as f32;
70 let scalar = (sample_time_ns - p.event_time) as f32 / interval;
71 let location =
72 p.location.to_f32() + (n.location - p.location).to_f32() * scalar;
73 let size = p.size.to_f32() + (n.size - p.size).to_f32() * scalar;
74 touch::Phase::Moved(location.to_i32(), size.to_i32())
75 } else {
76 touch::Phase::Moved(n.location, n.size)
77 },
78 }
79 });
80
81 let touch_event =
82 touch::Event { contacts: contacts.collect(), buttons: device.buttons.clone() };
83 Some(Event {
84 event_time: sample_time_ns,
85 device_id: device_id.clone(),
86 event_type: EventType::Touch(touch_event),
87 })
88 }
89 }));
90
91 events
92 }
93
94 fn process_events(&mut self, sample_time_ns: u64) {
95 for Event { event_time, device_id, event_type } in &self.events {
96 if let EventType::Touch(touch_event) = event_type {
97 if *event_time > sample_time_ns {
100 if let Some(device) = self.touch_devices.get_mut(&device_id.clone()) {
101 for touch::Contact { contact_id, phase } in &touch_event.contacts {
102 if let touch::Phase::Moved(location, size) = phase {
103 if let Some(down_contact) =
104 device.down_contacts.get_mut(&contact_id)
105 {
106 if down_contact.next.event_time < sample_time_ns {
109 down_contact.next = ContactDetails {
110 event_time: *event_time,
111 location: *location,
112 size: *size,
113 };
114 }
115 }
116 }
117 }
118 }
119 } else {
120 let device = self.touch_devices.entry(device_id.clone()).or_insert_with(|| {
122 TouchDevice {
123 down_contacts: BTreeMap::new(),
124 buttons: touch_event.buttons.clone(),
125 }
126 });
127
128 device.buttons = touch_event.buttons.clone();
130
131 for contact in &touch_event.contacts {
132 match contact.phase {
133 touch::Phase::Down(location, size)
134 | touch::Phase::Moved(location, size) => {
135 let details =
136 ContactDetails { event_time: *event_time, location, size };
137 device.down_contacts.insert(
138 contact.contact_id,
139 DownContact { last: details, next: details },
140 );
141 }
142 touch::Phase::Up | touch::Phase::Remove | touch::Phase::Cancel => {
143 device.down_contacts.remove(&contact.contact_id);
144 }
145 }
146 }
147 }
148 }
149 }
150 }
151
152 fn dequeue_events_until(&mut self, sample_time_ns: u64) -> Vec<Event> {
153 let mut events = vec![];
154
155 while let Some(event) = self.events.front() {
156 if event.event_time > sample_time_ns {
158 break;
159 }
160
161 let event = self.events.pop_front().unwrap();
162 if let EventType::Touch(touch_event) = &event.event_type {
163 if let Some(device) = self.touch_devices.get(&event.device_id.clone()) {
164 let contacts = touch_event.contacts.iter().filter_map(|contact| {
165 match contact.phase {
166 touch::Phase::Moved(_, _) => {
167 if device.down_contacts.contains_key(&contact.contact_id) {
169 None
170 } else {
171 Some(contact.clone())
172 }
173 }
174 _ => Some(contact.clone()),
175 }
176 });
177
178 let touch_event = touch::Event {
179 contacts: contacts.collect(),
180 buttons: device.buttons.clone(),
181 };
182 if !touch_event.contacts.is_empty() {
183 events.push(Event {
184 event_time: event.event_time,
185 device_id: event.device_id.clone(),
186 event_type: EventType::Touch(touch_event),
187 });
188 }
189 }
190 } else {
191 events.push(event);
192 }
193 }
194
195 events
196 }
197}
198
199#[cfg(test)]
200mod touch_event_resampling_tests {
201 use super::*;
202 use std::collections::HashSet;
203
204 fn create_test_down_phase(x: i32, y: i32) -> touch::Phase {
205 touch::Phase::Down(euclid::point2(x, y), IntSize::zero())
206 }
207
208 fn create_test_moved_phase(x: i32, y: i32) -> touch::Phase {
209 touch::Phase::Moved(euclid::point2(x, y), IntSize::zero())
210 }
211
212 fn create_test_event(phase: touch::Phase, event_time: u64) -> Event {
213 let touch_event = touch::Event {
214 contacts: vec![touch::Contact { contact_id: touch::ContactId(100), phase }],
215 buttons: HashSet::new(),
216 };
217 Event {
218 event_time: event_time,
219 device_id: DeviceId("test-device-id-1".to_string()),
220 event_type: EventType::Touch(touch_event),
221 }
222 }
223
224 #[test]
225 fn test_resampling() {
226 let mut resampler = TouchEventResampler::new();
227
228 resampler.enqueue(create_test_event(create_test_down_phase(0, 0), 1000));
229 resampler.enqueue(create_test_event(create_test_moved_phase(10, 0), 2000));
230 resampler.enqueue(create_test_event(create_test_moved_phase(20, 0), 3000));
231 resampler.enqueue(create_test_event(create_test_moved_phase(30, 0), 4000));
232 resampler.enqueue(create_test_event(touch::Phase::Up, 4000));
233
234 assert_eq!(resampler.dequeue_and_sample(MonotonicInstant::from_nanos(500)), vec![]);
236
237 let result = resampler.dequeue_and_sample(MonotonicInstant::from_nanos(1500));
239 assert_eq!(result.len(), 2);
240 assert_eq!(result[0], create_test_event(create_test_down_phase(0, 0), 1000));
241 assert_eq!(result[1], create_test_event(create_test_moved_phase(5, 0), 1500));
242
243 let result = resampler.dequeue_and_sample(MonotonicInstant::from_nanos(2500));
245 assert_eq!(result.len(), 1);
246 assert_eq!(result[0], create_test_event(create_test_moved_phase(15, 0), 2500));
247
248 let result = resampler.dequeue_and_sample(MonotonicInstant::from_nanos(3500));
250 assert_eq!(result.len(), 1);
251 assert_eq!(result[0], create_test_event(create_test_moved_phase(25, 0), 3500));
252
253 let result = resampler.dequeue_and_sample(MonotonicInstant::from_nanos(4500));
255 assert_eq!(result.len(), 2);
256 assert_eq!(result[0], create_test_event(create_test_moved_phase(30, 0), 4000));
257 assert_eq!(result[1], create_test_event(touch::Phase::Up, 4000));
258 }
259}