1#![warn(clippy::await_holding_refcell_ref)]
6
7use crate::input_handler::{InputHandler, InputHandlerStatus};
8use crate::utils::{CursorMessage, Position, Size};
9use crate::{input_device, metrics, mouse_binding};
10use anyhow::{Context, Error, Result, anyhow};
11use async_trait::async_trait;
12use async_utils::hanging_get::client::HangingGetStream;
13use fidl::endpoints::create_proxy;
14use fidl_fuchsia_input_report::Range;
15use fuchsia_component::client::connect_to_protocol;
16use fuchsia_inspect::health::Reporter;
17use futures::SinkExt;
18use futures::channel::mpsc::Sender;
19use futures::stream::StreamExt;
20use metrics_registry::*;
21use std::cell::{Ref, RefCell, RefMut};
22use std::collections::HashMap;
23use std::rc::Rc;
24use {
25 fidl_fuchsia_ui_pointerinjector as pointerinjector,
26 fidl_fuchsia_ui_pointerinjector_configuration as pointerinjector_config,
27};
28
29const MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL: f32 = 10.0;
37
38pub struct MouseInjectorHandler {
41 mutable_state: RefCell<MutableState>,
43
44 context_view_ref: fidl_fuchsia_ui_views::ViewRef,
47
48 target_view_ref: fidl_fuchsia_ui_views::ViewRef,
51
52 max_position: Position,
55
56 injector_registry_proxy: pointerinjector::RegistryProxy,
58
59 configuration_proxy: pointerinjector_config::SetupProxy,
61
62 pub inspect_status: InputHandlerStatus,
64
65 metrics_logger: metrics::MetricsLogger,
66}
67
68struct MutableState {
69 viewport: Option<pointerinjector::Viewport>,
72
73 injectors: HashMap<u32, pointerinjector::DeviceProxy>,
75
76 current_position: Position,
78
79 cursor_message_sender: Sender<CursorMessage>,
81}
82
83#[async_trait(?Send)]
84impl InputHandler for MouseInjectorHandler {
85 async fn handle_input_event(
86 self: Rc<Self>,
87 mut input_event: input_device::InputEvent,
88 ) -> Vec<input_device::InputEvent> {
89 match input_event {
90 input_device::InputEvent {
91 device_event: input_device::InputDeviceEvent::Mouse(ref mouse_event),
92 device_descriptor:
93 input_device::InputDeviceDescriptor::Mouse(ref mouse_device_descriptor),
94 event_time,
95 handled: input_device::Handled::No,
96 trace_id,
97 } => {
98 fuchsia_trace::duration!(c"input", c"mouse_injector_hander");
99 let trace_id = match trace_id {
100 Some(id) => {
101 fuchsia_trace::flow_end!(c"input", c"event_in_input_pipeline", id.into());
102 id
103 }
104 None => fuchsia_trace::Id::random(),
105 };
106
107 self.inspect_status
108 .count_received_event(input_device::InputEvent::from(input_event.clone()));
109 if let Err(e) =
111 self.update_cursor_renderer(mouse_event, &mouse_device_descriptor).await
112 {
113 self.metrics_logger.log_error(
114 InputPipelineErrorMetricDimensionEvent::MouseInjectorUpdateCursorRendererFailed,
115 std::format!("update_cursor_renderer failed: {}", e));
116 }
117
118 if let Err(e) = self
120 .ensure_injector_registered(&mouse_event, &mouse_device_descriptor, event_time)
121 .await
122 {
123 self.metrics_logger.log_error(
124 InputPipelineErrorMetricDimensionEvent::MouseInjectorEnsureInjectorRegisteredFailed,
125 std::format!("ensure_injector_registered failed: {}", e));
126 }
127
128 if let Err(e) = self
130 .send_event_to_scenic(
131 &mouse_event,
132 &mouse_device_descriptor,
133 event_time,
134 trace_id.into(),
135 )
136 .await
137 {
138 self.metrics_logger.log_error(
139 InputPipelineErrorMetricDimensionEvent::MouseInjectorSendEventToScenicFailed,
140 std::format!("send_event_to_scenic failed: {}", e));
141 }
142
143 input_event.handled = input_device::Handled::Yes;
145 self.inspect_status.count_handled_event();
146 }
147 _ => {}
148 }
149 vec![input_event]
150 }
151
152 fn set_handler_healthy(self: std::rc::Rc<Self>) {
153 self.inspect_status.health_node.borrow_mut().set_ok();
154 }
155
156 fn set_handler_unhealthy(self: std::rc::Rc<Self>, msg: &str) {
157 self.inspect_status.health_node.borrow_mut().set_unhealthy(msg);
158 }
159}
160
161impl MouseInjectorHandler {
162 pub async fn new(
175 display_size: Size,
176 cursor_message_sender: Sender<CursorMessage>,
177 input_handlers_node: &fuchsia_inspect::Node,
178 metrics_logger: metrics::MetricsLogger,
179 ) -> Result<Rc<Self>, Error> {
180 let configuration_proxy = connect_to_protocol::<pointerinjector_config::SetupMarker>()?;
181 let injector_registry_proxy = connect_to_protocol::<pointerinjector::RegistryMarker>()?;
182
183 Self::new_handler(
184 configuration_proxy,
185 injector_registry_proxy,
186 display_size,
187 cursor_message_sender,
188 input_handlers_node,
189 metrics_logger,
190 )
191 .await
192 }
193
194 pub async fn new_with_config_proxy(
210 configuration_proxy: pointerinjector_config::SetupProxy,
211 display_size: Size,
212 cursor_message_sender: Sender<CursorMessage>,
213 input_handlers_node: &fuchsia_inspect::Node,
214 metrics_logger: metrics::MetricsLogger,
215 ) -> Result<Rc<Self>, Error> {
216 let injector_registry_proxy = connect_to_protocol::<pointerinjector::RegistryMarker>()?;
217 Self::new_handler(
218 configuration_proxy,
219 injector_registry_proxy,
220 display_size,
221 cursor_message_sender,
222 input_handlers_node,
223 metrics_logger,
224 )
225 .await
226 }
227
228 fn inner(&self) -> Ref<'_, MutableState> {
229 self.mutable_state.borrow()
230 }
231
232 fn inner_mut(&self) -> RefMut<'_, MutableState> {
233 self.mutable_state.borrow_mut()
234 }
235
236 async fn new_handler(
252 configuration_proxy: pointerinjector_config::SetupProxy,
253 injector_registry_proxy: pointerinjector::RegistryProxy,
254 display_size: Size,
255 cursor_message_sender: Sender<CursorMessage>,
256 input_handlers_node: &fuchsia_inspect::Node,
257 metrics_logger: metrics::MetricsLogger,
258 ) -> Result<Rc<Self>, Error> {
259 let (context_view_ref, target_view_ref) = configuration_proxy.get_view_refs().await?;
261 let inspect_status = InputHandlerStatus::new(
262 input_handlers_node,
263 "mouse_injector_handler",
264 false,
265 );
266 let handler = Rc::new(Self {
267 mutable_state: RefCell::new(MutableState {
268 viewport: None,
269 injectors: HashMap::new(),
270 current_position: Position {
272 x: display_size.width / 2.0,
273 y: display_size.height / 2.0,
274 },
275 cursor_message_sender,
276 }),
277 context_view_ref,
278 target_view_ref,
279 max_position: Position { x: display_size.width, y: display_size.height },
280 injector_registry_proxy,
281 configuration_proxy,
282 inspect_status,
283 metrics_logger,
284 });
285
286 Ok(handler)
287 }
288
289 async fn ensure_injector_registered(
297 self: &Rc<Self>,
298 mouse_event: &mouse_binding::MouseEvent,
299 mouse_descriptor: &mouse_binding::MouseDeviceDescriptor,
300 event_time: zx::MonotonicInstant,
301 ) -> Result<(), anyhow::Error> {
302 if self.inner().injectors.contains_key(&mouse_descriptor.device_id) {
303 return Ok(());
304 }
305
306 let (device_proxy, device_server) = create_proxy::<pointerinjector::DeviceMarker>();
308 let context = fuchsia_scenic::duplicate_view_ref(&self.context_view_ref)
309 .context("Failed to duplicate context view ref.")?;
310 let target = fuchsia_scenic::duplicate_view_ref(&self.target_view_ref)
311 .context("Failed to duplicate target view ref.")?;
312
313 let viewport = self.inner().viewport.clone();
314 let config = pointerinjector::Config {
315 device_id: Some(mouse_descriptor.device_id),
316 device_type: Some(pointerinjector::DeviceType::Mouse),
317 context: Some(pointerinjector::Context::View(context)),
318 target: Some(pointerinjector::Target::View(target)),
319 viewport,
320 dispatch_policy: Some(pointerinjector::DispatchPolicy::MouseHoverAndLatchInTarget),
321 scroll_v_range: mouse_descriptor.wheel_v_range.clone(),
322 scroll_h_range: mouse_descriptor.wheel_h_range.clone(),
323 buttons: mouse_descriptor.buttons.clone(),
324 ..Default::default()
325 };
326
327 self.injector_registry_proxy
329 .register(config, device_server)
330 .await
331 .context("Failed to register injector.")?;
332 log::info!("Registered injector with device id {:?}", mouse_descriptor.device_id);
333
334 self.inner_mut().injectors.insert(mouse_descriptor.device_id, device_proxy.clone());
336
337 let events_to_send = vec![self.create_pointer_sample_event(
339 mouse_event,
340 event_time,
341 pointerinjector::EventPhase::Add,
342 self.inner().current_position,
343 None,
344 None,
345 )];
346 device_proxy.inject(events_to_send).await.context("Failed to ADD new MouseDevice.")?;
347
348 Ok(())
349 }
350
351 async fn update_cursor_renderer(
362 &self,
363 mouse_event: &mouse_binding::MouseEvent,
364 mouse_descriptor: &mouse_binding::MouseDeviceDescriptor,
365 ) -> Result<(), anyhow::Error> {
366 let mut new_position = match (mouse_event.location, mouse_descriptor) {
367 (
368 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
369 millimeters,
370 }),
371 _,
372 ) => {
373 self.inner().current_position
374 + self.relative_movement_mm_to_phyical_pixel(millimeters)
375 }
376 (
377 mouse_binding::MouseLocation::Absolute(position),
378 mouse_binding::MouseDeviceDescriptor {
379 absolute_x_range: Some(x_range),
380 absolute_y_range: Some(y_range),
381 ..
382 },
383 ) => self.scale_absolute_position(&position, &x_range, &y_range),
384 (mouse_binding::MouseLocation::Absolute(_), _) => {
385 return Err(anyhow!(
386 "Received an Absolute mouse location without absolute device ranges."
387 ));
388 }
389 };
390 Position::clamp(&mut new_position, Position::zero(), self.max_position);
391 self.inner_mut().current_position = new_position;
392
393 let mut cursor_message_sender = self.inner().cursor_message_sender.clone();
394 cursor_message_sender
395 .send(CursorMessage::SetPosition(new_position))
396 .await
397 .context("Failed to send current mouse position to cursor renderer")?;
398
399 Ok(())
400 }
401
402 fn scale_absolute_position(
410 &self,
411 position: &Position,
412 x_range: &Range,
413 y_range: &Range,
414 ) -> Position {
415 let range_min = Position { x: x_range.min as f32, y: y_range.min as f32 };
416 let range_max = Position { x: x_range.max as f32, y: y_range.max as f32 };
417 self.max_position * ((*position - range_min) / (range_max - range_min))
418 }
419
420 async fn send_event_to_scenic(
427 &self,
428 mouse_event: &mouse_binding::MouseEvent,
429 mouse_descriptor: &mouse_binding::MouseDeviceDescriptor,
430 event_time: zx::MonotonicInstant,
431 tracing_id: u64,
432 ) -> Result<(), anyhow::Error> {
433 let injector = self.inner().injectors.get(&mouse_descriptor.device_id).cloned();
434 if let Some(injector) = injector {
435 let relative_motion = match mouse_event.location {
436 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
437 millimeters: offset_mm,
438 }) if mouse_event.phase == mouse_binding::MousePhase::Move => {
439 let offset = self.relative_movement_mm_to_phyical_pixel(offset_mm);
440 Some([offset.x, offset.y])
441 }
442 _ => None,
443 };
444 let events_to_send = vec![self.create_pointer_sample_event(
445 mouse_event,
446 event_time,
447 pointerinjector::EventPhase::Change,
448 self.inner().current_position,
449 relative_motion,
450 Some(tracing_id),
451 )];
452
453 fuchsia_trace::flow_begin!(c"input", c"dispatch_event_to_scenic", tracing_id.into());
454
455 let _ = injector.inject(events_to_send).await;
456
457 Ok(())
458 } else {
459 Err(anyhow::format_err!(
460 "No injector found for mouse device {}.",
461 mouse_descriptor.device_id
462 ))
463 }
464 }
465
466 fn create_pointer_sample_event(
475 &self,
476 mouse_event: &mouse_binding::MouseEvent,
477 event_time: zx::MonotonicInstant,
478 phase: pointerinjector::EventPhase,
479 current_position: Position,
480 relative_motion: Option<[f32; 2]>,
481 trace_id: Option<u64>,
482 ) -> pointerinjector::Event {
483 let pointer_sample = pointerinjector::PointerSample {
484 pointer_id: Some(0),
485 phase: Some(phase),
486 position_in_viewport: Some([current_position.x, current_position.y]),
487 scroll_v: match mouse_event.wheel_delta_v {
488 Some(mouse_binding::WheelDelta {
489 raw_data: mouse_binding::RawWheelDelta::Ticks(tick),
490 ..
491 }) => Some(tick),
492 _ => None,
493 },
494 scroll_h: match mouse_event.wheel_delta_h {
495 Some(mouse_binding::WheelDelta {
496 raw_data: mouse_binding::RawWheelDelta::Ticks(tick),
497 ..
498 }) => Some(tick),
499 _ => None,
500 },
501 scroll_v_physical_pixel: match mouse_event.wheel_delta_v {
502 Some(mouse_binding::WheelDelta { physical_pixel: Some(pixel), .. }) => {
503 Some(pixel.into())
504 }
505 _ => None,
506 },
507 scroll_h_physical_pixel: match mouse_event.wheel_delta_h {
508 Some(mouse_binding::WheelDelta { physical_pixel: Some(pixel), .. }) => {
509 Some(pixel.into())
510 }
511 _ => None,
512 },
513 is_precision_scroll: match mouse_event.phase {
514 mouse_binding::MousePhase::Wheel => match mouse_event.is_precision_scroll {
515 Some(mouse_binding::PrecisionScroll::Yes) => Some(true),
516 Some(mouse_binding::PrecisionScroll::No) => Some(false),
517 None => {
518 self.metrics_logger.log_error(
519 InputPipelineErrorMetricDimensionEvent::MouseInjectorMissingIsPrecisionScroll,
520 "mouse wheel event does not have value in is_precision_scroll.");
521 None
522 }
523 },
524 _ => None,
525 },
526 pressed_buttons: Some(Vec::from_iter(mouse_event.pressed_buttons.iter().cloned())),
527 relative_motion,
528 ..Default::default()
529 };
530 pointerinjector::Event {
531 timestamp: Some(event_time.into_nanos()),
532 data: Some(pointerinjector::Data::PointerSample(pointer_sample)),
533 trace_flow_id: trace_id,
534 ..Default::default()
535 }
536 }
537
538 pub async fn watch_viewport(self: Rc<Self>) {
540 let configuration_proxy = self.configuration_proxy.clone();
541 let mut viewport_stream = HangingGetStream::new(
542 configuration_proxy,
543 pointerinjector_config::SetupProxy::watch_viewport,
544 );
545 loop {
546 match viewport_stream.next().await {
547 Some(Ok(new_viewport)) => {
548 self.inner_mut().viewport = Some(new_viewport.clone());
550
551 let injectors = self.inner().injectors.values().cloned().collect::<Vec<_>>();
553 for injector in injectors {
554 let events = vec![pointerinjector::Event {
555 timestamp: Some(fuchsia_async::MonotonicInstant::now().into_nanos()),
556 data: Some(pointerinjector::Data::Viewport(new_viewport.clone())),
557 trace_flow_id: Some(fuchsia_trace::Id::random().into()),
558 ..Default::default()
559 }];
560 injector.inject(events).await.expect("Failed to inject updated viewport.");
561 }
562 }
563 Some(Err(e)) => {
564 self.metrics_logger.log_error(
565 InputPipelineErrorMetricDimensionEvent::MouseInjectorErrorWhileReadingViewportUpdate,
566 std::format!("Error while reading viewport update: {}", e));
567 return;
568 }
569 None => {
570 self.metrics_logger.log_error(
571 InputPipelineErrorMetricDimensionEvent::MouseInjectorViewportUpdateStreamTerminatedUnexpectedly,
572 "Viewport update stream terminated unexpectedly");
573 return;
574 }
575 }
576 }
577 }
578
579 fn relative_movement_mm_to_phyical_pixel(&self, movement_mm: Position) -> Position {
583 Position {
584 x: movement_mm.x * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
585 y: movement_mm.y * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
586 }
587 }
588}
589
590#[cfg(test)]
591mod tests {
592 use super::*;
593 use crate::testing_utilities::{
594 assert_handler_ignores_input_event_sequence, create_mouse_event,
595 create_mouse_event_with_handled, create_mouse_pointer_sample_event,
596 create_mouse_pointer_sample_event_phase_add,
597 create_mouse_pointer_sample_event_with_wheel_physical_pixel,
598 };
599 use assert_matches::assert_matches;
600 use futures::channel::mpsc;
601 use pretty_assertions::assert_eq;
602 use std::collections::HashSet;
603 use std::ops::Add;
604 use test_case::test_case;
605 use {
606 fidl_fuchsia_input_report as fidl_input_report,
607 fidl_fuchsia_ui_pointerinjector as pointerinjector, fuchsia_async as fasync,
608 };
609
610 const DISPLAY_WIDTH_IN_PHYSICAL_PX: f32 = 100.0;
611 const DISPLAY_HEIGHT_IN_PHYSICAL_PX: f32 = 100.0;
612 const COUNTS_PER_MM: u32 = 12;
613
614 const DESCRIPTOR: input_device::InputDeviceDescriptor =
616 input_device::InputDeviceDescriptor::Mouse(mouse_binding::MouseDeviceDescriptor {
617 device_id: 1,
618 absolute_x_range: Some(fidl_input_report::Range { min: 0, max: 100 }),
619 absolute_y_range: Some(fidl_input_report::Range { min: 0, max: 100 }),
620 wheel_v_range: Some(fidl_input_report::Axis {
621 range: fidl_input_report::Range { min: -1, max: 1 },
622 unit: fidl_input_report::Unit {
623 type_: fidl_input_report::UnitType::Other,
624 exponent: 0,
625 },
626 }),
627 wheel_h_range: Some(fidl_input_report::Axis {
628 range: fidl_input_report::Range { min: -1, max: 1 },
629 unit: fidl_input_report::Unit {
630 type_: fidl_input_report::UnitType::Other,
631 exponent: 0,
632 },
633 }),
634 buttons: None,
635 counts_per_mm: COUNTS_PER_MM,
636 });
637
638 async fn handle_configuration_request_stream(
640 stream: &mut pointerinjector_config::SetupRequestStream,
641 ) {
642 if let Some(Ok(request)) = stream.next().await {
643 match request {
644 pointerinjector_config::SetupRequest::GetViewRefs { responder, .. } => {
645 let context = fuchsia_scenic::ViewRefPair::new()
646 .expect("Failed to create viewrefpair.")
647 .view_ref;
648 let target = fuchsia_scenic::ViewRefPair::new()
649 .expect("Failed to create viewrefpair.")
650 .view_ref;
651 let _ = responder.send(context, target);
652 }
653 _ => {}
654 };
655 }
656 }
657
658 async fn handle_registry_request_stream(
661 mut stream: pointerinjector::RegistryRequestStream,
662 injector_sender: futures::channel::oneshot::Sender<pointerinjector::DeviceRequestStream>,
663 ) {
664 if let Some(request) = stream.next().await {
665 match request {
666 Ok(pointerinjector::RegistryRequest::Register {
667 config: _,
668 injector,
669 responder,
670 ..
671 }) => {
672 let injector_stream = injector.into_stream();
673 let _ = injector_sender.send(injector_stream);
674 responder.send().expect("failed to respond");
675 }
676 _ => {}
677 };
678 } else {
679 panic!("RegistryRequestStream failed.");
680 }
681 }
682
683 async fn handle_registry_request_stream2(
685 mut stream: pointerinjector::RegistryRequestStream,
686 injector_sender: mpsc::UnboundedSender<Vec<pointerinjector::Event>>,
687 ) {
688 let (injector, responder) = match stream.next().await {
689 Some(Ok(pointerinjector::RegistryRequest::Register {
690 config: _,
691 injector,
692 responder,
693 ..
694 })) => (injector, responder),
695 other => panic!("expected register request, but got {:?}", other),
696 };
697 let injector_stream: pointerinjector::DeviceRequestStream = injector.into_stream();
698 responder.send().expect("failed to respond");
699 injector_stream
700 .for_each(|request| {
701 futures::future::ready({
702 match request {
703 Ok(pointerinjector::DeviceRequest::Inject {
704 events,
705 responder: device_injector_responder,
706 }) => {
707 let _ = injector_sender.unbounded_send(events);
708 device_injector_responder.send().expect("failed to respond")
709 }
710 Err(e) => panic!("FIDL error {}", e),
711 }
712 })
713 })
714 .await;
715 }
716
717 async fn handle_device_request_stream(
720 injector_stream_receiver: futures::channel::oneshot::Receiver<
721 pointerinjector::DeviceRequestStream,
722 >,
723 expected_events: Vec<pointerinjector::Event>,
724 ) {
725 let mut injector_stream =
726 injector_stream_receiver.await.expect("Failed to get DeviceRequestStream.");
727 for expected_event in expected_events {
728 match injector_stream.next().await {
729 Some(Ok(pointerinjector::DeviceRequest::Inject { events, responder })) => {
730 assert_eq!(events, vec![expected_event]);
731 responder.send().expect("failed to respond");
732 }
733 Some(Err(e)) => panic!("FIDL error {}", e),
734 None => panic!("Expected another event."),
735 }
736 }
737 }
738
739 fn create_viewport(min: f32, max: f32) -> pointerinjector::Viewport {
741 pointerinjector::Viewport {
742 extents: Some([[min, min], [max, max]]),
743 viewport_to_context_transform: None,
744 ..Default::default()
745 }
746 }
747
748 #[fuchsia::test]
751 fn receives_viewport_updates() {
752 let mut exec = fasync::TestExecutor::new();
753
754 let (configuration_proxy, mut configuration_request_stream) =
756 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
757 let (injector_registry_proxy, _) =
758 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
759 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(0);
760
761 let inspector = fuchsia_inspect::Inspector::default();
762 let test_node = inspector.root().create_child("test_node");
763
764 let mouse_handler_fut = MouseInjectorHandler::new_handler(
766 configuration_proxy,
767 injector_registry_proxy,
768 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
769 sender,
770 &test_node,
771 metrics::MetricsLogger::default(),
772 );
773 let config_request_stream_fut =
774 handle_configuration_request_stream(&mut configuration_request_stream);
775 let (mouse_handler_res, _) = exec.run_singlethreaded(futures::future::join(
776 mouse_handler_fut,
777 config_request_stream_fut,
778 ));
779 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
780
781 let (injector_device_proxy, mut injector_device_request_stream) =
783 fidl::endpoints::create_proxy_and_stream::<pointerinjector::DeviceMarker>();
784 mouse_handler.inner_mut().injectors.insert(1, injector_device_proxy);
785
786 {
788 let watch_viewport_fut = mouse_handler.clone().watch_viewport();
790 futures::pin_mut!(watch_viewport_fut);
791 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
792
793 match exec.run_singlethreaded(&mut configuration_request_stream.next()) {
795 Some(Ok(pointerinjector_config::SetupRequest::WatchViewport {
796 responder, ..
797 })) => {
798 responder.send(&create_viewport(0.0, 100.0)).expect("Failed to send viewport.");
799 }
800 other => panic!("Received unexpected value: {:?}", other),
801 };
802 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
803
804 exec.run_singlethreaded(async {
806 match injector_device_request_stream.next().await {
807 Some(Ok(pointerinjector::DeviceRequest::Inject { events, responder })) => {
808 assert_eq!(events.len(), 1);
809 assert!(events[0].data.is_some());
810 assert_eq!(
811 events[0].data,
812 Some(pointerinjector::Data::Viewport(create_viewport(0.0, 100.0)))
813 );
814 responder.send().expect("injector stream failed to respond.");
815 }
816 other => panic!("Received unexpected value: {:?}", other),
817 }
818 });
819
820 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
822
823 match exec.run_singlethreaded(&mut configuration_request_stream.next()) {
825 Some(Ok(pointerinjector_config::SetupRequest::WatchViewport {
826 responder, ..
827 })) => {
828 responder
829 .send(&create_viewport(100.0, 200.0))
830 .expect("Failed to send viewport.");
831 }
832 other => panic!("Received unexpected value: {:?}", other),
833 };
834
835 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
837 }
838
839 exec.run_singlethreaded(async {
841 match injector_device_request_stream.next().await {
842 Some(Ok(pointerinjector::DeviceRequest::Inject { events, responder })) => {
843 assert_eq!(events.len(), 1);
844 assert!(events[0].data.is_some());
845 assert_eq!(
846 events[0].data,
847 Some(pointerinjector::Data::Viewport(create_viewport(100.0, 200.0)))
848 );
849 responder.send().expect("injector stream failed to respond.");
850 }
851 other => panic!("Received unexpected value: {:?}", other),
852 }
853 });
854
855 let expected_viewport = create_viewport(100.0, 200.0);
857 assert_eq!(mouse_handler.inner().viewport, Some(expected_viewport));
858 }
859
860 fn wheel_delta_ticks(
861 ticks: i64,
862 physical_pixel: Option<f32>,
863 ) -> Option<mouse_binding::WheelDelta> {
864 Some(mouse_binding::WheelDelta {
865 raw_data: mouse_binding::RawWheelDelta::Ticks(ticks),
866 physical_pixel,
867 })
868 }
869
870 fn wheel_delta_mm(mm: f32, physical_pixel: Option<f32>) -> Option<mouse_binding::WheelDelta> {
871 Some(mouse_binding::WheelDelta {
872 raw_data: mouse_binding::RawWheelDelta::Millimeters(mm),
873 physical_pixel,
874 })
875 }
876
877 #[test_case(
880 mouse_binding::MouseLocation::Relative(
881 mouse_binding::RelativeLocation {
882 millimeters: Position { x: 1.0, y: 2.0 }
883 }),
884 Position {
885 x: DISPLAY_WIDTH_IN_PHYSICAL_PX / 2.0
886 + 1.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
887 y: DISPLAY_HEIGHT_IN_PHYSICAL_PX / 2.0
888 + 2.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
889 },
890 [
891 1.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
892 2.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
893 ]; "Valid move event."
894 )]
895 #[test_case(
896 mouse_binding::MouseLocation::Relative(
897 mouse_binding::RelativeLocation {
898 millimeters: Position {
899 x: DISPLAY_WIDTH_IN_PHYSICAL_PX / MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL + 2.0,
900 y: DISPLAY_HEIGHT_IN_PHYSICAL_PX / MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL + 1.0,
901 }}),
902 Position {
903 x: DISPLAY_WIDTH_IN_PHYSICAL_PX,
904 y: DISPLAY_HEIGHT_IN_PHYSICAL_PX,
905 },
906 [
907 DISPLAY_WIDTH_IN_PHYSICAL_PX + 2.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
908 DISPLAY_HEIGHT_IN_PHYSICAL_PX + 1.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
909 ]; "Move event exceeds max bounds."
910 )]
911 #[test_case(
912 mouse_binding::MouseLocation::Relative(
913 mouse_binding::RelativeLocation {
914 millimeters: Position {
915 x: -(DISPLAY_WIDTH_IN_PHYSICAL_PX / MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL + 2.0),
916 y: -(DISPLAY_HEIGHT_IN_PHYSICAL_PX / MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL + 1.0),
917 }}),
918 Position { x: 0.0, y: 0.0 },
919 [
920 -(DISPLAY_WIDTH_IN_PHYSICAL_PX + 2.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL),
921 -(DISPLAY_HEIGHT_IN_PHYSICAL_PX + 1.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL),
922 ]; "Move event exceeds min bounds."
923 )]
924 #[fuchsia::test(allow_stalls = false)]
925 async fn move_event(
926 move_location: mouse_binding::MouseLocation,
927 expected_position: Position,
928 expected_relative_motion: [f32; 2],
929 ) {
930 let (configuration_proxy, mut configuration_request_stream) =
932 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
933 let (injector_registry_proxy, injector_registry_request_stream) =
934 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
935 let config_request_stream_fut =
936 handle_configuration_request_stream(&mut configuration_request_stream);
937
938 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
940 let inspector = fuchsia_inspect::Inspector::default();
941 let test_node = inspector.root().create_child("test_node");
942 let mouse_handler_fut = MouseInjectorHandler::new_handler(
943 configuration_proxy,
944 injector_registry_proxy,
945 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
946 sender,
947 &test_node,
948 metrics::MetricsLogger::default(),
949 );
950 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
951 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
952
953 let event_time = zx::MonotonicInstant::get();
954 let input_event = create_mouse_event(
955 move_location,
956 None, None, None, mouse_binding::MousePhase::Move,
960 HashSet::new(),
961 HashSet::new(),
962 event_time,
963 &DESCRIPTOR,
964 );
965
966 let handle_event_fut = mouse_handler.handle_input_event(input_event);
968 let expected_events = vec![
969 create_mouse_pointer_sample_event_phase_add(vec![], expected_position, event_time),
970 create_mouse_pointer_sample_event(
971 pointerinjector::EventPhase::Change,
972 vec![],
973 expected_position,
974 Some(expected_relative_motion),
975 None, None, None, event_time,
979 ),
980 ];
981
982 let (injector_stream_sender, injector_stream_receiver) =
986 futures::channel::oneshot::channel::<pointerinjector::DeviceRequestStream>();
987 let registry_fut = handle_registry_request_stream(
988 injector_registry_request_stream,
989 injector_stream_sender,
990 );
991 let device_fut = handle_device_request_stream(injector_stream_receiver, expected_events);
992
993 let (handle_result, _, _) = futures::join!(handle_event_fut, registry_fut, device_fut);
996 match receiver.next().await {
997 Some(CursorMessage::SetPosition(position)) => {
998 pretty_assertions::assert_eq!(position, expected_position);
999 }
1000 Some(CursorMessage::SetVisibility(_)) => {
1001 panic!("Received unexpected cursor visibility update.")
1002 }
1003 None => panic!("Did not receive cursor update."),
1004 }
1005
1006 assert_matches!(
1008 handle_result.as_slice(),
1009 [input_device::InputEvent { handled: input_device::Handled::Yes, .. }]
1010 );
1011 }
1012
1013 #[fuchsia::test(allow_stalls = false)]
1016 async fn move_absolute_event() {
1017 const DEVICE_ID: u32 = 1;
1018
1019 let (configuration_proxy, mut configuration_request_stream) =
1021 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1022 let (injector_registry_proxy, injector_registry_request_stream) =
1023 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1024 let config_request_stream_fut =
1025 handle_configuration_request_stream(&mut configuration_request_stream);
1026
1027 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
1029 let inspector = fuchsia_inspect::Inspector::default();
1030 let test_node = inspector.root().create_child("test_node");
1031 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1032 configuration_proxy,
1033 injector_registry_proxy,
1034 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1035 sender,
1036 &test_node,
1037 metrics::MetricsLogger::default(),
1038 );
1039 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1040 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1041
1042 let cursor_location =
1058 mouse_binding::MouseLocation::Absolute(Position { x: -25.0, y: 25.0 });
1059 let event_time = zx::MonotonicInstant::get();
1060 let descriptor =
1061 input_device::InputDeviceDescriptor::Mouse(mouse_binding::MouseDeviceDescriptor {
1062 device_id: DEVICE_ID,
1063 absolute_x_range: Some(fidl_input_report::Range { min: -50, max: 50 }),
1064 absolute_y_range: Some(fidl_input_report::Range { min: -50, max: 50 }),
1065 wheel_v_range: None,
1066 wheel_h_range: None,
1067 buttons: None,
1068 counts_per_mm: COUNTS_PER_MM,
1069 });
1070 let input_event = create_mouse_event(
1071 cursor_location,
1072 None, None, None, mouse_binding::MousePhase::Move,
1076 HashSet::new(),
1077 HashSet::new(),
1078 event_time,
1079 &descriptor,
1080 );
1081
1082 let handle_event_fut = mouse_handler.handle_input_event(input_event);
1084 let expected_position = Position {
1085 x: DISPLAY_WIDTH_IN_PHYSICAL_PX * 0.25,
1086 y: DISPLAY_WIDTH_IN_PHYSICAL_PX * 0.75,
1087 };
1088 let expected_events = vec![
1089 create_mouse_pointer_sample_event_phase_add(vec![], expected_position, event_time),
1090 create_mouse_pointer_sample_event(
1091 pointerinjector::EventPhase::Change,
1092 vec![],
1093 expected_position,
1094 None, None, None, None, event_time,
1099 ),
1100 ];
1101
1102 let (injector_stream_sender, injector_stream_receiver) =
1106 futures::channel::oneshot::channel::<pointerinjector::DeviceRequestStream>();
1107 let registry_fut = handle_registry_request_stream(
1108 injector_registry_request_stream,
1109 injector_stream_sender,
1110 );
1111 let device_fut = handle_device_request_stream(injector_stream_receiver, expected_events);
1112
1113 let (handle_result, _, _) = futures::join!(handle_event_fut, registry_fut, device_fut);
1116 match receiver.next().await {
1117 Some(CursorMessage::SetPosition(position)) => {
1118 assert_eq!(position, expected_position);
1119 }
1120 Some(CursorMessage::SetVisibility(_)) => {
1121 panic!("Received unexpected cursor visibility update.")
1122 }
1123 None => panic!("Did not receive cursor update."),
1124 }
1125
1126 assert_matches!(
1128 handle_result.as_slice(),
1129 [input_device::InputEvent { handled: input_device::Handled::Yes, .. }]
1130 );
1131 }
1132
1133 #[test_case(
1135 mouse_binding::MousePhase::Down,
1136 vec![1], vec![1]; "Down event injects button press state."
1137 )]
1138 #[test_case(
1139 mouse_binding::MousePhase::Up,
1140 vec![1], vec![]; "Up event injects button press state."
1141 )]
1142 #[fuchsia::test(allow_stalls = false)]
1143 async fn button_state_event(
1144 phase: mouse_binding::MousePhase,
1145 affected_buttons: Vec<mouse_binding::MouseButton>,
1146 pressed_buttons: Vec<mouse_binding::MouseButton>,
1147 ) {
1148 let (configuration_proxy, mut configuration_request_stream) =
1150 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1151 let (injector_registry_proxy, injector_registry_request_stream) =
1152 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1153 let config_request_stream_fut =
1154 handle_configuration_request_stream(&mut configuration_request_stream);
1155
1156 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
1158 let inspector = fuchsia_inspect::Inspector::default();
1159 let test_node = inspector.root().create_child("test_node");
1160 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1161 configuration_proxy,
1162 injector_registry_proxy,
1163 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1164 sender,
1165 &test_node,
1166 metrics::MetricsLogger::default(),
1167 );
1168 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1169 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1170
1171 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
1172 let event_time = zx::MonotonicInstant::get();
1173
1174 let input_event = create_mouse_event(
1175 cursor_location,
1176 None, None, None, phase,
1180 HashSet::from_iter(affected_buttons.clone()),
1181 HashSet::from_iter(pressed_buttons.clone()),
1182 event_time,
1183 &DESCRIPTOR,
1184 );
1185
1186 let handle_event_fut = mouse_handler.handle_input_event(input_event);
1188 let expected_position = Position { x: 0.0, y: 0.0 };
1189 let expected_events = vec![
1190 create_mouse_pointer_sample_event_phase_add(
1191 pressed_buttons.clone(),
1192 expected_position,
1193 event_time,
1194 ),
1195 create_mouse_pointer_sample_event(
1196 pointerinjector::EventPhase::Change,
1197 pressed_buttons.clone(),
1198 expected_position,
1199 None, None, None, None, event_time,
1204 ),
1205 ];
1206
1207 let (injector_stream_sender, injector_stream_receiver) =
1211 futures::channel::oneshot::channel::<pointerinjector::DeviceRequestStream>();
1212 let registry_fut = handle_registry_request_stream(
1213 injector_registry_request_stream,
1214 injector_stream_sender,
1215 );
1216 let device_fut = handle_device_request_stream(injector_stream_receiver, expected_events);
1217
1218 let (handle_result, _, _) = futures::join!(handle_event_fut, registry_fut, device_fut);
1221 match receiver.next().await {
1222 Some(CursorMessage::SetPosition(position)) => {
1223 pretty_assertions::assert_eq!(position, expected_position);
1224 }
1225 Some(CursorMessage::SetVisibility(_)) => {
1226 panic!("Received unexpected cursor visibility update.")
1227 }
1228 None => panic!("Did not receive cursor update."),
1229 }
1230
1231 assert_matches!(
1233 handle_result.as_slice(),
1234 [input_device::InputEvent { handled: input_device::Handled::Yes, .. }]
1235 );
1236 }
1237
1238 #[fuchsia::test(allow_stalls = false)]
1240 async fn down_up_event() {
1241 let (configuration_proxy, mut configuration_request_stream) =
1243 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1244 let (injector_registry_proxy, injector_registry_request_stream) =
1245 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1246 let config_request_stream_fut =
1247 handle_configuration_request_stream(&mut configuration_request_stream);
1248
1249 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(2);
1253 let inspector = fuchsia_inspect::Inspector::default();
1254 let test_node = inspector.root().create_child("test_node");
1255 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1256 configuration_proxy,
1257 injector_registry_proxy,
1258 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1259 sender,
1260 &test_node,
1261 metrics::MetricsLogger::default(),
1262 );
1263 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1264 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1265
1266 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
1267 let event_time1 = zx::MonotonicInstant::get();
1268 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
1269
1270 let event1 = create_mouse_event(
1271 cursor_location,
1272 None, None, None, mouse_binding::MousePhase::Down,
1276 HashSet::from_iter(vec![1]),
1277 HashSet::from_iter(vec![1]),
1278 event_time1,
1279 &DESCRIPTOR,
1280 );
1281
1282 let event2 = create_mouse_event(
1283 cursor_location,
1284 None, None, None, mouse_binding::MousePhase::Up,
1288 HashSet::from_iter(vec![1]),
1289 HashSet::new(),
1290 event_time2,
1291 &DESCRIPTOR,
1292 );
1293
1294 let expected_position = Position { x: 0.0, y: 0.0 };
1295
1296 let (injector_stream_sender, injector_stream_receiver) =
1300 mpsc::unbounded::<Vec<pointerinjector::Event>>();
1301 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
1303 let registry_fut = handle_registry_request_stream2(
1304 injector_registry_request_stream,
1305 injector_stream_sender,
1306 );
1307
1308 let _registry_task = fasync::Task::local(registry_fut);
1310
1311 mouse_handler.clone().handle_input_event(event1).await;
1312 assert_eq!(
1313 injector_stream_receiver
1314 .next()
1315 .await
1316 .map(|events| events.into_iter().flatten().collect()),
1317 Some(vec![
1318 create_mouse_pointer_sample_event_phase_add(
1319 vec![1],
1320 expected_position,
1321 event_time1,
1322 ),
1323 create_mouse_pointer_sample_event(
1324 pointerinjector::EventPhase::Change,
1325 vec![1],
1326 expected_position,
1327 None, None, None, None, event_time1,
1332 )
1333 ])
1334 );
1335
1336 mouse_handler.clone().handle_input_event(event2).await;
1338 assert_eq!(
1339 injector_stream_receiver
1340 .next()
1341 .await
1342 .map(|events| events.into_iter().flatten().collect()),
1343 Some(vec![create_mouse_pointer_sample_event(
1344 pointerinjector::EventPhase::Change,
1345 vec![],
1346 expected_position,
1347 None, None, None, None, event_time2,
1352 )])
1353 );
1354
1355 match receiver.next().await {
1357 Some(CursorMessage::SetPosition(position)) => {
1358 assert_eq!(position, expected_position);
1359 }
1360 Some(CursorMessage::SetVisibility(_)) => {
1361 panic!("Received unexpected cursor visibility update.")
1362 }
1363 None => panic!("Did not receive cursor update."),
1364 }
1365 }
1366
1367 #[fuchsia::test(allow_stalls = false)]
1377 async fn down_down_up_up_event() {
1378 let (configuration_proxy, mut configuration_request_stream) =
1380 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1381 let (injector_registry_proxy, injector_registry_request_stream) =
1382 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1383 let config_request_stream_fut =
1384 handle_configuration_request_stream(&mut configuration_request_stream);
1385
1386 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(4);
1390 let inspector = fuchsia_inspect::Inspector::default();
1391 let test_node = inspector.root().create_child("test_node");
1392 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1393 configuration_proxy,
1394 injector_registry_proxy,
1395 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1396 sender,
1397 &test_node,
1398 metrics::MetricsLogger::default(),
1399 );
1400 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1401 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1402
1403 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
1404 let event_time1 = zx::MonotonicInstant::get();
1405 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
1406 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
1407 let event_time4 = event_time3.add(zx::MonotonicDuration::from_micros(1));
1408
1409 let event1 = create_mouse_event(
1410 cursor_location,
1411 None, None, None, mouse_binding::MousePhase::Down,
1415 HashSet::from_iter(vec![1]),
1416 HashSet::from_iter(vec![1]),
1417 event_time1,
1418 &DESCRIPTOR,
1419 );
1420 let event2 = create_mouse_event(
1421 cursor_location,
1422 None, None, None, mouse_binding::MousePhase::Down,
1426 HashSet::from_iter(vec![2]),
1427 HashSet::from_iter(vec![1, 2]),
1428 event_time2,
1429 &DESCRIPTOR,
1430 );
1431 let event3 = create_mouse_event(
1432 cursor_location,
1433 None, None, None, mouse_binding::MousePhase::Up,
1437 HashSet::from_iter(vec![1]),
1438 HashSet::from_iter(vec![2]),
1439 event_time3,
1440 &DESCRIPTOR,
1441 );
1442 let event4 = create_mouse_event(
1443 cursor_location,
1444 None, None, None, mouse_binding::MousePhase::Up,
1448 HashSet::from_iter(vec![2]),
1449 HashSet::new(),
1450 event_time4,
1451 &DESCRIPTOR,
1452 );
1453
1454 let expected_position = Position { x: 0.0, y: 0.0 };
1455
1456 let (injector_stream_sender, injector_stream_receiver) =
1460 mpsc::unbounded::<Vec<pointerinjector::Event>>();
1461 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
1463 let registry_fut = handle_registry_request_stream2(
1464 injector_registry_request_stream,
1465 injector_stream_sender,
1466 );
1467
1468 let _registry_task = fasync::Task::local(registry_fut);
1470 mouse_handler.clone().handle_input_event(event1).await;
1471 assert_eq!(
1472 injector_stream_receiver
1473 .next()
1474 .await
1475 .map(|events| events.into_iter().flatten().collect()),
1476 Some(vec![
1477 create_mouse_pointer_sample_event_phase_add(
1478 vec![1],
1479 expected_position,
1480 event_time1,
1481 ),
1482 create_mouse_pointer_sample_event(
1483 pointerinjector::EventPhase::Change,
1484 vec![1],
1485 expected_position,
1486 None, None, None, None, event_time1,
1491 )
1492 ])
1493 );
1494
1495 mouse_handler.clone().handle_input_event(event2).await;
1497 let pointer_sample_event2: Vec<_> = injector_stream_receiver
1498 .next()
1499 .await
1500 .map(|events| events.into_iter().flatten().collect())
1501 .expect("Failed to receive pointer sample event.");
1502 let expected_event_time: i64 = event_time2.into_nanos();
1503 assert_eq!(pointer_sample_event2.len(), 1);
1504
1505 match &pointer_sample_event2[0] {
1508 pointerinjector::Event {
1509 timestamp: Some(actual_event_time),
1510 data:
1511 Some(pointerinjector::Data::PointerSample(pointerinjector::PointerSample {
1512 pointer_id: Some(0),
1513 phase: Some(pointerinjector::EventPhase::Change),
1514 position_in_viewport: Some(actual_position),
1515 scroll_v: None,
1516 scroll_h: None,
1517 pressed_buttons: Some(actual_buttons),
1518 relative_motion: None,
1519 ..
1520 })),
1521 ..
1522 } => {
1523 assert_eq!(*actual_event_time, expected_event_time);
1524 assert_eq!(actual_position[0], expected_position.x);
1525 assert_eq!(actual_position[1], expected_position.y);
1526 assert_eq!(
1527 HashSet::<mouse_binding::MouseButton>::from_iter(actual_buttons.clone()),
1528 HashSet::from_iter(vec![1, 2])
1529 );
1530 }
1531 _ => panic!("Unexpected pointer sample event: {:?}", pointer_sample_event2[0]),
1532 }
1533
1534 mouse_handler.clone().handle_input_event(event3).await;
1536 assert_eq!(
1537 injector_stream_receiver
1538 .next()
1539 .await
1540 .map(|events| events.into_iter().flatten().collect()),
1541 Some(vec![create_mouse_pointer_sample_event(
1542 pointerinjector::EventPhase::Change,
1543 vec![2],
1544 expected_position,
1545 None, None, None, None, event_time3,
1550 )])
1551 );
1552
1553 mouse_handler.clone().handle_input_event(event4).await;
1555 assert_eq!(
1556 injector_stream_receiver
1557 .next()
1558 .await
1559 .map(|events| events.into_iter().flatten().collect()),
1560 Some(vec![create_mouse_pointer_sample_event(
1561 pointerinjector::EventPhase::Change,
1562 vec![],
1563 expected_position,
1564 None, None, None, None, event_time4,
1569 )])
1570 );
1571
1572 match receiver.next().await {
1574 Some(CursorMessage::SetPosition(position)) => {
1575 assert_eq!(position, expected_position);
1576 }
1577 Some(CursorMessage::SetVisibility(_)) => {
1578 panic!("Received unexpected cursor visibility update.")
1579 }
1580 None => panic!("Did not receive cursor update."),
1581 }
1582 }
1583
1584 #[fuchsia::test(allow_stalls = false)]
1586 async fn down_move_up_event() {
1587 let (configuration_proxy, mut configuration_request_stream) =
1589 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1590 let (injector_registry_proxy, injector_registry_request_stream) =
1591 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1592 let config_request_stream_fut =
1593 handle_configuration_request_stream(&mut configuration_request_stream);
1594
1595 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(3);
1599 let inspector = fuchsia_inspect::Inspector::default();
1600 let test_node = inspector.root().create_child("test_node");
1601 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1602 configuration_proxy,
1603 injector_registry_proxy,
1604 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1605 sender,
1606 &test_node,
1607 metrics::MetricsLogger::default(),
1608 );
1609 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1610 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1611
1612 let event_time1 = zx::MonotonicInstant::get();
1613 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
1614 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
1615 let zero_position = Position { x: 0.0, y: 0.0 };
1616 let expected_position = Position {
1617 x: 10.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
1618 y: 5.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
1619 };
1620 let expected_relative_motion = [
1621 10.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
1622 5.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
1623 ];
1624 let event1 = create_mouse_event(
1625 mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 }),
1626 None, None, None, mouse_binding::MousePhase::Down,
1630 HashSet::from_iter(vec![1]),
1631 HashSet::from_iter(vec![1]),
1632 event_time1,
1633 &DESCRIPTOR,
1634 );
1635 let event2 = create_mouse_event(
1636 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1637 millimeters: Position { x: 10.0, y: 5.0 },
1638 }),
1639 None, None, None, mouse_binding::MousePhase::Move,
1643 HashSet::from_iter(vec![1]),
1644 HashSet::from_iter(vec![1]),
1645 event_time2,
1646 &DESCRIPTOR,
1647 );
1648 let event3 = create_mouse_event(
1649 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1650 millimeters: Position { x: 0.0, y: 0.0 },
1651 }),
1652 None, None, None, mouse_binding::MousePhase::Up,
1656 HashSet::from_iter(vec![1]),
1657 HashSet::from_iter(vec![]),
1658 event_time3,
1659 &DESCRIPTOR,
1660 );
1661
1662 let (injector_stream_sender, injector_stream_receiver) =
1666 mpsc::unbounded::<Vec<pointerinjector::Event>>();
1667 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
1669 let registry_fut = handle_registry_request_stream2(
1670 injector_registry_request_stream,
1671 injector_stream_sender,
1672 );
1673
1674 let _registry_task = fasync::Task::local(registry_fut);
1676 mouse_handler.clone().handle_input_event(event1).await;
1677 assert_eq!(
1678 injector_stream_receiver
1679 .next()
1680 .await
1681 .map(|events| events.into_iter().flatten().collect()),
1682 Some(vec![
1683 create_mouse_pointer_sample_event_phase_add(vec![1], zero_position, event_time1,),
1684 create_mouse_pointer_sample_event(
1685 pointerinjector::EventPhase::Change,
1686 vec![1],
1687 zero_position,
1688 None, None, None, None, event_time1,
1693 )
1694 ])
1695 );
1696
1697 match receiver.next().await {
1699 Some(CursorMessage::SetPosition(position)) => {
1700 assert_eq!(position, zero_position);
1701 }
1702 Some(CursorMessage::SetVisibility(_)) => {
1703 panic!("Received unexpected cursor visibility update.")
1704 }
1705 None => panic!("Did not receive cursor update."),
1706 }
1707
1708 mouse_handler.clone().handle_input_event(event2).await;
1710 assert_eq!(
1711 injector_stream_receiver
1712 .next()
1713 .await
1714 .map(|events| events.into_iter().flatten().collect()),
1715 Some(vec![create_mouse_pointer_sample_event(
1716 pointerinjector::EventPhase::Change,
1717 vec![1],
1718 expected_position,
1719 Some(expected_relative_motion),
1720 None, None, None, event_time2,
1724 )])
1725 );
1726
1727 match receiver.next().await {
1729 Some(CursorMessage::SetPosition(position)) => {
1730 assert_eq!(position, expected_position);
1731 }
1732 Some(CursorMessage::SetVisibility(_)) => {
1733 panic!("Received unexpected cursor visibility update.")
1734 }
1735 None => panic!("Did not receive cursor update."),
1736 }
1737
1738 mouse_handler.clone().handle_input_event(event3).await;
1740 assert_eq!(
1741 injector_stream_receiver
1742 .next()
1743 .await
1744 .map(|events| events.into_iter().flatten().collect()),
1745 Some(vec![create_mouse_pointer_sample_event(
1746 pointerinjector::EventPhase::Change,
1747 vec![],
1748 expected_position,
1749 None, None, None, None, event_time3,
1754 )])
1755 );
1756
1757 match receiver.next().await {
1759 Some(CursorMessage::SetPosition(position)) => {
1760 assert_eq!(position, expected_position);
1761 }
1762 Some(CursorMessage::SetVisibility(_)) => {
1763 panic!("Received unexpected cursor visibility update.")
1764 }
1765 None => panic!("Did not receive cursor update."),
1766 }
1767 }
1768
1769 #[fuchsia::test(allow_stalls = false)]
1771 async fn handler_ignores_handled_events() {
1772 let (configuration_proxy, mut configuration_request_stream) =
1774 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1775 let (injector_registry_proxy, injector_registry_request_stream) =
1776 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1777 let config_request_stream_fut =
1778 handle_configuration_request_stream(&mut configuration_request_stream);
1779
1780 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
1782 let inspector = fuchsia_inspect::Inspector::default();
1783 let test_node = inspector.root().create_child("test_node");
1784 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1785 configuration_proxy,
1786 injector_registry_proxy,
1787 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1788 sender,
1789 &test_node,
1790 metrics::MetricsLogger::default(),
1791 );
1792 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1793 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1794
1795 let cursor_relative_position = Position { x: 50.0, y: 75.0 };
1796 let cursor_location =
1797 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1798 millimeters: Position {
1799 x: cursor_relative_position.x / COUNTS_PER_MM as f32,
1800 y: cursor_relative_position.y / COUNTS_PER_MM as f32,
1801 },
1802 });
1803 let event_time = zx::MonotonicInstant::get();
1804 let input_events = vec![create_mouse_event_with_handled(
1805 cursor_location,
1806 None, None, None, mouse_binding::MousePhase::Move,
1810 HashSet::new(),
1811 HashSet::new(),
1812 event_time,
1813 &DESCRIPTOR,
1814 input_device::Handled::Yes,
1815 )];
1816
1817 assert_handler_ignores_input_event_sequence(
1818 mouse_handler,
1819 input_events,
1820 injector_registry_request_stream,
1821 )
1822 .await;
1823
1824 assert!(receiver.next().await.is_none());
1826 }
1827
1828 fn zero_relative_location() -> mouse_binding::MouseLocation {
1829 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1830 millimeters: Position { x: 0.0, y: 0.0 },
1831 })
1832 }
1833
1834 #[test_case(
1835 create_mouse_event(
1836 zero_relative_location(),
1837 wheel_delta_ticks(1, None), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1841 HashSet::new(),
1842 HashSet::new(),
1843 zx::MonotonicInstant::ZERO,
1844 &DESCRIPTOR,
1845 ),
1846 create_mouse_pointer_sample_event(
1847 pointerinjector::EventPhase::Change,
1848 vec![],
1849 Position { x: 50.0, y: 50.0 },
1850 None, Some(1), None, Some(false), zx::MonotonicInstant::ZERO,
1855 ); "v tick scroll"
1856 )]
1857 #[test_case(
1858 create_mouse_event(
1859 zero_relative_location(),
1860 None, wheel_delta_ticks(1, None), Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1864 HashSet::new(),
1865 HashSet::new(),
1866 zx::MonotonicInstant::ZERO,
1867 &DESCRIPTOR,
1868 ),
1869 create_mouse_pointer_sample_event(
1870 pointerinjector::EventPhase::Change,
1871 vec![],
1872 Position { x: 50.0, y: 50.0 },
1873 None, None, Some(1), Some(false), zx::MonotonicInstant::ZERO,
1878 ); "h tick scroll"
1879 )]
1880 #[test_case(
1881 create_mouse_event(
1882 zero_relative_location(),
1883 wheel_delta_ticks(1, Some(120.0)), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1887 HashSet::new(),
1888 HashSet::new(),
1889 zx::MonotonicInstant::ZERO,
1890 &DESCRIPTOR,
1891 ),
1892 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
1893 pointerinjector::EventPhase::Change,
1894 vec![],
1895 Position { x: 50.0, y: 50.0 },
1896 None, Some(1), None, Some(120.0), None, Some(false), zx::MonotonicInstant::ZERO,
1903 ); "v tick scroll with physical pixel"
1904 )]
1905 #[test_case(
1906 create_mouse_event(
1907 zero_relative_location(),
1908 None, wheel_delta_ticks(1, Some(120.0)), Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1912 HashSet::new(),
1913 HashSet::new(),
1914 zx::MonotonicInstant::ZERO,
1915 &DESCRIPTOR,
1916 ),
1917 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
1918 pointerinjector::EventPhase::Change,
1919 vec![],
1920 Position { x: 50.0, y: 50.0 },
1921 None, None, Some(1), None, Some(120.0), Some(false), zx::MonotonicInstant::ZERO,
1928 ); "h tick scroll with physical pixel"
1929 )]
1930 #[test_case(
1931 create_mouse_event(
1932 zero_relative_location(),
1933 wheel_delta_mm(1.0, Some(120.0)), None, Some(mouse_binding::PrecisionScroll::Yes), mouse_binding::MousePhase::Wheel,
1937 HashSet::new(),
1938 HashSet::new(),
1939 zx::MonotonicInstant::ZERO,
1940 &DESCRIPTOR,
1941 ),
1942 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
1943 pointerinjector::EventPhase::Change,
1944 vec![],
1945 Position { x: 50.0, y: 50.0 },
1946 None, None, None, Some(120.0), None, Some(true), zx::MonotonicInstant::ZERO,
1953 ); "v mm scroll with physical pixel"
1954 )]
1955 #[test_case(
1956 create_mouse_event(
1957 zero_relative_location(),
1958 None, wheel_delta_mm(1.0, Some(120.0)), Some(mouse_binding::PrecisionScroll::Yes), mouse_binding::MousePhase::Wheel,
1962 HashSet::new(),
1963 HashSet::new(),
1964 zx::MonotonicInstant::ZERO,
1965 &DESCRIPTOR,
1966 ),
1967 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
1968 pointerinjector::EventPhase::Change,
1969 vec![],
1970 Position { x: 50.0, y: 50.0 },
1971 None, None, None, None, Some(120.0), Some(true), zx::MonotonicInstant::ZERO,
1978 ); "h mm scroll with physical pixel"
1979 )]
1980 #[fuchsia::test(allow_stalls = false)]
1982 async fn scroll(event: input_device::InputEvent, want_event: pointerinjector::Event) {
1983 let (configuration_proxy, mut configuration_request_stream) =
1985 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1986 let (injector_registry_proxy, injector_registry_request_stream) =
1987 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1988 let config_request_stream_fut =
1989 handle_configuration_request_stream(&mut configuration_request_stream);
1990
1991 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
1993 let inspector = fuchsia_inspect::Inspector::default();
1994 let test_node = inspector.root().create_child("test_node");
1995 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1996 configuration_proxy,
1997 injector_registry_proxy,
1998 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1999 sender,
2000 &test_node,
2001 metrics::MetricsLogger::default(),
2002 );
2003 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
2004 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
2005
2006 let (injector_stream_sender, injector_stream_receiver) =
2010 mpsc::unbounded::<Vec<pointerinjector::Event>>();
2011 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
2013 let registry_fut = handle_registry_request_stream2(
2014 injector_registry_request_stream,
2015 injector_stream_sender,
2016 );
2017
2018 let event_time = zx::MonotonicInstant::get();
2019
2020 let event = input_device::InputEvent { event_time, ..event };
2021
2022 let want_event =
2023 pointerinjector::Event { timestamp: Some(event_time.into_nanos()), ..want_event };
2024
2025 let _registry_task = fasync::Task::local(registry_fut);
2027
2028 mouse_handler.clone().handle_input_event(event).await;
2029 let got_events: Vec<_> = injector_stream_receiver
2030 .next()
2031 .await
2032 .map(|events| events.into_iter().flatten().collect())
2033 .unwrap();
2034 pretty_assertions::assert_eq!(got_events.len(), 2);
2035 assert_matches!(
2036 got_events[0],
2037 pointerinjector::Event {
2038 data: Some(pointerinjector::Data::PointerSample(pointerinjector::PointerSample {
2039 phase: Some(pointerinjector::EventPhase::Add),
2040 ..
2041 })),
2042 ..
2043 }
2044 );
2045
2046 pretty_assertions::assert_eq!(got_events[1], want_event);
2047 }
2048
2049 #[fuchsia::test(allow_stalls = false)]
2051 async fn down_scroll_up_scroll() {
2052 let (configuration_proxy, mut configuration_request_stream) =
2054 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
2055 let (injector_registry_proxy, injector_registry_request_stream) =
2056 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
2057 let config_request_stream_fut =
2058 handle_configuration_request_stream(&mut configuration_request_stream);
2059
2060 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
2062 let inspector = fuchsia_inspect::Inspector::default();
2063 let test_node = inspector.root().create_child("test_node");
2064 let mouse_handler_fut = MouseInjectorHandler::new_handler(
2065 configuration_proxy,
2066 injector_registry_proxy,
2067 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
2068 sender,
2069 &test_node,
2070 metrics::MetricsLogger::default(),
2071 );
2072 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
2073 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
2074
2075 let (injector_stream_sender, injector_stream_receiver) =
2079 mpsc::unbounded::<Vec<pointerinjector::Event>>();
2080 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
2082 let registry_fut = handle_registry_request_stream2(
2083 injector_registry_request_stream,
2084 injector_stream_sender,
2085 );
2086
2087 let event_time1 = zx::MonotonicInstant::get();
2088 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
2089 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
2090 let event_time4 = event_time3.add(zx::MonotonicDuration::from_micros(1));
2091
2092 let _registry_task = fasync::Task::local(registry_fut);
2094
2095 let zero_location =
2096 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
2097 millimeters: Position { x: 0.0, y: 0.0 },
2098 });
2099 let expected_position = Position { x: 50.0, y: 50.0 };
2100
2101 let down_event = create_mouse_event(
2102 zero_location,
2103 None, None, None, mouse_binding::MousePhase::Down,
2107 HashSet::from_iter(vec![1]),
2108 HashSet::from_iter(vec![1]),
2109 event_time1,
2110 &DESCRIPTOR,
2111 );
2112
2113 let wheel_event = create_mouse_event(
2114 zero_location,
2115 wheel_delta_ticks(1, None), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
2119 HashSet::from_iter(vec![1]),
2120 HashSet::from_iter(vec![1]),
2121 event_time2,
2122 &DESCRIPTOR,
2123 );
2124
2125 let up_event = create_mouse_event(
2126 zero_location,
2127 None,
2128 None,
2129 None, mouse_binding::MousePhase::Up,
2131 HashSet::from_iter(vec![1]),
2132 HashSet::new(),
2133 event_time3,
2134 &DESCRIPTOR,
2135 );
2136
2137 let continue_wheel_event = create_mouse_event(
2138 zero_location,
2139 wheel_delta_ticks(1, None), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
2143 HashSet::new(),
2144 HashSet::new(),
2145 event_time4,
2146 &DESCRIPTOR,
2147 );
2148
2149 mouse_handler.clone().handle_input_event(down_event).await;
2151 assert_eq!(
2152 injector_stream_receiver
2153 .next()
2154 .await
2155 .map(|events| events.into_iter().flatten().collect()),
2156 Some(vec![
2157 create_mouse_pointer_sample_event_phase_add(
2158 vec![1],
2159 expected_position,
2160 event_time1,
2161 ),
2162 create_mouse_pointer_sample_event(
2163 pointerinjector::EventPhase::Change,
2164 vec![1],
2165 expected_position,
2166 None, None, None, None, event_time1,
2171 ),
2172 ])
2173 );
2174
2175 mouse_handler.clone().handle_input_event(wheel_event).await;
2177 assert_eq!(
2178 injector_stream_receiver
2179 .next()
2180 .await
2181 .map(|events| events.into_iter().flatten().collect()),
2182 Some(vec![create_mouse_pointer_sample_event(
2183 pointerinjector::EventPhase::Change,
2184 vec![1],
2185 expected_position,
2186 None, Some(1), None, Some(false), event_time2,
2191 )])
2192 );
2193
2194 mouse_handler.clone().handle_input_event(up_event).await;
2196 assert_eq!(
2197 injector_stream_receiver
2198 .next()
2199 .await
2200 .map(|events| events.into_iter().flatten().collect()),
2201 Some(vec![create_mouse_pointer_sample_event(
2202 pointerinjector::EventPhase::Change,
2203 vec![],
2204 expected_position,
2205 None, None, None, None, event_time3,
2210 )])
2211 );
2212
2213 mouse_handler.clone().handle_input_event(continue_wheel_event).await;
2215 assert_eq!(
2216 injector_stream_receiver
2217 .next()
2218 .await
2219 .map(|events| events.into_iter().flatten().collect()),
2220 Some(vec![create_mouse_pointer_sample_event(
2221 pointerinjector::EventPhase::Change,
2222 vec![],
2223 expected_position,
2224 None, Some(1), None, Some(false), event_time4,
2229 )])
2230 );
2231 }
2232
2233 #[fuchsia::test(allow_stalls = false)]
2234 async fn mouse_injector_handler_initialized_with_inspect_node() {
2235 let (configuration_proxy, mut configuration_request_stream) =
2236 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
2237 let config_request_stream_fut =
2238 handle_configuration_request_stream(&mut configuration_request_stream);
2239 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
2240 let inspector = fuchsia_inspect::Inspector::default();
2241 let fake_handlers_node = inspector.root().create_child("input_handlers_node");
2242 let mouse_handler_fut = MouseInjectorHandler::new_with_config_proxy(
2243 configuration_proxy,
2244 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
2245 sender,
2246 &fake_handlers_node,
2247 metrics::MetricsLogger::default(),
2248 );
2249 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
2250 let _handler = mouse_handler_res.expect("Failed to create mouse handler");
2251
2252 diagnostics_assertions::assert_data_tree!(inspector, root: {
2253 input_handlers_node: {
2254 mouse_injector_handler: {
2255 events_received_count: 0u64,
2256 events_handled_count: 0u64,
2257 last_received_timestamp_ns: 0u64,
2258 "fuchsia.inspect.Health": {
2259 status: "STARTING_UP",
2260 start_timestamp_nanos: diagnostics_assertions::AnyProperty
2263 },
2264 }
2265 }
2266 });
2267 }
2268
2269 #[fuchsia::test(allow_stalls = false)]
2270 async fn mouse_injector_handler_inspect_counts_events() {
2271 let (configuration_proxy, mut configuration_request_stream) =
2273 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
2274 let (injector_registry_proxy, injector_registry_request_stream) =
2275 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
2276 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
2277
2278 let inspector = fuchsia_inspect::Inspector::default();
2279 let fake_handlers_node = inspector.root().create_child("input_handlers_node");
2280
2281 let mouse_handler_fut = MouseInjectorHandler::new_handler(
2283 configuration_proxy,
2284 injector_registry_proxy,
2285 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
2286 sender,
2287 &fake_handlers_node,
2288 metrics::MetricsLogger::default(),
2289 );
2290 let config_request_stream_fut =
2291 handle_configuration_request_stream(&mut configuration_request_stream);
2292
2293 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
2294 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
2295
2296 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
2297 let event_time1 = zx::MonotonicInstant::get();
2298 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
2299 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
2300
2301 let input_events = vec![
2302 create_mouse_event(
2303 cursor_location,
2304 None, None, None, mouse_binding::MousePhase::Down,
2308 HashSet::from_iter(vec![1]),
2309 HashSet::from_iter(vec![1]),
2310 event_time1,
2311 &DESCRIPTOR,
2312 ),
2313 create_mouse_event(
2314 cursor_location,
2315 None, None, None, mouse_binding::MousePhase::Up,
2319 HashSet::from_iter(vec![1]),
2320 HashSet::new(),
2321 event_time2,
2322 &DESCRIPTOR,
2323 ),
2324 create_mouse_event_with_handled(
2325 cursor_location,
2326 None, None, None, mouse_binding::MousePhase::Down,
2330 HashSet::from_iter(vec![1]),
2331 HashSet::from_iter(vec![1]),
2332 event_time3,
2333 &DESCRIPTOR,
2334 input_device::Handled::Yes,
2335 ),
2336 ];
2337
2338 let (injector_stream_sender, _) = mpsc::unbounded::<Vec<pointerinjector::Event>>();
2342 let registry_fut = handle_registry_request_stream2(
2343 injector_registry_request_stream,
2344 injector_stream_sender,
2345 );
2346
2347 let _registry_task = fasync::Task::local(registry_fut);
2349 for input_event in input_events {
2350 mouse_handler.clone().handle_input_event(input_event).await;
2351 }
2352
2353 let last_received_event_time: u64 = event_time2.into_nanos().try_into().unwrap();
2354
2355 diagnostics_assertions::assert_data_tree!(inspector, root: {
2356 input_handlers_node: {
2357 mouse_injector_handler: {
2358 events_received_count: 2u64,
2359 events_handled_count: 2u64,
2360 last_received_timestamp_ns: last_received_event_time,
2361 "fuchsia.inspect.Health": {
2362 status: "STARTING_UP",
2363 start_timestamp_nanos: diagnostics_assertions::AnyProperty
2366 },
2367 }
2368 }
2369 });
2370 }
2371}