1use super::gesture_arena::{
6 self, DetailedReasonFloat, DetailedReasonInt, DetailedReasonUint, ExamineEventResult,
7 ProcessBufferedEventsResult, Reason, RecognizedGesture, TouchpadEvent, VerifyEventResult,
8 SECONDARY_BUTTON,
9};
10use crate::mouse_binding::{MouseEvent, MouseLocation, MousePhase, RelativeLocation};
11use crate::utils::{euclidean_distance, Position};
12
13use maplit::hashset;
14
15#[derive(Debug)]
18pub(super) struct InitialContender {
19 pub(super) max_finger_displacement_in_mm: f32,
22
23 pub(super) max_time_elapsed: zx::MonotonicDuration,
26}
27
28impl InitialContender {
29 #[allow(clippy::boxed_local, reason = "mass allow for https://fxbug.dev/381896734")]
30 fn into_one_finger_contact_contender(
31 self: Box<Self>,
32 one_finger_contact_event: TouchpadEvent,
33 ) -> Box<dyn gesture_arena::Contender> {
34 Box::new(OneFingerContactContender {
35 one_finger_contact_event,
36 max_finger_displacement_in_mm: self.max_finger_displacement_in_mm,
37 max_time_elapsed: self.max_time_elapsed,
38 })
39 }
40
41 #[allow(clippy::boxed_local, reason = "mass allow for https://fxbug.dev/381896734")]
42 fn into_two_finger_contacts_contender(
43 self: Box<Self>,
44 two_finger_contacts_event: TouchpadEvent,
45 ) -> Box<dyn gesture_arena::Contender> {
46 Box::new(TwoFingerContactsContender {
47 two_finger_contacts_event,
48 max_finger_displacement_in_mm: self.max_finger_displacement_in_mm,
49 max_time_elapsed: self.max_time_elapsed,
50 })
51 }
52}
53
54impl gesture_arena::Contender for InitialContender {
55 fn examine_event(self: Box<Self>, event: &TouchpadEvent) -> ExamineEventResult {
56 let num_pressed_buttons = event.pressed_buttons.len();
57 if num_pressed_buttons != 0 {
58 return ExamineEventResult::Mismatch(Reason::DetailedUint(DetailedReasonUint {
59 criterion: "num_pressed_buttons",
60 min: Some(0),
61 max: Some(0),
62 actual: num_pressed_buttons,
63 }));
64 }
65
66 let num_contacts = event.contacts.len();
67 match num_contacts {
68 1 => {
69 ExamineEventResult::Contender(self.into_one_finger_contact_contender(event.clone()))
70 }
71 2 => ExamineEventResult::Contender(
72 self.into_two_finger_contacts_contender(event.clone()),
73 ),
74 0 | _ => ExamineEventResult::Mismatch(Reason::DetailedUint(DetailedReasonUint {
75 criterion: "num_contacts",
76 min: Some(1),
77 max: Some(2),
78 actual: num_contacts,
79 })),
80 }
81 }
82
83 fn start_from_idle(&self) -> bool {
84 true
85 }
86}
87
88#[derive(Debug)]
90struct OneFingerContactContender {
91 one_finger_contact_event: TouchpadEvent,
93
94 max_finger_displacement_in_mm: f32,
97
98 max_time_elapsed: zx::MonotonicDuration,
101}
102
103impl OneFingerContactContender {
104 #[allow(clippy::boxed_local, reason = "mass allow for https://fxbug.dev/381896734")]
105 fn into_two_finger_contacts_contender(
106 self: Box<Self>,
107 two_finger_contacts_event: TouchpadEvent,
108 ) -> Box<dyn gesture_arena::Contender> {
109 Box::new(TwoFingerContactsContender {
110 two_finger_contacts_event,
111 max_finger_displacement_in_mm: self.max_finger_displacement_in_mm,
112 max_time_elapsed: self.max_time_elapsed,
113 })
114 }
115}
116
117impl gesture_arena::Contender for OneFingerContactContender {
118 fn examine_event(self: Box<Self>, event: &TouchpadEvent) -> ExamineEventResult {
119 let elapsed_time = event.timestamp - self.one_finger_contact_event.timestamp;
120 if elapsed_time >= self.max_time_elapsed {
121 return ExamineEventResult::Mismatch(Reason::DetailedInt(DetailedReasonInt {
122 criterion: "elapsed_time_micros",
123 min: None,
124 max: Some(self.max_time_elapsed.into_micros()),
125 actual: elapsed_time.into_micros(),
126 }));
127 }
128
129 let num_pressed_buttons = event.pressed_buttons.len();
130 if num_pressed_buttons != 0 {
131 return ExamineEventResult::Mismatch(Reason::DetailedUint(DetailedReasonUint {
132 criterion: "num_pressed_buttons",
133 min: Some(0),
134 max: Some(0),
135 actual: num_pressed_buttons,
136 }));
137 }
138
139 let num_contacts = event.contacts.len();
140 match num_contacts {
141 1 => {
142 let displacement_mm = euclidean_distance(
143 position_from_event(event, 0),
144 position_from_event(&self.one_finger_contact_event, 0),
145 );
146 if displacement_mm >= self.max_finger_displacement_in_mm {
147 return ExamineEventResult::Mismatch(Reason::DetailedFloat(
148 DetailedReasonFloat {
149 criterion: "displacement_mm",
150 min: None,
151 max: Some(self.max_finger_displacement_in_mm),
152 actual: displacement_mm,
153 },
154 ));
155 }
156 ExamineEventResult::Contender(self)
157 }
158 2 => {
159 let displacement_mm = euclidean_distance(
160 position_from_event(event, 0),
161 position_from_event(&self.one_finger_contact_event, 0),
162 );
163 if displacement_mm >= self.max_finger_displacement_in_mm {
164 return ExamineEventResult::Mismatch(Reason::DetailedFloat(
165 DetailedReasonFloat {
166 criterion: "displacement_mm",
167 min: None,
168 max: Some(self.max_finger_displacement_in_mm),
169 actual: displacement_mm,
170 },
171 ));
172 }
173 ExamineEventResult::Contender(
174 self.into_two_finger_contacts_contender(event.clone()),
175 )
176 }
177 0 | _ => ExamineEventResult::Mismatch(Reason::DetailedUint(DetailedReasonUint {
178 criterion: "num_contacts",
179 min: Some(1),
180 max: Some(2),
181 actual: num_contacts,
182 })),
183 }
184 }
185}
186
187#[derive(Debug)]
189struct TwoFingerContactsContender {
190 two_finger_contacts_event: TouchpadEvent,
192
193 max_finger_displacement_in_mm: f32,
196
197 max_time_elapsed: zx::MonotonicDuration,
200}
201
202impl TwoFingerContactsContender {
203 #[allow(clippy::boxed_local, reason = "mass allow for https://fxbug.dev/381896734")]
204 fn into_one_finger_raised_contender(self: Box<Self>) -> Box<dyn gesture_arena::Contender> {
205 Box::new(OneFingerRaisedContender {
206 two_finger_contacts_event: self.two_finger_contacts_event,
207 max_finger_displacement_in_mm: self.max_finger_displacement_in_mm,
208 max_time_elapsed: self.max_time_elapsed,
209 })
210 }
211
212 #[allow(clippy::boxed_local, reason = "mass allow for https://fxbug.dev/381896734")]
213 fn into_matched_contender(
214 self: Box<Self>,
215 no_contacts_event: TouchpadEvent,
216 ) -> Box<dyn gesture_arena::MatchedContender> {
217 Box::new(MatchedContender {
218 two_finger_contacts_event: self.two_finger_contacts_event,
219 no_contacts_event,
220 max_time_elapsed: self.max_time_elapsed,
221 })
222 }
223}
224
225impl gesture_arena::Contender for TwoFingerContactsContender {
226 fn examine_event(self: Box<Self>, event: &TouchpadEvent) -> ExamineEventResult {
227 let elapsed_time = event.timestamp - self.two_finger_contacts_event.timestamp;
228 if elapsed_time >= self.max_time_elapsed {
229 return ExamineEventResult::Mismatch(Reason::DetailedInt(DetailedReasonInt {
230 criterion: "elapsed_time_micros",
231 min: None,
232 max: Some(self.max_time_elapsed.into_micros()),
233 actual: elapsed_time.into_micros(),
234 }));
235 }
236
237 let num_pressed_buttons = event.pressed_buttons.len();
238 if num_pressed_buttons != 0 {
239 return ExamineEventResult::Mismatch(Reason::DetailedUint(DetailedReasonUint {
240 criterion: "num_pressed_buttons",
241 min: Some(0),
242 max: Some(0),
243 actual: num_pressed_buttons,
244 }));
245 }
246
247 let num_contacts = u8::try_from(event.contacts.len()).unwrap_or(u8::MAX);
248 match num_contacts {
249 0 => ExamineEventResult::MatchedContender(self.into_matched_contender(event.clone())),
250 1 => {
251 match &self
252 .two_finger_contacts_event
253 .clone()
254 .contacts
255 .into_iter()
256 .find(|contact| contact.id == event.contacts[0].id)
257 {
258 Some(contact) => {
259 let displacement_mm =
260 euclidean_distance(position_from_event(event, 0), contact.position);
261 if displacement_mm >= self.max_finger_displacement_in_mm {
262 return ExamineEventResult::Mismatch(Reason::DetailedFloat(
263 DetailedReasonFloat {
264 criterion: "displacement_mm",
265 min: None,
266 max: Some(self.max_finger_displacement_in_mm),
267 actual: displacement_mm,
268 },
269 ));
270 }
271 }
272 None => {
273 return ExamineEventResult::Mismatch(Reason::Basic(
274 "remaining contact id differs from initial two finger contacts",
275 ));
276 }
277 }
278
279 ExamineEventResult::Contender(self.into_one_finger_raised_contender())
280 }
281 2 => {
282 let displacement_mm = euclidean_distance(
284 position_from_event(event, 0),
285 position_from_event(&self.two_finger_contacts_event, 0),
286 );
287 if displacement_mm >= self.max_finger_displacement_in_mm {
288 return ExamineEventResult::Mismatch(Reason::DetailedFloat(
289 DetailedReasonFloat {
290 criterion: "displacement_mm",
291 min: None,
292 max: Some(self.max_finger_displacement_in_mm),
293 actual: displacement_mm,
294 },
295 ));
296 }
297
298 let displacement_mm = euclidean_distance(
300 position_from_event(event, 1),
301 position_from_event(&self.two_finger_contacts_event, 1),
302 );
303 if displacement_mm >= self.max_finger_displacement_in_mm {
304 return ExamineEventResult::Mismatch(Reason::DetailedFloat(
305 DetailedReasonFloat {
306 criterion: "displacement_mm",
307 min: None,
308 max: Some(self.max_finger_displacement_in_mm),
309 actual: displacement_mm,
310 },
311 ));
312 }
313
314 ExamineEventResult::Contender(self)
315 }
316 3.. => ExamineEventResult::Mismatch(Reason::DetailedUint(DetailedReasonUint {
317 criterion: "num_contacts",
318 min: Some(0),
319 max: Some(2),
320 actual: usize::from(num_contacts),
321 })),
322 }
323 }
324}
325
326#[derive(Debug)]
329struct OneFingerRaisedContender {
330 two_finger_contacts_event: TouchpadEvent,
332
333 max_finger_displacement_in_mm: f32,
336
337 max_time_elapsed: zx::MonotonicDuration,
340}
341
342impl OneFingerRaisedContender {
343 #[allow(clippy::boxed_local, reason = "mass allow for https://fxbug.dev/381896734")]
344 fn into_matched_contender(
345 self: Box<Self>,
346 no_contacts_event: TouchpadEvent,
347 ) -> Box<dyn gesture_arena::MatchedContender> {
348 Box::new(MatchedContender {
349 two_finger_contacts_event: self.two_finger_contacts_event,
350 no_contacts_event,
351 max_time_elapsed: self.max_time_elapsed,
352 })
353 }
354}
355
356impl gesture_arena::Contender for OneFingerRaisedContender {
357 fn examine_event(self: Box<Self>, event: &TouchpadEvent) -> ExamineEventResult {
358 let elapsed_time = event.timestamp - self.two_finger_contacts_event.timestamp;
359 if elapsed_time >= self.max_time_elapsed {
360 return ExamineEventResult::Mismatch(Reason::DetailedInt(DetailedReasonInt {
361 criterion: "elapsed_time_micros",
362 min: None,
363 max: Some(self.max_time_elapsed.into_micros()),
364 actual: elapsed_time.into_micros(),
365 }));
366 }
367
368 let num_pressed_buttons = event.pressed_buttons.len();
369 if num_pressed_buttons != 0 {
370 return ExamineEventResult::Mismatch(Reason::DetailedUint(DetailedReasonUint {
371 criterion: "num_pressed_buttons",
372 min: Some(0),
373 max: Some(0),
374 actual: num_pressed_buttons,
375 }));
376 }
377
378 let num_contacts = u8::try_from(event.contacts.len()).unwrap_or(u8::MAX);
379 match num_contacts {
380 0 => ExamineEventResult::MatchedContender(self.into_matched_contender(event.clone())),
381 1 => {
382 match &self
383 .two_finger_contacts_event
384 .clone()
385 .contacts
386 .into_iter()
387 .find(|contact| contact.id == event.contacts[0].id)
388 {
389 Some(contact) => {
390 let displacement_mm =
391 euclidean_distance(position_from_event(event, 0), contact.position);
392 if displacement_mm >= self.max_finger_displacement_in_mm {
393 return ExamineEventResult::Mismatch(Reason::DetailedFloat(
394 DetailedReasonFloat {
395 criterion: "displacement_mm",
396 min: None,
397 max: Some(self.max_finger_displacement_in_mm),
398 actual: displacement_mm,
399 },
400 ));
401 }
402 }
403 None => {
404 return ExamineEventResult::Mismatch(Reason::Basic(
405 "remaining contact id differs from initial two finger contacts",
406 ));
407 }
408 }
409
410 ExamineEventResult::Contender(self)
411 }
412 2.. => ExamineEventResult::Mismatch(Reason::DetailedUint(DetailedReasonUint {
413 criterion: "num_contacts",
414 min: Some(0),
415 max: Some(1),
416 actual: usize::from(num_contacts),
417 })),
418 }
419 }
420}
421
422#[derive(Debug)]
425struct MatchedContender {
426 two_finger_contacts_event: TouchpadEvent,
428
429 no_contacts_event: TouchpadEvent,
431
432 max_time_elapsed: zx::MonotonicDuration,
435}
436
437impl gesture_arena::MatchedContender for MatchedContender {
438 fn verify_event(self: Box<Self>, event: &TouchpadEvent) -> VerifyEventResult {
439 let elapsed_time = event.timestamp - self.two_finger_contacts_event.timestamp;
440 if elapsed_time >= self.max_time_elapsed {
441 return VerifyEventResult::Mismatch(Reason::DetailedInt(DetailedReasonInt {
442 criterion: "elapsed_time_micros",
443 min: None,
444 max: Some(self.max_time_elapsed.into_micros()),
445 actual: elapsed_time.into_micros(),
446 }));
447 }
448
449 let num_contacts = event.contacts.len();
450 if num_contacts != 0 {
451 return VerifyEventResult::Mismatch(Reason::DetailedUint(DetailedReasonUint {
452 criterion: "num_contacts",
453 min: Some(0),
454 max: Some(0),
455 actual: num_contacts,
456 }));
457 }
458
459 let num_pressed_buttons = event.pressed_buttons.len();
460 if num_pressed_buttons != 0 {
461 return VerifyEventResult::Mismatch(Reason::DetailedUint(DetailedReasonUint {
462 criterion: "num_pressed_buttons",
463 min: Some(0),
464 max: Some(0),
465 actual: num_pressed_buttons,
466 }));
467 }
468
469 VerifyEventResult::MatchedContender(self)
470 }
471
472 fn process_buffered_events(
473 self: Box<Self>,
474 _events: Vec<TouchpadEvent>,
475 ) -> ProcessBufferedEventsResult {
476 ProcessBufferedEventsResult {
477 generated_events: vec![
478 gesture_arena::MouseEvent {
479 timestamp: self.two_finger_contacts_event.timestamp,
480 mouse_data: MouseEvent {
481 location: MouseLocation::Relative(RelativeLocation {
482 millimeters: Position::zero(),
483 }),
484 wheel_delta_v: None,
485 wheel_delta_h: None,
486 phase: MousePhase::Down,
487 affected_buttons: hashset! {SECONDARY_BUTTON},
488 pressed_buttons: hashset! {SECONDARY_BUTTON},
489 is_precision_scroll: None,
490 },
491 },
492 gesture_arena::MouseEvent {
493 timestamp: self.no_contacts_event.timestamp,
494 mouse_data: MouseEvent {
495 location: MouseLocation::Relative(RelativeLocation {
496 millimeters: Position::zero(),
497 }),
498 wheel_delta_v: None,
499 wheel_delta_h: None,
500 phase: MousePhase::Up,
501 affected_buttons: hashset! {SECONDARY_BUTTON},
502 pressed_buttons: hashset! {},
503 is_precision_scroll: None,
504 },
505 },
506 ],
507 winner: None,
508 recognized_gesture: RecognizedGesture::SecondaryTap,
509 }
510 }
511}
512
513fn position_from_event(event: &TouchpadEvent, index: usize) -> Position {
516 event.contacts[index].position
517}
518
519#[cfg(test)]
520mod tests {
521 use super::*;
522 use crate::gestures::gesture_arena::{Contender, MatchedContender as _};
523 use crate::testing_utilities::create_touch_contact;
524 use assert_matches::assert_matches;
525 use std::any::TypeId;
526
527 const MAX_TIME_ELAPSED: zx::MonotonicDuration = zx::MonotonicDuration::from_nanos(10000);
528 const MAX_FINGER_DISPLACEMENT_IN_MM: f32 = 10.0;
529 const HALF_MOTION: f32 = MAX_FINGER_DISPLACEMENT_IN_MM / 2.0;
530
531 fn get_initial_contender() -> Box<InitialContender> {
532 Box::new(InitialContender {
533 max_finger_displacement_in_mm: MAX_FINGER_DISPLACEMENT_IN_MM,
534 max_time_elapsed: MAX_TIME_ELAPSED,
535 })
536 }
537
538 fn get_one_finger_contact_contender() -> Box<OneFingerContactContender> {
539 Box::new(OneFingerContactContender {
540 max_finger_displacement_in_mm: MAX_FINGER_DISPLACEMENT_IN_MM,
541 max_time_elapsed: MAX_TIME_ELAPSED,
542 one_finger_contact_event: TouchpadEvent {
543 contacts: vec![create_touch_contact(0, Position::zero())],
544 timestamp: zx::MonotonicInstant::from_nanos(0),
545 pressed_buttons: vec![],
546 filtered_palm_contacts: vec![],
547 },
548 })
549 }
550
551 fn get_two_finger_contacts_contender() -> Box<TwoFingerContactsContender> {
552 Box::new(TwoFingerContactsContender {
553 max_finger_displacement_in_mm: MAX_FINGER_DISPLACEMENT_IN_MM,
554 max_time_elapsed: MAX_TIME_ELAPSED,
555 two_finger_contacts_event: TouchpadEvent {
556 contacts: vec![
557 create_touch_contact(0, Position::zero()),
558 create_touch_contact(1, Position::zero()),
559 ],
560 timestamp: zx::MonotonicInstant::from_nanos(0),
561 pressed_buttons: vec![],
562 filtered_palm_contacts: vec![],
563 },
564 })
565 }
566
567 fn get_one_finger_raised_contender() -> Box<OneFingerRaisedContender> {
568 Box::new(OneFingerRaisedContender {
569 max_finger_displacement_in_mm: MAX_FINGER_DISPLACEMENT_IN_MM,
570 max_time_elapsed: MAX_TIME_ELAPSED,
571 two_finger_contacts_event: TouchpadEvent {
572 contacts: vec![
573 create_touch_contact(0, Position::zero()),
574 create_touch_contact(1, Position::zero()),
575 ],
576 timestamp: zx::MonotonicInstant::from_nanos(0),
577 pressed_buttons: vec![],
578 filtered_palm_contacts: vec![],
579 },
580 })
581 }
582
583 fn get_matched_contender() -> Box<MatchedContender> {
584 Box::new(MatchedContender {
585 two_finger_contacts_event: TouchpadEvent {
586 contacts: vec![
587 create_touch_contact(0, Position::zero()),
588 create_touch_contact(1, Position::zero()),
589 ],
590 timestamp: zx::MonotonicInstant::from_nanos(0),
591 pressed_buttons: vec![],
592 filtered_palm_contacts: vec![],
593 },
594 no_contacts_event: TouchpadEvent {
595 contacts: vec![],
596 timestamp: zx::MonotonicInstant::from_nanos(123),
597 pressed_buttons: vec![],
598 filtered_palm_contacts: vec![],
599 },
600 max_time_elapsed: MAX_TIME_ELAPSED,
601 })
602 }
603
604 fn assert_contender(result: ExamineEventResult, type_id: TypeId) {
605 match result {
606 ExamineEventResult::Contender(boxed) => {
607 assert_eq!((&*boxed).as_any().type_id(), type_id);
608 }
609 other => panic!("Expected a Contender but found {:?}", other),
610 }
611 }
612
613 fn assert_examined_matched_contender(result: ExamineEventResult) {
614 match result {
615 ExamineEventResult::MatchedContender(boxed) => {
616 assert_eq!((&*boxed).as_any().type_id(), TypeId::of::<MatchedContender>());
617 }
618 other => panic!("Expected a MatchedContender but found {:?}", other),
619 }
620 }
621
622 fn assert_verified_matched_contender(result: VerifyEventResult) {
623 match result {
624 VerifyEventResult::MatchedContender(boxed) => {
625 assert_eq!((&*boxed).as_any().type_id(), TypeId::of::<MatchedContender>());
626 }
627 other => panic!("Expected a MatchedContender but found {:?}", other),
628 }
629 }
630
631 #[fuchsia::test]
634 fn contender_single_button() {
635 assert_matches!(
636 get_initial_contender().examine_event(&TouchpadEvent {
637 contacts: vec![create_touch_contact(0, Position::zero())],
638 timestamp: zx::MonotonicInstant::from_nanos(0),
639 pressed_buttons: vec![0],
640 filtered_palm_contacts: vec![],
641 },),
642 ExamineEventResult::Mismatch(_)
643 );
644 }
645
646 #[fuchsia::test]
649 fn contender_many_buttons() {
650 assert_matches!(
651 get_initial_contender().examine_event(&TouchpadEvent {
652 contacts: vec![create_touch_contact(0, Position::zero())],
653 timestamp: zx::MonotonicInstant::from_nanos(0),
654 pressed_buttons: vec![0, 1],
655 filtered_palm_contacts: vec![],
656 },),
657 ExamineEventResult::Mismatch(_)
658 );
659 }
660
661 #[fuchsia::test]
664 fn contender_no_contacts() {
665 assert_matches!(
666 get_initial_contender().examine_event(&TouchpadEvent {
667 contacts: vec![],
668 timestamp: zx::MonotonicInstant::from_nanos(0),
669 pressed_buttons: vec![],
670 filtered_palm_contacts: vec![],
671 }),
672 ExamineEventResult::Mismatch(_)
673 );
674 }
675
676 #[fuchsia::test]
679 fn contender_one_contact() {
680 assert_contender(
681 get_initial_contender().examine_event(&TouchpadEvent {
682 contacts: vec![create_touch_contact(0, Position::zero())],
683 timestamp: zx::MonotonicInstant::from_nanos(0),
684 pressed_buttons: vec![],
685 filtered_palm_contacts: vec![],
686 }),
687 TypeId::of::<OneFingerContactContender>(),
688 );
689 }
690
691 #[fuchsia::test]
694 fn contender_two_contacts() {
695 assert_contender(
696 get_initial_contender().examine_event(&TouchpadEvent {
697 contacts: vec![
698 create_touch_contact(0, Position::zero()),
699 create_touch_contact(1, Position::zero()),
700 ],
701 timestamp: zx::MonotonicInstant::from_nanos(0),
702 pressed_buttons: vec![],
703 filtered_palm_contacts: vec![],
704 }),
705 TypeId::of::<TwoFingerContactsContender>(),
706 );
707 }
708
709 #[fuchsia::test]
712 fn contender_many_contacts() {
713 assert_matches!(
714 get_initial_contender().examine_event(&TouchpadEvent {
715 contacts: vec![
716 create_touch_contact(0, Position::zero()),
717 create_touch_contact(1, Position::zero()),
718 create_touch_contact(2, Position::zero())
719 ],
720 timestamp: zx::MonotonicInstant::from_nanos(0),
721 pressed_buttons: vec![],
722 filtered_palm_contacts: vec![],
723 }),
724 ExamineEventResult::Mismatch(_)
725 );
726 }
727
728 #[fuchsia::test]
731 fn one_finger_contact_contender_too_long() {
732 assert_matches!(
733 get_one_finger_contact_contender().examine_event(&TouchpadEvent {
734 contacts: vec![create_touch_contact(0, Position::zero()),],
735 timestamp: MAX_TIME_ELAPSED + zx::MonotonicInstant::from_nanos(1),
736 pressed_buttons: vec![],
737 filtered_palm_contacts: vec![],
738 }),
739 ExamineEventResult::Mismatch(_)
740 );
741 }
742
743 #[fuchsia::test]
746 fn one_finger_contact_contender_single_button() {
747 assert_matches!(
748 get_one_finger_contact_contender().examine_event(&TouchpadEvent {
749 contacts: vec![create_touch_contact(0, Position::zero())],
750 timestamp: zx::MonotonicInstant::from_nanos(0),
751 pressed_buttons: vec![0],
752 filtered_palm_contacts: vec![],
753 }),
754 ExamineEventResult::Mismatch(_)
755 );
756 }
757
758 #[fuchsia::test]
761 fn one_finger_contact_contender_many_buttons() {
762 assert_matches!(
763 get_one_finger_contact_contender().examine_event(&TouchpadEvent {
764 contacts: vec![create_touch_contact(0, Position::zero())],
765 timestamp: zx::MonotonicInstant::from_nanos(0),
766 pressed_buttons: vec![0, 1],
767 filtered_palm_contacts: vec![],
768 }),
769 ExamineEventResult::Mismatch(_)
770 );
771 }
772
773 #[fuchsia::test]
776 fn one_finger_contact_contender_no_contacts() {
777 assert_matches!(
778 get_one_finger_contact_contender().examine_event(&TouchpadEvent {
779 contacts: vec![],
780 timestamp: zx::MonotonicInstant::from_nanos(0),
781 pressed_buttons: vec![],
782 filtered_palm_contacts: vec![],
783 }),
784 ExamineEventResult::Mismatch(_)
785 );
786 }
787
788 #[fuchsia::test]
791 fn one_finger_contact_contender_many_touch_contacts() {
792 assert_matches!(
793 get_one_finger_contact_contender().examine_event(&TouchpadEvent {
794 contacts: vec![
795 create_touch_contact(0, Position::zero()),
796 create_touch_contact(1, Position::zero()),
797 create_touch_contact(2, Position::zero())
798 ],
799 timestamp: zx::MonotonicInstant::from_nanos(0),
800 pressed_buttons: vec![],
801 filtered_palm_contacts: vec![],
802 }),
803 ExamineEventResult::Mismatch(_)
804 );
805 }
806
807 #[fuchsia::test]
810 fn one_finger_contact_contender_one_contact() {
811 assert_contender(
812 get_one_finger_contact_contender().examine_event(&TouchpadEvent {
813 contacts: vec![create_touch_contact(0, Position::zero())],
814 timestamp: zx::MonotonicInstant::from_nanos(0),
815 pressed_buttons: vec![],
816 filtered_palm_contacts: vec![],
817 }),
818 TypeId::of::<OneFingerContactContender>(),
819 );
820 }
821
822 #[fuchsia::test]
825 fn one_finger_contact_contender_two_touch_contacts() {
826 assert_contender(
827 get_one_finger_contact_contender().examine_event(&TouchpadEvent {
828 contacts: vec![
829 create_touch_contact(0, Position::zero()),
830 create_touch_contact(1, Position::zero()),
831 ],
832 timestamp: zx::MonotonicInstant::from_nanos(0),
833 pressed_buttons: vec![],
834 filtered_palm_contacts: vec![],
835 }),
836 TypeId::of::<TwoFingerContactsContender>(),
837 );
838 }
839
840 #[fuchsia::test]
843 fn one_finger_contact_contender_one_contact_large_displacement() {
844 assert_matches!(
845 get_one_finger_contact_contender().examine_event(&TouchpadEvent {
846 contacts: vec![create_touch_contact(
847 0,
848 Position { x: MAX_FINGER_DISPLACEMENT_IN_MM, y: MAX_FINGER_DISPLACEMENT_IN_MM }
849 )],
850 timestamp: zx::MonotonicInstant::from_nanos(0),
851 pressed_buttons: vec![],
852 filtered_palm_contacts: vec![],
853 }),
854 ExamineEventResult::Mismatch(_)
855 );
856 }
857
858 #[fuchsia::test]
861 fn one_finger_contact_contender_two_contacts_large_displacement() {
862 assert_matches!(
863 get_one_finger_contact_contender().examine_event(&TouchpadEvent {
864 contacts: vec![
865 create_touch_contact(
866 0,
867 Position {
868 x: MAX_FINGER_DISPLACEMENT_IN_MM,
869 y: MAX_FINGER_DISPLACEMENT_IN_MM
870 }
871 ),
872 create_touch_contact(1, Position::zero())
873 ],
874 timestamp: zx::MonotonicInstant::from_nanos(0),
875 pressed_buttons: vec![],
876 filtered_palm_contacts: vec![],
877 }),
878 ExamineEventResult::Mismatch(_)
879 );
880 }
881
882 #[fuchsia::test]
885 fn one_finger_contact_contender_one_contact_some_displacement() {
886 assert_contender(
887 get_one_finger_contact_contender().examine_event(&TouchpadEvent {
888 contacts: vec![create_touch_contact(
889 0,
890 Position { x: HALF_MOTION, y: HALF_MOTION },
891 )],
892 timestamp: zx::MonotonicInstant::from_nanos(0),
893 pressed_buttons: vec![],
894 filtered_palm_contacts: vec![],
895 }),
896 TypeId::of::<OneFingerContactContender>(),
897 );
898 }
899
900 #[fuchsia::test]
903 fn one_finger_contact_contender_two_contacts_some_displacement() {
904 assert_contender(
905 get_one_finger_contact_contender().examine_event(&TouchpadEvent {
906 contacts: vec![
907 create_touch_contact(0, Position { x: HALF_MOTION, y: HALF_MOTION }),
908 create_touch_contact(1, Position::zero()),
909 ],
910 timestamp: zx::MonotonicInstant::from_nanos(0),
911 pressed_buttons: vec![],
912 filtered_palm_contacts: vec![],
913 }),
914 TypeId::of::<TwoFingerContactsContender>(),
915 );
916 }
917
918 #[fuchsia::test]
921 fn two_finger_contacts_contender_too_long() {
922 assert_matches!(
923 get_two_finger_contacts_contender().examine_event(&TouchpadEvent {
924 contacts: vec![],
925 timestamp: MAX_TIME_ELAPSED + zx::MonotonicInstant::from_nanos(1),
926 pressed_buttons: vec![],
927 filtered_palm_contacts: vec![],
928 }),
929 ExamineEventResult::Mismatch(_)
930 );
931 }
932
933 #[fuchsia::test]
936 fn two_finger_contacts_contender_single_button() {
937 assert_matches!(
938 get_two_finger_contacts_contender().examine_event(&TouchpadEvent {
939 contacts: vec![],
940 timestamp: zx::MonotonicInstant::from_nanos(0),
941 pressed_buttons: vec![0],
942 filtered_palm_contacts: vec![],
943 }),
944 ExamineEventResult::Mismatch(_)
945 );
946 }
947
948 #[fuchsia::test]
951 fn two_finger_contacts_contender_many_buttons() {
952 assert_matches!(
953 get_two_finger_contacts_contender().examine_event(&TouchpadEvent {
954 contacts: vec![],
955 timestamp: zx::MonotonicInstant::from_nanos(0),
956 pressed_buttons: vec![0, 1],
957 filtered_palm_contacts: vec![],
958 }),
959 ExamineEventResult::Mismatch(_)
960 );
961 }
962
963 #[fuchsia::test]
966 fn two_finger_contacts_contender_no_touch_contacts() {
967 assert_examined_matched_contender(get_two_finger_contacts_contender().examine_event(
968 &TouchpadEvent {
969 contacts: vec![],
970 timestamp: zx::MonotonicInstant::from_nanos(0),
971 pressed_buttons: vec![],
972 filtered_palm_contacts: vec![],
973 },
974 ));
975 }
976
977 #[fuchsia::test]
980 fn two_finger_contacts_contender_one_contact() {
981 assert_contender(
982 get_two_finger_contacts_contender().examine_event(&TouchpadEvent {
983 contacts: vec![create_touch_contact(0, Position::zero())],
984 timestamp: zx::MonotonicInstant::from_nanos(0),
985 pressed_buttons: vec![],
986 filtered_palm_contacts: vec![],
987 }),
988 TypeId::of::<OneFingerRaisedContender>(),
989 );
990 }
991
992 #[fuchsia::test]
995 fn two_finger_contacts_contender_one_contact_large_displacement() {
996 assert_matches!(
997 get_two_finger_contacts_contender().examine_event(&TouchpadEvent {
998 contacts: vec![create_touch_contact(
999 0,
1000 Position { x: MAX_FINGER_DISPLACEMENT_IN_MM, y: MAX_FINGER_DISPLACEMENT_IN_MM },
1001 )],
1002 timestamp: zx::MonotonicInstant::from_nanos(0),
1003 pressed_buttons: vec![],
1004 filtered_palm_contacts: vec![],
1005 }),
1006 ExamineEventResult::Mismatch(_)
1007 );
1008 }
1009
1010 #[fuchsia::test]
1013 fn two_finger_contacts_contender_many_touch_contacts() {
1014 assert_matches!(
1015 get_two_finger_contacts_contender().examine_event(&TouchpadEvent {
1016 contacts: vec![
1017 create_touch_contact(0, Position::zero()),
1018 create_touch_contact(1, Position::zero()),
1019 create_touch_contact(2, Position::zero())
1020 ],
1021 timestamp: zx::MonotonicInstant::from_nanos(0),
1022 pressed_buttons: vec![],
1023 filtered_palm_contacts: vec![],
1024 }),
1025 ExamineEventResult::Mismatch(_)
1026 );
1027 }
1028
1029 #[fuchsia::test]
1032 fn two_finger_contacts_contender_two_touch_contacts() {
1033 assert_contender(
1034 get_two_finger_contacts_contender().examine_event(&TouchpadEvent {
1035 contacts: vec![
1036 create_touch_contact(0, Position::zero()),
1037 create_touch_contact(1, Position::zero()),
1038 ],
1039 timestamp: zx::MonotonicInstant::from_nanos(0),
1040 pressed_buttons: vec![],
1041 filtered_palm_contacts: vec![],
1042 }),
1043 TypeId::of::<TwoFingerContactsContender>(),
1044 );
1045 }
1046
1047 #[fuchsia::test]
1050 fn two_finger_contacts_contender_two_contacts_large_displacement() {
1051 assert_matches!(
1052 get_two_finger_contacts_contender().examine_event(&TouchpadEvent {
1053 contacts: vec![
1054 create_touch_contact(
1055 0,
1056 Position {
1057 x: MAX_FINGER_DISPLACEMENT_IN_MM,
1058 y: MAX_FINGER_DISPLACEMENT_IN_MM
1059 }
1060 ),
1061 create_touch_contact(1, Position::zero())
1062 ],
1063 timestamp: zx::MonotonicInstant::from_nanos(0),
1064 pressed_buttons: vec![],
1065 filtered_palm_contacts: vec![],
1066 }),
1067 ExamineEventResult::Mismatch(_)
1068 );
1069
1070 assert_matches!(
1071 get_two_finger_contacts_contender().examine_event(&TouchpadEvent {
1072 contacts: vec![
1073 create_touch_contact(0, Position::zero()),
1074 create_touch_contact(
1075 1,
1076 Position {
1077 x: MAX_FINGER_DISPLACEMENT_IN_MM,
1078 y: MAX_FINGER_DISPLACEMENT_IN_MM
1079 }
1080 ),
1081 ],
1082 timestamp: zx::MonotonicInstant::from_nanos(0),
1083 pressed_buttons: vec![],
1084 filtered_palm_contacts: vec![],
1085 }),
1086 ExamineEventResult::Mismatch(_)
1087 );
1088 }
1089
1090 #[fuchsia::test]
1093 fn two_finger_contacts_contender_two_contacts_some_displacement() {
1094 assert_contender(
1095 get_two_finger_contacts_contender().examine_event(&TouchpadEvent {
1096 contacts: vec![
1097 create_touch_contact(0, Position::zero()),
1098 create_touch_contact(1, Position { x: HALF_MOTION, y: HALF_MOTION }),
1099 ],
1100 timestamp: zx::MonotonicInstant::from_nanos(0),
1101 pressed_buttons: vec![],
1102 filtered_palm_contacts: vec![],
1103 }),
1104 TypeId::of::<TwoFingerContactsContender>(),
1105 );
1106
1107 assert_contender(
1108 get_two_finger_contacts_contender().examine_event(&TouchpadEvent {
1109 contacts: vec![
1110 create_touch_contact(0, Position { x: HALF_MOTION, y: HALF_MOTION }),
1111 create_touch_contact(1, Position::zero()),
1112 ],
1113 timestamp: zx::MonotonicInstant::from_nanos(0),
1114 pressed_buttons: vec![],
1115 filtered_palm_contacts: vec![],
1116 }),
1117 TypeId::of::<TwoFingerContactsContender>(),
1118 );
1119
1120 assert_contender(
1121 get_two_finger_contacts_contender().examine_event(&TouchpadEvent {
1122 contacts: vec![
1123 create_touch_contact(0, Position { x: HALF_MOTION, y: HALF_MOTION }),
1124 create_touch_contact(1, Position { x: HALF_MOTION, y: HALF_MOTION }),
1125 ],
1126 timestamp: zx::MonotonicInstant::from_nanos(0),
1127 pressed_buttons: vec![],
1128 filtered_palm_contacts: vec![],
1129 }),
1130 TypeId::of::<TwoFingerContactsContender>(),
1131 );
1132 }
1133
1134 #[fuchsia::test]
1137 fn one_finger_raised_contender_too_long() {
1138 assert_matches!(
1139 get_one_finger_raised_contender().examine_event(&TouchpadEvent {
1140 contacts: vec![],
1141 timestamp: MAX_TIME_ELAPSED + zx::MonotonicInstant::from_nanos(1),
1142 pressed_buttons: vec![],
1143 filtered_palm_contacts: vec![],
1144 }),
1145 ExamineEventResult::Mismatch(_)
1146 );
1147 }
1148
1149 #[fuchsia::test]
1152 fn one_finger_raised_contender_single_button() {
1153 assert_matches!(
1154 get_one_finger_raised_contender().examine_event(&TouchpadEvent {
1155 contacts: vec![],
1156 timestamp: zx::MonotonicInstant::from_nanos(0),
1157 pressed_buttons: vec![0],
1158 filtered_palm_contacts: vec![],
1159 }),
1160 ExamineEventResult::Mismatch(_)
1161 );
1162 }
1163
1164 #[fuchsia::test]
1167 fn one_finger_raised_contender_many_buttons() {
1168 assert_matches!(
1169 get_one_finger_raised_contender().examine_event(&TouchpadEvent {
1170 contacts: vec![],
1171 timestamp: zx::MonotonicInstant::from_nanos(0),
1172 pressed_buttons: vec![0, 1],
1173 filtered_palm_contacts: vec![],
1174 }),
1175 ExamineEventResult::Mismatch(_)
1176 );
1177 }
1178
1179 #[fuchsia::test]
1182 fn one_finger_raised_contender_no_touch_contacts() {
1183 assert_examined_matched_contender(get_one_finger_raised_contender().examine_event(
1184 &TouchpadEvent {
1185 contacts: vec![],
1186 timestamp: zx::MonotonicInstant::from_nanos(0),
1187 pressed_buttons: vec![],
1188 filtered_palm_contacts: vec![],
1189 },
1190 ));
1191 }
1192
1193 #[fuchsia::test]
1197 fn one_finger_raised_contender_one_contact_first_id() {
1198 assert_contender(
1199 get_one_finger_raised_contender().examine_event(&TouchpadEvent {
1200 contacts: vec![create_touch_contact(0, Position::zero())],
1201 timestamp: zx::MonotonicInstant::from_nanos(0),
1202 pressed_buttons: vec![],
1203 filtered_palm_contacts: vec![],
1204 }),
1205 TypeId::of::<OneFingerRaisedContender>(),
1206 );
1207
1208 assert_contender(
1209 get_one_finger_raised_contender().examine_event(&TouchpadEvent {
1210 contacts: vec![create_touch_contact(
1211 0,
1212 Position { x: HALF_MOTION, y: HALF_MOTION },
1213 )],
1214 timestamp: zx::MonotonicInstant::from_nanos(0),
1215 pressed_buttons: vec![],
1216 filtered_palm_contacts: vec![],
1217 }),
1218 TypeId::of::<OneFingerRaisedContender>(),
1219 );
1220 }
1221
1222 #[fuchsia::test]
1226 fn one_finger_raised_contender_one_contact_second_id() {
1227 assert_contender(
1228 get_one_finger_raised_contender().examine_event(&TouchpadEvent {
1229 contacts: vec![create_touch_contact(1, Position::zero())],
1230 timestamp: zx::MonotonicInstant::from_nanos(0),
1231 pressed_buttons: vec![],
1232 filtered_palm_contacts: vec![],
1233 }),
1234 TypeId::of::<OneFingerRaisedContender>(),
1235 );
1236
1237 assert_contender(
1238 get_one_finger_raised_contender().examine_event(&TouchpadEvent {
1239 contacts: vec![create_touch_contact(
1240 1,
1241 Position { x: HALF_MOTION, y: HALF_MOTION },
1242 )],
1243 timestamp: zx::MonotonicInstant::from_nanos(0),
1244 pressed_buttons: vec![],
1245 filtered_palm_contacts: vec![],
1246 }),
1247 TypeId::of::<OneFingerRaisedContender>(),
1248 );
1249 }
1250
1251 #[fuchsia::test]
1255 fn one_finger_raised_contender_one_contact_invalid_id() {
1256 assert_matches!(
1257 get_one_finger_raised_contender().examine_event(&TouchpadEvent {
1258 contacts: vec![create_touch_contact(2, Position::zero(),)],
1259 timestamp: zx::MonotonicInstant::from_nanos(0),
1260 pressed_buttons: vec![],
1261 filtered_palm_contacts: vec![],
1262 }),
1263 ExamineEventResult::Mismatch(_)
1264 );
1265 }
1266
1267 #[fuchsia::test]
1270 fn one_finger_raised_contender_one_contact_large_displacement() {
1271 assert_matches!(
1272 get_one_finger_raised_contender().examine_event(&TouchpadEvent {
1273 contacts: vec![create_touch_contact(
1274 0,
1275 Position { x: MAX_FINGER_DISPLACEMENT_IN_MM, y: MAX_FINGER_DISPLACEMENT_IN_MM },
1276 )],
1277 timestamp: zx::MonotonicInstant::from_nanos(0),
1278 pressed_buttons: vec![],
1279 filtered_palm_contacts: vec![],
1280 }),
1281 ExamineEventResult::Mismatch(_)
1282 );
1283 }
1284
1285 #[fuchsia::test]
1288 fn one_finger_raised_contender_many_touch_contacts() {
1289 assert_matches!(
1290 get_one_finger_raised_contender().examine_event(&TouchpadEvent {
1291 contacts: vec![
1292 create_touch_contact(0, Position::zero()),
1293 create_touch_contact(1, Position::zero()),
1294 ],
1295 timestamp: zx::MonotonicInstant::from_nanos(0),
1296 pressed_buttons: vec![],
1297 filtered_palm_contacts: vec![],
1298 }),
1299 ExamineEventResult::Mismatch(_)
1300 );
1301 }
1302
1303 #[fuchsia::test]
1306 fn matched_contender_too_long() {
1307 assert_matches!(
1308 get_matched_contender().verify_event(&TouchpadEvent {
1309 contacts: vec![],
1310 timestamp: MAX_TIME_ELAPSED + zx::MonotonicInstant::from_nanos(1),
1311 pressed_buttons: vec![],
1312 filtered_palm_contacts: vec![],
1313 }),
1314 VerifyEventResult::Mismatch(_)
1315 );
1316 }
1317
1318 #[fuchsia::test]
1320 fn matched_contender_one_contact() {
1321 assert_matches!(
1322 get_matched_contender().verify_event(&TouchpadEvent {
1323 contacts: vec![create_touch_contact(0, Position::zero())],
1324 timestamp: zx::MonotonicInstant::from_nanos(0),
1325 pressed_buttons: vec![],
1326 filtered_palm_contacts: vec![],
1327 }),
1328 VerifyEventResult::Mismatch(_)
1329 );
1330 }
1331
1332 #[fuchsia::test]
1335 fn matched_contender_many_contacts() {
1336 assert_matches!(
1337 get_matched_contender().verify_event(&TouchpadEvent {
1338 contacts: vec![
1339 create_touch_contact(0, Position::zero()),
1340 create_touch_contact(1, Position::zero())
1341 ],
1342 timestamp: zx::MonotonicInstant::from_nanos(0),
1343 pressed_buttons: vec![],
1344 filtered_palm_contacts: vec![],
1345 }),
1346 VerifyEventResult::Mismatch(_)
1347 );
1348 }
1349
1350 #[fuchsia::test]
1352 fn matched_contender_one_button() {
1353 assert_matches!(
1354 get_matched_contender().verify_event(&TouchpadEvent {
1355 contacts: vec![],
1356 timestamp: zx::MonotonicInstant::from_nanos(0),
1357 pressed_buttons: vec![0],
1358 filtered_palm_contacts: vec![],
1359 }),
1360 VerifyEventResult::Mismatch(_)
1361 );
1362 }
1363
1364 #[fuchsia::test]
1367 fn matched_contender_many_buttons() {
1368 assert_matches!(
1369 get_matched_contender().verify_event(&TouchpadEvent {
1370 contacts: vec![],
1371 timestamp: zx::MonotonicInstant::from_nanos(0),
1372 pressed_buttons: vec![0, 1],
1373 filtered_palm_contacts: vec![],
1374 }),
1375 VerifyEventResult::Mismatch(_)
1376 );
1377 }
1378
1379 #[fuchsia::test]
1382 fn matched_contender_no_contacts() {
1383 assert_verified_matched_contender(get_matched_contender().verify_event(&TouchpadEvent {
1384 contacts: vec![],
1385 timestamp: zx::MonotonicInstant::from_nanos(0),
1386 pressed_buttons: vec![],
1387 filtered_palm_contacts: vec![],
1388 }));
1389 }
1390
1391 #[fuchsia::test]
1394 fn matched_contender_process_buffered_events() {
1395 let ProcessBufferedEventsResult { generated_events, winner, recognized_gesture } =
1396 get_matched_contender().process_buffered_events(vec![]);
1397
1398 assert_eq!(
1399 generated_events,
1400 [
1401 gesture_arena::MouseEvent {
1402 timestamp: zx::MonotonicInstant::from_nanos(0),
1403 mouse_data: MouseEvent {
1404 location: MouseLocation::Relative(RelativeLocation {
1405 millimeters: Position { x: 0.0, y: 0.0 }
1406 }),
1407 wheel_delta_v: None,
1408 wheel_delta_h: None,
1409 phase: MousePhase::Down,
1410 affected_buttons: hashset! {SECONDARY_BUTTON},
1411 pressed_buttons: hashset! {SECONDARY_BUTTON},
1412 is_precision_scroll: None,
1413 },
1414 },
1415 gesture_arena::MouseEvent {
1416 timestamp: zx::MonotonicInstant::from_nanos(123),
1417 mouse_data: MouseEvent {
1418 location: MouseLocation::Relative(RelativeLocation {
1419 millimeters: Position { x: 0.0, y: 0.0 }
1420 }),
1421 wheel_delta_v: None,
1422 wheel_delta_h: None,
1423 phase: MousePhase::Up,
1424 affected_buttons: hashset! {SECONDARY_BUTTON},
1425 pressed_buttons: hashset! {},
1426 is_precision_scroll: None,
1427 },
1428 }
1429 ]
1430 );
1431 assert_matches!(winner, None);
1432 assert_eq!(recognized_gesture, RecognizedGesture::SecondaryTap);
1433 }
1434}