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 fidl_fuchsia_input_report as fidl_input_report;
11use fuchsia_inspect::ArrayProperty;
12use fuchsia_inspect::health::Reporter;
13use futures::channel::mpsc::{UnboundedReceiver, UnboundedSender};
14use metrics_registry::*;
15use sorted_vec_map::SortedVecSet;
16use zx;
17
18pub type MouseButton = u8;
19
20#[derive(Copy, Clone, Debug, PartialEq)]
22pub enum PrecisionScroll {
23 Yes,
25 No,
27}
28
29#[derive(Copy, Clone, Debug, PartialEq)]
31pub enum MouseLocation {
32 Relative(RelativeLocation),
34
35 Absolute(Position),
37}
38
39#[derive(Copy, Clone, Debug, PartialEq)]
40pub enum MousePhase {
41 Down, Move, Up, Wheel, }
46
47#[derive(Copy, Clone, Debug, PartialEq)]
49pub struct RelativeLocation {
50 pub counts: Position,
52}
53
54impl Default for RelativeLocation {
55 fn default() -> Self {
56 RelativeLocation { counts: Position::zero() }
57 }
58}
59
60#[derive(Clone, Debug, PartialEq)]
63pub struct WheelDelta {
64 pub ticks: i64,
65 pub physical_pixel: Option<f32>,
66}
67
68#[derive(Debug)]
90pub struct MouseEvent {
91 pub location: MouseLocation,
93
94 pub wheel_delta_v: Option<WheelDelta>,
96
97 pub wheel_delta_h: Option<WheelDelta>,
99
100 pub is_precision_scroll: Option<PrecisionScroll>,
102
103 pub phase: MousePhase,
105
106 pub affected_buttons: SortedVecSet<MouseButton>,
108
109 pub pressed_buttons: SortedVecSet<MouseButton>,
111
112 pub wake_lease: Option<zx::EventPair>,
114}
115
116impl Clone for MouseEvent {
117 fn clone(&self) -> Self {
118 log::debug!("MouseEvent cloned without wake lease.");
119 Self {
120 location: self.location,
121 wheel_delta_v: self.wheel_delta_v.clone(),
122 wheel_delta_h: self.wheel_delta_h.clone(),
123 is_precision_scroll: self.is_precision_scroll,
124 phase: self.phase,
125 affected_buttons: self.affected_buttons.clone(),
126 pressed_buttons: self.pressed_buttons.clone(),
127 wake_lease: None,
128 }
129 }
130}
131
132impl PartialEq for MouseEvent {
133 fn eq(&self, other: &Self) -> bool {
134 self.location == other.location
135 && self.wheel_delta_v == other.wheel_delta_v
136 && self.wheel_delta_h == other.wheel_delta_h
137 && self.is_precision_scroll == other.is_precision_scroll
138 && self.phase == other.phase
139 && self.affected_buttons == other.affected_buttons
140 && self.pressed_buttons == other.pressed_buttons
141 }
142}
143
144impl MouseEvent {
145 pub fn new(
153 location: MouseLocation,
154 wheel_delta_v: Option<WheelDelta>,
155 wheel_delta_h: Option<WheelDelta>,
156 phase: MousePhase,
157 affected_buttons: SortedVecSet<MouseButton>,
158 pressed_buttons: SortedVecSet<MouseButton>,
159 is_precision_scroll: Option<PrecisionScroll>,
160 wake_lease: Option<zx::EventPair>,
161 ) -> MouseEvent {
162 MouseEvent {
163 location,
164 wheel_delta_v,
165 wheel_delta_h,
166 phase,
167 affected_buttons,
168 pressed_buttons,
169 is_precision_scroll,
170 wake_lease,
171 }
172 }
173
174 pub fn record_inspect(&self, node: &fuchsia_inspect::Node) {
175 match self.location {
176 MouseLocation::Relative(pos) => {
177 node.record_child("location_relative", move |location_node| {
178 location_node.record_double("x", f64::from(pos.counts.x));
179 location_node.record_double("y", f64::from(pos.counts.y));
180 })
181 }
182 MouseLocation::Absolute(pos) => {
183 node.record_child("location_absolute", move |location_node| {
184 location_node.record_double("x", f64::from(pos.x));
185 location_node.record_double("y", f64::from(pos.y));
186 })
187 }
188 };
189
190 if let Some(wheel_delta_v) = &self.wheel_delta_v {
191 node.record_child("wheel_delta_v", move |wheel_delta_v_node| {
192 wheel_delta_v_node.record_int("ticks", wheel_delta_v.ticks);
193 if let Some(physical_pixel) = wheel_delta_v.physical_pixel {
194 wheel_delta_v_node.record_double("physical_pixel", f64::from(physical_pixel));
195 }
196 });
197 }
198
199 if let Some(wheel_delta_h) = &self.wheel_delta_h {
200 node.record_child("wheel_delta_h", move |wheel_delta_h_node| {
201 wheel_delta_h_node.record_int("ticks", wheel_delta_h.ticks);
202 if let Some(physical_pixel) = wheel_delta_h.physical_pixel {
203 wheel_delta_h_node.record_double("physical_pixel", f64::from(physical_pixel));
204 }
205 });
206 }
207
208 if let Some(is_precision_scroll) = self.is_precision_scroll {
209 match is_precision_scroll {
210 PrecisionScroll::Yes => node.record_string("is_precision_scroll", "yes"),
211 PrecisionScroll::No => node.record_string("is_precision_scroll", "no"),
212 }
213 }
214
215 match self.phase {
216 MousePhase::Down => node.record_string("phase", "down"),
217 MousePhase::Move => node.record_string("phase", "move"),
218 MousePhase::Up => node.record_string("phase", "up"),
219 MousePhase::Wheel => node.record_string("phase", "wheel"),
220 }
221
222 let affected_buttons_node =
223 node.create_uint_array("affected_buttons", self.affected_buttons.len());
224 self.affected_buttons.iter().enumerate().for_each(|(i, button)| {
225 affected_buttons_node.set(i, *button);
226 });
227 node.record(affected_buttons_node);
228
229 let pressed_buttons_node =
230 node.create_uint_array("pressed_buttons", self.pressed_buttons.len());
231 self.pressed_buttons.iter().enumerate().for_each(|(i, button)| {
232 pressed_buttons_node.set(i, *button);
233 });
234 node.record(pressed_buttons_node);
235 }
236}
237
238pub struct MouseBinding {
244 event_sender: UnboundedSender<Vec<InputEvent>>,
246
247 device_descriptor: MouseDeviceDescriptor,
249}
250
251#[derive(Clone, Debug, Eq, PartialEq)]
252pub struct MouseDeviceDescriptor {
253 pub device_id: u32,
255
256 pub absolute_x_range: Option<fidl_input_report::Range>,
258
259 pub absolute_y_range: Option<fidl_input_report::Range>,
261
262 pub wheel_v_range: Option<fidl_input_report::Axis>,
264
265 pub wheel_h_range: Option<fidl_input_report::Axis>,
267
268 pub buttons: Option<Vec<MouseButton>>,
270}
271
272#[async_trait]
273impl input_device::InputDeviceBinding for MouseBinding {
274 fn input_event_sender(&self) -> UnboundedSender<Vec<InputEvent>> {
275 self.event_sender.clone()
276 }
277
278 fn get_device_descriptor(&self) -> input_device::InputDeviceDescriptor {
279 input_device::InputDeviceDescriptor::Mouse(self.device_descriptor.clone())
280 }
281}
282
283impl MouseBinding {
284 pub async fn new(
299 device_proxy: fidl_next::Client<fidl_next_fuchsia_input_report::InputDevice, Transport>,
300 device_id: u32,
301 input_event_sender: UnboundedSender<Vec<InputEvent>>,
302 device_node: fuchsia_inspect::Node,
303 _feature_flags: input_device::InputPipelineFeatureFlags,
304 metrics_logger: metrics::MetricsLogger,
305 ) -> Result<Self, Error> {
306 let (device_binding, mut inspect_status) =
307 Self::bind_device(&device_proxy, device_id, input_event_sender, device_node).await?;
308 inspect_status.health_node.set_ok();
309 input_device::initialize_report_stream(
310 device_proxy,
311 device_binding.get_device_descriptor(),
312 device_binding.input_event_sender(),
313 inspect_status,
314 metrics_logger,
315 _feature_flags,
316 Self::process_reports,
317 );
318
319 Ok(device_binding)
320 }
321
322 async fn bind_device(
334 device: &fidl_next::Client<fidl_next_fuchsia_input_report::InputDevice, Transport>,
335 device_id: u32,
336 input_event_sender: UnboundedSender<Vec<InputEvent>>,
337 device_node: fuchsia_inspect::Node,
338 ) -> Result<(Self, InputDeviceStatus), Error> {
339 let mut input_device_status = InputDeviceStatus::new(device_node);
340 let device_descriptor: fidl_next_fuchsia_input_report::DeviceDescriptor = match device
341 .get_descriptor()
342 .await
343 {
344 Ok(res) => res.descriptor,
345 Err(_) => {
346 input_device_status.health_node.set_unhealthy("Could not get device descriptor.");
347 return Err(format_err!("Could not get descriptor for device_id: {}", device_id));
348 }
349 };
350
351 let mouse_descriptor = device_descriptor.mouse.ok_or_else(|| {
352 input_device_status
353 .health_node
354 .set_unhealthy("DeviceDescriptor does not have a MouseDescriptor.");
355 format_err!("DeviceDescriptor does not have a MouseDescriptor")
356 })?;
357
358 let mouse_input_descriptor = mouse_descriptor.input.ok_or_else(|| {
359 input_device_status
360 .health_node
361 .set_unhealthy("MouseDescriptor does not have a MouseInputDescriptor.");
362 format_err!("MouseDescriptor does not have a MouseInputDescriptor")
363 })?;
364
365 let device_descriptor: MouseDeviceDescriptor = MouseDeviceDescriptor {
366 device_id,
367 absolute_x_range: mouse_input_descriptor
368 .position_x
369 .as_ref()
370 .map(|axis| utils::range_to_old(&axis.range)),
371 absolute_y_range: mouse_input_descriptor
372 .position_y
373 .as_ref()
374 .map(|axis| utils::range_to_old(&axis.range)),
375 wheel_v_range: utils::axis_to_old(mouse_input_descriptor.scroll_v.as_ref()),
376 wheel_h_range: utils::axis_to_old(mouse_input_descriptor.scroll_h.as_ref()),
377 buttons: mouse_input_descriptor.buttons,
378 };
379
380 Ok((Self { event_sender: input_event_sender, device_descriptor }, input_device_status))
381 }
382
383 fn process_reports(
405 reports: &[fidl_next_fuchsia_input_report::wire::InputReport<'_>],
406 mut previous_state: Option<input_device::PreviousDeviceState>,
407 device_descriptor: &input_device::InputDeviceDescriptor,
408 input_event_sender: &mut UnboundedSender<Vec<InputEvent>>,
409 inspect_status: &InputDeviceStatus,
410 metrics_logger: &metrics::MetricsLogger,
411 _feature_flags: &input_device::InputPipelineFeatureFlags,
412 ) -> (Option<input_device::PreviousDeviceState>, Option<UnboundedReceiver<InputEvent>>) {
413 fuchsia_trace::duration!("input", "mouse-binding-process-reports", "num_reports" => reports.len());
414 for report in reports {
415 previous_state = Self::process_report(
416 report,
417 previous_state,
418 device_descriptor,
419 input_event_sender,
420 inspect_status,
421 metrics_logger,
422 );
423 }
424 (previous_state, None)
425 }
426
427 fn process_report(
428 report: &fidl_next_fuchsia_input_report::wire::InputReport<'_>,
429 previous_state: Option<input_device::PreviousDeviceState>,
430 device_descriptor: &input_device::InputDeviceDescriptor,
431 input_event_sender: &mut UnboundedSender<Vec<input_device::InputEvent>>,
432 inspect_status: &InputDeviceStatus,
433 metrics_logger: &metrics::MetricsLogger,
434 ) -> Option<input_device::PreviousDeviceState> {
435 if let Some(trace_id) = report.trace_id() {
436 fuchsia_trace::flow_end!("input", "input_report", trace_id.0.into());
437 }
438
439 let wake_lease = utils::duplicate_wake_lease(report.wake_lease());
443
444 inspect_status.count_received_report_wire(report);
445 let mouse_report = match report.mouse() {
447 Some(mouse) => mouse,
448 None => {
449 inspect_status.count_filtered_report();
450 return previous_state;
451 }
452 };
453
454 let previous_buttons: SortedVecSet<MouseButton> = match previous_state {
455 Some(input_device::PreviousDeviceState::Mouse { pressed_buttons }) => pressed_buttons,
456 _ => SortedVecSet::new(),
457 };
458 let current_buttons: SortedVecSet<MouseButton> =
459 buttons_from_mouse_report_wire(mouse_report);
460
461 send_mouse_event(
467 MouseLocation::Relative(Default::default()),
468 None, None, MousePhase::Down,
471 current_buttons.difference(&previous_buttons).cloned().collect(),
472 current_buttons.clone(),
473 device_descriptor,
474 input_event_sender,
475 inspect_status,
476 metrics_logger,
477 wake_lease.as_ref().map(|lease| {
478 lease
479 .duplicate_handle(zx::Rights::SAME_RIGHTS)
480 .expect("failed to duplicate event pair")
481 }),
482 );
483
484 let location = if let (Some(position_x), Some(position_y)) =
486 (mouse_report.position_x(), mouse_report.position_y())
487 {
488 MouseLocation::Absolute(Position { x: position_x.0 as f32, y: position_y.0 as f32 })
489 } else {
490 let movement_x = mouse_report.movement_x().map(|x| x.0).unwrap_or_default() as f32;
491 let movement_y = mouse_report.movement_y().map(|y| y.0).unwrap_or_default() as f32;
492 MouseLocation::Relative(RelativeLocation {
493 counts: Position { x: movement_x, y: movement_y },
494 })
495 };
496
497 send_mouse_event(
501 location,
502 None, None, MousePhase::Move,
505 current_buttons.union(&previous_buttons).cloned().collect(),
506 current_buttons.union(&previous_buttons).cloned().collect(),
507 device_descriptor,
508 input_event_sender,
509 inspect_status,
510 metrics_logger,
511 wake_lease.as_ref().map(|lease| {
512 lease
513 .duplicate_handle(zx::Rights::SAME_RIGHTS)
514 .expect("failed to duplicate event pair")
515 }),
516 );
517
518 let wheel_delta_v = mouse_report
519 .scroll_v()
520 .map(|ticks| WheelDelta { ticks: ticks.0, physical_pixel: None });
521
522 let wheel_delta_h = mouse_report
523 .scroll_h()
524 .map(|ticks| WheelDelta { ticks: ticks.0, physical_pixel: None });
525
526 send_mouse_event(
528 MouseLocation::Relative(Default::default()),
529 wheel_delta_v,
530 wheel_delta_h,
531 MousePhase::Wheel,
532 current_buttons.union(&previous_buttons).cloned().collect(),
533 current_buttons.union(&previous_buttons).cloned().collect(),
534 device_descriptor,
535 input_event_sender,
536 inspect_status,
537 metrics_logger,
538 wake_lease.as_ref().map(|lease| {
539 lease
540 .duplicate_handle(zx::Rights::SAME_RIGHTS)
541 .expect("failed to duplicate event pair")
542 }),
543 );
544
545 send_mouse_event(
551 MouseLocation::Relative(Default::default()),
552 None, None, MousePhase::Up,
555 previous_buttons.difference(¤t_buttons).cloned().collect(),
556 current_buttons.clone(),
557 device_descriptor,
558 input_event_sender,
559 inspect_status,
560 metrics_logger,
561 wake_lease,
562 );
563
564 Some(input_device::PreviousDeviceState::Mouse { pressed_buttons: current_buttons })
565 }
566}
567
568fn send_mouse_event(
583 location: MouseLocation,
584 wheel_delta_v: Option<WheelDelta>,
585 wheel_delta_h: Option<WheelDelta>,
586 phase: MousePhase,
587 affected_buttons: SortedVecSet<MouseButton>,
588 pressed_buttons: SortedVecSet<MouseButton>,
589 device_descriptor: &input_device::InputDeviceDescriptor,
590 sender: &mut UnboundedSender<Vec<input_device::InputEvent>>,
591 inspect_status: &InputDeviceStatus,
592 metrics_logger: &metrics::MetricsLogger,
593 wake_lease: Option<zx::EventPair>,
594) {
595 if (phase == MousePhase::Down || phase == MousePhase::Up) && affected_buttons.is_empty() {
597 return;
598 }
599
600 if phase == MousePhase::Move && location == MouseLocation::Relative(Default::default()) {
603 return;
604 }
605
606 if phase == MousePhase::Wheel && wheel_delta_v.is_none() && wheel_delta_h.is_none() {
608 return;
609 }
610
611 let trace_id = fuchsia_trace::Id::new();
612 fuchsia_trace::duration!("input", "mouse-binding-send-event");
613 fuchsia_trace::flow_begin!("input", "event_in_input_pipeline", trace_id);
614
615 let event = input_device::InputEvent {
616 device_event: input_device::InputDeviceEvent::Mouse(MouseEvent::new(
617 location,
618 wheel_delta_v,
619 wheel_delta_h,
620 phase,
621 affected_buttons,
622 pressed_buttons,
623 match phase {
624 MousePhase::Wheel => Some(PrecisionScroll::No),
625 _ => None,
626 },
627 wake_lease,
628 )),
629 device_descriptor: device_descriptor.clone(),
630 event_time: zx::MonotonicInstant::get(),
631 handled: Handled::No,
632 trace_id: Some(trace_id),
633 };
634 let events = vec![event];
635 inspect_status.count_generated_events(&events);
636
637 if let Err(e) = sender.unbounded_send(events) {
638 metrics_logger.log_error(
639 InputPipelineErrorMetricDimensionEvent::MouseFailedToSendEvent,
640 std::format!("Failed to send MouseEvent with error: {:?}", e),
641 );
642 }
643}
644
645fn buttons_from_mouse_report_wire(
646 mouse_report: &fidl_next_fuchsia_input_report::wire::MouseInputReport<'_>,
647) -> SortedVecSet<MouseButton> {
648 mouse_report
649 .pressed_buttons()
650 .map(|buttons| SortedVecSet::from_iter(buttons.iter().copied()))
651 .unwrap_or_default()
652}
653
654#[cfg(test)]
655mod tests {
656 use super::*;
657 use crate::testing_utilities;
658 use fuchsia_async as fasync;
659 use futures::StreamExt;
660 use sorted_vec_map::SortedVecSet;
661
662 const DEVICE_ID: u32 = 1;
663
664 fn mouse_device_descriptor(device_id: u32) -> input_device::InputDeviceDescriptor {
665 input_device::InputDeviceDescriptor::Mouse(MouseDeviceDescriptor {
666 device_id,
667 absolute_x_range: None,
668 absolute_y_range: None,
669 wheel_v_range: Some(fidl_fuchsia_input_report::Axis {
670 range: fidl_input_report::Range { min: -1, max: 1 },
671 unit: fidl_input_report::Unit {
672 type_: fidl_input_report::UnitType::Other,
673 exponent: 1,
674 },
675 }),
676 wheel_h_range: Some(fidl_fuchsia_input_report::Axis {
677 range: fidl_input_report::Range { min: -1, max: 1 },
678 unit: fidl_input_report::Unit {
679 type_: fidl_input_report::UnitType::Other,
680 exponent: 1,
681 },
682 }),
683 buttons: None,
684 })
685 }
686
687 fn wheel_delta_ticks(ticks: i64) -> Option<WheelDelta> {
688 Some(WheelDelta { ticks, physical_pixel: None })
689 }
690
691 #[fasync::run_singlethreaded(test)]
693 async fn movement_without_button() {
694 let (event_time_i64, event_time_u64) = testing_utilities::event_times();
695 let first_report = testing_utilities::create_mouse_input_report_relative(
696 Position { x: 10.0, y: 16.0 },
697 None, None, vec![],
700 event_time_i64,
701 );
702 let descriptor = mouse_device_descriptor(DEVICE_ID);
703
704 let input_reports = vec![first_report];
705 let expected_events = vec![testing_utilities::create_mouse_event(
706 MouseLocation::Relative(RelativeLocation { counts: Position { x: 10.0, y: 16.0 } }),
707 None, None, None, MousePhase::Move,
711 SortedVecSet::new(),
712 SortedVecSet::new(),
713 event_time_u64,
714 &descriptor,
715 )];
716
717 assert_input_report_sequence_generates_events!(
718 input_reports: input_reports,
719 expected_events: expected_events,
720 device_descriptor: descriptor,
721 device_type: MouseBinding,
722 );
723 }
724
725 #[fasync::run_singlethreaded(test)]
727 async fn down_without_movement() {
728 let mouse_button: MouseButton = 3;
729 let (event_time_i64, event_time_u64) = testing_utilities::event_times();
730 let first_report = testing_utilities::create_mouse_input_report_relative(
731 Position::zero(),
732 None, None, vec![mouse_button],
735 event_time_i64,
736 );
737 let descriptor = mouse_device_descriptor(DEVICE_ID);
738
739 let input_reports = vec![first_report];
740 let expected_events = vec![testing_utilities::create_mouse_event(
741 MouseLocation::Relative(Default::default()),
742 None, None, None, MousePhase::Down,
746 SortedVecSet::from(vec![mouse_button]),
747 SortedVecSet::from(vec![mouse_button]),
748 event_time_u64,
749 &descriptor,
750 )];
751
752 assert_input_report_sequence_generates_events!(
753 input_reports: input_reports,
754 expected_events: expected_events,
755 device_descriptor: descriptor,
756 device_type: MouseBinding,
757 );
758 }
759
760 #[fasync::run_singlethreaded(test)]
763 async fn down_with_movement() {
764 let mouse_button: MouseButton = 3;
765 let (event_time_i64, event_time_u64) = testing_utilities::event_times();
766 let first_report = testing_utilities::create_mouse_input_report_relative(
767 Position { x: 10.0, y: 16.0 },
768 None, None, vec![mouse_button],
771 event_time_i64,
772 );
773 let descriptor = mouse_device_descriptor(DEVICE_ID);
774
775 let input_reports = vec![first_report];
776 let expected_events = vec![
777 testing_utilities::create_mouse_event(
778 MouseLocation::Relative(Default::default()),
779 None, None, None, MousePhase::Down,
783 SortedVecSet::from(vec![mouse_button]),
784 SortedVecSet::from(vec![mouse_button]),
785 event_time_u64,
786 &descriptor,
787 ),
788 testing_utilities::create_mouse_event(
789 MouseLocation::Relative(RelativeLocation { counts: Position { x: 10.0, y: 16.0 } }),
790 None, None, None, MousePhase::Move,
794 SortedVecSet::from(vec![mouse_button]),
795 SortedVecSet::from(vec![mouse_button]),
796 event_time_u64,
797 &descriptor,
798 ),
799 ];
800
801 assert_input_report_sequence_generates_events!(
802 input_reports: input_reports,
803 expected_events: expected_events,
804 device_descriptor: descriptor,
805 device_type: MouseBinding,
806 );
807 }
808
809 #[fasync::run_singlethreaded(test)]
811 async fn down_up() {
812 let button = 1;
813 let (event_time_i64, event_time_u64) = testing_utilities::event_times();
814 let first_report = testing_utilities::create_mouse_input_report_relative(
815 Position::zero(),
816 None, None, vec![button],
819 event_time_i64,
820 );
821 let second_report = testing_utilities::create_mouse_input_report_relative(
822 Position::zero(),
823 None, None, vec![],
826 event_time_i64,
827 );
828 let descriptor = mouse_device_descriptor(DEVICE_ID);
829
830 let input_reports = vec![first_report, second_report];
831 let expected_events = vec![
832 testing_utilities::create_mouse_event(
833 MouseLocation::Relative(Default::default()),
834 None, None, None, MousePhase::Down,
838 SortedVecSet::from(vec![button]),
839 SortedVecSet::from(vec![button]),
840 event_time_u64,
841 &descriptor,
842 ),
843 testing_utilities::create_mouse_event(
844 MouseLocation::Relative(Default::default()),
845 None, None, None, MousePhase::Up,
849 SortedVecSet::from(vec![button]),
850 SortedVecSet::new(),
851 event_time_u64,
852 &descriptor,
853 ),
854 ];
855
856 assert_input_report_sequence_generates_events!(
857 input_reports: input_reports,
858 expected_events: expected_events,
859 device_descriptor: descriptor,
860 device_type: MouseBinding,
861 );
862 }
863
864 #[fasync::run_singlethreaded(test)]
866 async fn down_up_with_movement() {
867 let button = 1;
868
869 let (event_time_i64, event_time_u64) = testing_utilities::event_times();
870 let first_report = testing_utilities::create_mouse_input_report_relative(
871 Position::zero(),
872 None, None, vec![button],
875 event_time_i64,
876 );
877 let second_report = testing_utilities::create_mouse_input_report_relative(
878 Position { x: 10.0, y: 16.0 },
879 None, None, vec![],
882 event_time_i64,
883 );
884 let descriptor = mouse_device_descriptor(DEVICE_ID);
885
886 let input_reports = vec![first_report, second_report];
887 let expected_events = vec![
888 testing_utilities::create_mouse_event(
889 MouseLocation::Relative(Default::default()),
890 None, None, None, MousePhase::Down,
894 SortedVecSet::from(vec![button]),
895 SortedVecSet::from(vec![button]),
896 event_time_u64,
897 &descriptor,
898 ),
899 testing_utilities::create_mouse_event(
900 MouseLocation::Relative(RelativeLocation { counts: Position { x: 10.0, y: 16.0 } }),
901 None, None, None, MousePhase::Move,
905 SortedVecSet::from(vec![button]),
906 SortedVecSet::from(vec![button]),
907 event_time_u64,
908 &descriptor,
909 ),
910 testing_utilities::create_mouse_event(
911 MouseLocation::Relative(Default::default()),
912 None, None, None, MousePhase::Up,
916 SortedVecSet::from(vec![button]),
917 SortedVecSet::new(),
918 event_time_u64,
919 &descriptor,
920 ),
921 ];
922
923 assert_input_report_sequence_generates_events!(
924 input_reports: input_reports,
925 expected_events: expected_events,
926 device_descriptor: descriptor,
927 device_type: MouseBinding,
928 );
929 }
930
931 #[fasync::run_singlethreaded(test)]
935 async fn down_move_up() {
936 let button = 1;
937
938 let (event_time_i64, event_time_u64) = testing_utilities::event_times();
939 let first_report = testing_utilities::create_mouse_input_report_relative(
940 Position::zero(),
941 None, None, vec![button],
944 event_time_i64,
945 );
946 let second_report = testing_utilities::create_mouse_input_report_relative(
947 Position { x: 10.0, y: 16.0 },
948 None, None, vec![button],
951 event_time_i64,
952 );
953 let third_report = testing_utilities::create_mouse_input_report_relative(
954 Position::zero(),
955 None, None, vec![],
958 event_time_i64,
959 );
960 let descriptor = mouse_device_descriptor(DEVICE_ID);
961
962 let input_reports = vec![first_report, second_report, third_report];
963 let expected_events = vec![
964 testing_utilities::create_mouse_event(
965 MouseLocation::Relative(Default::default()),
966 None, None, None, MousePhase::Down,
970 SortedVecSet::from(vec![button]),
971 SortedVecSet::from(vec![button]),
972 event_time_u64,
973 &descriptor,
974 ),
975 testing_utilities::create_mouse_event(
976 MouseLocation::Relative(RelativeLocation { counts: Position { x: 10.0, y: 16.0 } }),
977 None, None, None, MousePhase::Move,
981 SortedVecSet::from(vec![button]),
982 SortedVecSet::from(vec![button]),
983 event_time_u64,
984 &descriptor,
985 ),
986 testing_utilities::create_mouse_event(
987 MouseLocation::Relative(Default::default()),
988 None, None, None, MousePhase::Up,
992 SortedVecSet::from(vec![button]),
993 SortedVecSet::new(),
994 event_time_u64,
995 &descriptor,
996 ),
997 ];
998
999 assert_input_report_sequence_generates_events!(
1000 input_reports: input_reports,
1001 expected_events: expected_events,
1002 device_descriptor: descriptor,
1003 device_type: MouseBinding,
1004 );
1005 }
1006
1007 #[fasync::run_until_stalled(test)]
1009 async fn absolute_movement_to_origin() {
1010 let (event_time_i64, event_time_u64) = testing_utilities::event_times();
1011 let descriptor = mouse_device_descriptor(DEVICE_ID);
1012
1013 let input_reports = vec![testing_utilities::create_mouse_input_report_absolute(
1014 Position::zero(),
1015 None, None, vec![],
1018 event_time_i64,
1019 )];
1020 let expected_events = vec![testing_utilities::create_mouse_event(
1021 MouseLocation::Absolute(Position { x: 0.0, y: 0.0 }),
1022 None, None, None, MousePhase::Move,
1026 SortedVecSet::new(),
1027 SortedVecSet::new(),
1028 event_time_u64,
1029 &descriptor,
1030 )];
1031
1032 assert_input_report_sequence_generates_events!(
1033 input_reports: input_reports,
1034 expected_events: expected_events,
1035 device_descriptor: descriptor,
1036 device_type: MouseBinding,
1037 );
1038 }
1039
1040 #[fasync::run_until_stalled(test)]
1043 async fn report_with_both_movement_and_position() {
1044 let relative_movement = Position { x: 5.0, y: 5.0 };
1045 let absolute_position = Position { x: 10.0, y: 10.0 };
1046 let expected_location = MouseLocation::Absolute(absolute_position);
1047
1048 let (event_time_i64, event_time_u64) = testing_utilities::event_times();
1049 let descriptor = mouse_device_descriptor(DEVICE_ID);
1050
1051 let input_reports = vec![fidl_next_fuchsia_input_report::InputReport {
1052 event_time: Some(event_time_i64),
1053 keyboard: None,
1054 mouse: Some(fidl_next_fuchsia_input_report::MouseInputReport {
1055 movement_x: Some(relative_movement.x as i64),
1056 movement_y: Some(relative_movement.y as i64),
1057 position_x: Some(absolute_position.x as i64),
1058 position_y: Some(absolute_position.y as i64),
1059 scroll_h: None,
1060 scroll_v: None,
1061 pressed_buttons: None,
1062 ..Default::default()
1063 }),
1064 touch: None,
1065 sensor: None,
1066 consumer_control: None,
1067 trace_id: None,
1068 ..Default::default()
1069 }];
1070 let expected_events = vec![testing_utilities::create_mouse_event(
1071 expected_location,
1072 None, None, None, MousePhase::Move,
1076 SortedVecSet::new(),
1077 SortedVecSet::new(),
1078 event_time_u64,
1079 &descriptor,
1080 )];
1081
1082 assert_input_report_sequence_generates_events!(
1083 input_reports: input_reports,
1084 expected_events: expected_events,
1085 device_descriptor: descriptor,
1086 device_type: MouseBinding,
1087 );
1088 }
1089
1090 #[fasync::run_singlethreaded(test)]
1093 async fn down_down() {
1094 const PRIMARY_BUTTON: u8 = 1;
1095 const SECONDARY_BUTTON: u8 = 2;
1096
1097 let (event_time_i64, event_time_u64) = testing_utilities::event_times();
1098 let first_report = testing_utilities::create_mouse_input_report_relative(
1099 Position::zero(),
1100 None, None, vec![PRIMARY_BUTTON],
1103 event_time_i64,
1104 );
1105 let second_report = testing_utilities::create_mouse_input_report_relative(
1106 Position::zero(),
1107 None, None, vec![PRIMARY_BUTTON, SECONDARY_BUTTON],
1110 event_time_i64,
1111 );
1112 let descriptor = mouse_device_descriptor(DEVICE_ID);
1113
1114 let input_reports = vec![first_report, second_report];
1115 let expected_events = vec![
1116 testing_utilities::create_mouse_event(
1117 MouseLocation::Relative(Default::default()),
1118 None, None, None, MousePhase::Down,
1122 SortedVecSet::from(vec![PRIMARY_BUTTON]),
1123 SortedVecSet::from(vec![PRIMARY_BUTTON]),
1124 event_time_u64,
1125 &descriptor,
1126 ),
1127 testing_utilities::create_mouse_event(
1128 MouseLocation::Relative(Default::default()),
1129 None, None, None, MousePhase::Down,
1133 SortedVecSet::from(vec![SECONDARY_BUTTON]),
1134 SortedVecSet::from(vec![PRIMARY_BUTTON, SECONDARY_BUTTON]),
1135 event_time_u64,
1136 &descriptor,
1137 ),
1138 ];
1139
1140 assert_input_report_sequence_generates_events!(
1141 input_reports: input_reports,
1142 expected_events: expected_events,
1143 device_descriptor: descriptor,
1144 device_type: MouseBinding,
1145 );
1146 }
1147
1148 #[fasync::run_singlethreaded(test)]
1158 async fn down_down_up_up() {
1159 const PRIMARY_BUTTON: u8 = 1;
1160 const SECONDARY_BUTTON: u8 = 2;
1161
1162 let (event_time_i64, event_time_u64) = testing_utilities::event_times();
1163 let first_report = testing_utilities::create_mouse_input_report_relative(
1164 Position::zero(),
1165 None, None, vec![PRIMARY_BUTTON],
1168 event_time_i64,
1169 );
1170 let second_report = testing_utilities::create_mouse_input_report_relative(
1171 Position::zero(),
1172 None, None, vec![PRIMARY_BUTTON, SECONDARY_BUTTON],
1175 event_time_i64,
1176 );
1177 let third_report = testing_utilities::create_mouse_input_report_relative(
1178 Position::zero(),
1179 None, None, vec![SECONDARY_BUTTON],
1182 event_time_i64,
1183 );
1184 let fourth_report = testing_utilities::create_mouse_input_report_relative(
1185 Position::zero(),
1186 None, None, vec![],
1189 event_time_i64,
1190 );
1191 let descriptor = mouse_device_descriptor(DEVICE_ID);
1192
1193 let input_reports = vec![first_report, second_report, third_report, fourth_report];
1194 let expected_events = vec![
1195 testing_utilities::create_mouse_event(
1196 MouseLocation::Relative(Default::default()),
1197 None, None, None, MousePhase::Down,
1201 SortedVecSet::from(vec![PRIMARY_BUTTON]),
1202 SortedVecSet::from(vec![PRIMARY_BUTTON]),
1203 event_time_u64,
1204 &descriptor,
1205 ),
1206 testing_utilities::create_mouse_event(
1207 MouseLocation::Relative(Default::default()),
1208 None, None, None, MousePhase::Down,
1212 SortedVecSet::from(vec![SECONDARY_BUTTON]),
1213 SortedVecSet::from(vec![PRIMARY_BUTTON, SECONDARY_BUTTON]),
1214 event_time_u64,
1215 &descriptor,
1216 ),
1217 testing_utilities::create_mouse_event(
1218 MouseLocation::Relative(Default::default()),
1219 None, None, None, MousePhase::Up,
1223 SortedVecSet::from(vec![PRIMARY_BUTTON]),
1224 SortedVecSet::from(vec![SECONDARY_BUTTON]),
1225 event_time_u64,
1226 &descriptor,
1227 ),
1228 testing_utilities::create_mouse_event(
1229 MouseLocation::Relative(Default::default()),
1230 None, None, None, MousePhase::Up,
1234 SortedVecSet::from(vec![SECONDARY_BUTTON]),
1235 SortedVecSet::new(),
1236 event_time_u64,
1237 &descriptor,
1238 ),
1239 ];
1240
1241 assert_input_report_sequence_generates_events!(
1242 input_reports: input_reports,
1243 expected_events: expected_events,
1244 device_descriptor: descriptor,
1245 device_type: MouseBinding,
1246 );
1247 }
1248
1249 #[fasync::run_singlethreaded(test)]
1251 async fn scroll() {
1252 let (event_time_i64, event_time_u64) = testing_utilities::event_times();
1253 let first_report = testing_utilities::create_mouse_input_report_relative(
1254 Position::zero(),
1255 Some(1),
1256 None,
1257 vec![],
1258 event_time_i64,
1259 );
1260 let second_report = testing_utilities::create_mouse_input_report_relative(
1261 Position::zero(),
1262 None,
1263 Some(1),
1264 vec![],
1265 event_time_i64,
1266 );
1267
1268 let descriptor = mouse_device_descriptor(DEVICE_ID);
1269
1270 let input_reports = vec![first_report, second_report];
1271 let expected_events = vec![
1272 testing_utilities::create_mouse_event(
1273 MouseLocation::Relative(Default::default()),
1274 wheel_delta_ticks(1),
1275 None,
1276 Some(PrecisionScroll::No),
1277 MousePhase::Wheel,
1278 SortedVecSet::new(),
1279 SortedVecSet::new(),
1280 event_time_u64,
1281 &descriptor,
1282 ),
1283 testing_utilities::create_mouse_event(
1284 MouseLocation::Relative(Default::default()),
1285 None,
1286 wheel_delta_ticks(1),
1287 Some(PrecisionScroll::No),
1288 MousePhase::Wheel,
1289 SortedVecSet::new(),
1290 SortedVecSet::new(),
1291 event_time_u64,
1292 &descriptor,
1293 ),
1294 ];
1295
1296 assert_input_report_sequence_generates_events!(
1297 input_reports: input_reports,
1298 expected_events: expected_events,
1299 device_descriptor: descriptor,
1300 device_type: MouseBinding,
1301 );
1302 }
1303
1304 #[fasync::run_singlethreaded(test)]
1306 async fn down_scroll_up_scroll() {
1307 const PRIMARY_BUTTON: u8 = 1;
1308
1309 let (event_time_i64, event_time_u64) = testing_utilities::event_times();
1310 let first_report = testing_utilities::create_mouse_input_report_relative(
1311 Position::zero(),
1312 None, None, vec![PRIMARY_BUTTON],
1315 event_time_i64,
1316 );
1317 let second_report = testing_utilities::create_mouse_input_report_relative(
1318 Position::zero(),
1319 Some(1),
1320 None,
1321 vec![PRIMARY_BUTTON],
1322 event_time_i64,
1323 );
1324 let third_report = testing_utilities::create_mouse_input_report_relative(
1325 Position::zero(),
1326 None, None, vec![],
1329 event_time_i64,
1330 );
1331 let fourth_report = testing_utilities::create_mouse_input_report_relative(
1332 Position::zero(),
1333 Some(1),
1334 None,
1335 vec![],
1336 event_time_i64,
1337 );
1338
1339 let descriptor = mouse_device_descriptor(DEVICE_ID);
1340
1341 let input_reports = vec![first_report, second_report, third_report, fourth_report];
1342 let expected_events = vec![
1343 testing_utilities::create_mouse_event(
1344 MouseLocation::Relative(Default::default()),
1345 None, None, None, MousePhase::Down,
1349 SortedVecSet::from(vec![PRIMARY_BUTTON]),
1350 SortedVecSet::from(vec![PRIMARY_BUTTON]),
1351 event_time_u64,
1352 &descriptor,
1353 ),
1354 testing_utilities::create_mouse_event(
1355 MouseLocation::Relative(Default::default()),
1356 wheel_delta_ticks(1),
1357 None,
1358 Some(PrecisionScroll::No),
1359 MousePhase::Wheel,
1360 SortedVecSet::from(vec![PRIMARY_BUTTON]),
1361 SortedVecSet::from(vec![PRIMARY_BUTTON]),
1362 event_time_u64,
1363 &descriptor,
1364 ),
1365 testing_utilities::create_mouse_event(
1366 MouseLocation::Relative(Default::default()),
1367 None, None, None, MousePhase::Up,
1371 SortedVecSet::from(vec![PRIMARY_BUTTON]),
1372 SortedVecSet::new(),
1373 event_time_u64,
1374 &descriptor,
1375 ),
1376 testing_utilities::create_mouse_event(
1377 MouseLocation::Relative(Default::default()),
1378 wheel_delta_ticks(1),
1379 None,
1380 Some(PrecisionScroll::No),
1381 MousePhase::Wheel,
1382 SortedVecSet::new(),
1383 SortedVecSet::new(),
1384 event_time_u64,
1385 &descriptor,
1386 ),
1387 ];
1388
1389 assert_input_report_sequence_generates_events!(
1390 input_reports: input_reports,
1391 expected_events: expected_events,
1392 device_descriptor: descriptor,
1393 device_type: MouseBinding,
1394 );
1395 }
1396
1397 #[fasync::run_singlethreaded(test)]
1399 async fn down_scroll_bundle_up_scroll_bundle() {
1400 const PRIMARY_BUTTON: u8 = 1;
1401
1402 let (event_time_i64, event_time_u64) = testing_utilities::event_times();
1403 let first_report = testing_utilities::create_mouse_input_report_relative(
1404 Position::zero(),
1405 Some(1),
1406 None,
1407 vec![PRIMARY_BUTTON],
1408 event_time_i64,
1409 );
1410 let second_report = testing_utilities::create_mouse_input_report_relative(
1411 Position::zero(),
1412 Some(1),
1413 None,
1414 vec![],
1415 event_time_i64,
1416 );
1417 let third_report = testing_utilities::create_mouse_input_report_relative(
1418 Position::zero(),
1419 Some(1),
1420 None,
1421 vec![],
1422 event_time_i64,
1423 );
1424
1425 let descriptor = mouse_device_descriptor(DEVICE_ID);
1426
1427 let input_reports = vec![first_report, second_report, third_report];
1428 let expected_events = vec![
1429 testing_utilities::create_mouse_event(
1430 MouseLocation::Relative(Default::default()),
1431 None, None, None, MousePhase::Down,
1435 SortedVecSet::from(vec![PRIMARY_BUTTON]),
1436 SortedVecSet::from(vec![PRIMARY_BUTTON]),
1437 event_time_u64,
1438 &descriptor,
1439 ),
1440 testing_utilities::create_mouse_event(
1441 MouseLocation::Relative(Default::default()),
1442 wheel_delta_ticks(1),
1443 None,
1444 Some(PrecisionScroll::No),
1445 MousePhase::Wheel,
1446 SortedVecSet::from(vec![PRIMARY_BUTTON]),
1447 SortedVecSet::from(vec![PRIMARY_BUTTON]),
1448 event_time_u64,
1449 &descriptor,
1450 ),
1451 testing_utilities::create_mouse_event(
1452 MouseLocation::Relative(Default::default()),
1453 wheel_delta_ticks(1),
1454 None,
1455 Some(PrecisionScroll::No),
1456 MousePhase::Wheel,
1457 SortedVecSet::from(vec![PRIMARY_BUTTON]),
1458 SortedVecSet::from(vec![PRIMARY_BUTTON]),
1459 event_time_u64,
1460 &descriptor,
1461 ),
1462 testing_utilities::create_mouse_event(
1463 MouseLocation::Relative(Default::default()),
1464 None, None, None, MousePhase::Up,
1468 SortedVecSet::from(vec![PRIMARY_BUTTON]),
1469 SortedVecSet::new(),
1470 event_time_u64,
1471 &descriptor,
1472 ),
1473 testing_utilities::create_mouse_event(
1474 MouseLocation::Relative(Default::default()),
1475 wheel_delta_ticks(1),
1476 None,
1477 Some(PrecisionScroll::No),
1478 MousePhase::Wheel,
1479 SortedVecSet::new(),
1480 SortedVecSet::new(),
1481 event_time_u64,
1482 &descriptor,
1483 ),
1484 ];
1485
1486 assert_input_report_sequence_generates_events!(
1487 input_reports: input_reports,
1488 expected_events: expected_events,
1489 device_descriptor: descriptor,
1490 device_type: MouseBinding,
1491 );
1492 }
1493}