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 fuchsia_trace::duration!(c"input", c"mouse_injector_handler");
90 match input_event {
91 input_device::InputEvent {
92 device_event: input_device::InputDeviceEvent::Mouse(ref mouse_event),
93 device_descriptor:
94 input_device::InputDeviceDescriptor::Mouse(ref mouse_device_descriptor),
95 event_time,
96 handled: input_device::Handled::No,
97 trace_id,
98 } => {
99 fuchsia_trace::duration!(c"input", c"mouse_injector_handler[processing]");
100 let trace_id = match trace_id {
101 Some(id) => {
102 fuchsia_trace::flow_end!(c"input", c"event_in_input_pipeline", id.into());
103 id
104 }
105 None => fuchsia_trace::Id::random(),
106 };
107
108 self.inspect_status.count_received_event(&event_time);
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 wake_lease: mouse_event.wake_lease.lock().unwrap().take(),
535 ..Default::default()
536 }
537 }
538
539 pub async fn watch_viewport(self: Rc<Self>) {
541 let configuration_proxy = self.configuration_proxy.clone();
542 let mut viewport_stream = HangingGetStream::new(
543 configuration_proxy,
544 pointerinjector_config::SetupProxy::watch_viewport,
545 );
546 loop {
547 match viewport_stream.next().await {
548 Some(Ok(new_viewport)) => {
549 self.inner_mut().viewport = Some(new_viewport.clone());
551
552 let injectors = self.inner().injectors.values().cloned().collect::<Vec<_>>();
554 for injector in injectors {
555 let events = vec![pointerinjector::Event {
556 timestamp: Some(fuchsia_async::MonotonicInstant::now().into_nanos()),
557 data: Some(pointerinjector::Data::Viewport(new_viewport.clone())),
558 trace_flow_id: Some(fuchsia_trace::Id::random().into()),
559 ..Default::default()
560 }];
561 injector.inject(events).await.expect("Failed to inject updated viewport.");
562 }
563 }
564 Some(Err(e)) => {
565 self.metrics_logger.log_error(
566 InputPipelineErrorMetricDimensionEvent::MouseInjectorErrorWhileReadingViewportUpdate,
567 std::format!("Error while reading viewport update: {}", e));
568 return;
569 }
570 None => {
571 self.metrics_logger.log_error(
572 InputPipelineErrorMetricDimensionEvent::MouseInjectorViewportUpdateStreamTerminatedUnexpectedly,
573 "Viewport update stream terminated unexpectedly");
574 return;
575 }
576 }
577 }
578 }
579
580 fn relative_movement_mm_to_phyical_pixel(&self, movement_mm: Position) -> Position {
584 Position {
585 x: movement_mm.x * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
586 y: movement_mm.y * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
587 }
588 }
589}
590
591#[cfg(test)]
592mod tests {
593 use super::*;
594 use crate::testing_utilities::{
595 assert_handler_ignores_input_event_sequence, create_mouse_event,
596 create_mouse_event_with_handled, create_mouse_pointer_sample_event,
597 create_mouse_pointer_sample_event_phase_add,
598 create_mouse_pointer_sample_event_with_wheel_physical_pixel,
599 };
600 use assert_matches::assert_matches;
601 use futures::channel::mpsc;
602 use pretty_assertions::assert_eq;
603 use std::collections::HashSet;
604 use std::ops::Add;
605 use test_case::test_case;
606 use {
607 fidl_fuchsia_input_report as fidl_input_report,
608 fidl_fuchsia_ui_pointerinjector as pointerinjector, fuchsia_async as fasync,
609 };
610
611 const DISPLAY_WIDTH_IN_PHYSICAL_PX: f32 = 100.0;
612 const DISPLAY_HEIGHT_IN_PHYSICAL_PX: f32 = 100.0;
613 const COUNTS_PER_MM: u32 = 12;
614
615 const DESCRIPTOR: input_device::InputDeviceDescriptor =
617 input_device::InputDeviceDescriptor::Mouse(mouse_binding::MouseDeviceDescriptor {
618 device_id: 1,
619 absolute_x_range: Some(fidl_input_report::Range { min: 0, max: 100 }),
620 absolute_y_range: Some(fidl_input_report::Range { min: 0, max: 100 }),
621 wheel_v_range: Some(fidl_input_report::Axis {
622 range: fidl_input_report::Range { min: -1, max: 1 },
623 unit: fidl_input_report::Unit {
624 type_: fidl_input_report::UnitType::Other,
625 exponent: 0,
626 },
627 }),
628 wheel_h_range: Some(fidl_input_report::Axis {
629 range: fidl_input_report::Range { min: -1, max: 1 },
630 unit: fidl_input_report::Unit {
631 type_: fidl_input_report::UnitType::Other,
632 exponent: 0,
633 },
634 }),
635 buttons: None,
636 counts_per_mm: COUNTS_PER_MM,
637 });
638
639 async fn handle_configuration_request_stream(
641 stream: &mut pointerinjector_config::SetupRequestStream,
642 ) {
643 if let Some(Ok(request)) = stream.next().await {
644 match request {
645 pointerinjector_config::SetupRequest::GetViewRefs { responder, .. } => {
646 let context = fuchsia_scenic::ViewRefPair::new()
647 .expect("Failed to create viewrefpair.")
648 .view_ref;
649 let target = fuchsia_scenic::ViewRefPair::new()
650 .expect("Failed to create viewrefpair.")
651 .view_ref;
652 let _ = responder.send(context, target);
653 }
654 _ => {}
655 };
656 }
657 }
658
659 async fn handle_registry_request_stream(
662 mut stream: pointerinjector::RegistryRequestStream,
663 injector_sender: futures::channel::oneshot::Sender<pointerinjector::DeviceRequestStream>,
664 ) {
665 if let Some(request) = stream.next().await {
666 match request {
667 Ok(pointerinjector::RegistryRequest::Register {
668 config: _,
669 injector,
670 responder,
671 ..
672 }) => {
673 let injector_stream = injector.into_stream();
674 let _ = injector_sender.send(injector_stream);
675 responder.send().expect("failed to respond");
676 }
677 _ => {}
678 };
679 } else {
680 panic!("RegistryRequestStream failed.");
681 }
682 }
683
684 async fn handle_registry_request_stream2(
686 mut stream: pointerinjector::RegistryRequestStream,
687 injector_sender: mpsc::UnboundedSender<Vec<pointerinjector::Event>>,
688 ) {
689 let (injector, responder) = match stream.next().await {
690 Some(Ok(pointerinjector::RegistryRequest::Register {
691 config: _,
692 injector,
693 responder,
694 ..
695 })) => (injector, responder),
696 other => panic!("expected register request, but got {:?}", other),
697 };
698 let injector_stream: pointerinjector::DeviceRequestStream = injector.into_stream();
699 responder.send().expect("failed to respond");
700 injector_stream
701 .for_each(|request| {
702 futures::future::ready({
703 match request {
704 Ok(pointerinjector::DeviceRequest::Inject {
705 events,
706 responder: device_injector_responder,
707 }) => {
708 let _ = injector_sender.unbounded_send(events);
709 device_injector_responder.send().expect("failed to respond")
710 }
711 Err(e) => panic!("FIDL error {}", e),
712 }
713 })
714 })
715 .await;
716 }
717
718 async fn handle_device_request_stream(
721 injector_stream_receiver: futures::channel::oneshot::Receiver<
722 pointerinjector::DeviceRequestStream,
723 >,
724 expected_events: Vec<pointerinjector::Event>,
725 ) {
726 let mut injector_stream =
727 injector_stream_receiver.await.expect("Failed to get DeviceRequestStream.");
728 for expected_event in expected_events {
729 match injector_stream.next().await {
730 Some(Ok(pointerinjector::DeviceRequest::Inject { events, responder })) => {
731 assert_eq!(events, vec![expected_event]);
732 responder.send().expect("failed to respond");
733 }
734 Some(Err(e)) => panic!("FIDL error {}", e),
735 None => panic!("Expected another event."),
736 }
737 }
738 }
739
740 fn create_viewport(min: f32, max: f32) -> pointerinjector::Viewport {
742 pointerinjector::Viewport {
743 extents: Some([[min, min], [max, max]]),
744 viewport_to_context_transform: None,
745 ..Default::default()
746 }
747 }
748
749 #[fuchsia::test]
752 fn receives_viewport_updates() {
753 let mut exec = fasync::TestExecutor::new();
754
755 let (configuration_proxy, mut configuration_request_stream) =
757 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
758 let (injector_registry_proxy, _) =
759 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
760 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(0);
761
762 let inspector = fuchsia_inspect::Inspector::default();
763 let test_node = inspector.root().create_child("test_node");
764
765 let mouse_handler_fut = MouseInjectorHandler::new_handler(
767 configuration_proxy,
768 injector_registry_proxy,
769 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
770 sender,
771 &test_node,
772 metrics::MetricsLogger::default(),
773 );
774 let config_request_stream_fut =
775 handle_configuration_request_stream(&mut configuration_request_stream);
776 let (mouse_handler_res, _) = exec.run_singlethreaded(futures::future::join(
777 mouse_handler_fut,
778 config_request_stream_fut,
779 ));
780 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
781
782 let (injector_device_proxy, mut injector_device_request_stream) =
784 fidl::endpoints::create_proxy_and_stream::<pointerinjector::DeviceMarker>();
785 mouse_handler.inner_mut().injectors.insert(1, injector_device_proxy);
786
787 {
789 let watch_viewport_fut = mouse_handler.clone().watch_viewport();
791 futures::pin_mut!(watch_viewport_fut);
792 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
793
794 match exec.run_singlethreaded(&mut configuration_request_stream.next()) {
796 Some(Ok(pointerinjector_config::SetupRequest::WatchViewport {
797 responder, ..
798 })) => {
799 responder.send(&create_viewport(0.0, 100.0)).expect("Failed to send viewport.");
800 }
801 other => panic!("Received unexpected value: {:?}", other),
802 };
803 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
804
805 exec.run_singlethreaded(async {
807 match injector_device_request_stream.next().await {
808 Some(Ok(pointerinjector::DeviceRequest::Inject { events, responder })) => {
809 assert_eq!(events.len(), 1);
810 assert!(events[0].data.is_some());
811 assert_eq!(
812 events[0].data,
813 Some(pointerinjector::Data::Viewport(create_viewport(0.0, 100.0)))
814 );
815 responder.send().expect("injector stream failed to respond.");
816 }
817 other => panic!("Received unexpected value: {:?}", other),
818 }
819 });
820
821 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
823
824 match exec.run_singlethreaded(&mut configuration_request_stream.next()) {
826 Some(Ok(pointerinjector_config::SetupRequest::WatchViewport {
827 responder, ..
828 })) => {
829 responder
830 .send(&create_viewport(100.0, 200.0))
831 .expect("Failed to send viewport.");
832 }
833 other => panic!("Received unexpected value: {:?}", other),
834 };
835
836 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
838 }
839
840 exec.run_singlethreaded(async {
842 match injector_device_request_stream.next().await {
843 Some(Ok(pointerinjector::DeviceRequest::Inject { events, responder })) => {
844 assert_eq!(events.len(), 1);
845 assert!(events[0].data.is_some());
846 assert_eq!(
847 events[0].data,
848 Some(pointerinjector::Data::Viewport(create_viewport(100.0, 200.0)))
849 );
850 responder.send().expect("injector stream failed to respond.");
851 }
852 other => panic!("Received unexpected value: {:?}", other),
853 }
854 });
855
856 let expected_viewport = create_viewport(100.0, 200.0);
858 assert_eq!(mouse_handler.inner().viewport, Some(expected_viewport));
859 }
860
861 fn wheel_delta_ticks(
862 ticks: i64,
863 physical_pixel: Option<f32>,
864 ) -> Option<mouse_binding::WheelDelta> {
865 Some(mouse_binding::WheelDelta {
866 raw_data: mouse_binding::RawWheelDelta::Ticks(ticks),
867 physical_pixel,
868 })
869 }
870
871 fn wheel_delta_mm(mm: f32, physical_pixel: Option<f32>) -> Option<mouse_binding::WheelDelta> {
872 Some(mouse_binding::WheelDelta {
873 raw_data: mouse_binding::RawWheelDelta::Millimeters(mm),
874 physical_pixel,
875 })
876 }
877
878 #[test_case(
881 mouse_binding::MouseLocation::Relative(
882 mouse_binding::RelativeLocation {
883 millimeters: Position { x: 1.0, y: 2.0 }
884 }),
885 Position {
886 x: DISPLAY_WIDTH_IN_PHYSICAL_PX / 2.0
887 + 1.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
888 y: DISPLAY_HEIGHT_IN_PHYSICAL_PX / 2.0
889 + 2.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
890 },
891 [
892 1.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
893 2.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
894 ]; "Valid move event."
895 )]
896 #[test_case(
897 mouse_binding::MouseLocation::Relative(
898 mouse_binding::RelativeLocation {
899 millimeters: Position {
900 x: DISPLAY_WIDTH_IN_PHYSICAL_PX / MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL + 2.0,
901 y: DISPLAY_HEIGHT_IN_PHYSICAL_PX / MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL + 1.0,
902 }}),
903 Position {
904 x: DISPLAY_WIDTH_IN_PHYSICAL_PX,
905 y: DISPLAY_HEIGHT_IN_PHYSICAL_PX,
906 },
907 [
908 DISPLAY_WIDTH_IN_PHYSICAL_PX + 2.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
909 DISPLAY_HEIGHT_IN_PHYSICAL_PX + 1.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
910 ]; "Move event exceeds max bounds."
911 )]
912 #[test_case(
913 mouse_binding::MouseLocation::Relative(
914 mouse_binding::RelativeLocation {
915 millimeters: Position {
916 x: -(DISPLAY_WIDTH_IN_PHYSICAL_PX / MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL + 2.0),
917 y: -(DISPLAY_HEIGHT_IN_PHYSICAL_PX / MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL + 1.0),
918 }}),
919 Position { x: 0.0, y: 0.0 },
920 [
921 -(DISPLAY_WIDTH_IN_PHYSICAL_PX + 2.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL),
922 -(DISPLAY_HEIGHT_IN_PHYSICAL_PX + 1.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL),
923 ]; "Move event exceeds min bounds."
924 )]
925 #[fuchsia::test(allow_stalls = false)]
926 async fn move_event(
927 move_location: mouse_binding::MouseLocation,
928 expected_position: Position,
929 expected_relative_motion: [f32; 2],
930 ) {
931 let (configuration_proxy, mut configuration_request_stream) =
933 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
934 let (injector_registry_proxy, injector_registry_request_stream) =
935 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
936 let config_request_stream_fut =
937 handle_configuration_request_stream(&mut configuration_request_stream);
938
939 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
941 let inspector = fuchsia_inspect::Inspector::default();
942 let test_node = inspector.root().create_child("test_node");
943 let mouse_handler_fut = MouseInjectorHandler::new_handler(
944 configuration_proxy,
945 injector_registry_proxy,
946 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
947 sender,
948 &test_node,
949 metrics::MetricsLogger::default(),
950 );
951 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
952 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
953
954 let event_time = zx::MonotonicInstant::get();
955 let input_event = create_mouse_event(
956 move_location,
957 None, None, None, mouse_binding::MousePhase::Move,
961 HashSet::new(),
962 HashSet::new(),
963 event_time,
964 &DESCRIPTOR,
965 );
966
967 let handle_event_fut = mouse_handler.handle_input_event(input_event);
969 let expected_events = vec![
970 create_mouse_pointer_sample_event_phase_add(vec![], expected_position, event_time),
971 create_mouse_pointer_sample_event(
972 pointerinjector::EventPhase::Change,
973 vec![],
974 expected_position,
975 Some(expected_relative_motion),
976 None, None, None, event_time,
980 ),
981 ];
982
983 let (injector_stream_sender, injector_stream_receiver) =
987 futures::channel::oneshot::channel::<pointerinjector::DeviceRequestStream>();
988 let registry_fut = handle_registry_request_stream(
989 injector_registry_request_stream,
990 injector_stream_sender,
991 );
992 let device_fut = handle_device_request_stream(injector_stream_receiver, expected_events);
993
994 let (handle_result, _, _) = futures::join!(handle_event_fut, registry_fut, device_fut);
997 match receiver.next().await {
998 Some(CursorMessage::SetPosition(position)) => {
999 pretty_assertions::assert_eq!(position, expected_position);
1000 }
1001 Some(CursorMessage::SetVisibility(_)) => {
1002 panic!("Received unexpected cursor visibility update.")
1003 }
1004 None => panic!("Did not receive cursor update."),
1005 }
1006
1007 assert_matches!(
1009 handle_result.as_slice(),
1010 [input_device::InputEvent { handled: input_device::Handled::Yes, .. }]
1011 );
1012 }
1013
1014 #[fuchsia::test(allow_stalls = false)]
1017 async fn move_absolute_event() {
1018 const DEVICE_ID: u32 = 1;
1019
1020 let (configuration_proxy, mut configuration_request_stream) =
1022 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1023 let (injector_registry_proxy, injector_registry_request_stream) =
1024 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1025 let config_request_stream_fut =
1026 handle_configuration_request_stream(&mut configuration_request_stream);
1027
1028 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
1030 let inspector = fuchsia_inspect::Inspector::default();
1031 let test_node = inspector.root().create_child("test_node");
1032 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1033 configuration_proxy,
1034 injector_registry_proxy,
1035 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1036 sender,
1037 &test_node,
1038 metrics::MetricsLogger::default(),
1039 );
1040 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1041 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1042
1043 let cursor_location =
1059 mouse_binding::MouseLocation::Absolute(Position { x: -25.0, y: 25.0 });
1060 let event_time = zx::MonotonicInstant::get();
1061 let descriptor =
1062 input_device::InputDeviceDescriptor::Mouse(mouse_binding::MouseDeviceDescriptor {
1063 device_id: DEVICE_ID,
1064 absolute_x_range: Some(fidl_input_report::Range { min: -50, max: 50 }),
1065 absolute_y_range: Some(fidl_input_report::Range { min: -50, max: 50 }),
1066 wheel_v_range: None,
1067 wheel_h_range: None,
1068 buttons: None,
1069 counts_per_mm: COUNTS_PER_MM,
1070 });
1071 let input_event = create_mouse_event(
1072 cursor_location,
1073 None, None, None, mouse_binding::MousePhase::Move,
1077 HashSet::new(),
1078 HashSet::new(),
1079 event_time,
1080 &descriptor,
1081 );
1082
1083 let handle_event_fut = mouse_handler.handle_input_event(input_event);
1085 let expected_position = Position {
1086 x: DISPLAY_WIDTH_IN_PHYSICAL_PX * 0.25,
1087 y: DISPLAY_WIDTH_IN_PHYSICAL_PX * 0.75,
1088 };
1089 let expected_events = vec![
1090 create_mouse_pointer_sample_event_phase_add(vec![], expected_position, event_time),
1091 create_mouse_pointer_sample_event(
1092 pointerinjector::EventPhase::Change,
1093 vec![],
1094 expected_position,
1095 None, None, None, None, event_time,
1100 ),
1101 ];
1102
1103 let (injector_stream_sender, injector_stream_receiver) =
1107 futures::channel::oneshot::channel::<pointerinjector::DeviceRequestStream>();
1108 let registry_fut = handle_registry_request_stream(
1109 injector_registry_request_stream,
1110 injector_stream_sender,
1111 );
1112 let device_fut = handle_device_request_stream(injector_stream_receiver, expected_events);
1113
1114 let (handle_result, _, _) = futures::join!(handle_event_fut, registry_fut, device_fut);
1117 match receiver.next().await {
1118 Some(CursorMessage::SetPosition(position)) => {
1119 assert_eq!(position, expected_position);
1120 }
1121 Some(CursorMessage::SetVisibility(_)) => {
1122 panic!("Received unexpected cursor visibility update.")
1123 }
1124 None => panic!("Did not receive cursor update."),
1125 }
1126
1127 assert_matches!(
1129 handle_result.as_slice(),
1130 [input_device::InputEvent { handled: input_device::Handled::Yes, .. }]
1131 );
1132 }
1133
1134 #[test_case(
1136 mouse_binding::MousePhase::Down,
1137 vec![1], vec![1]; "Down event injects button press state."
1138 )]
1139 #[test_case(
1140 mouse_binding::MousePhase::Up,
1141 vec![1], vec![]; "Up event injects button press state."
1142 )]
1143 #[fuchsia::test(allow_stalls = false)]
1144 async fn button_state_event(
1145 phase: mouse_binding::MousePhase,
1146 affected_buttons: Vec<mouse_binding::MouseButton>,
1147 pressed_buttons: Vec<mouse_binding::MouseButton>,
1148 ) {
1149 let (configuration_proxy, mut configuration_request_stream) =
1151 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1152 let (injector_registry_proxy, injector_registry_request_stream) =
1153 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1154 let config_request_stream_fut =
1155 handle_configuration_request_stream(&mut configuration_request_stream);
1156
1157 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
1159 let inspector = fuchsia_inspect::Inspector::default();
1160 let test_node = inspector.root().create_child("test_node");
1161 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1162 configuration_proxy,
1163 injector_registry_proxy,
1164 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1165 sender,
1166 &test_node,
1167 metrics::MetricsLogger::default(),
1168 );
1169 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1170 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1171
1172 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
1173 let event_time = zx::MonotonicInstant::get();
1174
1175 let input_event = create_mouse_event(
1176 cursor_location,
1177 None, None, None, phase,
1181 HashSet::from_iter(affected_buttons.clone()),
1182 HashSet::from_iter(pressed_buttons.clone()),
1183 event_time,
1184 &DESCRIPTOR,
1185 );
1186
1187 let handle_event_fut = mouse_handler.handle_input_event(input_event);
1189 let expected_position = Position { x: 0.0, y: 0.0 };
1190 let expected_events = vec![
1191 create_mouse_pointer_sample_event_phase_add(
1192 pressed_buttons.clone(),
1193 expected_position,
1194 event_time,
1195 ),
1196 create_mouse_pointer_sample_event(
1197 pointerinjector::EventPhase::Change,
1198 pressed_buttons.clone(),
1199 expected_position,
1200 None, None, None, None, event_time,
1205 ),
1206 ];
1207
1208 let (injector_stream_sender, injector_stream_receiver) =
1212 futures::channel::oneshot::channel::<pointerinjector::DeviceRequestStream>();
1213 let registry_fut = handle_registry_request_stream(
1214 injector_registry_request_stream,
1215 injector_stream_sender,
1216 );
1217 let device_fut = handle_device_request_stream(injector_stream_receiver, expected_events);
1218
1219 let (handle_result, _, _) = futures::join!(handle_event_fut, registry_fut, device_fut);
1222 match receiver.next().await {
1223 Some(CursorMessage::SetPosition(position)) => {
1224 pretty_assertions::assert_eq!(position, expected_position);
1225 }
1226 Some(CursorMessage::SetVisibility(_)) => {
1227 panic!("Received unexpected cursor visibility update.")
1228 }
1229 None => panic!("Did not receive cursor update."),
1230 }
1231
1232 assert_matches!(
1234 handle_result.as_slice(),
1235 [input_device::InputEvent { handled: input_device::Handled::Yes, .. }]
1236 );
1237 }
1238
1239 #[fuchsia::test(allow_stalls = false)]
1241 async fn down_up_event() {
1242 let (configuration_proxy, mut configuration_request_stream) =
1244 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1245 let (injector_registry_proxy, injector_registry_request_stream) =
1246 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1247 let config_request_stream_fut =
1248 handle_configuration_request_stream(&mut configuration_request_stream);
1249
1250 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(2);
1254 let inspector = fuchsia_inspect::Inspector::default();
1255 let test_node = inspector.root().create_child("test_node");
1256 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1257 configuration_proxy,
1258 injector_registry_proxy,
1259 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1260 sender,
1261 &test_node,
1262 metrics::MetricsLogger::default(),
1263 );
1264 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1265 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1266
1267 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
1268 let event_time1 = zx::MonotonicInstant::get();
1269 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
1270
1271 let event1 = create_mouse_event(
1272 cursor_location,
1273 None, None, None, mouse_binding::MousePhase::Down,
1277 HashSet::from_iter(vec![1]),
1278 HashSet::from_iter(vec![1]),
1279 event_time1,
1280 &DESCRIPTOR,
1281 );
1282
1283 let event2 = create_mouse_event(
1284 cursor_location,
1285 None, None, None, mouse_binding::MousePhase::Up,
1289 HashSet::from_iter(vec![1]),
1290 HashSet::new(),
1291 event_time2,
1292 &DESCRIPTOR,
1293 );
1294
1295 let expected_position = Position { x: 0.0, y: 0.0 };
1296
1297 let (injector_stream_sender, injector_stream_receiver) =
1301 mpsc::unbounded::<Vec<pointerinjector::Event>>();
1302 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
1304 let registry_fut = handle_registry_request_stream2(
1305 injector_registry_request_stream,
1306 injector_stream_sender,
1307 );
1308
1309 let _registry_task = fasync::Task::local(registry_fut);
1311
1312 mouse_handler.clone().handle_input_event(event1).await;
1313 assert_eq!(
1314 injector_stream_receiver
1315 .next()
1316 .await
1317 .map(|events| events.into_iter().flatten().collect()),
1318 Some(vec![
1319 create_mouse_pointer_sample_event_phase_add(
1320 vec![1],
1321 expected_position,
1322 event_time1,
1323 ),
1324 create_mouse_pointer_sample_event(
1325 pointerinjector::EventPhase::Change,
1326 vec![1],
1327 expected_position,
1328 None, None, None, None, event_time1,
1333 )
1334 ])
1335 );
1336
1337 mouse_handler.clone().handle_input_event(event2).await;
1339 assert_eq!(
1340 injector_stream_receiver
1341 .next()
1342 .await
1343 .map(|events| events.into_iter().flatten().collect()),
1344 Some(vec![create_mouse_pointer_sample_event(
1345 pointerinjector::EventPhase::Change,
1346 vec![],
1347 expected_position,
1348 None, None, None, None, event_time2,
1353 )])
1354 );
1355
1356 match receiver.next().await {
1358 Some(CursorMessage::SetPosition(position)) => {
1359 assert_eq!(position, expected_position);
1360 }
1361 Some(CursorMessage::SetVisibility(_)) => {
1362 panic!("Received unexpected cursor visibility update.")
1363 }
1364 None => panic!("Did not receive cursor update."),
1365 }
1366 }
1367
1368 #[fuchsia::test(allow_stalls = false)]
1378 async fn down_down_up_up_event() {
1379 let (configuration_proxy, mut configuration_request_stream) =
1381 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1382 let (injector_registry_proxy, injector_registry_request_stream) =
1383 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1384 let config_request_stream_fut =
1385 handle_configuration_request_stream(&mut configuration_request_stream);
1386
1387 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(4);
1391 let inspector = fuchsia_inspect::Inspector::default();
1392 let test_node = inspector.root().create_child("test_node");
1393 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1394 configuration_proxy,
1395 injector_registry_proxy,
1396 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1397 sender,
1398 &test_node,
1399 metrics::MetricsLogger::default(),
1400 );
1401 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1402 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1403
1404 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
1405 let event_time1 = zx::MonotonicInstant::get();
1406 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
1407 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
1408 let event_time4 = event_time3.add(zx::MonotonicDuration::from_micros(1));
1409
1410 let event1 = create_mouse_event(
1411 cursor_location,
1412 None, None, None, mouse_binding::MousePhase::Down,
1416 HashSet::from_iter(vec![1]),
1417 HashSet::from_iter(vec![1]),
1418 event_time1,
1419 &DESCRIPTOR,
1420 );
1421 let event2 = create_mouse_event(
1422 cursor_location,
1423 None, None, None, mouse_binding::MousePhase::Down,
1427 HashSet::from_iter(vec![2]),
1428 HashSet::from_iter(vec![1, 2]),
1429 event_time2,
1430 &DESCRIPTOR,
1431 );
1432 let event3 = create_mouse_event(
1433 cursor_location,
1434 None, None, None, mouse_binding::MousePhase::Up,
1438 HashSet::from_iter(vec![1]),
1439 HashSet::from_iter(vec![2]),
1440 event_time3,
1441 &DESCRIPTOR,
1442 );
1443 let event4 = create_mouse_event(
1444 cursor_location,
1445 None, None, None, mouse_binding::MousePhase::Up,
1449 HashSet::from_iter(vec![2]),
1450 HashSet::new(),
1451 event_time4,
1452 &DESCRIPTOR,
1453 );
1454
1455 let expected_position = Position { x: 0.0, y: 0.0 };
1456
1457 let (injector_stream_sender, injector_stream_receiver) =
1461 mpsc::unbounded::<Vec<pointerinjector::Event>>();
1462 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
1464 let registry_fut = handle_registry_request_stream2(
1465 injector_registry_request_stream,
1466 injector_stream_sender,
1467 );
1468
1469 let _registry_task = fasync::Task::local(registry_fut);
1471 mouse_handler.clone().handle_input_event(event1).await;
1472 assert_eq!(
1473 injector_stream_receiver
1474 .next()
1475 .await
1476 .map(|events| events.into_iter().flatten().collect()),
1477 Some(vec![
1478 create_mouse_pointer_sample_event_phase_add(
1479 vec![1],
1480 expected_position,
1481 event_time1,
1482 ),
1483 create_mouse_pointer_sample_event(
1484 pointerinjector::EventPhase::Change,
1485 vec![1],
1486 expected_position,
1487 None, None, None, None, event_time1,
1492 )
1493 ])
1494 );
1495
1496 mouse_handler.clone().handle_input_event(event2).await;
1498 let pointer_sample_event2: Vec<_> = injector_stream_receiver
1499 .next()
1500 .await
1501 .map(|events| events.into_iter().flatten().collect())
1502 .expect("Failed to receive pointer sample event.");
1503 let expected_event_time: i64 = event_time2.into_nanos();
1504 assert_eq!(pointer_sample_event2.len(), 1);
1505
1506 match &pointer_sample_event2[0] {
1509 pointerinjector::Event {
1510 timestamp: Some(actual_event_time),
1511 data:
1512 Some(pointerinjector::Data::PointerSample(pointerinjector::PointerSample {
1513 pointer_id: Some(0),
1514 phase: Some(pointerinjector::EventPhase::Change),
1515 position_in_viewport: Some(actual_position),
1516 scroll_v: None,
1517 scroll_h: None,
1518 pressed_buttons: Some(actual_buttons),
1519 relative_motion: None,
1520 ..
1521 })),
1522 ..
1523 } => {
1524 assert_eq!(*actual_event_time, expected_event_time);
1525 assert_eq!(actual_position[0], expected_position.x);
1526 assert_eq!(actual_position[1], expected_position.y);
1527 assert_eq!(
1528 HashSet::<mouse_binding::MouseButton>::from_iter(actual_buttons.clone()),
1529 HashSet::from_iter(vec![1, 2])
1530 );
1531 }
1532 _ => panic!("Unexpected pointer sample event: {:?}", pointer_sample_event2[0]),
1533 }
1534
1535 mouse_handler.clone().handle_input_event(event3).await;
1537 assert_eq!(
1538 injector_stream_receiver
1539 .next()
1540 .await
1541 .map(|events| events.into_iter().flatten().collect()),
1542 Some(vec![create_mouse_pointer_sample_event(
1543 pointerinjector::EventPhase::Change,
1544 vec![2],
1545 expected_position,
1546 None, None, None, None, event_time3,
1551 )])
1552 );
1553
1554 mouse_handler.clone().handle_input_event(event4).await;
1556 assert_eq!(
1557 injector_stream_receiver
1558 .next()
1559 .await
1560 .map(|events| events.into_iter().flatten().collect()),
1561 Some(vec![create_mouse_pointer_sample_event(
1562 pointerinjector::EventPhase::Change,
1563 vec![],
1564 expected_position,
1565 None, None, None, None, event_time4,
1570 )])
1571 );
1572
1573 match receiver.next().await {
1575 Some(CursorMessage::SetPosition(position)) => {
1576 assert_eq!(position, expected_position);
1577 }
1578 Some(CursorMessage::SetVisibility(_)) => {
1579 panic!("Received unexpected cursor visibility update.")
1580 }
1581 None => panic!("Did not receive cursor update."),
1582 }
1583 }
1584
1585 #[fuchsia::test(allow_stalls = false)]
1587 async fn down_move_up_event() {
1588 let (configuration_proxy, mut configuration_request_stream) =
1590 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1591 let (injector_registry_proxy, injector_registry_request_stream) =
1592 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1593 let config_request_stream_fut =
1594 handle_configuration_request_stream(&mut configuration_request_stream);
1595
1596 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(3);
1600 let inspector = fuchsia_inspect::Inspector::default();
1601 let test_node = inspector.root().create_child("test_node");
1602 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1603 configuration_proxy,
1604 injector_registry_proxy,
1605 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1606 sender,
1607 &test_node,
1608 metrics::MetricsLogger::default(),
1609 );
1610 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1611 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1612
1613 let event_time1 = zx::MonotonicInstant::get();
1614 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
1615 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
1616 let zero_position = Position { x: 0.0, y: 0.0 };
1617 let expected_position = Position {
1618 x: 10.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
1619 y: 5.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
1620 };
1621 let expected_relative_motion = [
1622 10.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
1623 5.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
1624 ];
1625 let event1 = create_mouse_event(
1626 mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 }),
1627 None, None, None, mouse_binding::MousePhase::Down,
1631 HashSet::from_iter(vec![1]),
1632 HashSet::from_iter(vec![1]),
1633 event_time1,
1634 &DESCRIPTOR,
1635 );
1636 let event2 = create_mouse_event(
1637 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1638 millimeters: Position { x: 10.0, y: 5.0 },
1639 }),
1640 None, None, None, mouse_binding::MousePhase::Move,
1644 HashSet::from_iter(vec![1]),
1645 HashSet::from_iter(vec![1]),
1646 event_time2,
1647 &DESCRIPTOR,
1648 );
1649 let event3 = create_mouse_event(
1650 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1651 millimeters: Position { x: 0.0, y: 0.0 },
1652 }),
1653 None, None, None, mouse_binding::MousePhase::Up,
1657 HashSet::from_iter(vec![1]),
1658 HashSet::from_iter(vec![]),
1659 event_time3,
1660 &DESCRIPTOR,
1661 );
1662
1663 let (injector_stream_sender, injector_stream_receiver) =
1667 mpsc::unbounded::<Vec<pointerinjector::Event>>();
1668 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
1670 let registry_fut = handle_registry_request_stream2(
1671 injector_registry_request_stream,
1672 injector_stream_sender,
1673 );
1674
1675 let _registry_task = fasync::Task::local(registry_fut);
1677 mouse_handler.clone().handle_input_event(event1).await;
1678 assert_eq!(
1679 injector_stream_receiver
1680 .next()
1681 .await
1682 .map(|events| events.into_iter().flatten().collect()),
1683 Some(vec![
1684 create_mouse_pointer_sample_event_phase_add(vec![1], zero_position, event_time1,),
1685 create_mouse_pointer_sample_event(
1686 pointerinjector::EventPhase::Change,
1687 vec![1],
1688 zero_position,
1689 None, None, None, None, event_time1,
1694 )
1695 ])
1696 );
1697
1698 match receiver.next().await {
1700 Some(CursorMessage::SetPosition(position)) => {
1701 assert_eq!(position, zero_position);
1702 }
1703 Some(CursorMessage::SetVisibility(_)) => {
1704 panic!("Received unexpected cursor visibility update.")
1705 }
1706 None => panic!("Did not receive cursor update."),
1707 }
1708
1709 mouse_handler.clone().handle_input_event(event2).await;
1711 assert_eq!(
1712 injector_stream_receiver
1713 .next()
1714 .await
1715 .map(|events| events.into_iter().flatten().collect()),
1716 Some(vec![create_mouse_pointer_sample_event(
1717 pointerinjector::EventPhase::Change,
1718 vec![1],
1719 expected_position,
1720 Some(expected_relative_motion),
1721 None, None, None, event_time2,
1725 )])
1726 );
1727
1728 match receiver.next().await {
1730 Some(CursorMessage::SetPosition(position)) => {
1731 assert_eq!(position, expected_position);
1732 }
1733 Some(CursorMessage::SetVisibility(_)) => {
1734 panic!("Received unexpected cursor visibility update.")
1735 }
1736 None => panic!("Did not receive cursor update."),
1737 }
1738
1739 mouse_handler.clone().handle_input_event(event3).await;
1741 assert_eq!(
1742 injector_stream_receiver
1743 .next()
1744 .await
1745 .map(|events| events.into_iter().flatten().collect()),
1746 Some(vec![create_mouse_pointer_sample_event(
1747 pointerinjector::EventPhase::Change,
1748 vec![],
1749 expected_position,
1750 None, None, None, None, event_time3,
1755 )])
1756 );
1757
1758 match receiver.next().await {
1760 Some(CursorMessage::SetPosition(position)) => {
1761 assert_eq!(position, expected_position);
1762 }
1763 Some(CursorMessage::SetVisibility(_)) => {
1764 panic!("Received unexpected cursor visibility update.")
1765 }
1766 None => panic!("Did not receive cursor update."),
1767 }
1768 }
1769
1770 #[fuchsia::test(allow_stalls = false)]
1772 async fn handler_ignores_handled_events() {
1773 let (configuration_proxy, mut configuration_request_stream) =
1775 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1776 let (injector_registry_proxy, injector_registry_request_stream) =
1777 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1778 let config_request_stream_fut =
1779 handle_configuration_request_stream(&mut configuration_request_stream);
1780
1781 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
1783 let inspector = fuchsia_inspect::Inspector::default();
1784 let test_node = inspector.root().create_child("test_node");
1785 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1786 configuration_proxy,
1787 injector_registry_proxy,
1788 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1789 sender,
1790 &test_node,
1791 metrics::MetricsLogger::default(),
1792 );
1793 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1794 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1795
1796 let cursor_relative_position = Position { x: 50.0, y: 75.0 };
1797 let cursor_location =
1798 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1799 millimeters: Position {
1800 x: cursor_relative_position.x / COUNTS_PER_MM as f32,
1801 y: cursor_relative_position.y / COUNTS_PER_MM as f32,
1802 },
1803 });
1804 let event_time = zx::MonotonicInstant::get();
1805 let input_events = vec![create_mouse_event_with_handled(
1806 cursor_location,
1807 None, None, None, mouse_binding::MousePhase::Move,
1811 HashSet::new(),
1812 HashSet::new(),
1813 event_time,
1814 &DESCRIPTOR,
1815 input_device::Handled::Yes,
1816 )];
1817
1818 assert_handler_ignores_input_event_sequence(
1819 mouse_handler,
1820 input_events,
1821 injector_registry_request_stream,
1822 )
1823 .await;
1824
1825 assert!(receiver.next().await.is_none());
1827 }
1828
1829 fn zero_relative_location() -> mouse_binding::MouseLocation {
1830 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1831 millimeters: Position { x: 0.0, y: 0.0 },
1832 })
1833 }
1834
1835 #[test_case(
1836 create_mouse_event(
1837 zero_relative_location(),
1838 wheel_delta_ticks(1, None), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1842 HashSet::new(),
1843 HashSet::new(),
1844 zx::MonotonicInstant::ZERO,
1845 &DESCRIPTOR,
1846 ),
1847 create_mouse_pointer_sample_event(
1848 pointerinjector::EventPhase::Change,
1849 vec![],
1850 Position { x: 50.0, y: 50.0 },
1851 None, Some(1), None, Some(false), zx::MonotonicInstant::ZERO,
1856 ); "v tick scroll"
1857 )]
1858 #[test_case(
1859 create_mouse_event(
1860 zero_relative_location(),
1861 None, wheel_delta_ticks(1, None), Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1865 HashSet::new(),
1866 HashSet::new(),
1867 zx::MonotonicInstant::ZERO,
1868 &DESCRIPTOR,
1869 ),
1870 create_mouse_pointer_sample_event(
1871 pointerinjector::EventPhase::Change,
1872 vec![],
1873 Position { x: 50.0, y: 50.0 },
1874 None, None, Some(1), Some(false), zx::MonotonicInstant::ZERO,
1879 ); "h tick scroll"
1880 )]
1881 #[test_case(
1882 create_mouse_event(
1883 zero_relative_location(),
1884 wheel_delta_ticks(1, Some(120.0)), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1888 HashSet::new(),
1889 HashSet::new(),
1890 zx::MonotonicInstant::ZERO,
1891 &DESCRIPTOR,
1892 ),
1893 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
1894 pointerinjector::EventPhase::Change,
1895 vec![],
1896 Position { x: 50.0, y: 50.0 },
1897 None, Some(1), None, Some(120.0), None, Some(false), zx::MonotonicInstant::ZERO,
1904 ); "v tick scroll with physical pixel"
1905 )]
1906 #[test_case(
1907 create_mouse_event(
1908 zero_relative_location(),
1909 None, wheel_delta_ticks(1, Some(120.0)), Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1913 HashSet::new(),
1914 HashSet::new(),
1915 zx::MonotonicInstant::ZERO,
1916 &DESCRIPTOR,
1917 ),
1918 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
1919 pointerinjector::EventPhase::Change,
1920 vec![],
1921 Position { x: 50.0, y: 50.0 },
1922 None, None, Some(1), None, Some(120.0), Some(false), zx::MonotonicInstant::ZERO,
1929 ); "h tick scroll with physical pixel"
1930 )]
1931 #[test_case(
1932 create_mouse_event(
1933 zero_relative_location(),
1934 wheel_delta_mm(1.0, Some(120.0)), None, Some(mouse_binding::PrecisionScroll::Yes), mouse_binding::MousePhase::Wheel,
1938 HashSet::new(),
1939 HashSet::new(),
1940 zx::MonotonicInstant::ZERO,
1941 &DESCRIPTOR,
1942 ),
1943 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
1944 pointerinjector::EventPhase::Change,
1945 vec![],
1946 Position { x: 50.0, y: 50.0 },
1947 None, None, None, Some(120.0), None, Some(true), zx::MonotonicInstant::ZERO,
1954 ); "v mm scroll with physical pixel"
1955 )]
1956 #[test_case(
1957 create_mouse_event(
1958 zero_relative_location(),
1959 None, wheel_delta_mm(1.0, Some(120.0)), Some(mouse_binding::PrecisionScroll::Yes), mouse_binding::MousePhase::Wheel,
1963 HashSet::new(),
1964 HashSet::new(),
1965 zx::MonotonicInstant::ZERO,
1966 &DESCRIPTOR,
1967 ),
1968 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
1969 pointerinjector::EventPhase::Change,
1970 vec![],
1971 Position { x: 50.0, y: 50.0 },
1972 None, None, None, None, Some(120.0), Some(true), zx::MonotonicInstant::ZERO,
1979 ); "h mm scroll with physical pixel"
1980 )]
1981 #[fuchsia::test(allow_stalls = false)]
1983 async fn scroll(event: input_device::InputEvent, want_event: pointerinjector::Event) {
1984 let (configuration_proxy, mut configuration_request_stream) =
1986 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1987 let (injector_registry_proxy, injector_registry_request_stream) =
1988 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1989 let config_request_stream_fut =
1990 handle_configuration_request_stream(&mut configuration_request_stream);
1991
1992 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
1994 let inspector = fuchsia_inspect::Inspector::default();
1995 let test_node = inspector.root().create_child("test_node");
1996 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1997 configuration_proxy,
1998 injector_registry_proxy,
1999 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
2000 sender,
2001 &test_node,
2002 metrics::MetricsLogger::default(),
2003 );
2004 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
2005 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
2006
2007 let (injector_stream_sender, injector_stream_receiver) =
2011 mpsc::unbounded::<Vec<pointerinjector::Event>>();
2012 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
2014 let registry_fut = handle_registry_request_stream2(
2015 injector_registry_request_stream,
2016 injector_stream_sender,
2017 );
2018
2019 let event_time = zx::MonotonicInstant::get();
2020
2021 let event = input_device::InputEvent { event_time, ..event };
2022
2023 let want_event =
2024 pointerinjector::Event { timestamp: Some(event_time.into_nanos()), ..want_event };
2025
2026 let _registry_task = fasync::Task::local(registry_fut);
2028
2029 mouse_handler.clone().handle_input_event(event).await;
2030 let got_events: Vec<_> = injector_stream_receiver
2031 .next()
2032 .await
2033 .map(|events| events.into_iter().flatten().collect())
2034 .unwrap();
2035 pretty_assertions::assert_eq!(got_events.len(), 2);
2036 assert_matches!(
2037 got_events[0],
2038 pointerinjector::Event {
2039 data: Some(pointerinjector::Data::PointerSample(pointerinjector::PointerSample {
2040 phase: Some(pointerinjector::EventPhase::Add),
2041 ..
2042 })),
2043 ..
2044 }
2045 );
2046
2047 pretty_assertions::assert_eq!(got_events[1], want_event);
2048 }
2049
2050 #[fuchsia::test(allow_stalls = false)]
2052 async fn down_scroll_up_scroll() {
2053 let (configuration_proxy, mut configuration_request_stream) =
2055 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
2056 let (injector_registry_proxy, injector_registry_request_stream) =
2057 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
2058 let config_request_stream_fut =
2059 handle_configuration_request_stream(&mut configuration_request_stream);
2060
2061 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
2063 let inspector = fuchsia_inspect::Inspector::default();
2064 let test_node = inspector.root().create_child("test_node");
2065 let mouse_handler_fut = MouseInjectorHandler::new_handler(
2066 configuration_proxy,
2067 injector_registry_proxy,
2068 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
2069 sender,
2070 &test_node,
2071 metrics::MetricsLogger::default(),
2072 );
2073 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
2074 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
2075
2076 let (injector_stream_sender, injector_stream_receiver) =
2080 mpsc::unbounded::<Vec<pointerinjector::Event>>();
2081 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
2083 let registry_fut = handle_registry_request_stream2(
2084 injector_registry_request_stream,
2085 injector_stream_sender,
2086 );
2087
2088 let event_time1 = zx::MonotonicInstant::get();
2089 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
2090 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
2091 let event_time4 = event_time3.add(zx::MonotonicDuration::from_micros(1));
2092
2093 let _registry_task = fasync::Task::local(registry_fut);
2095
2096 let zero_location =
2097 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
2098 millimeters: Position { x: 0.0, y: 0.0 },
2099 });
2100 let expected_position = Position { x: 50.0, y: 50.0 };
2101
2102 let down_event = create_mouse_event(
2103 zero_location,
2104 None, None, None, mouse_binding::MousePhase::Down,
2108 HashSet::from_iter(vec![1]),
2109 HashSet::from_iter(vec![1]),
2110 event_time1,
2111 &DESCRIPTOR,
2112 );
2113
2114 let wheel_event = create_mouse_event(
2115 zero_location,
2116 wheel_delta_ticks(1, None), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
2120 HashSet::from_iter(vec![1]),
2121 HashSet::from_iter(vec![1]),
2122 event_time2,
2123 &DESCRIPTOR,
2124 );
2125
2126 let up_event = create_mouse_event(
2127 zero_location,
2128 None,
2129 None,
2130 None, mouse_binding::MousePhase::Up,
2132 HashSet::from_iter(vec![1]),
2133 HashSet::new(),
2134 event_time3,
2135 &DESCRIPTOR,
2136 );
2137
2138 let continue_wheel_event = create_mouse_event(
2139 zero_location,
2140 wheel_delta_ticks(1, None), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
2144 HashSet::new(),
2145 HashSet::new(),
2146 event_time4,
2147 &DESCRIPTOR,
2148 );
2149
2150 mouse_handler.clone().handle_input_event(down_event).await;
2152 assert_eq!(
2153 injector_stream_receiver
2154 .next()
2155 .await
2156 .map(|events| events.into_iter().flatten().collect()),
2157 Some(vec![
2158 create_mouse_pointer_sample_event_phase_add(
2159 vec![1],
2160 expected_position,
2161 event_time1,
2162 ),
2163 create_mouse_pointer_sample_event(
2164 pointerinjector::EventPhase::Change,
2165 vec![1],
2166 expected_position,
2167 None, None, None, None, event_time1,
2172 ),
2173 ])
2174 );
2175
2176 mouse_handler.clone().handle_input_event(wheel_event).await;
2178 assert_eq!(
2179 injector_stream_receiver
2180 .next()
2181 .await
2182 .map(|events| events.into_iter().flatten().collect()),
2183 Some(vec![create_mouse_pointer_sample_event(
2184 pointerinjector::EventPhase::Change,
2185 vec![1],
2186 expected_position,
2187 None, Some(1), None, Some(false), event_time2,
2192 )])
2193 );
2194
2195 mouse_handler.clone().handle_input_event(up_event).await;
2197 assert_eq!(
2198 injector_stream_receiver
2199 .next()
2200 .await
2201 .map(|events| events.into_iter().flatten().collect()),
2202 Some(vec![create_mouse_pointer_sample_event(
2203 pointerinjector::EventPhase::Change,
2204 vec![],
2205 expected_position,
2206 None, None, None, None, event_time3,
2211 )])
2212 );
2213
2214 mouse_handler.clone().handle_input_event(continue_wheel_event).await;
2216 assert_eq!(
2217 injector_stream_receiver
2218 .next()
2219 .await
2220 .map(|events| events.into_iter().flatten().collect()),
2221 Some(vec![create_mouse_pointer_sample_event(
2222 pointerinjector::EventPhase::Change,
2223 vec![],
2224 expected_position,
2225 None, Some(1), None, Some(false), event_time4,
2230 )])
2231 );
2232 }
2233
2234 #[fuchsia::test(allow_stalls = false)]
2235 async fn mouse_injector_handler_initialized_with_inspect_node() {
2236 let (configuration_proxy, mut configuration_request_stream) =
2237 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
2238 let config_request_stream_fut =
2239 handle_configuration_request_stream(&mut configuration_request_stream);
2240 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
2241 let inspector = fuchsia_inspect::Inspector::default();
2242 let fake_handlers_node = inspector.root().create_child("input_handlers_node");
2243 let mouse_handler_fut = MouseInjectorHandler::new_with_config_proxy(
2244 configuration_proxy,
2245 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
2246 sender,
2247 &fake_handlers_node,
2248 metrics::MetricsLogger::default(),
2249 );
2250 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
2251 let _handler = mouse_handler_res.expect("Failed to create mouse handler");
2252
2253 diagnostics_assertions::assert_data_tree!(inspector, root: {
2254 input_handlers_node: {
2255 mouse_injector_handler: {
2256 events_received_count: 0u64,
2257 events_handled_count: 0u64,
2258 last_received_timestamp_ns: 0u64,
2259 "fuchsia.inspect.Health": {
2260 status: "STARTING_UP",
2261 start_timestamp_nanos: diagnostics_assertions::AnyProperty
2264 },
2265 }
2266 }
2267 });
2268 }
2269
2270 #[fuchsia::test(allow_stalls = false)]
2271 async fn mouse_injector_handler_inspect_counts_events() {
2272 let (configuration_proxy, mut configuration_request_stream) =
2274 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
2275 let (injector_registry_proxy, injector_registry_request_stream) =
2276 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
2277 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
2278
2279 let inspector = fuchsia_inspect::Inspector::default();
2280 let fake_handlers_node = inspector.root().create_child("input_handlers_node");
2281
2282 let mouse_handler_fut = MouseInjectorHandler::new_handler(
2284 configuration_proxy,
2285 injector_registry_proxy,
2286 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
2287 sender,
2288 &fake_handlers_node,
2289 metrics::MetricsLogger::default(),
2290 );
2291 let config_request_stream_fut =
2292 handle_configuration_request_stream(&mut configuration_request_stream);
2293
2294 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
2295 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
2296
2297 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
2298 let event_time1 = zx::MonotonicInstant::get();
2299 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
2300 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
2301
2302 let input_events = vec![
2303 create_mouse_event(
2304 cursor_location,
2305 None, None, None, mouse_binding::MousePhase::Down,
2309 HashSet::from_iter(vec![1]),
2310 HashSet::from_iter(vec![1]),
2311 event_time1,
2312 &DESCRIPTOR,
2313 ),
2314 create_mouse_event(
2315 cursor_location,
2316 None, None, None, mouse_binding::MousePhase::Up,
2320 HashSet::from_iter(vec![1]),
2321 HashSet::new(),
2322 event_time2,
2323 &DESCRIPTOR,
2324 ),
2325 create_mouse_event_with_handled(
2326 cursor_location,
2327 None, None, None, mouse_binding::MousePhase::Down,
2331 HashSet::from_iter(vec![1]),
2332 HashSet::from_iter(vec![1]),
2333 event_time3,
2334 &DESCRIPTOR,
2335 input_device::Handled::Yes,
2336 ),
2337 ];
2338
2339 let (injector_stream_sender, _) = mpsc::unbounded::<Vec<pointerinjector::Event>>();
2343 let registry_fut = handle_registry_request_stream2(
2344 injector_registry_request_stream,
2345 injector_stream_sender,
2346 );
2347
2348 let _registry_task = fasync::Task::local(registry_fut);
2350 for input_event in input_events {
2351 mouse_handler.clone().handle_input_event(input_event).await;
2352 }
2353
2354 let last_received_event_time: u64 = event_time2.into_nanos().try_into().unwrap();
2355
2356 diagnostics_assertions::assert_data_tree!(inspector, root: {
2357 input_handlers_node: {
2358 mouse_injector_handler: {
2359 events_received_count: 2u64,
2360 events_handled_count: 2u64,
2361 last_received_timestamp_ns: last_received_event_time,
2362 "fuchsia.inspect.Health": {
2363 status: "STARTING_UP",
2364 start_timestamp_nanos: diagnostics_assertions::AnyProperty
2367 },
2368 }
2369 }
2370 });
2371 }
2372}