1use std::collections::HashMap;
4
5use crate::{PointerChange, PointerData, PointerDataPacket, PointerSignalKind, ViewId};
6
7#[derive(Clone, Copy, Debug)]
8struct PointerState {
9 pointer_identifier: i64,
10 is_down: bool,
11 is_pan_zoom_active: bool,
12 physical_x: f64,
13 physical_y: f64,
14 pan_x: f64,
15 pan_y: f64,
16 scale: f64,
17 rotation: f64,
18 buttons: i64,
19 view_id: ViewId,
20}
21
22#[derive(Debug, Default)]
25pub struct PointerDataPacketConverter {
26 states: HashMap<i64, PointerState>,
28
29 pointer: i64,
30}
31
32impl PointerDataPacketConverter {
33 pub fn new() -> PointerDataPacketConverter {
34 PointerDataPacketConverter::default()
35 }
36
37 pub fn convert(
48 &mut self,
49 packet: &PointerDataPacket,
50 view_exists: impl Fn(ViewId) -> bool,
51 ) -> PointerDataPacket {
52 let mut converted_pointers = Vec::new();
53 for pointer_data in &packet.data {
55 self.convert_pointer_data(*pointer_data, &view_exists, &mut converted_pointers);
56 }
57 PointerDataPacket::new(converted_pointers)
58 }
59
60 fn convert_pointer_data(
61 &mut self,
62 mut pointer_data: PointerData,
63 view_exists: &impl Fn(ViewId) -> bool,
64 converted_pointers: &mut Vec<PointerData>,
65 ) {
66 if !view_exists(pointer_data.view_id) {
68 return;
69 }
70 match pointer_data.signal_kind.unwrap_or(PointerSignalKind::None) {
71 PointerSignalKind::None => match pointer_data.change {
72 PointerChange::Cancel => {
73 if let Some(mut state) = self.states.get(&pointer_data.device).copied() {
78 self.update_pointer_identifier(&mut pointer_data, &mut state, false);
79
80 if Self::location_needs_update(&pointer_data, &state) {
81 let mut synthesized_move_event = pointer_data;
83 synthesized_move_event.change = PointerChange::Move;
84 synthesized_move_event.synthesized = true;
85
86 self.update_delta_and_state(&mut synthesized_move_event, &mut state);
87 converted_pointers.push(synthesized_move_event);
88 }
89
90 state.is_down = false;
91 self.states.insert(pointer_data.device, state);
92 converted_pointers.push(pointer_data);
93 }
94 }
95 PointerChange::Add => {
96 if let Some(mut state) = self.states.get(&pointer_data.device).copied() {
97 let mut synthesized_data = pointer_data;
100 synthesized_data.physical_x = state.physical_x;
101 synthesized_data.physical_y = state.physical_y;
102 synthesized_data.pan_x = state.pan_x;
103 synthesized_data.pan_y = state.pan_y;
104 synthesized_data.scale = state.scale;
105 synthesized_data.rotation = state.rotation;
106 synthesized_data.buttons = state.buttons;
107 synthesized_data.synthesized = true;
108
109 if view_exists(state.view_id) {
114 synthesized_data.view_id = state.view_id;
115
116 if state.is_down {
117 let mut synthesized_cancel_event = synthesized_data;
119 synthesized_cancel_event.change = PointerChange::Cancel;
120 self.update_pointer_identifier(
121 &mut synthesized_cancel_event,
122 &mut state,
123 false,
124 );
125
126 converted_pointers.push(synthesized_cancel_event);
127 }
128 }
129
130 let mut synthesized_remove_event = synthesized_data;
131 synthesized_remove_event.change = PointerChange::Remove;
132
133 converted_pointers.push(synthesized_remove_event);
134 }
135
136 self.ensure_pointer_state(&pointer_data);
137 converted_pointers.push(pointer_data);
138 }
139 PointerChange::Remove => {
140 let Some(mut state) = self.states.get(&pointer_data.device).copied() else {
142 return;
143 };
144 if state.view_id != pointer_data.view_id {
145 return;
148 }
149
150 if state.is_down {
151 let mut synthesized_cancel_event = pointer_data;
153 synthesized_cancel_event.change = PointerChange::Cancel;
154 synthesized_cancel_event.synthesized = true;
155 self.update_pointer_identifier(
156 &mut synthesized_cancel_event,
157 &mut state,
158 false,
159 );
160
161 state.is_down = false;
162 self.states.insert(synthesized_cancel_event.device, state);
163 converted_pointers.push(synthesized_cancel_event);
164 }
165
166 if Self::location_needs_update(&pointer_data, &state) {
167 let mut synthesized_hover_event = pointer_data;
169 synthesized_hover_event.change = PointerChange::Hover;
170 synthesized_hover_event.synthesized = true;
171
172 self.update_delta_and_state(&mut synthesized_hover_event, &mut state);
173 converted_pointers.push(synthesized_hover_event);
174 }
175
176 self.states.remove(&pointer_data.device);
177 converted_pointers.push(pointer_data);
178 }
179 PointerChange::Hover => {
180 let mut state = match self.states.get(&pointer_data.device).copied() {
181 Some(state) => state,
182 None => {
183 let mut synthesized_add_event = pointer_data;
185 synthesized_add_event.change = PointerChange::Add;
186 synthesized_add_event.synthesized = true;
187 synthesized_add_event.buttons = 0;
188 let state = self.ensure_pointer_state(&synthesized_add_event);
189 converted_pointers.push(synthesized_add_event);
190 state
191 }
192 };
193
194 state.buttons = pointer_data.buttons;
195 if Self::location_needs_update(&pointer_data, &state) {
196 self.update_delta_and_state(&mut pointer_data, &mut state);
197 converted_pointers.push(pointer_data);
198 }
199 }
200 PointerChange::Down => {
201 let mut state = match self.states.get(&pointer_data.device).copied() {
202 Some(state) => state,
203 None => {
204 let mut synthesized_add_event = pointer_data;
206 synthesized_add_event.change = PointerChange::Add;
207 synthesized_add_event.synthesized = true;
208 synthesized_add_event.buttons = 0;
209 let state = self.ensure_pointer_state(&synthesized_add_event);
210 converted_pointers.push(synthesized_add_event);
211 state
212 }
213 };
214
215 if Self::location_needs_update(&pointer_data, &state) {
216 let mut synthesized_hover_event = pointer_data;
218 synthesized_hover_event.change = PointerChange::Hover;
219 synthesized_hover_event.synthesized = true;
220 synthesized_hover_event.buttons = 0;
221
222 self.update_delta_and_state(&mut synthesized_hover_event, &mut state);
223 converted_pointers.push(synthesized_hover_event);
224 }
225
226 self.update_pointer_identifier(&mut pointer_data, &mut state, true);
227 state.is_down = true;
228 state.buttons = pointer_data.buttons;
229 self.states.insert(pointer_data.device, state);
230 converted_pointers.push(pointer_data);
231 }
232 PointerChange::Move => {
233 let Some(mut state) = self.states.get(&pointer_data.device).copied() else {
235 return;
236 };
237
238 self.update_pointer_identifier(&mut pointer_data, &mut state, false);
239 self.update_delta_and_state(&mut pointer_data, &mut state);
240 converted_pointers.push(pointer_data);
241 }
242 PointerChange::Up => {
243 let Some(mut state) = self.states.get(&pointer_data.device).copied() else {
245 return;
246 };
247
248 self.update_pointer_identifier(&mut pointer_data, &mut state, false);
249
250 if Self::location_needs_update(&pointer_data, &state) {
251 let mut synthesized_move_event = pointer_data;
253 synthesized_move_event.change = PointerChange::Move;
254 synthesized_move_event.buttons = state.buttons;
255 synthesized_move_event.synthesized = true;
256
257 self.update_delta_and_state(&mut synthesized_move_event, &mut state);
258 converted_pointers.push(synthesized_move_event);
259 }
260
261 state.is_down = false;
262 state.buttons = pointer_data.buttons;
263 self.states.insert(pointer_data.device, state);
264 converted_pointers.push(pointer_data);
265 }
266 PointerChange::PanZoomStart => {
267 let mut state = match self.states.get(&pointer_data.device).copied() {
269 Some(state) => state,
270 None => {
271 let mut synthesized_add_event = pointer_data;
273 synthesized_add_event.change = PointerChange::Add;
274 synthesized_add_event.synthesized = true;
275 synthesized_add_event.buttons = 0;
276 let state = self.ensure_pointer_state(&synthesized_add_event);
277 converted_pointers.push(synthesized_add_event);
278 state
279 }
280 };
281 if Self::location_needs_update(&pointer_data, &state) {
282 let mut synthesized_hover_event = pointer_data;
284 synthesized_hover_event.change = PointerChange::Hover;
285 synthesized_hover_event.synthesized = true;
286 synthesized_hover_event.buttons = 0;
287
288 self.update_delta_and_state(&mut synthesized_hover_event, &mut state);
289 converted_pointers.push(synthesized_hover_event);
290 }
291
292 self.update_pointer_identifier(&mut pointer_data, &mut state, true);
293 state.is_pan_zoom_active = true;
294 state.pan_x = 0.0;
295 state.pan_y = 0.0;
296 state.scale = 1.0;
297 state.rotation = 0.0;
298 self.states.insert(pointer_data.device, state);
299 converted_pointers.push(pointer_data);
300 }
301 PointerChange::PanZoomUpdate => {
302 let Some(mut state) = self.states.get(&pointer_data.device).copied() else {
304 return;
305 };
306
307 self.update_pointer_identifier(&mut pointer_data, &mut state, false);
308 self.update_delta_and_state(&mut pointer_data, &mut state);
309
310 converted_pointers.push(pointer_data);
311 }
312 PointerChange::PanZoomEnd => {
313 let Some(mut state) = self.states.get(&pointer_data.device).copied() else {
315 return;
316 };
317
318 self.update_pointer_identifier(&mut pointer_data, &mut state, false);
319
320 if Self::location_needs_update(&pointer_data, &state) {
321 let mut synthesized_move_event = pointer_data;
323 synthesized_move_event.change = PointerChange::PanZoomUpdate;
324 synthesized_move_event.pan_x = state.pan_x;
325 synthesized_move_event.pan_y = state.pan_y;
326 synthesized_move_event.pan_delta_x = 0.0;
327 synthesized_move_event.pan_delta_y = 0.0;
328 synthesized_move_event.scale = state.scale;
329 synthesized_move_event.rotation = state.rotation;
330 synthesized_move_event.synthesized = true;
331
332 self.update_delta_and_state(&mut synthesized_move_event, &mut state);
333 converted_pointers.push(synthesized_move_event);
334 }
335
336 state.is_pan_zoom_active = false;
337 self.states.insert(pointer_data.device, state);
338 converted_pointers.push(pointer_data);
339 }
340 },
341 PointerSignalKind::Scroll
342 | PointerSignalKind::ScrollInertiaCancel
343 | PointerSignalKind::Scale => {
344 let mut state = match self.states.get(&pointer_data.device).copied() {
346 Some(state) => state,
347 None => {
348 let mut synthesized_add_event = pointer_data;
350 synthesized_add_event.signal_kind = None;
351 synthesized_add_event.change = PointerChange::Add;
352 synthesized_add_event.synthesized = true;
353 synthesized_add_event.buttons = 0;
354 let state = self.ensure_pointer_state(&synthesized_add_event);
355 converted_pointers.push(synthesized_add_event);
356 state
357 }
358 };
359
360 if Self::location_needs_update(&pointer_data, &state) {
361 if state.is_down {
362 let mut synthesized_move_event = pointer_data;
364 synthesized_move_event.signal_kind = None;
365 synthesized_move_event.change = PointerChange::Move;
366 synthesized_move_event.buttons = state.buttons;
367 synthesized_move_event.synthesized = true;
368
369 self.update_delta_and_state(&mut synthesized_move_event, &mut state);
370 converted_pointers.push(synthesized_move_event);
371 } else {
372 let mut synthesized_hover_event = pointer_data;
374 synthesized_hover_event.signal_kind = None;
375 synthesized_hover_event.change = PointerChange::Hover;
376 synthesized_hover_event.buttons = 0;
377 synthesized_hover_event.synthesized = true;
378
379 self.update_delta_and_state(&mut synthesized_hover_event, &mut state);
380 converted_pointers.push(synthesized_hover_event);
381 }
382 }
383
384 converted_pointers.push(pointer_data);
385 }
386 PointerSignalKind::Unknown => {}
388 }
389 }
390
391 fn ensure_pointer_state(&mut self, pointer_data: &PointerData) -> PointerState {
392 let state = PointerState {
393 pointer_identifier: 0,
394 is_down: false,
395 is_pan_zoom_active: false,
396 physical_x: pointer_data.physical_x,
397 physical_y: pointer_data.physical_y,
398 pan_x: 0.0,
399 pan_y: 0.0,
400 scale: 0.0,
401 rotation: 0.0,
402 buttons: 0,
403 view_id: pointer_data.view_id,
404 };
405 self.states.insert(pointer_data.device, state);
406 state
407 }
408
409 fn update_delta_and_state(&mut self, pointer_data: &mut PointerData, state: &mut PointerState) {
410 pointer_data.physical_delta_x = pointer_data.physical_x - state.physical_x;
411 pointer_data.physical_delta_y = pointer_data.physical_y - state.physical_y;
412 pointer_data.pan_delta_x = pointer_data.pan_x - state.pan_x;
413 pointer_data.pan_delta_y = pointer_data.pan_y - state.pan_y;
414 state.physical_x = pointer_data.physical_x;
415 state.physical_y = pointer_data.physical_y;
416 state.pan_x = pointer_data.pan_x;
417 state.pan_y = pointer_data.pan_y;
418 state.scale = pointer_data.scale;
419 state.rotation = pointer_data.rotation;
420 self.states.insert(pointer_data.device, *state);
421 }
422
423 fn update_pointer_identifier(
424 &mut self,
425 pointer_data: &mut PointerData,
426 state: &mut PointerState,
427 start_new_pointer: bool,
428 ) {
429 if start_new_pointer {
430 self.pointer += 1;
431 state.pointer_identifier = self.pointer;
432 self.states.insert(pointer_data.device, *state);
433 }
434 pointer_data.pointer_identifier = state.pointer_identifier;
435 }
436
437 fn location_needs_update(pointer_data: &PointerData, state: &PointerState) -> bool {
438 state.physical_x != pointer_data.physical_x || state.physical_y != pointer_data.physical_y
439 }
440}
441
442#[cfg(test)]
443mod tests {
444 use std::collections::HashSet;
445
446 use super::*;
447 use crate::PointerDeviceKind;
448
449 const IMPLICIT_VIEW_ID: ViewId = ViewId(0);
450
451 fn pointer_data(
452 change: PointerChange,
453 device: i64,
454 dx: f64,
455 dy: f64,
456 buttons: i64,
457 ) -> PointerData {
458 PointerData {
459 change,
460 kind: PointerDeviceKind::Touch,
461 device,
462 physical_x: dx,
463 physical_y: dy,
464 buttons,
465 view_id: IMPLICIT_VIEW_ID,
466 ..PointerData::default()
467 }
468 }
469
470 #[allow(clippy::too_many_arguments)]
471 fn mouse_pointer_data(
472 change: PointerChange,
473 signal_kind: PointerSignalKind,
474 device: i64,
475 dx: f64,
476 dy: f64,
477 scroll_delta_x: f64,
478 scroll_delta_y: f64,
479 buttons: i64,
480 ) -> PointerData {
481 PointerData {
482 change,
483 kind: PointerDeviceKind::Mouse,
484 signal_kind: Some(signal_kind),
485 device,
486 physical_x: dx,
487 physical_y: dy,
488 buttons,
489 scroll_delta_x,
490 scroll_delta_y,
491 view_id: IMPLICIT_VIEW_ID,
492 ..PointerData::default()
493 }
494 }
495
496 #[allow(clippy::too_many_arguments)]
497 fn trackpad_gesture_data(
498 change: PointerChange,
499 device: i64,
500 dx: f64,
501 dy: f64,
502 pan_x: f64,
503 pan_y: f64,
504 scale: f64,
505 rotation: f64,
506 ) -> PointerData {
507 PointerData {
508 change,
509 kind: PointerDeviceKind::Mouse,
510 device,
511 physical_x: dx,
512 physical_y: dy,
513 pan_x,
514 pan_y,
515 scale,
516 rotation,
517 view_id: IMPLICIT_VIEW_ID,
518 ..PointerData::default()
519 }
520 }
521
522 fn convert(
523 converter: &mut PointerDataPacketConverter,
524 views: &HashSet<ViewId>,
525 data: Vec<PointerData>,
526 ) -> Vec<PointerData> {
527 converter
528 .convert(&PointerDataPacket::new(data), |view_id| {
529 views.contains(&view_id)
530 })
531 .data
532 }
533
534 fn implicit_view() -> HashSet<ViewId> {
535 HashSet::from([IMPLICIT_VIEW_ID])
536 }
537
538 fn changes(result: &[PointerData]) -> Vec<PointerChange> {
539 result.iter().map(|datum| datum.change).collect()
540 }
541
542 fn synthesized(result: &[PointerData]) -> Vec<bool> {
543 result.iter().map(|datum| datum.synthesized).collect()
544 }
545
546 #[test]
547 fn can_convert_pointer_data_packet() {
548 let mut converter = PointerDataPacketConverter::new();
549 let result = convert(
550 &mut converter,
551 &implicit_view(),
552 vec![
553 pointer_data(PointerChange::Add, 0, 0.0, 0.0, 0),
554 pointer_data(PointerChange::Hover, 0, 3.0, 0.0, 0),
555 pointer_data(PointerChange::Down, 0, 3.0, 0.0, 1),
556 pointer_data(PointerChange::Move, 0, 3.0, 4.0, 1),
557 pointer_data(PointerChange::Up, 0, 3.0, 4.0, 0),
558 pointer_data(PointerChange::Remove, 0, 3.0, 4.0, 0),
559 ],
560 );
561
562 use PointerChange::*;
563 assert_eq!(changes(&result), [Add, Hover, Down, Move, Up, Remove]);
564 assert_eq!(synthesized(&result), [false; 6]);
565 assert_eq!(
566 [result[1].physical_delta_x, result[1].physical_delta_y],
567 [3.0, 0.0]
568 );
569 assert_eq!(result[2].pointer_identifier, 1);
570 assert_eq!(result[3].pointer_identifier, 1);
571 assert_eq!(
572 [result[3].physical_delta_x, result[3].physical_delta_y],
573 [0.0, 4.0]
574 );
575 assert_eq!(result[4].pointer_identifier, 1);
576 }
577
578 #[test]
579 fn can_synthesize_down_and_up() {
580 let mut converter = PointerDataPacketConverter::new();
581 let result = convert(
582 &mut converter,
583 &implicit_view(),
584 vec![
585 pointer_data(PointerChange::Add, 0, 0.0, 0.0, 0),
586 pointer_data(PointerChange::Down, 0, 3.0, 0.0, 1),
587 pointer_data(PointerChange::Up, 0, 3.0, 4.0, 0),
588 pointer_data(PointerChange::Remove, 0, 3.0, 4.0, 0),
589 ],
590 );
591
592 use PointerChange::*;
593 assert_eq!(changes(&result), [Add, Hover, Down, Move, Up, Remove]);
594 assert_eq!(
595 synthesized(&result),
596 [false, true, false, true, false, false]
597 );
598 assert_eq!(
600 [result[1].physical_delta_x, result[1].physical_delta_y],
601 [3.0, 0.0]
602 );
603 assert_eq!(result[1].buttons, 0);
604 assert_eq!((result[2].pointer_identifier, result[2].buttons), (1, 1));
605 assert_eq!((result[3].pointer_identifier, result[3].buttons), (1, 1));
607 assert_eq!(
608 [result[3].physical_delta_x, result[3].physical_delta_y],
609 [0.0, 4.0]
610 );
611 assert_eq!((result[4].pointer_identifier, result[4].buttons), (1, 0));
612 }
613
614 #[test]
615 fn can_update_pointer_identifier() {
616 let mut converter = PointerDataPacketConverter::new();
617 let result = convert(
618 &mut converter,
619 &implicit_view(),
620 vec![
621 pointer_data(PointerChange::Add, 0, 0.0, 0.0, 0),
622 pointer_data(PointerChange::Down, 0, 0.0, 0.0, 1),
623 pointer_data(PointerChange::Up, 0, 0.0, 0.0, 0),
624 pointer_data(PointerChange::Down, 0, 0.0, 0.0, 1),
625 pointer_data(PointerChange::Move, 0, 3.0, 0.0, 1),
626 pointer_data(PointerChange::Up, 0, 3.0, 0.0, 0),
627 pointer_data(PointerChange::Remove, 0, 3.0, 0.0, 0),
628 ],
629 );
630
631 use PointerChange::*;
632 assert_eq!(changes(&result), [Add, Down, Up, Down, Move, Up, Remove]);
633 assert_eq!(synthesized(&result), [false; 7]);
634 let identifiers: Vec<i64> = result.iter().map(|d| d.pointer_identifier).collect();
635 assert_eq!(identifiers[1..6], [1, 1, 2, 2, 2]);
637 assert_eq!(
638 [result[4].physical_delta_x, result[4].physical_delta_y],
639 [3.0, 0.0]
640 );
641 }
642
643 #[test]
644 fn always_forward_move_event() {
645 let mut converter = PointerDataPacketConverter::new();
646 let result = convert(
647 &mut converter,
648 &implicit_view(),
649 vec![
650 pointer_data(PointerChange::Add, 0, 0.0, 0.0, 0),
651 pointer_data(PointerChange::Down, 0, 0.0, 0.0, 1),
652 pointer_data(PointerChange::Move, 0, 0.0, 0.0, 1),
654 pointer_data(PointerChange::Up, 0, 0.0, 0.0, 0),
655 ],
656 );
657
658 use PointerChange::*;
659 assert_eq!(changes(&result), [Add, Down, Move, Up]);
661 assert_eq!(synthesized(&result), [false; 4]);
662 assert_eq!(result[2].pointer_identifier, 1);
663 }
664
665 #[test]
666 fn can_work_with_different_devices() {
667 let mut converter = PointerDataPacketConverter::new();
668 let result = convert(
669 &mut converter,
670 &implicit_view(),
671 vec![
672 pointer_data(PointerChange::Add, 0, 0.0, 0.0, 0),
673 pointer_data(PointerChange::Down, 0, 0.0, 0.0, 1),
674 pointer_data(PointerChange::Add, 1, 0.0, 0.0, 0),
675 pointer_data(PointerChange::Down, 1, 0.0, 0.0, 1),
676 pointer_data(PointerChange::Up, 0, 0.0, 0.0, 0),
677 pointer_data(PointerChange::Down, 0, 0.0, 0.0, 1),
678 pointer_data(PointerChange::Move, 1, 0.0, 4.0, 1),
679 pointer_data(PointerChange::Move, 0, 3.0, 0.0, 1),
680 pointer_data(PointerChange::Up, 1, 0.0, 4.0, 0),
681 pointer_data(PointerChange::Up, 0, 3.0, 0.0, 0),
682 pointer_data(PointerChange::Remove, 0, 3.0, 0.0, 0),
683 pointer_data(PointerChange::Remove, 1, 0.0, 4.0, 0),
684 ],
685 );
686
687 use PointerChange::*;
688 assert_eq!(
689 changes(&result),
690 [
691 Add, Down, Add, Down, Up, Down, Move, Move, Up, Up, Remove, Remove
692 ]
693 );
694 assert_eq!(synthesized(&result), [false; 12]);
695 let devices: Vec<i64> = result.iter().map(|d| d.device).collect();
696 assert_eq!(devices, [0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1]);
697 let identifiers: Vec<i64> = result.iter().map(|d| d.pointer_identifier).collect();
698 assert_eq!(
699 [
700 identifiers[1],
701 identifiers[3],
702 identifiers[4],
703 identifiers[5]
704 ],
705 [1, 2, 1, 3]
706 );
707 assert_eq!(identifiers[6..10], [2, 3, 2, 3]);
708 assert_eq!(
709 [result[6].physical_delta_x, result[6].physical_delta_y],
710 [0.0, 4.0]
711 );
712 assert_eq!(
713 [result[7].physical_delta_x, result[7].physical_delta_y],
714 [3.0, 0.0]
715 );
716 }
717
718 #[test]
719 fn can_synthesize_add() {
720 let mut converter = PointerDataPacketConverter::new();
721 let result = convert(
722 &mut converter,
723 &implicit_view(),
724 vec![
725 pointer_data(PointerChange::Down, 0, 330.0, 450.0, 1),
726 pointer_data(PointerChange::Up, 0, 0.0, 0.0, 0),
727 ],
728 );
729
730 use PointerChange::*;
731 assert_eq!(changes(&result), [Add, Down, Move, Up]);
732 assert_eq!(synthesized(&result), [true, false, true, false]);
733 assert_eq!([result[0].physical_x, result[0].physical_y], [330.0, 450.0]);
735 assert_eq!(result[0].buttons, 0);
736 assert_eq!(result[1].buttons, 1);
737 assert_eq!(
739 [result[2].physical_delta_x, result[2].physical_delta_y],
740 [-330.0, -450.0]
741 );
742 assert_eq!([result[2].physical_x, result[2].physical_y], [0.0, 0.0]);
743 assert_eq!(result[2].buttons, 1);
744 assert_eq!(result[3].buttons, 0);
745 }
746
747 #[test]
748 fn can_synthesize_remove() {
749 let views = HashSet::from([ViewId(100), ViewId(200)]);
750 let mut converter = PointerDataPacketConverter::new();
751 let result = convert(
752 &mut converter,
753 &views,
754 vec![
755 PointerData {
756 view_id: ViewId(100),
757 ..pointer_data(PointerChange::Add, 0, 0.0, 0.0, 0)
758 },
759 PointerData {
760 view_id: ViewId(100),
761 ..pointer_data(PointerChange::Down, 0, 3.0, 4.0, 1)
762 },
763 PointerData {
764 view_id: ViewId(200),
765 ..pointer_data(PointerChange::Add, 0, 0.0, 0.0, 0)
766 },
767 ],
768 );
769
770 use PointerChange::*;
771 assert_eq!(changes(&result), [Add, Hover, Down, Cancel, Remove, Add]);
772 assert_eq!(
773 synthesized(&result),
774 [false, true, false, true, true, false]
775 );
776 assert_eq!(result[0].view_id, ViewId(100));
777 assert_eq!(
779 [result[1].physical_delta_x, result[1].physical_delta_y],
780 [3.0, 4.0]
781 );
782 assert_eq!(result[1].buttons, 0);
783 assert_eq!((result[2].pointer_identifier, result[2].buttons), (1, 1));
784 assert_eq!((result[3].pointer_identifier, result[3].buttons), (1, 1));
786 assert_eq!([result[3].physical_x, result[3].physical_y], [3.0, 4.0]);
787 assert_eq!([result[4].physical_x, result[4].physical_y], [3.0, 4.0]);
789 assert_eq!(result[4].view_id, ViewId(100));
790 assert_eq!(result[5].view_id, ViewId(200));
791 }
792
793 #[test]
794 fn can_avoid_double_remove_after_synthesized_remove() {
795 let views = HashSet::from([ViewId(100), ViewId(200)]);
796 let mut converter = PointerDataPacketConverter::new();
797 let result = convert(
798 &mut converter,
799 &views,
800 vec![
801 PointerData {
802 view_id: ViewId(100),
803 ..pointer_data(PointerChange::Add, 0, 0.0, 0.0, 0)
804 },
805 PointerData {
806 view_id: ViewId(200),
807 ..pointer_data(PointerChange::Add, 0, 0.0, 0.0, 0)
808 },
809 ],
810 );
811
812 assert_eq!(synthesized(&result), [false, true, false]);
813 let views_of: Vec<ViewId> = result.iter().map(|d| d.view_id).collect();
815 assert_eq!(views_of, [ViewId(100), ViewId(100), ViewId(200)]);
816
817 let result = convert(
819 &mut converter,
820 &views,
821 vec![PointerData {
822 view_id: ViewId(100),
823 ..pointer_data(PointerChange::Remove, 0, 0.0, 0.0, 0)
824 }],
825 );
826 assert!(result.is_empty());
828 }
829
830 #[test]
831 fn can_handle_three_finger_gesture() {
832 let views = implicit_view();
834 let mut converter = PointerDataPacketConverter::new();
835 let mut result = Vec::new();
836 result.extend(convert(
838 &mut converter,
839 &views,
840 vec![pointer_data(PointerChange::Down, 0, 0.0, 0.0, 1)],
841 ));
842 result.extend(convert(
844 &mut converter,
845 &views,
846 vec![pointer_data(PointerChange::Down, 1, 33.0, 44.0, 1)],
847 ));
848 result.extend(convert(
850 &mut converter,
851 &views,
852 vec![
853 pointer_data(PointerChange::Cancel, 1, 33.0, 44.0, 0),
854 pointer_data(PointerChange::Cancel, 0, 0.0, 0.0, 0),
855 pointer_data(PointerChange::Cancel, 2, 40.0, 50.0, 0),
856 ],
857 ));
858
859 use PointerChange::*;
860 assert_eq!(changes(&result), [Add, Down, Add, Down, Cancel, Cancel]);
862 assert_eq!(
863 synthesized(&result),
864 [true, false, true, false, false, false]
865 );
866 let devices: Vec<i64> = result.iter().map(|d| d.device).collect();
867 assert_eq!(devices, [0, 0, 1, 1, 1, 0]);
868 assert_eq!((result[0].buttons, result[1].buttons), (0, 1));
869 assert_eq!([result[2].physical_x, result[2].physical_y], [33.0, 44.0]);
870 assert_eq!((result[2].buttons, result[3].buttons), (0, 1));
871 assert_eq!([result[4].physical_x, result[4].physical_y], [33.0, 44.0]);
872 }
873
874 #[test]
875 fn can_convert_pointer_signals() {
876 for kind in [
877 PointerSignalKind::Scroll,
878 PointerSignalKind::ScrollInertiaCancel,
879 PointerSignalKind::Scale,
880 ] {
881 let mut converter = PointerDataPacketConverter::new();
882 let none = PointerSignalKind::None;
883 let result = convert(
884 &mut converter,
885 &implicit_view(),
886 vec![
887 mouse_pointer_data(PointerChange::Add, none, 0, 0.0, 0.0, 0.0, 0.0, 0),
888 mouse_pointer_data(PointerChange::Add, none, 1, 0.0, 0.0, 0.0, 0.0, 0),
889 mouse_pointer_data(PointerChange::Down, none, 1, 0.0, 0.0, 0.0, 0.0, 1),
890 mouse_pointer_data(PointerChange::Hover, kind, 0, 34.0, 34.0, 30.0, 0.0, 0),
891 mouse_pointer_data(PointerChange::Hover, kind, 1, 49.0, 49.0, 50.0, 0.0, 0),
892 mouse_pointer_data(PointerChange::Hover, kind, 2, 10.0, 20.0, 30.0, 40.0, 0),
893 ],
894 );
895
896 use PointerChange::*;
897 assert_eq!(
898 changes(&result),
899 [Add, Add, Down, Hover, Hover, Move, Hover, Add, Hover]
900 );
901 let signals: Vec<PointerSignalKind> = result
902 .iter()
903 .map(|d| d.signal_kind.unwrap_or(PointerSignalKind::None))
904 .collect();
905 assert_eq!(
906 signals,
907 [none, none, none, none, kind, none, kind, none, kind]
908 );
909 let devices: Vec<i64> = result.iter().map(|d| d.device).collect();
910 assert_eq!(devices, [0, 1, 1, 0, 0, 1, 1, 2, 2]);
911 assert_eq!(
912 synthesized(&result),
913 [false, false, false, true, false, true, false, true, false]
914 );
915
916 assert_eq!([result[3].physical_x, result[3].physical_y], [34.0, 34.0]);
918 assert_eq!(
919 [result[3].physical_delta_x, result[3].physical_delta_y],
920 [34.0, 34.0]
921 );
922 assert_eq!(result[3].buttons, 0);
923 assert_eq!([result[4].physical_x, result[4].physical_y], [34.0, 34.0]);
924 assert_eq!(
925 [result[4].scroll_delta_x, result[4].scroll_delta_y],
926 [30.0, 0.0]
927 );
928
929 assert_eq!([result[5].physical_x, result[5].physical_y], [49.0, 49.0]);
931 assert_eq!(
932 [result[5].physical_delta_x, result[5].physical_delta_y],
933 [49.0, 49.0]
934 );
935 assert_eq!(result[5].buttons, 1);
936 assert_eq!([result[6].physical_x, result[6].physical_y], [49.0, 49.0]);
937 assert_eq!(
938 [result[6].scroll_delta_x, result[6].scroll_delta_y],
939 [50.0, 0.0]
940 );
941
942 assert_eq!([result[7].physical_x, result[7].physical_y], [10.0, 20.0]);
944 assert_eq!([result[8].physical_x, result[8].physical_y], [10.0, 20.0]);
945 assert_eq!(
946 [result[8].scroll_delta_x, result[8].scroll_delta_y],
947 [30.0, 40.0]
948 );
949 }
950 }
951
952 #[test]
953 fn can_convert_trackpad_gesture() {
954 let mut converter = PointerDataPacketConverter::new();
955 let result = convert(
956 &mut converter,
957 &implicit_view(),
958 vec![
959 trackpad_gesture_data(PointerChange::PanZoomStart, 0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0),
960 trackpad_gesture_data(
961 PointerChange::PanZoomUpdate,
962 0,
963 0.0,
964 0.0,
965 3.0,
966 4.0,
967 1.0,
968 0.0,
969 ),
970 trackpad_gesture_data(PointerChange::PanZoomEnd, 0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0),
971 ],
972 );
973
974 use PointerChange::*;
975 assert_eq!(
976 changes(&result),
977 [Add, PanZoomStart, PanZoomUpdate, PanZoomEnd]
978 );
979 assert_eq!(synthesized(&result), [true, false, false, false]);
980 assert_eq!([result[2].pan_x, result[2].pan_y], [3.0, 4.0]);
981 assert_eq!([result[2].pan_delta_x, result[2].pan_delta_y], [3.0, 4.0]);
982 assert_eq!((result[2].scale, result[2].rotation), (1.0, 0.0));
983 }
984
985 #[test]
986 fn a_pan_zoom_away_from_where_its_device_was_starts_with_a_hover_and_ends_with_an_update() {
987 let mut converter = PointerDataPacketConverter::new();
988 let views = implicit_view();
989 let first = convert(
990 &mut converter,
991 &views,
992 vec![
993 trackpad_gesture_data(PointerChange::PanZoomStart, 1, 5.0, 5.0, 0.0, 0.0, 1.0, 0.0),
994 trackpad_gesture_data(
995 PointerChange::PanZoomUpdate,
996 1,
997 5.0,
998 5.0,
999 0.0,
1000 6.0,
1001 1.5,
1002 0.0,
1003 ),
1004 trackpad_gesture_data(PointerChange::PanZoomEnd, 1, 9.0, 5.0, 0.0, 0.0, 0.0, 0.0),
1005 ],
1006 );
1007 let second = convert(
1008 &mut converter,
1009 &views,
1010 vec![trackpad_gesture_data(
1011 PointerChange::PanZoomStart,
1012 1,
1013 20.0,
1014 5.0,
1015 0.0,
1016 0.0,
1017 1.0,
1018 0.0,
1019 )],
1020 );
1021
1022 use PointerChange::*;
1023 assert_eq!(
1024 changes(&first),
1025 [Add, PanZoomStart, PanZoomUpdate, PanZoomUpdate, PanZoomEnd]
1026 );
1027 let ending = first[3];
1028 assert!(ending.synthesized);
1029 assert_eq!([ending.physical_delta_x, ending.pan_delta_y], [4.0, 0.0]);
1030 assert_eq!((ending.pan_y, ending.scale), (6.0, 1.5));
1031 assert_eq!(changes(&second), [Hover, PanZoomStart]);
1032 assert!(second[0].synthesized);
1033 assert_eq!(second[0].physical_delta_x, 11.0);
1034 assert_eq!(
1035 [first[1].pointer_identifier, second[1].pointer_identifier],
1036 [1, 2]
1037 );
1038 }
1039
1040 #[test]
1041 fn a_move_up_or_remove_of_a_device_never_added_is_dropped() {
1042 let mut converter = PointerDataPacketConverter::new();
1043 let result = convert(
1044 &mut converter,
1045 &implicit_view(),
1046 vec![
1047 pointer_data(PointerChange::Move, 0, 1.0, 0.0, 1),
1048 pointer_data(PointerChange::Up, 0, 1.0, 0.0, 0),
1049 pointer_data(PointerChange::Remove, 0, 1.0, 0.0, 0),
1050 trackpad_gesture_data(
1051 PointerChange::PanZoomUpdate,
1052 1,
1053 0.0,
1054 0.0,
1055 1.0,
1056 0.0,
1057 1.0,
1058 0.0,
1059 ),
1060 trackpad_gesture_data(PointerChange::PanZoomEnd, 1, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0),
1061 ],
1062 );
1063 assert!(result.is_empty());
1064 }
1065
1066 #[test]
1067 fn can_convert_view_id() {
1068 let views = HashSet::from([ViewId(100), ViewId(200)]);
1069 let mut converter = PointerDataPacketConverter::new();
1070 let result = convert(
1071 &mut converter,
1072 &views,
1073 vec![
1074 PointerData {
1075 view_id: ViewId(100),
1076 ..pointer_data(PointerChange::Add, 0, 0.0, 0.0, 0)
1077 },
1078 PointerData {
1079 view_id: ViewId(200),
1080 ..pointer_data(PointerChange::Hover, 0, 1.0, 0.0, 0)
1081 },
1082 ],
1083 );
1084
1085 let views_of: Vec<ViewId> = result.iter().map(|d| d.view_id).collect();
1086 assert_eq!(views_of, [ViewId(100), ViewId(200)]);
1087 }
1088}