use super::gesture_arena::{
self, DetailedReasonFloat, DetailedReasonInt, DetailedReasonUint, ExamineEventResult,
ProcessBufferedEventsResult, Reason, RecognizedGesture, TouchpadEvent, VerifyEventResult,
SECONDARY_BUTTON,
};
use crate::mouse_binding::{MouseEvent, MouseLocation, MousePhase, RelativeLocation};
use crate::utils::{euclidean_distance, Position};
use maplit::hashset;
#[derive(Debug)]
pub(super) struct InitialContender {
pub(super) max_finger_displacement_in_mm: f32,
pub(super) max_time_elapsed: zx::MonotonicDuration,
}
impl InitialContender {
#[allow(clippy::boxed_local, reason = "mass allow for https://fxbug.dev/381896734")]
fn into_one_finger_contact_contender(
self: Box<Self>,
one_finger_contact_event: TouchpadEvent,
) -> Box<dyn gesture_arena::Contender> {
Box::new(OneFingerContactContender {
one_finger_contact_event,
max_finger_displacement_in_mm: self.max_finger_displacement_in_mm,
max_time_elapsed: self.max_time_elapsed,
})
}
#[allow(clippy::boxed_local, reason = "mass allow for https://fxbug.dev/381896734")]
fn into_two_finger_contacts_contender(
self: Box<Self>,
two_finger_contacts_event: TouchpadEvent,
) -> Box<dyn gesture_arena::Contender> {
Box::new(TwoFingerContactsContender {
two_finger_contacts_event,
max_finger_displacement_in_mm: self.max_finger_displacement_in_mm,
max_time_elapsed: self.max_time_elapsed,
})
}
}
impl gesture_arena::Contender for InitialContender {
fn examine_event(self: Box<Self>, event: &TouchpadEvent) -> ExamineEventResult {
let num_pressed_buttons = event.pressed_buttons.len();
if num_pressed_buttons != 0 {
return ExamineEventResult::Mismatch(Reason::DetailedUint(DetailedReasonUint {
criterion: "num_pressed_buttons",
min: Some(0),
max: Some(0),
actual: num_pressed_buttons,
}));
}
let num_contacts = event.contacts.len();
match num_contacts {
1 => {
ExamineEventResult::Contender(self.into_one_finger_contact_contender(event.clone()))
}
2 => ExamineEventResult::Contender(
self.into_two_finger_contacts_contender(event.clone()),
),
0 | _ => ExamineEventResult::Mismatch(Reason::DetailedUint(DetailedReasonUint {
criterion: "num_contacts",
min: Some(1),
max: Some(2),
actual: num_contacts,
})),
}
}
fn start_from_idle(&self) -> bool {
true
}
}
#[derive(Debug)]
struct OneFingerContactContender {
one_finger_contact_event: TouchpadEvent,
max_finger_displacement_in_mm: f32,
max_time_elapsed: zx::MonotonicDuration,
}
impl OneFingerContactContender {
#[allow(clippy::boxed_local, reason = "mass allow for https://fxbug.dev/381896734")]
fn into_two_finger_contacts_contender(
self: Box<Self>,
two_finger_contacts_event: TouchpadEvent,
) -> Box<dyn gesture_arena::Contender> {
Box::new(TwoFingerContactsContender {
two_finger_contacts_event,
max_finger_displacement_in_mm: self.max_finger_displacement_in_mm,
max_time_elapsed: self.max_time_elapsed,
})
}
}
impl gesture_arena::Contender for OneFingerContactContender {
fn examine_event(self: Box<Self>, event: &TouchpadEvent) -> ExamineEventResult {
let elapsed_time = event.timestamp - self.one_finger_contact_event.timestamp;
if elapsed_time >= self.max_time_elapsed {
return ExamineEventResult::Mismatch(Reason::DetailedInt(DetailedReasonInt {
criterion: "elapsed_time_micros",
min: None,
max: Some(self.max_time_elapsed.into_micros()),
actual: elapsed_time.into_micros(),
}));
}
let num_pressed_buttons = event.pressed_buttons.len();
if num_pressed_buttons != 0 {
return ExamineEventResult::Mismatch(Reason::DetailedUint(DetailedReasonUint {
criterion: "num_pressed_buttons",
min: Some(0),
max: Some(0),
actual: num_pressed_buttons,
}));
}
let num_contacts = event.contacts.len();
match num_contacts {
1 => {
let displacement_mm = euclidean_distance(
position_from_event(event, 0),
position_from_event(&self.one_finger_contact_event, 0),
);
if displacement_mm >= self.max_finger_displacement_in_mm {
return ExamineEventResult::Mismatch(Reason::DetailedFloat(
DetailedReasonFloat {
criterion: "displacement_mm",
min: None,
max: Some(self.max_finger_displacement_in_mm),
actual: displacement_mm,
},
));
}
ExamineEventResult::Contender(self)
}
2 => {
let displacement_mm = euclidean_distance(
position_from_event(event, 0),
position_from_event(&self.one_finger_contact_event, 0),
);
if displacement_mm >= self.max_finger_displacement_in_mm {
return ExamineEventResult::Mismatch(Reason::DetailedFloat(
DetailedReasonFloat {
criterion: "displacement_mm",
min: None,
max: Some(self.max_finger_displacement_in_mm),
actual: displacement_mm,
},
));
}
ExamineEventResult::Contender(
self.into_two_finger_contacts_contender(event.clone()),
)
}
0 | _ => ExamineEventResult::Mismatch(Reason::DetailedUint(DetailedReasonUint {
criterion: "num_contacts",
min: Some(1),
max: Some(2),
actual: num_contacts,
})),
}
}
}
#[derive(Debug)]
struct TwoFingerContactsContender {
two_finger_contacts_event: TouchpadEvent,
max_finger_displacement_in_mm: f32,
max_time_elapsed: zx::MonotonicDuration,
}
impl TwoFingerContactsContender {
#[allow(clippy::boxed_local, reason = "mass allow for https://fxbug.dev/381896734")]
fn into_one_finger_raised_contender(self: Box<Self>) -> Box<dyn gesture_arena::Contender> {
Box::new(OneFingerRaisedContender {
two_finger_contacts_event: self.two_finger_contacts_event,
max_finger_displacement_in_mm: self.max_finger_displacement_in_mm,
max_time_elapsed: self.max_time_elapsed,
})
}
#[allow(clippy::boxed_local, reason = "mass allow for https://fxbug.dev/381896734")]
fn into_matched_contender(
self: Box<Self>,
no_contacts_event: TouchpadEvent,
) -> Box<dyn gesture_arena::MatchedContender> {
Box::new(MatchedContender {
two_finger_contacts_event: self.two_finger_contacts_event,
no_contacts_event,
max_time_elapsed: self.max_time_elapsed,
})
}
}
impl gesture_arena::Contender for TwoFingerContactsContender {
fn examine_event(self: Box<Self>, event: &TouchpadEvent) -> ExamineEventResult {
let elapsed_time = event.timestamp - self.two_finger_contacts_event.timestamp;
if elapsed_time >= self.max_time_elapsed {
return ExamineEventResult::Mismatch(Reason::DetailedInt(DetailedReasonInt {
criterion: "elapsed_time_micros",
min: None,
max: Some(self.max_time_elapsed.into_micros()),
actual: elapsed_time.into_micros(),
}));
}
let num_pressed_buttons = event.pressed_buttons.len();
if num_pressed_buttons != 0 {
return ExamineEventResult::Mismatch(Reason::DetailedUint(DetailedReasonUint {
criterion: "num_pressed_buttons",
min: Some(0),
max: Some(0),
actual: num_pressed_buttons,
}));
}
let num_contacts = u8::try_from(event.contacts.len()).unwrap_or(u8::MAX);
match num_contacts {
0 => ExamineEventResult::MatchedContender(self.into_matched_contender(event.clone())),
1 => {
match &self
.two_finger_contacts_event
.clone()
.contacts
.into_iter()
.find(|contact| contact.id == event.contacts[0].id)
{
Some(contact) => {
let displacement_mm =
euclidean_distance(position_from_event(event, 0), contact.position);
if displacement_mm >= self.max_finger_displacement_in_mm {
return ExamineEventResult::Mismatch(Reason::DetailedFloat(
DetailedReasonFloat {
criterion: "displacement_mm",
min: None,
max: Some(self.max_finger_displacement_in_mm),
actual: displacement_mm,
},
));
}
}
None => {
return ExamineEventResult::Mismatch(Reason::Basic(
"remaining contact id differs from initial two finger contacts",
));
}
}
ExamineEventResult::Contender(self.into_one_finger_raised_contender())
}
2 => {
let displacement_mm = euclidean_distance(
position_from_event(event, 0),
position_from_event(&self.two_finger_contacts_event, 0),
);
if displacement_mm >= self.max_finger_displacement_in_mm {
return ExamineEventResult::Mismatch(Reason::DetailedFloat(
DetailedReasonFloat {
criterion: "displacement_mm",
min: None,
max: Some(self.max_finger_displacement_in_mm),
actual: displacement_mm,
},
));
}
let displacement_mm = euclidean_distance(
position_from_event(event, 1),
position_from_event(&self.two_finger_contacts_event, 1),
);
if displacement_mm >= self.max_finger_displacement_in_mm {
return ExamineEventResult::Mismatch(Reason::DetailedFloat(
DetailedReasonFloat {
criterion: "displacement_mm",
min: None,
max: Some(self.max_finger_displacement_in_mm),
actual: displacement_mm,
},
));
}
ExamineEventResult::Contender(self)
}
3.. => ExamineEventResult::Mismatch(Reason::DetailedUint(DetailedReasonUint {
criterion: "num_contacts",
min: Some(0),
max: Some(2),
actual: usize::from(num_contacts),
})),
}
}
}
#[derive(Debug)]
struct OneFingerRaisedContender {
two_finger_contacts_event: TouchpadEvent,
max_finger_displacement_in_mm: f32,
max_time_elapsed: zx::MonotonicDuration,
}
impl OneFingerRaisedContender {
#[allow(clippy::boxed_local, reason = "mass allow for https://fxbug.dev/381896734")]
fn into_matched_contender(
self: Box<Self>,
no_contacts_event: TouchpadEvent,
) -> Box<dyn gesture_arena::MatchedContender> {
Box::new(MatchedContender {
two_finger_contacts_event: self.two_finger_contacts_event,
no_contacts_event,
max_time_elapsed: self.max_time_elapsed,
})
}
}
impl gesture_arena::Contender for OneFingerRaisedContender {
fn examine_event(self: Box<Self>, event: &TouchpadEvent) -> ExamineEventResult {
let elapsed_time = event.timestamp - self.two_finger_contacts_event.timestamp;
if elapsed_time >= self.max_time_elapsed {
return ExamineEventResult::Mismatch(Reason::DetailedInt(DetailedReasonInt {
criterion: "elapsed_time_micros",
min: None,
max: Some(self.max_time_elapsed.into_micros()),
actual: elapsed_time.into_micros(),
}));
}
let num_pressed_buttons = event.pressed_buttons.len();
if num_pressed_buttons != 0 {
return ExamineEventResult::Mismatch(Reason::DetailedUint(DetailedReasonUint {
criterion: "num_pressed_buttons",
min: Some(0),
max: Some(0),
actual: num_pressed_buttons,
}));
}
let num_contacts = u8::try_from(event.contacts.len()).unwrap_or(u8::MAX);
match num_contacts {
0 => ExamineEventResult::MatchedContender(self.into_matched_contender(event.clone())),
1 => {
match &self
.two_finger_contacts_event
.clone()
.contacts
.into_iter()
.find(|contact| contact.id == event.contacts[0].id)
{
Some(contact) => {
let displacement_mm =
euclidean_distance(position_from_event(event, 0), contact.position);
if displacement_mm >= self.max_finger_displacement_in_mm {
return ExamineEventResult::Mismatch(Reason::DetailedFloat(
DetailedReasonFloat {
criterion: "displacement_mm",
min: None,
max: Some(self.max_finger_displacement_in_mm),
actual: displacement_mm,
},
));
}
}
None => {
return ExamineEventResult::Mismatch(Reason::Basic(
"remaining contact id differs from initial two finger contacts",
));
}
}
ExamineEventResult::Contender(self)
}
2.. => ExamineEventResult::Mismatch(Reason::DetailedUint(DetailedReasonUint {
criterion: "num_contacts",
min: Some(0),
max: Some(1),
actual: usize::from(num_contacts),
})),
}
}
}
#[derive(Debug)]
struct MatchedContender {
two_finger_contacts_event: TouchpadEvent,
no_contacts_event: TouchpadEvent,
max_time_elapsed: zx::MonotonicDuration,
}
impl gesture_arena::MatchedContender for MatchedContender {
fn verify_event(self: Box<Self>, event: &TouchpadEvent) -> VerifyEventResult {
let elapsed_time = event.timestamp - self.two_finger_contacts_event.timestamp;
if elapsed_time >= self.max_time_elapsed {
return VerifyEventResult::Mismatch(Reason::DetailedInt(DetailedReasonInt {
criterion: "elapsed_time_micros",
min: None,
max: Some(self.max_time_elapsed.into_micros()),
actual: elapsed_time.into_micros(),
}));
}
let num_contacts = event.contacts.len();
if num_contacts != 0 {
return VerifyEventResult::Mismatch(Reason::DetailedUint(DetailedReasonUint {
criterion: "num_contacts",
min: Some(0),
max: Some(0),
actual: num_contacts,
}));
}
let num_pressed_buttons = event.pressed_buttons.len();
if num_pressed_buttons != 0 {
return VerifyEventResult::Mismatch(Reason::DetailedUint(DetailedReasonUint {
criterion: "num_pressed_buttons",
min: Some(0),
max: Some(0),
actual: num_pressed_buttons,
}));
}
VerifyEventResult::MatchedContender(self)
}
fn process_buffered_events(
self: Box<Self>,
_events: Vec<TouchpadEvent>,
) -> ProcessBufferedEventsResult {
ProcessBufferedEventsResult {
generated_events: vec![
gesture_arena::MouseEvent {
timestamp: self.two_finger_contacts_event.timestamp,
mouse_data: MouseEvent {
location: MouseLocation::Relative(RelativeLocation {
millimeters: Position::zero(),
}),
wheel_delta_v: None,
wheel_delta_h: None,
phase: MousePhase::Down,
affected_buttons: hashset! {SECONDARY_BUTTON},
pressed_buttons: hashset! {SECONDARY_BUTTON},
is_precision_scroll: None,
},
},
gesture_arena::MouseEvent {
timestamp: self.no_contacts_event.timestamp,
mouse_data: MouseEvent {
location: MouseLocation::Relative(RelativeLocation {
millimeters: Position::zero(),
}),
wheel_delta_v: None,
wheel_delta_h: None,
phase: MousePhase::Up,
affected_buttons: hashset! {SECONDARY_BUTTON},
pressed_buttons: hashset! {},
is_precision_scroll: None,
},
},
],
winner: None,
recognized_gesture: RecognizedGesture::SecondaryTap,
}
}
}
fn position_from_event(event: &TouchpadEvent, index: usize) -> Position {
event.contacts[index].position
}
#[cfg(test)]
mod tests {
use super::*;
use crate::gestures::gesture_arena::{Contender, MatchedContender as _};
use crate::testing_utilities::create_touch_contact;
use assert_matches::assert_matches;
use std::any::TypeId;
const MAX_TIME_ELAPSED: zx::MonotonicDuration = zx::MonotonicDuration::from_nanos(10000);
const MAX_FINGER_DISPLACEMENT_IN_MM: f32 = 10.0;
const HALF_MOTION: f32 = MAX_FINGER_DISPLACEMENT_IN_MM / 2.0;
fn get_initial_contender() -> Box<InitialContender> {
Box::new(InitialContender {
max_finger_displacement_in_mm: MAX_FINGER_DISPLACEMENT_IN_MM,
max_time_elapsed: MAX_TIME_ELAPSED,
})
}
fn get_one_finger_contact_contender() -> Box<OneFingerContactContender> {
Box::new(OneFingerContactContender {
max_finger_displacement_in_mm: MAX_FINGER_DISPLACEMENT_IN_MM,
max_time_elapsed: MAX_TIME_ELAPSED,
one_finger_contact_event: TouchpadEvent {
contacts: vec![create_touch_contact(0, Position::zero())],
timestamp: zx::MonotonicInstant::from_nanos(0),
pressed_buttons: vec![],
filtered_palm_contacts: vec![],
},
})
}
fn get_two_finger_contacts_contender() -> Box<TwoFingerContactsContender> {
Box::new(TwoFingerContactsContender {
max_finger_displacement_in_mm: MAX_FINGER_DISPLACEMENT_IN_MM,
max_time_elapsed: MAX_TIME_ELAPSED,
two_finger_contacts_event: TouchpadEvent {
contacts: vec![
create_touch_contact(0, Position::zero()),
create_touch_contact(1, Position::zero()),
],
timestamp: zx::MonotonicInstant::from_nanos(0),
pressed_buttons: vec![],
filtered_palm_contacts: vec![],
},
})
}
fn get_one_finger_raised_contender() -> Box<OneFingerRaisedContender> {
Box::new(OneFingerRaisedContender {
max_finger_displacement_in_mm: MAX_FINGER_DISPLACEMENT_IN_MM,
max_time_elapsed: MAX_TIME_ELAPSED,
two_finger_contacts_event: TouchpadEvent {
contacts: vec![
create_touch_contact(0, Position::zero()),
create_touch_contact(1, Position::zero()),
],
timestamp: zx::MonotonicInstant::from_nanos(0),
pressed_buttons: vec![],
filtered_palm_contacts: vec![],
},
})
}
fn get_matched_contender() -> Box<MatchedContender> {
Box::new(MatchedContender {
two_finger_contacts_event: TouchpadEvent {
contacts: vec![
create_touch_contact(0, Position::zero()),
create_touch_contact(1, Position::zero()),
],
timestamp: zx::MonotonicInstant::from_nanos(0),
pressed_buttons: vec![],
filtered_palm_contacts: vec![],
},
no_contacts_event: TouchpadEvent {
contacts: vec![],
timestamp: zx::MonotonicInstant::from_nanos(123),
pressed_buttons: vec![],
filtered_palm_contacts: vec![],
},
max_time_elapsed: MAX_TIME_ELAPSED,
})
}
fn assert_contender(result: ExamineEventResult, type_id: TypeId) {
match result {
ExamineEventResult::Contender(boxed) => {
assert_eq!((&*boxed).as_any().type_id(), type_id);
}
other => panic!("Expected a Contender but found {:?}", other),
}
}
fn assert_examined_matched_contender(result: ExamineEventResult) {
match result {
ExamineEventResult::MatchedContender(boxed) => {
assert_eq!((&*boxed).as_any().type_id(), TypeId::of::<MatchedContender>());
}
other => panic!("Expected a MatchedContender but found {:?}", other),
}
}
fn assert_verified_matched_contender(result: VerifyEventResult) {
match result {
VerifyEventResult::MatchedContender(boxed) => {
assert_eq!((&*boxed).as_any().type_id(), TypeId::of::<MatchedContender>());
}
other => panic!("Expected a MatchedContender but found {:?}", other),
}
}
#[fuchsia::test]
fn contender_single_button() {
assert_matches!(
get_initial_contender().examine_event(&TouchpadEvent {
contacts: vec![create_touch_contact(0, Position::zero())],
timestamp: zx::MonotonicInstant::from_nanos(0),
pressed_buttons: vec![0],
filtered_palm_contacts: vec![],
},),
ExamineEventResult::Mismatch(_)
);
}
#[fuchsia::test]
fn contender_many_buttons() {
assert_matches!(
get_initial_contender().examine_event(&TouchpadEvent {
contacts: vec![create_touch_contact(0, Position::zero())],
timestamp: zx::MonotonicInstant::from_nanos(0),
pressed_buttons: vec![0, 1],
filtered_palm_contacts: vec![],
},),
ExamineEventResult::Mismatch(_)
);
}
#[fuchsia::test]
fn contender_no_contacts() {
assert_matches!(
get_initial_contender().examine_event(&TouchpadEvent {
contacts: vec![],
timestamp: zx::MonotonicInstant::from_nanos(0),
pressed_buttons: vec![],
filtered_palm_contacts: vec![],
}),
ExamineEventResult::Mismatch(_)
);
}
#[fuchsia::test]
fn contender_one_contact() {
assert_contender(
get_initial_contender().examine_event(&TouchpadEvent {
contacts: vec![create_touch_contact(0, Position::zero())],
timestamp: zx::MonotonicInstant::from_nanos(0),
pressed_buttons: vec![],
filtered_palm_contacts: vec![],
}),
TypeId::of::<OneFingerContactContender>(),
);
}
#[fuchsia::test]
fn contender_two_contacts() {
assert_contender(
get_initial_contender().examine_event(&TouchpadEvent {
contacts: vec![
create_touch_contact(0, Position::zero()),
create_touch_contact(1, Position::zero()),
],
timestamp: zx::MonotonicInstant::from_nanos(0),
pressed_buttons: vec![],
filtered_palm_contacts: vec![],
}),
TypeId::of::<TwoFingerContactsContender>(),
);
}
#[fuchsia::test]
fn contender_many_contacts() {
assert_matches!(
get_initial_contender().examine_event(&TouchpadEvent {
contacts: vec![
create_touch_contact(0, Position::zero()),
create_touch_contact(1, Position::zero()),
create_touch_contact(2, Position::zero())
],
timestamp: zx::MonotonicInstant::from_nanos(0),
pressed_buttons: vec![],
filtered_palm_contacts: vec![],
}),
ExamineEventResult::Mismatch(_)
);
}
#[fuchsia::test]
fn one_finger_contact_contender_too_long() {
assert_matches!(
get_one_finger_contact_contender().examine_event(&TouchpadEvent {
contacts: vec![create_touch_contact(0, Position::zero()),],
timestamp: MAX_TIME_ELAPSED + zx::MonotonicInstant::from_nanos(1),
pressed_buttons: vec![],
filtered_palm_contacts: vec![],
}),
ExamineEventResult::Mismatch(_)
);
}
#[fuchsia::test]
fn one_finger_contact_contender_single_button() {
assert_matches!(
get_one_finger_contact_contender().examine_event(&TouchpadEvent {
contacts: vec![create_touch_contact(0, Position::zero())],
timestamp: zx::MonotonicInstant::from_nanos(0),
pressed_buttons: vec![0],
filtered_palm_contacts: vec![],
}),
ExamineEventResult::Mismatch(_)
);
}
#[fuchsia::test]
fn one_finger_contact_contender_many_buttons() {
assert_matches!(
get_one_finger_contact_contender().examine_event(&TouchpadEvent {
contacts: vec![create_touch_contact(0, Position::zero())],
timestamp: zx::MonotonicInstant::from_nanos(0),
pressed_buttons: vec![0, 1],
filtered_palm_contacts: vec![],
}),
ExamineEventResult::Mismatch(_)
);
}
#[fuchsia::test]
fn one_finger_contact_contender_no_contacts() {
assert_matches!(
get_one_finger_contact_contender().examine_event(&TouchpadEvent {
contacts: vec![],
timestamp: zx::MonotonicInstant::from_nanos(0),
pressed_buttons: vec![],
filtered_palm_contacts: vec![],
}),
ExamineEventResult::Mismatch(_)
);
}
#[fuchsia::test]
fn one_finger_contact_contender_many_touch_contacts() {
assert_matches!(
get_one_finger_contact_contender().examine_event(&TouchpadEvent {
contacts: vec![
create_touch_contact(0, Position::zero()),
create_touch_contact(1, Position::zero()),
create_touch_contact(2, Position::zero())
],
timestamp: zx::MonotonicInstant::from_nanos(0),
pressed_buttons: vec![],
filtered_palm_contacts: vec![],
}),
ExamineEventResult::Mismatch(_)
);
}
#[fuchsia::test]
fn one_finger_contact_contender_one_contact() {
assert_contender(
get_one_finger_contact_contender().examine_event(&TouchpadEvent {
contacts: vec![create_touch_contact(0, Position::zero())],
timestamp: zx::MonotonicInstant::from_nanos(0),
pressed_buttons: vec![],
filtered_palm_contacts: vec![],
}),
TypeId::of::<OneFingerContactContender>(),
);
}
#[fuchsia::test]
fn one_finger_contact_contender_two_touch_contacts() {
assert_contender(
get_one_finger_contact_contender().examine_event(&TouchpadEvent {
contacts: vec![
create_touch_contact(0, Position::zero()),
create_touch_contact(1, Position::zero()),
],
timestamp: zx::MonotonicInstant::from_nanos(0),
pressed_buttons: vec![],
filtered_palm_contacts: vec![],
}),
TypeId::of::<TwoFingerContactsContender>(),
);
}
#[fuchsia::test]
fn one_finger_contact_contender_one_contact_large_displacement() {
assert_matches!(
get_one_finger_contact_contender().examine_event(&TouchpadEvent {
contacts: vec![create_touch_contact(
0,
Position { x: MAX_FINGER_DISPLACEMENT_IN_MM, y: MAX_FINGER_DISPLACEMENT_IN_MM }
)],
timestamp: zx::MonotonicInstant::from_nanos(0),
pressed_buttons: vec![],
filtered_palm_contacts: vec![],
}),
ExamineEventResult::Mismatch(_)
);
}
#[fuchsia::test]
fn one_finger_contact_contender_two_contacts_large_displacement() {
assert_matches!(
get_one_finger_contact_contender().examine_event(&TouchpadEvent {
contacts: vec![
create_touch_contact(
0,
Position {
x: MAX_FINGER_DISPLACEMENT_IN_MM,
y: MAX_FINGER_DISPLACEMENT_IN_MM
}
),
create_touch_contact(1, Position::zero())
],
timestamp: zx::MonotonicInstant::from_nanos(0),
pressed_buttons: vec![],
filtered_palm_contacts: vec![],
}),
ExamineEventResult::Mismatch(_)
);
}
#[fuchsia::test]
fn one_finger_contact_contender_one_contact_some_displacement() {
assert_contender(
get_one_finger_contact_contender().examine_event(&TouchpadEvent {
contacts: vec![create_touch_contact(
0,
Position { x: HALF_MOTION, y: HALF_MOTION },
)],
timestamp: zx::MonotonicInstant::from_nanos(0),
pressed_buttons: vec![],
filtered_palm_contacts: vec![],
}),
TypeId::of::<OneFingerContactContender>(),
);
}
#[fuchsia::test]
fn one_finger_contact_contender_two_contacts_some_displacement() {
assert_contender(
get_one_finger_contact_contender().examine_event(&TouchpadEvent {
contacts: vec![
create_touch_contact(0, Position { x: HALF_MOTION, y: HALF_MOTION }),
create_touch_contact(1, Position::zero()),
],
timestamp: zx::MonotonicInstant::from_nanos(0),
pressed_buttons: vec![],
filtered_palm_contacts: vec![],
}),
TypeId::of::<TwoFingerContactsContender>(),
);
}
#[fuchsia::test]
fn two_finger_contacts_contender_too_long() {
assert_matches!(
get_two_finger_contacts_contender().examine_event(&TouchpadEvent {
contacts: vec![],
timestamp: MAX_TIME_ELAPSED + zx::MonotonicInstant::from_nanos(1),
pressed_buttons: vec![],
filtered_palm_contacts: vec![],
}),
ExamineEventResult::Mismatch(_)
);
}
#[fuchsia::test]
fn two_finger_contacts_contender_single_button() {
assert_matches!(
get_two_finger_contacts_contender().examine_event(&TouchpadEvent {
contacts: vec![],
timestamp: zx::MonotonicInstant::from_nanos(0),
pressed_buttons: vec![0],
filtered_palm_contacts: vec![],
}),
ExamineEventResult::Mismatch(_)
);
}
#[fuchsia::test]
fn two_finger_contacts_contender_many_buttons() {
assert_matches!(
get_two_finger_contacts_contender().examine_event(&TouchpadEvent {
contacts: vec![],
timestamp: zx::MonotonicInstant::from_nanos(0),
pressed_buttons: vec![0, 1],
filtered_palm_contacts: vec![],
}),
ExamineEventResult::Mismatch(_)
);
}
#[fuchsia::test]
fn two_finger_contacts_contender_no_touch_contacts() {
assert_examined_matched_contender(get_two_finger_contacts_contender().examine_event(
&TouchpadEvent {
contacts: vec![],
timestamp: zx::MonotonicInstant::from_nanos(0),
pressed_buttons: vec![],
filtered_palm_contacts: vec![],
},
));
}
#[fuchsia::test]
fn two_finger_contacts_contender_one_contact() {
assert_contender(
get_two_finger_contacts_contender().examine_event(&TouchpadEvent {
contacts: vec![create_touch_contact(0, Position::zero())],
timestamp: zx::MonotonicInstant::from_nanos(0),
pressed_buttons: vec![],
filtered_palm_contacts: vec![],
}),
TypeId::of::<OneFingerRaisedContender>(),
);
}
#[fuchsia::test]
fn two_finger_contacts_contender_one_contact_large_displacement() {
assert_matches!(
get_two_finger_contacts_contender().examine_event(&TouchpadEvent {
contacts: vec![create_touch_contact(
0,
Position { x: MAX_FINGER_DISPLACEMENT_IN_MM, y: MAX_FINGER_DISPLACEMENT_IN_MM },
)],
timestamp: zx::MonotonicInstant::from_nanos(0),
pressed_buttons: vec![],
filtered_palm_contacts: vec![],
}),
ExamineEventResult::Mismatch(_)
);
}
#[fuchsia::test]
fn two_finger_contacts_contender_many_touch_contacts() {
assert_matches!(
get_two_finger_contacts_contender().examine_event(&TouchpadEvent {
contacts: vec![
create_touch_contact(0, Position::zero()),
create_touch_contact(1, Position::zero()),
create_touch_contact(2, Position::zero())
],
timestamp: zx::MonotonicInstant::from_nanos(0),
pressed_buttons: vec![],
filtered_palm_contacts: vec![],
}),
ExamineEventResult::Mismatch(_)
);
}
#[fuchsia::test]
fn two_finger_contacts_contender_two_touch_contacts() {
assert_contender(
get_two_finger_contacts_contender().examine_event(&TouchpadEvent {
contacts: vec![
create_touch_contact(0, Position::zero()),
create_touch_contact(1, Position::zero()),
],
timestamp: zx::MonotonicInstant::from_nanos(0),
pressed_buttons: vec![],
filtered_palm_contacts: vec![],
}),
TypeId::of::<TwoFingerContactsContender>(),
);
}
#[fuchsia::test]
fn two_finger_contacts_contender_two_contacts_large_displacement() {
assert_matches!(
get_two_finger_contacts_contender().examine_event(&TouchpadEvent {
contacts: vec![
create_touch_contact(
0,
Position {
x: MAX_FINGER_DISPLACEMENT_IN_MM,
y: MAX_FINGER_DISPLACEMENT_IN_MM
}
),
create_touch_contact(1, Position::zero())
],
timestamp: zx::MonotonicInstant::from_nanos(0),
pressed_buttons: vec![],
filtered_palm_contacts: vec![],
}),
ExamineEventResult::Mismatch(_)
);
assert_matches!(
get_two_finger_contacts_contender().examine_event(&TouchpadEvent {
contacts: vec![
create_touch_contact(0, Position::zero()),
create_touch_contact(
1,
Position {
x: MAX_FINGER_DISPLACEMENT_IN_MM,
y: MAX_FINGER_DISPLACEMENT_IN_MM
}
),
],
timestamp: zx::MonotonicInstant::from_nanos(0),
pressed_buttons: vec![],
filtered_palm_contacts: vec![],
}),
ExamineEventResult::Mismatch(_)
);
}
#[fuchsia::test]
fn two_finger_contacts_contender_two_contacts_some_displacement() {
assert_contender(
get_two_finger_contacts_contender().examine_event(&TouchpadEvent {
contacts: vec![
create_touch_contact(0, Position::zero()),
create_touch_contact(1, Position { x: HALF_MOTION, y: HALF_MOTION }),
],
timestamp: zx::MonotonicInstant::from_nanos(0),
pressed_buttons: vec![],
filtered_palm_contacts: vec![],
}),
TypeId::of::<TwoFingerContactsContender>(),
);
assert_contender(
get_two_finger_contacts_contender().examine_event(&TouchpadEvent {
contacts: vec![
create_touch_contact(0, Position { x: HALF_MOTION, y: HALF_MOTION }),
create_touch_contact(1, Position::zero()),
],
timestamp: zx::MonotonicInstant::from_nanos(0),
pressed_buttons: vec![],
filtered_palm_contacts: vec![],
}),
TypeId::of::<TwoFingerContactsContender>(),
);
assert_contender(
get_two_finger_contacts_contender().examine_event(&TouchpadEvent {
contacts: vec![
create_touch_contact(0, Position { x: HALF_MOTION, y: HALF_MOTION }),
create_touch_contact(1, Position { x: HALF_MOTION, y: HALF_MOTION }),
],
timestamp: zx::MonotonicInstant::from_nanos(0),
pressed_buttons: vec![],
filtered_palm_contacts: vec![],
}),
TypeId::of::<TwoFingerContactsContender>(),
);
}
#[fuchsia::test]
fn one_finger_raised_contender_too_long() {
assert_matches!(
get_one_finger_raised_contender().examine_event(&TouchpadEvent {
contacts: vec![],
timestamp: MAX_TIME_ELAPSED + zx::MonotonicInstant::from_nanos(1),
pressed_buttons: vec![],
filtered_palm_contacts: vec![],
}),
ExamineEventResult::Mismatch(_)
);
}
#[fuchsia::test]
fn one_finger_raised_contender_single_button() {
assert_matches!(
get_one_finger_raised_contender().examine_event(&TouchpadEvent {
contacts: vec![],
timestamp: zx::MonotonicInstant::from_nanos(0),
pressed_buttons: vec![0],
filtered_palm_contacts: vec![],
}),
ExamineEventResult::Mismatch(_)
);
}
#[fuchsia::test]
fn one_finger_raised_contender_many_buttons() {
assert_matches!(
get_one_finger_raised_contender().examine_event(&TouchpadEvent {
contacts: vec![],
timestamp: zx::MonotonicInstant::from_nanos(0),
pressed_buttons: vec![0, 1],
filtered_palm_contacts: vec![],
}),
ExamineEventResult::Mismatch(_)
);
}
#[fuchsia::test]
fn one_finger_raised_contender_no_touch_contacts() {
assert_examined_matched_contender(get_one_finger_raised_contender().examine_event(
&TouchpadEvent {
contacts: vec![],
timestamp: zx::MonotonicInstant::from_nanos(0),
pressed_buttons: vec![],
filtered_palm_contacts: vec![],
},
));
}
#[fuchsia::test]
fn one_finger_raised_contender_one_contact_first_id() {
assert_contender(
get_one_finger_raised_contender().examine_event(&TouchpadEvent {
contacts: vec![create_touch_contact(0, Position::zero())],
timestamp: zx::MonotonicInstant::from_nanos(0),
pressed_buttons: vec![],
filtered_palm_contacts: vec![],
}),
TypeId::of::<OneFingerRaisedContender>(),
);
assert_contender(
get_one_finger_raised_contender().examine_event(&TouchpadEvent {
contacts: vec![create_touch_contact(
0,
Position { x: HALF_MOTION, y: HALF_MOTION },
)],
timestamp: zx::MonotonicInstant::from_nanos(0),
pressed_buttons: vec![],
filtered_palm_contacts: vec![],
}),
TypeId::of::<OneFingerRaisedContender>(),
);
}
#[fuchsia::test]
fn one_finger_raised_contender_one_contact_second_id() {
assert_contender(
get_one_finger_raised_contender().examine_event(&TouchpadEvent {
contacts: vec![create_touch_contact(1, Position::zero())],
timestamp: zx::MonotonicInstant::from_nanos(0),
pressed_buttons: vec![],
filtered_palm_contacts: vec![],
}),
TypeId::of::<OneFingerRaisedContender>(),
);
assert_contender(
get_one_finger_raised_contender().examine_event(&TouchpadEvent {
contacts: vec![create_touch_contact(
1,
Position { x: HALF_MOTION, y: HALF_MOTION },
)],
timestamp: zx::MonotonicInstant::from_nanos(0),
pressed_buttons: vec![],
filtered_palm_contacts: vec![],
}),
TypeId::of::<OneFingerRaisedContender>(),
);
}
#[fuchsia::test]
fn one_finger_raised_contender_one_contact_invalid_id() {
assert_matches!(
get_one_finger_raised_contender().examine_event(&TouchpadEvent {
contacts: vec![create_touch_contact(2, Position::zero(),)],
timestamp: zx::MonotonicInstant::from_nanos(0),
pressed_buttons: vec![],
filtered_palm_contacts: vec![],
}),
ExamineEventResult::Mismatch(_)
);
}
#[fuchsia::test]
fn one_finger_raised_contender_one_contact_large_displacement() {
assert_matches!(
get_one_finger_raised_contender().examine_event(&TouchpadEvent {
contacts: vec![create_touch_contact(
0,
Position { x: MAX_FINGER_DISPLACEMENT_IN_MM, y: MAX_FINGER_DISPLACEMENT_IN_MM },
)],
timestamp: zx::MonotonicInstant::from_nanos(0),
pressed_buttons: vec![],
filtered_palm_contacts: vec![],
}),
ExamineEventResult::Mismatch(_)
);
}
#[fuchsia::test]
fn one_finger_raised_contender_many_touch_contacts() {
assert_matches!(
get_one_finger_raised_contender().examine_event(&TouchpadEvent {
contacts: vec![
create_touch_contact(0, Position::zero()),
create_touch_contact(1, Position::zero()),
],
timestamp: zx::MonotonicInstant::from_nanos(0),
pressed_buttons: vec![],
filtered_palm_contacts: vec![],
}),
ExamineEventResult::Mismatch(_)
);
}
#[fuchsia::test]
fn matched_contender_too_long() {
assert_matches!(
get_matched_contender().verify_event(&TouchpadEvent {
contacts: vec![],
timestamp: MAX_TIME_ELAPSED + zx::MonotonicInstant::from_nanos(1),
pressed_buttons: vec![],
filtered_palm_contacts: vec![],
}),
VerifyEventResult::Mismatch(_)
);
}
#[fuchsia::test]
fn matched_contender_one_contact() {
assert_matches!(
get_matched_contender().verify_event(&TouchpadEvent {
contacts: vec![create_touch_contact(0, Position::zero())],
timestamp: zx::MonotonicInstant::from_nanos(0),
pressed_buttons: vec![],
filtered_palm_contacts: vec![],
}),
VerifyEventResult::Mismatch(_)
);
}
#[fuchsia::test]
fn matched_contender_many_contacts() {
assert_matches!(
get_matched_contender().verify_event(&TouchpadEvent {
contacts: vec![
create_touch_contact(0, Position::zero()),
create_touch_contact(1, Position::zero())
],
timestamp: zx::MonotonicInstant::from_nanos(0),
pressed_buttons: vec![],
filtered_palm_contacts: vec![],
}),
VerifyEventResult::Mismatch(_)
);
}
#[fuchsia::test]
fn matched_contender_one_button() {
assert_matches!(
get_matched_contender().verify_event(&TouchpadEvent {
contacts: vec![],
timestamp: zx::MonotonicInstant::from_nanos(0),
pressed_buttons: vec![0],
filtered_palm_contacts: vec![],
}),
VerifyEventResult::Mismatch(_)
);
}
#[fuchsia::test]
fn matched_contender_many_buttons() {
assert_matches!(
get_matched_contender().verify_event(&TouchpadEvent {
contacts: vec![],
timestamp: zx::MonotonicInstant::from_nanos(0),
pressed_buttons: vec![0, 1],
filtered_palm_contacts: vec![],
}),
VerifyEventResult::Mismatch(_)
);
}
#[fuchsia::test]
fn matched_contender_no_contacts() {
assert_verified_matched_contender(get_matched_contender().verify_event(&TouchpadEvent {
contacts: vec![],
timestamp: zx::MonotonicInstant::from_nanos(0),
pressed_buttons: vec![],
filtered_palm_contacts: vec![],
}));
}
#[fuchsia::test]
fn matched_contender_process_buffered_events() {
let ProcessBufferedEventsResult { generated_events, winner, recognized_gesture } =
get_matched_contender().process_buffered_events(vec![]);
assert_eq!(
generated_events,
[
gesture_arena::MouseEvent {
timestamp: zx::MonotonicInstant::from_nanos(0),
mouse_data: MouseEvent {
location: MouseLocation::Relative(RelativeLocation {
millimeters: Position { x: 0.0, y: 0.0 }
}),
wheel_delta_v: None,
wheel_delta_h: None,
phase: MousePhase::Down,
affected_buttons: hashset! {SECONDARY_BUTTON},
pressed_buttons: hashset! {SECONDARY_BUTTON},
is_precision_scroll: None,
},
},
gesture_arena::MouseEvent {
timestamp: zx::MonotonicInstant::from_nanos(123),
mouse_data: MouseEvent {
location: MouseLocation::Relative(RelativeLocation {
millimeters: Position { x: 0.0, y: 0.0 }
}),
wheel_delta_v: None,
wheel_delta_h: None,
phase: MousePhase::Up,
affected_buttons: hashset! {SECONDARY_BUTTON},
pressed_buttons: hashset! {},
is_precision_scroll: None,
},
}
]
);
assert_matches!(winner, None);
assert_eq!(recognized_gesture, RecognizedGesture::SecondaryTap);
}
}