1use crate::input_device::{self, Handled, InputDeviceBinding, InputDeviceStatus, InputEvent};
6use crate::utils::{self, Position};
7use crate::{Transport, metrics};
8use anyhow::{Error, format_err};
9use async_trait::async_trait;
10use fuchsia_inspect::ArrayProperty;
11use fuchsia_inspect::health::Reporter;
12use futures::channel::mpsc::{UnboundedReceiver, UnboundedSender};
13use metrics_registry::*;
14use sorted_vec_map::SortedVecSet;
15use zx;
16
17pub type MouseButton = u8;
18
19#[derive(Copy, Clone, Debug, PartialEq)]
21pub enum PrecisionScroll {
22 Yes,
24 No,
26}
27
28#[derive(Copy, Clone, Debug, PartialEq)]
30pub enum MouseLocation {
31 Relative(RelativeLocation),
33
34 Absolute(Position),
36}
37
38#[derive(Copy, Clone, Debug, PartialEq)]
39pub enum MousePhase {
40 Down, Move, Up, Wheel, }
45
46#[derive(Copy, Clone, Debug, PartialEq)]
48pub struct RelativeLocation {
49 pub counts: Position,
51}
52
53impl Default for RelativeLocation {
54 fn default() -> Self {
55 RelativeLocation { counts: Position::zero() }
56 }
57}
58
59#[derive(Clone, Debug, PartialEq)]
62pub struct WheelDelta {
63 pub ticks: i64,
64 pub physical_pixel: Option<f32>,
65}
66
67#[derive(Debug)]
89pub struct MouseEvent {
90 pub location: MouseLocation,
92
93 pub wheel_delta_v: Option<WheelDelta>,
95
96 pub wheel_delta_h: Option<WheelDelta>,
98
99 pub is_precision_scroll: Option<PrecisionScroll>,
101
102 pub phase: MousePhase,
104
105 pub affected_buttons: SortedVecSet<MouseButton>,
107
108 pub pressed_buttons: SortedVecSet<MouseButton>,
110
111 pub wake_lease: Option<zx::EventPair>,
113}
114
115impl Clone for MouseEvent {
116 fn clone(&self) -> Self {
117 log::debug!("MouseEvent cloned without wake lease.");
118 Self {
119 location: self.location,
120 wheel_delta_v: self.wheel_delta_v.clone(),
121 wheel_delta_h: self.wheel_delta_h.clone(),
122 is_precision_scroll: self.is_precision_scroll,
123 phase: self.phase,
124 affected_buttons: self.affected_buttons.clone(),
125 pressed_buttons: self.pressed_buttons.clone(),
126 wake_lease: None,
127 }
128 }
129}
130
131impl PartialEq for MouseEvent {
132 fn eq(&self, other: &Self) -> bool {
133 self.location == other.location
134 && self.wheel_delta_v == other.wheel_delta_v
135 && self.wheel_delta_h == other.wheel_delta_h
136 && self.is_precision_scroll == other.is_precision_scroll
137 && self.phase == other.phase
138 && self.affected_buttons == other.affected_buttons
139 && self.pressed_buttons == other.pressed_buttons
140 }
141}
142
143impl MouseEvent {
144 pub fn new(
152 location: MouseLocation,
153 wheel_delta_v: Option<WheelDelta>,
154 wheel_delta_h: Option<WheelDelta>,
155 phase: MousePhase,
156 affected_buttons: SortedVecSet<MouseButton>,
157 pressed_buttons: SortedVecSet<MouseButton>,
158 is_precision_scroll: Option<PrecisionScroll>,
159 wake_lease: Option<zx::EventPair>,
160 ) -> MouseEvent {
161 MouseEvent {
162 location,
163 wheel_delta_v,
164 wheel_delta_h,
165 phase,
166 affected_buttons,
167 pressed_buttons,
168 is_precision_scroll,
169 wake_lease,
170 }
171 }
172
173 pub fn record_inspect(&self, node: &fuchsia_inspect::Node) {
174 if let Some(wheel_delta_v) = &self.wheel_delta_v {
176 node.record_child("wheel_delta_v", move |wheel_delta_v_node| {
177 wheel_delta_v_node.record_int("ticks", wheel_delta_v.ticks);
178 if let Some(physical_pixel) = wheel_delta_v.physical_pixel {
179 wheel_delta_v_node.record_double("physical_pixel", f64::from(physical_pixel));
180 }
181 });
182 }
183
184 if let Some(wheel_delta_h) = &self.wheel_delta_h {
185 node.record_child("wheel_delta_h", move |wheel_delta_h_node| {
186 wheel_delta_h_node.record_int("ticks", wheel_delta_h.ticks);
187 if let Some(physical_pixel) = wheel_delta_h.physical_pixel {
188 wheel_delta_h_node.record_double("physical_pixel", f64::from(physical_pixel));
189 }
190 });
191 }
192
193 if let Some(is_precision_scroll) = self.is_precision_scroll {
194 match is_precision_scroll {
195 PrecisionScroll::Yes => node.record_string("is_precision_scroll", "yes"),
196 PrecisionScroll::No => node.record_string("is_precision_scroll", "no"),
197 }
198 }
199
200 match self.phase {
201 MousePhase::Down => node.record_string("phase", "down"),
202 MousePhase::Move => node.record_string("phase", "move"),
203 MousePhase::Up => node.record_string("phase", "up"),
204 MousePhase::Wheel => node.record_string("phase", "wheel"),
205 }
206
207 let affected_buttons_node =
208 node.create_uint_array("affected_buttons", self.affected_buttons.len());
209 self.affected_buttons.iter().enumerate().for_each(|(i, button)| {
210 affected_buttons_node.set(i, *button);
211 });
212 node.record(affected_buttons_node);
213
214 let pressed_buttons_node =
215 node.create_uint_array("pressed_buttons", self.pressed_buttons.len());
216 self.pressed_buttons.iter().enumerate().for_each(|(i, button)| {
217 pressed_buttons_node.set(i, *button);
218 });
219 node.record(pressed_buttons_node);
220 }
221}
222
223pub struct MouseBinding {
229 event_sender: UnboundedSender<Vec<InputEvent>>,
231
232 device_descriptor: MouseDeviceDescriptor,
234}
235
236#[derive(Clone, Debug, Eq, PartialEq)]
237pub struct MouseDeviceDescriptor {
238 pub device_id: u32,
240
241 pub absolute_x_range: Option<fidl_fuchsia_input::Range>,
243
244 pub absolute_y_range: Option<fidl_fuchsia_input::Range>,
246
247 pub wheel_v_range: Option<fidl_fuchsia_input::Axis>,
249
250 pub wheel_h_range: Option<fidl_fuchsia_input::Axis>,
252
253 pub buttons: Option<Vec<MouseButton>>,
255}
256
257#[async_trait]
258impl input_device::InputDeviceBinding for MouseBinding {
259 fn input_event_sender(&self) -> UnboundedSender<Vec<InputEvent>> {
260 self.event_sender.clone()
261 }
262
263 fn get_device_descriptor(&self) -> input_device::InputDeviceDescriptor {
264 input_device::InputDeviceDescriptor::Mouse(self.device_descriptor.clone())
265 }
266}
267
268impl MouseBinding {
269 pub async fn new(
284 device_proxy: fidl_next::Client<fidl_next_fuchsia_input_report::InputDevice, Transport>,
285 device_id: u32,
286 input_event_sender: UnboundedSender<Vec<InputEvent>>,
287 device_node: fuchsia_inspect::Node,
288 _feature_flags: input_device::InputPipelineFeatureFlags,
289 metrics_logger: metrics::MetricsLogger,
290 ) -> Result<Self, Error> {
291 let (device_binding, mut inspect_status) =
292 Self::bind_device(&device_proxy, device_id, input_event_sender, device_node).await?;
293 inspect_status.health_node.set_ok();
294 input_device::initialize_report_stream(
295 device_proxy,
296 device_binding.get_device_descriptor(),
297 device_binding.input_event_sender(),
298 inspect_status,
299 metrics_logger,
300 _feature_flags,
301 Self::process_reports,
302 );
303
304 Ok(device_binding)
305 }
306
307 async fn bind_device(
319 device: &fidl_next::Client<fidl_next_fuchsia_input_report::InputDevice, Transport>,
320 device_id: u32,
321 input_event_sender: UnboundedSender<Vec<InputEvent>>,
322 device_node: fuchsia_inspect::Node,
323 ) -> Result<(Self, InputDeviceStatus), Error> {
324 let mut input_device_status = InputDeviceStatus::new(device_node);
325 let device_descriptor: fidl_next_fuchsia_input_report::DeviceDescriptor = match device
326 .get_descriptor()
327 .await
328 {
329 Ok(res) => res.descriptor,
330 Err(_) => {
331 input_device_status.health_node.set_unhealthy("Could not get device descriptor.");
332 return Err(format_err!("Could not get descriptor for device_id: {}", device_id));
333 }
334 };
335
336 let mouse_descriptor = device_descriptor.mouse.ok_or_else(|| {
337 input_device_status
338 .health_node
339 .set_unhealthy("DeviceDescriptor does not have a MouseDescriptor.");
340 format_err!("DeviceDescriptor does not have a MouseDescriptor")
341 })?;
342
343 let mouse_input_descriptor = mouse_descriptor.input.ok_or_else(|| {
344 input_device_status
345 .health_node
346 .set_unhealthy("MouseDescriptor does not have a MouseInputDescriptor.");
347 format_err!("MouseDescriptor does not have a MouseInputDescriptor")
348 })?;
349
350 let device_descriptor: MouseDeviceDescriptor = MouseDeviceDescriptor {
351 device_id,
352 absolute_x_range: mouse_input_descriptor
353 .position_x
354 .as_ref()
355 .map(|axis| utils::range_to_old(&axis.range)),
356 absolute_y_range: mouse_input_descriptor
357 .position_y
358 .as_ref()
359 .map(|axis| utils::range_to_old(&axis.range)),
360 wheel_v_range: utils::axis_to_old(mouse_input_descriptor.scroll_v.as_ref()),
361 wheel_h_range: utils::axis_to_old(mouse_input_descriptor.scroll_h.as_ref()),
362 buttons: mouse_input_descriptor.buttons,
363 };
364
365 Ok((Self { event_sender: input_event_sender, device_descriptor }, input_device_status))
366 }
367
368 fn process_reports(
390 reports: &[fidl_next_fuchsia_input_report::wire::InputReport<'_>],
391 mut previous_state: Option<input_device::PreviousDeviceState>,
392 device_descriptor: &input_device::InputDeviceDescriptor,
393 input_event_sender: &mut UnboundedSender<Vec<InputEvent>>,
394 inspect_status: &InputDeviceStatus,
395 metrics_logger: &metrics::MetricsLogger,
396 _feature_flags: &input_device::InputPipelineFeatureFlags,
397 ) -> (Option<input_device::PreviousDeviceState>, Option<UnboundedReceiver<InputEvent>>) {
398 fuchsia_trace::duration!("input", "mouse-binding-process-reports", "num_reports" => reports.len());
399 for report in reports {
400 previous_state = Self::process_report(
401 report,
402 previous_state,
403 device_descriptor,
404 input_event_sender,
405 inspect_status,
406 metrics_logger,
407 );
408 }
409 (previous_state, None)
410 }
411
412 fn process_report(
413 report: &fidl_next_fuchsia_input_report::wire::InputReport<'_>,
414 previous_state: Option<input_device::PreviousDeviceState>,
415 device_descriptor: &input_device::InputDeviceDescriptor,
416 input_event_sender: &mut UnboundedSender<Vec<input_device::InputEvent>>,
417 inspect_status: &InputDeviceStatus,
418 metrics_logger: &metrics::MetricsLogger,
419 ) -> Option<input_device::PreviousDeviceState> {
420 if let Some(trace_id) = report.trace_id() {
421 fuchsia_trace::flow_end!("input", "input_report", trace_id.0.into());
422 }
423
424 let wake_lease = utils::duplicate_wake_lease(report.wake_lease());
428
429 inspect_status.count_received_report_wire(report);
430 let mouse_report = match report.mouse() {
432 Some(mouse) => mouse,
433 None => {
434 inspect_status.count_filtered_report();
435 return previous_state;
436 }
437 };
438
439 let previous_buttons: SortedVecSet<MouseButton> = match previous_state {
440 Some(input_device::PreviousDeviceState::Mouse { pressed_buttons }) => pressed_buttons,
441 _ => SortedVecSet::new(),
442 };
443 let current_buttons: SortedVecSet<MouseButton> =
444 buttons_from_mouse_report_wire(mouse_report);
445
446 send_mouse_event(
452 MouseLocation::Relative(Default::default()),
453 None, None, MousePhase::Down,
456 current_buttons.difference(&previous_buttons).cloned().collect(),
457 current_buttons.clone(),
458 device_descriptor,
459 input_event_sender,
460 inspect_status,
461 metrics_logger,
462 wake_lease.as_ref().map(|lease| {
463 lease
464 .duplicate_handle(zx::Rights::SAME_RIGHTS)
465 .expect("failed to duplicate event pair")
466 }),
467 );
468
469 let location = if let (Some(position_x), Some(position_y)) =
471 (mouse_report.position_x(), mouse_report.position_y())
472 {
473 MouseLocation::Absolute(Position { x: position_x.0 as f32, y: position_y.0 as f32 })
474 } else {
475 let movement_x = mouse_report.movement_x().map(|x| x.0).unwrap_or_default() as f32;
476 let movement_y = mouse_report.movement_y().map(|y| y.0).unwrap_or_default() as f32;
477 MouseLocation::Relative(RelativeLocation {
478 counts: Position { x: movement_x, y: movement_y },
479 })
480 };
481
482 send_mouse_event(
486 location,
487 None, None, MousePhase::Move,
490 current_buttons.union(&previous_buttons).cloned().collect(),
491 current_buttons.union(&previous_buttons).cloned().collect(),
492 device_descriptor,
493 input_event_sender,
494 inspect_status,
495 metrics_logger,
496 wake_lease.as_ref().map(|lease| {
497 lease
498 .duplicate_handle(zx::Rights::SAME_RIGHTS)
499 .expect("failed to duplicate event pair")
500 }),
501 );
502
503 let wheel_delta_v = mouse_report
504 .scroll_v()
505 .map(|ticks| WheelDelta { ticks: ticks.0, physical_pixel: None });
506
507 let wheel_delta_h = mouse_report
508 .scroll_h()
509 .map(|ticks| WheelDelta { ticks: ticks.0, physical_pixel: None });
510
511 send_mouse_event(
513 MouseLocation::Relative(Default::default()),
514 wheel_delta_v,
515 wheel_delta_h,
516 MousePhase::Wheel,
517 current_buttons.union(&previous_buttons).cloned().collect(),
518 current_buttons.union(&previous_buttons).cloned().collect(),
519 device_descriptor,
520 input_event_sender,
521 inspect_status,
522 metrics_logger,
523 wake_lease.as_ref().map(|lease| {
524 lease
525 .duplicate_handle(zx::Rights::SAME_RIGHTS)
526 .expect("failed to duplicate event pair")
527 }),
528 );
529
530 send_mouse_event(
536 MouseLocation::Relative(Default::default()),
537 None, None, MousePhase::Up,
540 previous_buttons.difference(¤t_buttons).cloned().collect(),
541 current_buttons.clone(),
542 device_descriptor,
543 input_event_sender,
544 inspect_status,
545 metrics_logger,
546 wake_lease,
547 );
548
549 Some(input_device::PreviousDeviceState::Mouse { pressed_buttons: current_buttons })
550 }
551}
552
553fn send_mouse_event(
568 location: MouseLocation,
569 wheel_delta_v: Option<WheelDelta>,
570 wheel_delta_h: Option<WheelDelta>,
571 phase: MousePhase,
572 affected_buttons: SortedVecSet<MouseButton>,
573 pressed_buttons: SortedVecSet<MouseButton>,
574 device_descriptor: &input_device::InputDeviceDescriptor,
575 sender: &mut UnboundedSender<Vec<input_device::InputEvent>>,
576 inspect_status: &InputDeviceStatus,
577 metrics_logger: &metrics::MetricsLogger,
578 wake_lease: Option<zx::EventPair>,
579) {
580 if (phase == MousePhase::Down || phase == MousePhase::Up) && affected_buttons.is_empty() {
582 return;
583 }
584
585 if phase == MousePhase::Move && location == MouseLocation::Relative(Default::default()) {
588 return;
589 }
590
591 if phase == MousePhase::Wheel && wheel_delta_v.is_none() && wheel_delta_h.is_none() {
593 return;
594 }
595
596 let trace_id = fuchsia_trace::Id::new();
597 fuchsia_trace::duration!("input", "mouse-binding-send-event");
598 fuchsia_trace::flow_begin!("input", "event_in_input_pipeline", trace_id);
599
600 let event = input_device::InputEvent {
601 device_event: input_device::InputDeviceEvent::Mouse(MouseEvent::new(
602 location,
603 wheel_delta_v,
604 wheel_delta_h,
605 phase,
606 affected_buttons,
607 pressed_buttons,
608 match phase {
609 MousePhase::Wheel => Some(PrecisionScroll::No),
610 _ => None,
611 },
612 wake_lease,
613 )),
614 device_descriptor: device_descriptor.clone(),
615 event_time: zx::MonotonicInstant::get(),
616 handled: Handled::No,
617 trace_id: Some(trace_id),
618 };
619 let events = vec![event];
620 inspect_status.count_generated_events(&events);
621
622 if let Err(e) = sender.unbounded_send(events) {
623 metrics_logger.log_error(
624 InputPipelineErrorMetricDimensionEvent::MouseFailedToSendEvent,
625 std::format!("Failed to send MouseEvent with error: {:?}", e),
626 );
627 }
628}
629
630fn buttons_from_mouse_report_wire(
631 mouse_report: &fidl_next_fuchsia_input_report::wire::MouseInputReport<'_>,
632) -> SortedVecSet<MouseButton> {
633 mouse_report
634 .pressed_buttons()
635 .map(|buttons| SortedVecSet::from_iter(buttons.iter().copied()))
636 .unwrap_or_default()
637}
638
639#[cfg(test)]
640mod tests {
641 use super::*;
642 use crate::testing_utilities;
643 use fuchsia_async as fasync;
644 use futures::StreamExt;
645 use sorted_vec_map::SortedVecSet;
646
647 const DEVICE_ID: u32 = 1;
648
649 fn mouse_device_descriptor(device_id: u32) -> input_device::InputDeviceDescriptor {
650 input_device::InputDeviceDescriptor::Mouse(MouseDeviceDescriptor {
651 device_id,
652 absolute_x_range: None,
653 absolute_y_range: None,
654 wheel_v_range: Some(fidl_fuchsia_input::Axis {
655 range: fidl_fuchsia_input::Range { min: -1, max: 1 },
656 unit: fidl_fuchsia_input::Unit {
657 type_: fidl_fuchsia_input::UnitType::Other,
658 exponent: 1,
659 },
660 }),
661 wheel_h_range: Some(fidl_fuchsia_input::Axis {
662 range: fidl_fuchsia_input::Range { min: -1, max: 1 },
663 unit: fidl_fuchsia_input::Unit {
664 type_: fidl_fuchsia_input::UnitType::Other,
665 exponent: 1,
666 },
667 }),
668 buttons: None,
669 })
670 }
671
672 fn wheel_delta_ticks(ticks: i64) -> Option<WheelDelta> {
673 Some(WheelDelta { ticks, physical_pixel: None })
674 }
675
676 #[fasync::run_singlethreaded(test)]
678 async fn movement_without_button() {
679 let (event_time_i64, event_time_u64) = testing_utilities::event_times();
680 let first_report = testing_utilities::create_mouse_input_report_relative(
681 Position { x: 10.0, y: 16.0 },
682 None, None, vec![],
685 event_time_i64,
686 );
687 let descriptor = mouse_device_descriptor(DEVICE_ID);
688
689 let input_reports = vec![first_report];
690 let expected_events = vec![testing_utilities::create_mouse_event(
691 MouseLocation::Relative(RelativeLocation { counts: Position { x: 10.0, y: 16.0 } }),
692 None, None, None, MousePhase::Move,
696 SortedVecSet::new(),
697 SortedVecSet::new(),
698 event_time_u64,
699 &descriptor,
700 )];
701
702 assert_input_report_sequence_generates_events!(
703 input_reports: input_reports,
704 expected_events: expected_events,
705 device_descriptor: descriptor,
706 device_type: MouseBinding,
707 );
708 }
709
710 #[fasync::run_singlethreaded(test)]
712 async fn down_without_movement() {
713 let mouse_button: MouseButton = 3;
714 let (event_time_i64, event_time_u64) = testing_utilities::event_times();
715 let first_report = testing_utilities::create_mouse_input_report_relative(
716 Position::zero(),
717 None, None, vec![mouse_button],
720 event_time_i64,
721 );
722 let descriptor = mouse_device_descriptor(DEVICE_ID);
723
724 let input_reports = vec![first_report];
725 let expected_events = vec![testing_utilities::create_mouse_event(
726 MouseLocation::Relative(Default::default()),
727 None, None, None, MousePhase::Down,
731 SortedVecSet::from(vec![mouse_button]),
732 SortedVecSet::from(vec![mouse_button]),
733 event_time_u64,
734 &descriptor,
735 )];
736
737 assert_input_report_sequence_generates_events!(
738 input_reports: input_reports,
739 expected_events: expected_events,
740 device_descriptor: descriptor,
741 device_type: MouseBinding,
742 );
743 }
744
745 #[fasync::run_singlethreaded(test)]
748 async fn down_with_movement() {
749 let mouse_button: MouseButton = 3;
750 let (event_time_i64, event_time_u64) = testing_utilities::event_times();
751 let first_report = testing_utilities::create_mouse_input_report_relative(
752 Position { x: 10.0, y: 16.0 },
753 None, None, vec![mouse_button],
756 event_time_i64,
757 );
758 let descriptor = mouse_device_descriptor(DEVICE_ID);
759
760 let input_reports = vec![first_report];
761 let expected_events = vec![
762 testing_utilities::create_mouse_event(
763 MouseLocation::Relative(Default::default()),
764 None, None, None, MousePhase::Down,
768 SortedVecSet::from(vec![mouse_button]),
769 SortedVecSet::from(vec![mouse_button]),
770 event_time_u64,
771 &descriptor,
772 ),
773 testing_utilities::create_mouse_event(
774 MouseLocation::Relative(RelativeLocation { counts: Position { x: 10.0, y: 16.0 } }),
775 None, None, None, MousePhase::Move,
779 SortedVecSet::from(vec![mouse_button]),
780 SortedVecSet::from(vec![mouse_button]),
781 event_time_u64,
782 &descriptor,
783 ),
784 ];
785
786 assert_input_report_sequence_generates_events!(
787 input_reports: input_reports,
788 expected_events: expected_events,
789 device_descriptor: descriptor,
790 device_type: MouseBinding,
791 );
792 }
793
794 #[fasync::run_singlethreaded(test)]
796 async fn down_up() {
797 let button = 1;
798 let (event_time_i64, event_time_u64) = testing_utilities::event_times();
799 let first_report = testing_utilities::create_mouse_input_report_relative(
800 Position::zero(),
801 None, None, vec![button],
804 event_time_i64,
805 );
806 let second_report = testing_utilities::create_mouse_input_report_relative(
807 Position::zero(),
808 None, None, vec![],
811 event_time_i64,
812 );
813 let descriptor = mouse_device_descriptor(DEVICE_ID);
814
815 let input_reports = vec![first_report, second_report];
816 let expected_events = vec![
817 testing_utilities::create_mouse_event(
818 MouseLocation::Relative(Default::default()),
819 None, None, None, MousePhase::Down,
823 SortedVecSet::from(vec![button]),
824 SortedVecSet::from(vec![button]),
825 event_time_u64,
826 &descriptor,
827 ),
828 testing_utilities::create_mouse_event(
829 MouseLocation::Relative(Default::default()),
830 None, None, None, MousePhase::Up,
834 SortedVecSet::from(vec![button]),
835 SortedVecSet::new(),
836 event_time_u64,
837 &descriptor,
838 ),
839 ];
840
841 assert_input_report_sequence_generates_events!(
842 input_reports: input_reports,
843 expected_events: expected_events,
844 device_descriptor: descriptor,
845 device_type: MouseBinding,
846 );
847 }
848
849 #[fasync::run_singlethreaded(test)]
851 async fn down_up_with_movement() {
852 let button = 1;
853
854 let (event_time_i64, event_time_u64) = testing_utilities::event_times();
855 let first_report = testing_utilities::create_mouse_input_report_relative(
856 Position::zero(),
857 None, None, vec![button],
860 event_time_i64,
861 );
862 let second_report = testing_utilities::create_mouse_input_report_relative(
863 Position { x: 10.0, y: 16.0 },
864 None, None, vec![],
867 event_time_i64,
868 );
869 let descriptor = mouse_device_descriptor(DEVICE_ID);
870
871 let input_reports = vec![first_report, second_report];
872 let expected_events = vec![
873 testing_utilities::create_mouse_event(
874 MouseLocation::Relative(Default::default()),
875 None, None, None, MousePhase::Down,
879 SortedVecSet::from(vec![button]),
880 SortedVecSet::from(vec![button]),
881 event_time_u64,
882 &descriptor,
883 ),
884 testing_utilities::create_mouse_event(
885 MouseLocation::Relative(RelativeLocation { counts: Position { x: 10.0, y: 16.0 } }),
886 None, None, None, MousePhase::Move,
890 SortedVecSet::from(vec![button]),
891 SortedVecSet::from(vec![button]),
892 event_time_u64,
893 &descriptor,
894 ),
895 testing_utilities::create_mouse_event(
896 MouseLocation::Relative(Default::default()),
897 None, None, None, MousePhase::Up,
901 SortedVecSet::from(vec![button]),
902 SortedVecSet::new(),
903 event_time_u64,
904 &descriptor,
905 ),
906 ];
907
908 assert_input_report_sequence_generates_events!(
909 input_reports: input_reports,
910 expected_events: expected_events,
911 device_descriptor: descriptor,
912 device_type: MouseBinding,
913 );
914 }
915
916 #[fasync::run_singlethreaded(test)]
920 async fn down_move_up() {
921 let button = 1;
922
923 let (event_time_i64, event_time_u64) = testing_utilities::event_times();
924 let first_report = testing_utilities::create_mouse_input_report_relative(
925 Position::zero(),
926 None, None, vec![button],
929 event_time_i64,
930 );
931 let second_report = testing_utilities::create_mouse_input_report_relative(
932 Position { x: 10.0, y: 16.0 },
933 None, None, vec![button],
936 event_time_i64,
937 );
938 let third_report = testing_utilities::create_mouse_input_report_relative(
939 Position::zero(),
940 None, None, vec![],
943 event_time_i64,
944 );
945 let descriptor = mouse_device_descriptor(DEVICE_ID);
946
947 let input_reports = vec![first_report, second_report, third_report];
948 let expected_events = vec![
949 testing_utilities::create_mouse_event(
950 MouseLocation::Relative(Default::default()),
951 None, None, None, MousePhase::Down,
955 SortedVecSet::from(vec![button]),
956 SortedVecSet::from(vec![button]),
957 event_time_u64,
958 &descriptor,
959 ),
960 testing_utilities::create_mouse_event(
961 MouseLocation::Relative(RelativeLocation { counts: Position { x: 10.0, y: 16.0 } }),
962 None, None, None, MousePhase::Move,
966 SortedVecSet::from(vec![button]),
967 SortedVecSet::from(vec![button]),
968 event_time_u64,
969 &descriptor,
970 ),
971 testing_utilities::create_mouse_event(
972 MouseLocation::Relative(Default::default()),
973 None, None, None, MousePhase::Up,
977 SortedVecSet::from(vec![button]),
978 SortedVecSet::new(),
979 event_time_u64,
980 &descriptor,
981 ),
982 ];
983
984 assert_input_report_sequence_generates_events!(
985 input_reports: input_reports,
986 expected_events: expected_events,
987 device_descriptor: descriptor,
988 device_type: MouseBinding,
989 );
990 }
991
992 #[fasync::run_until_stalled(test)]
994 async fn absolute_movement_to_origin() {
995 let (event_time_i64, event_time_u64) = testing_utilities::event_times();
996 let descriptor = mouse_device_descriptor(DEVICE_ID);
997
998 let input_reports = vec![testing_utilities::create_mouse_input_report_absolute(
999 Position::zero(),
1000 None, None, vec![],
1003 event_time_i64,
1004 )];
1005 let expected_events = vec![testing_utilities::create_mouse_event(
1006 MouseLocation::Absolute(Position { x: 0.0, y: 0.0 }),
1007 None, None, None, MousePhase::Move,
1011 SortedVecSet::new(),
1012 SortedVecSet::new(),
1013 event_time_u64,
1014 &descriptor,
1015 )];
1016
1017 assert_input_report_sequence_generates_events!(
1018 input_reports: input_reports,
1019 expected_events: expected_events,
1020 device_descriptor: descriptor,
1021 device_type: MouseBinding,
1022 );
1023 }
1024
1025 #[fasync::run_until_stalled(test)]
1028 async fn report_with_both_movement_and_position() {
1029 let relative_movement = Position { x: 5.0, y: 5.0 };
1030 let absolute_position = Position { x: 10.0, y: 10.0 };
1031 let expected_location = MouseLocation::Absolute(absolute_position);
1032
1033 let (event_time_i64, event_time_u64) = testing_utilities::event_times();
1034 let descriptor = mouse_device_descriptor(DEVICE_ID);
1035
1036 let input_reports = vec![fidl_next_fuchsia_input_report::InputReport {
1037 event_time: Some(event_time_i64),
1038 keyboard: None,
1039 mouse: Some(fidl_next_fuchsia_input_report::MouseInputReport {
1040 movement_x: Some(relative_movement.x as i64),
1041 movement_y: Some(relative_movement.y as i64),
1042 position_x: Some(absolute_position.x as i64),
1043 position_y: Some(absolute_position.y as i64),
1044 scroll_h: None,
1045 scroll_v: None,
1046 pressed_buttons: None,
1047 ..Default::default()
1048 }),
1049 touch: None,
1050 sensor: None,
1051 consumer_control: None,
1052 trace_id: None,
1053 ..Default::default()
1054 }];
1055 let expected_events = vec![testing_utilities::create_mouse_event(
1056 expected_location,
1057 None, None, None, MousePhase::Move,
1061 SortedVecSet::new(),
1062 SortedVecSet::new(),
1063 event_time_u64,
1064 &descriptor,
1065 )];
1066
1067 assert_input_report_sequence_generates_events!(
1068 input_reports: input_reports,
1069 expected_events: expected_events,
1070 device_descriptor: descriptor,
1071 device_type: MouseBinding,
1072 );
1073 }
1074
1075 #[fasync::run_singlethreaded(test)]
1078 async fn down_down() {
1079 const PRIMARY_BUTTON: u8 = 1;
1080 const SECONDARY_BUTTON: u8 = 2;
1081
1082 let (event_time_i64, event_time_u64) = testing_utilities::event_times();
1083 let first_report = testing_utilities::create_mouse_input_report_relative(
1084 Position::zero(),
1085 None, None, vec![PRIMARY_BUTTON],
1088 event_time_i64,
1089 );
1090 let second_report = testing_utilities::create_mouse_input_report_relative(
1091 Position::zero(),
1092 None, None, vec![PRIMARY_BUTTON, SECONDARY_BUTTON],
1095 event_time_i64,
1096 );
1097 let descriptor = mouse_device_descriptor(DEVICE_ID);
1098
1099 let input_reports = vec![first_report, second_report];
1100 let expected_events = vec![
1101 testing_utilities::create_mouse_event(
1102 MouseLocation::Relative(Default::default()),
1103 None, None, None, MousePhase::Down,
1107 SortedVecSet::from(vec![PRIMARY_BUTTON]),
1108 SortedVecSet::from(vec![PRIMARY_BUTTON]),
1109 event_time_u64,
1110 &descriptor,
1111 ),
1112 testing_utilities::create_mouse_event(
1113 MouseLocation::Relative(Default::default()),
1114 None, None, None, MousePhase::Down,
1118 SortedVecSet::from(vec![SECONDARY_BUTTON]),
1119 SortedVecSet::from(vec![PRIMARY_BUTTON, SECONDARY_BUTTON]),
1120 event_time_u64,
1121 &descriptor,
1122 ),
1123 ];
1124
1125 assert_input_report_sequence_generates_events!(
1126 input_reports: input_reports,
1127 expected_events: expected_events,
1128 device_descriptor: descriptor,
1129 device_type: MouseBinding,
1130 );
1131 }
1132
1133 #[fasync::run_singlethreaded(test)]
1143 async fn down_down_up_up() {
1144 const PRIMARY_BUTTON: u8 = 1;
1145 const SECONDARY_BUTTON: u8 = 2;
1146
1147 let (event_time_i64, event_time_u64) = testing_utilities::event_times();
1148 let first_report = testing_utilities::create_mouse_input_report_relative(
1149 Position::zero(),
1150 None, None, vec![PRIMARY_BUTTON],
1153 event_time_i64,
1154 );
1155 let second_report = testing_utilities::create_mouse_input_report_relative(
1156 Position::zero(),
1157 None, None, vec![PRIMARY_BUTTON, SECONDARY_BUTTON],
1160 event_time_i64,
1161 );
1162 let third_report = testing_utilities::create_mouse_input_report_relative(
1163 Position::zero(),
1164 None, None, vec![SECONDARY_BUTTON],
1167 event_time_i64,
1168 );
1169 let fourth_report = testing_utilities::create_mouse_input_report_relative(
1170 Position::zero(),
1171 None, None, vec![],
1174 event_time_i64,
1175 );
1176 let descriptor = mouse_device_descriptor(DEVICE_ID);
1177
1178 let input_reports = vec![first_report, second_report, third_report, fourth_report];
1179 let expected_events = vec![
1180 testing_utilities::create_mouse_event(
1181 MouseLocation::Relative(Default::default()),
1182 None, None, None, MousePhase::Down,
1186 SortedVecSet::from(vec![PRIMARY_BUTTON]),
1187 SortedVecSet::from(vec![PRIMARY_BUTTON]),
1188 event_time_u64,
1189 &descriptor,
1190 ),
1191 testing_utilities::create_mouse_event(
1192 MouseLocation::Relative(Default::default()),
1193 None, None, None, MousePhase::Down,
1197 SortedVecSet::from(vec![SECONDARY_BUTTON]),
1198 SortedVecSet::from(vec![PRIMARY_BUTTON, SECONDARY_BUTTON]),
1199 event_time_u64,
1200 &descriptor,
1201 ),
1202 testing_utilities::create_mouse_event(
1203 MouseLocation::Relative(Default::default()),
1204 None, None, None, MousePhase::Up,
1208 SortedVecSet::from(vec![PRIMARY_BUTTON]),
1209 SortedVecSet::from(vec![SECONDARY_BUTTON]),
1210 event_time_u64,
1211 &descriptor,
1212 ),
1213 testing_utilities::create_mouse_event(
1214 MouseLocation::Relative(Default::default()),
1215 None, None, None, MousePhase::Up,
1219 SortedVecSet::from(vec![SECONDARY_BUTTON]),
1220 SortedVecSet::new(),
1221 event_time_u64,
1222 &descriptor,
1223 ),
1224 ];
1225
1226 assert_input_report_sequence_generates_events!(
1227 input_reports: input_reports,
1228 expected_events: expected_events,
1229 device_descriptor: descriptor,
1230 device_type: MouseBinding,
1231 );
1232 }
1233
1234 #[fasync::run_singlethreaded(test)]
1236 async fn scroll() {
1237 let (event_time_i64, event_time_u64) = testing_utilities::event_times();
1238 let first_report = testing_utilities::create_mouse_input_report_relative(
1239 Position::zero(),
1240 Some(1),
1241 None,
1242 vec![],
1243 event_time_i64,
1244 );
1245 let second_report = testing_utilities::create_mouse_input_report_relative(
1246 Position::zero(),
1247 None,
1248 Some(1),
1249 vec![],
1250 event_time_i64,
1251 );
1252
1253 let descriptor = mouse_device_descriptor(DEVICE_ID);
1254
1255 let input_reports = vec![first_report, second_report];
1256 let expected_events = vec![
1257 testing_utilities::create_mouse_event(
1258 MouseLocation::Relative(Default::default()),
1259 wheel_delta_ticks(1),
1260 None,
1261 Some(PrecisionScroll::No),
1262 MousePhase::Wheel,
1263 SortedVecSet::new(),
1264 SortedVecSet::new(),
1265 event_time_u64,
1266 &descriptor,
1267 ),
1268 testing_utilities::create_mouse_event(
1269 MouseLocation::Relative(Default::default()),
1270 None,
1271 wheel_delta_ticks(1),
1272 Some(PrecisionScroll::No),
1273 MousePhase::Wheel,
1274 SortedVecSet::new(),
1275 SortedVecSet::new(),
1276 event_time_u64,
1277 &descriptor,
1278 ),
1279 ];
1280
1281 assert_input_report_sequence_generates_events!(
1282 input_reports: input_reports,
1283 expected_events: expected_events,
1284 device_descriptor: descriptor,
1285 device_type: MouseBinding,
1286 );
1287 }
1288
1289 #[fasync::run_singlethreaded(test)]
1291 async fn down_scroll_up_scroll() {
1292 const PRIMARY_BUTTON: u8 = 1;
1293
1294 let (event_time_i64, event_time_u64) = testing_utilities::event_times();
1295 let first_report = testing_utilities::create_mouse_input_report_relative(
1296 Position::zero(),
1297 None, None, vec![PRIMARY_BUTTON],
1300 event_time_i64,
1301 );
1302 let second_report = testing_utilities::create_mouse_input_report_relative(
1303 Position::zero(),
1304 Some(1),
1305 None,
1306 vec![PRIMARY_BUTTON],
1307 event_time_i64,
1308 );
1309 let third_report = testing_utilities::create_mouse_input_report_relative(
1310 Position::zero(),
1311 None, None, vec![],
1314 event_time_i64,
1315 );
1316 let fourth_report = testing_utilities::create_mouse_input_report_relative(
1317 Position::zero(),
1318 Some(1),
1319 None,
1320 vec![],
1321 event_time_i64,
1322 );
1323
1324 let descriptor = mouse_device_descriptor(DEVICE_ID);
1325
1326 let input_reports = vec![first_report, second_report, third_report, fourth_report];
1327 let expected_events = vec![
1328 testing_utilities::create_mouse_event(
1329 MouseLocation::Relative(Default::default()),
1330 None, None, None, MousePhase::Down,
1334 SortedVecSet::from(vec![PRIMARY_BUTTON]),
1335 SortedVecSet::from(vec![PRIMARY_BUTTON]),
1336 event_time_u64,
1337 &descriptor,
1338 ),
1339 testing_utilities::create_mouse_event(
1340 MouseLocation::Relative(Default::default()),
1341 wheel_delta_ticks(1),
1342 None,
1343 Some(PrecisionScroll::No),
1344 MousePhase::Wheel,
1345 SortedVecSet::from(vec![PRIMARY_BUTTON]),
1346 SortedVecSet::from(vec![PRIMARY_BUTTON]),
1347 event_time_u64,
1348 &descriptor,
1349 ),
1350 testing_utilities::create_mouse_event(
1351 MouseLocation::Relative(Default::default()),
1352 None, None, None, MousePhase::Up,
1356 SortedVecSet::from(vec![PRIMARY_BUTTON]),
1357 SortedVecSet::new(),
1358 event_time_u64,
1359 &descriptor,
1360 ),
1361 testing_utilities::create_mouse_event(
1362 MouseLocation::Relative(Default::default()),
1363 wheel_delta_ticks(1),
1364 None,
1365 Some(PrecisionScroll::No),
1366 MousePhase::Wheel,
1367 SortedVecSet::new(),
1368 SortedVecSet::new(),
1369 event_time_u64,
1370 &descriptor,
1371 ),
1372 ];
1373
1374 assert_input_report_sequence_generates_events!(
1375 input_reports: input_reports,
1376 expected_events: expected_events,
1377 device_descriptor: descriptor,
1378 device_type: MouseBinding,
1379 );
1380 }
1381
1382 #[fasync::run_singlethreaded(test)]
1384 async fn down_scroll_bundle_up_scroll_bundle() {
1385 const PRIMARY_BUTTON: u8 = 1;
1386
1387 let (event_time_i64, event_time_u64) = testing_utilities::event_times();
1388 let first_report = testing_utilities::create_mouse_input_report_relative(
1389 Position::zero(),
1390 Some(1),
1391 None,
1392 vec![PRIMARY_BUTTON],
1393 event_time_i64,
1394 );
1395 let second_report = testing_utilities::create_mouse_input_report_relative(
1396 Position::zero(),
1397 Some(1),
1398 None,
1399 vec![],
1400 event_time_i64,
1401 );
1402 let third_report = testing_utilities::create_mouse_input_report_relative(
1403 Position::zero(),
1404 Some(1),
1405 None,
1406 vec![],
1407 event_time_i64,
1408 );
1409
1410 let descriptor = mouse_device_descriptor(DEVICE_ID);
1411
1412 let input_reports = vec![first_report, second_report, third_report];
1413 let expected_events = vec![
1414 testing_utilities::create_mouse_event(
1415 MouseLocation::Relative(Default::default()),
1416 None, None, None, MousePhase::Down,
1420 SortedVecSet::from(vec![PRIMARY_BUTTON]),
1421 SortedVecSet::from(vec![PRIMARY_BUTTON]),
1422 event_time_u64,
1423 &descriptor,
1424 ),
1425 testing_utilities::create_mouse_event(
1426 MouseLocation::Relative(Default::default()),
1427 wheel_delta_ticks(1),
1428 None,
1429 Some(PrecisionScroll::No),
1430 MousePhase::Wheel,
1431 SortedVecSet::from(vec![PRIMARY_BUTTON]),
1432 SortedVecSet::from(vec![PRIMARY_BUTTON]),
1433 event_time_u64,
1434 &descriptor,
1435 ),
1436 testing_utilities::create_mouse_event(
1437 MouseLocation::Relative(Default::default()),
1438 wheel_delta_ticks(1),
1439 None,
1440 Some(PrecisionScroll::No),
1441 MousePhase::Wheel,
1442 SortedVecSet::from(vec![PRIMARY_BUTTON]),
1443 SortedVecSet::from(vec![PRIMARY_BUTTON]),
1444 event_time_u64,
1445 &descriptor,
1446 ),
1447 testing_utilities::create_mouse_event(
1448 MouseLocation::Relative(Default::default()),
1449 None, None, None, MousePhase::Up,
1453 SortedVecSet::from(vec![PRIMARY_BUTTON]),
1454 SortedVecSet::new(),
1455 event_time_u64,
1456 &descriptor,
1457 ),
1458 testing_utilities::create_mouse_event(
1459 MouseLocation::Relative(Default::default()),
1460 wheel_delta_ticks(1),
1461 None,
1462 Some(PrecisionScroll::No),
1463 MousePhase::Wheel,
1464 SortedVecSet::new(),
1465 SortedVecSet::new(),
1466 event_time_u64,
1467 &descriptor,
1468 ),
1469 ];
1470
1471 assert_input_report_sequence_generates_events!(
1472 input_reports: input_reports,
1473 expected_events: expected_events,
1474 device_descriptor: descriptor,
1475 device_type: MouseBinding,
1476 );
1477 }
1478}