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