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!("input", "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!("input", "mouse_injector_handler[processing]");
100 let trace_id = match trace_id {
101 Some(id) => {
102 fuchsia_trace::flow_end!("input", "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 log::warn!("Unhandled input event: {:?}", input_event.get_event_type());
150 }
151 }
152 vec![input_event]
153 }
154
155 fn set_handler_healthy(self: std::rc::Rc<Self>) {
156 self.inspect_status.health_node.borrow_mut().set_ok();
157 }
158
159 fn set_handler_unhealthy(self: std::rc::Rc<Self>, msg: &str) {
160 self.inspect_status.health_node.borrow_mut().set_unhealthy(msg);
161 }
162
163 fn get_name(&self) -> &'static str {
164 "MouseInjectorHandler"
165 }
166
167 fn interest(&self) -> Vec<input_device::InputEventType> {
168 vec![input_device::InputEventType::Mouse]
169 }
170}
171
172impl MouseInjectorHandler {
173 pub async fn new(
186 display_size: Size,
187 cursor_message_sender: Sender<CursorMessage>,
188 input_handlers_node: &fuchsia_inspect::Node,
189 metrics_logger: metrics::MetricsLogger,
190 ) -> Result<Rc<Self>, Error> {
191 let configuration_proxy = connect_to_protocol::<pointerinjector_config::SetupMarker>()?;
192 let injector_registry_proxy = connect_to_protocol::<pointerinjector::RegistryMarker>()?;
193
194 Self::new_handler(
195 configuration_proxy,
196 injector_registry_proxy,
197 display_size,
198 cursor_message_sender,
199 input_handlers_node,
200 metrics_logger,
201 )
202 .await
203 }
204
205 pub async fn new_with_config_proxy(
221 configuration_proxy: pointerinjector_config::SetupProxy,
222 display_size: Size,
223 cursor_message_sender: Sender<CursorMessage>,
224 input_handlers_node: &fuchsia_inspect::Node,
225 metrics_logger: metrics::MetricsLogger,
226 ) -> Result<Rc<Self>, Error> {
227 let injector_registry_proxy = connect_to_protocol::<pointerinjector::RegistryMarker>()?;
228 Self::new_handler(
229 configuration_proxy,
230 injector_registry_proxy,
231 display_size,
232 cursor_message_sender,
233 input_handlers_node,
234 metrics_logger,
235 )
236 .await
237 }
238
239 fn inner(&self) -> Ref<'_, MutableState> {
240 self.mutable_state.borrow()
241 }
242
243 fn inner_mut(&self) -> RefMut<'_, MutableState> {
244 self.mutable_state.borrow_mut()
245 }
246
247 async fn new_handler(
263 configuration_proxy: pointerinjector_config::SetupProxy,
264 injector_registry_proxy: pointerinjector::RegistryProxy,
265 display_size: Size,
266 cursor_message_sender: Sender<CursorMessage>,
267 input_handlers_node: &fuchsia_inspect::Node,
268 metrics_logger: metrics::MetricsLogger,
269 ) -> Result<Rc<Self>, Error> {
270 let (context_view_ref, target_view_ref) = configuration_proxy.get_view_refs().await?;
272 let inspect_status = InputHandlerStatus::new(
273 input_handlers_node,
274 "mouse_injector_handler",
275 false,
276 );
277 let handler = Rc::new(Self {
278 mutable_state: RefCell::new(MutableState {
279 viewport: None,
280 injectors: HashMap::new(),
281 current_position: Position {
283 x: display_size.width / 2.0,
284 y: display_size.height / 2.0,
285 },
286 cursor_message_sender,
287 }),
288 context_view_ref,
289 target_view_ref,
290 max_position: Position { x: display_size.width, y: display_size.height },
291 injector_registry_proxy,
292 configuration_proxy,
293 inspect_status,
294 metrics_logger,
295 });
296
297 Ok(handler)
298 }
299
300 async fn ensure_injector_registered(
308 self: &Rc<Self>,
309 mouse_event: &mouse_binding::MouseEvent,
310 mouse_descriptor: &mouse_binding::MouseDeviceDescriptor,
311 event_time: zx::MonotonicInstant,
312 ) -> Result<(), anyhow::Error> {
313 if self.inner().injectors.contains_key(&mouse_descriptor.device_id) {
314 return Ok(());
315 }
316
317 let (device_proxy, device_server) = create_proxy::<pointerinjector::DeviceMarker>();
319 let context = fuchsia_scenic::duplicate_view_ref(&self.context_view_ref)
320 .context("Failed to duplicate context view ref.")?;
321 let target = fuchsia_scenic::duplicate_view_ref(&self.target_view_ref)
322 .context("Failed to duplicate target view ref.")?;
323
324 let viewport = self.inner().viewport.clone();
325 let config = pointerinjector::Config {
326 device_id: Some(mouse_descriptor.device_id),
327 device_type: Some(pointerinjector::DeviceType::Mouse),
328 context: Some(pointerinjector::Context::View(context)),
329 target: Some(pointerinjector::Target::View(target)),
330 viewport,
331 dispatch_policy: Some(pointerinjector::DispatchPolicy::MouseHoverAndLatchInTarget),
332 scroll_v_range: mouse_descriptor.wheel_v_range.clone(),
333 scroll_h_range: mouse_descriptor.wheel_h_range.clone(),
334 buttons: mouse_descriptor.buttons.clone(),
335 ..Default::default()
336 };
337
338 self.injector_registry_proxy
340 .register(config, device_server)
341 .await
342 .context("Failed to register injector.")?;
343 log::info!("Registered injector with device id {:?}", mouse_descriptor.device_id);
344
345 self.inner_mut().injectors.insert(mouse_descriptor.device_id, device_proxy.clone());
347
348 let events_to_send = vec![self.create_pointer_sample_event(
350 mouse_event,
351 event_time,
352 pointerinjector::EventPhase::Add,
353 self.inner().current_position,
354 None,
355 None,
356 )];
357 device_proxy.inject_events(events_to_send).context("Failed to ADD new MouseDevice.")?;
358
359 Ok(())
360 }
361
362 async fn update_cursor_renderer(
373 &self,
374 mouse_event: &mouse_binding::MouseEvent,
375 mouse_descriptor: &mouse_binding::MouseDeviceDescriptor,
376 ) -> Result<(), anyhow::Error> {
377 let mut new_position = match (mouse_event.location, mouse_descriptor) {
378 (
379 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
380 millimeters,
381 }),
382 _,
383 ) => {
384 self.inner().current_position
385 + self.relative_movement_mm_to_phyical_pixel(millimeters)
386 }
387 (
388 mouse_binding::MouseLocation::Absolute(position),
389 mouse_binding::MouseDeviceDescriptor {
390 absolute_x_range: Some(x_range),
391 absolute_y_range: Some(y_range),
392 ..
393 },
394 ) => self.scale_absolute_position(&position, &x_range, &y_range),
395 (mouse_binding::MouseLocation::Absolute(_), _) => {
396 return Err(anyhow!(
397 "Received an Absolute mouse location without absolute device ranges."
398 ));
399 }
400 };
401 Position::clamp(&mut new_position, Position::zero(), self.max_position);
402 self.inner_mut().current_position = new_position;
403
404 let mut cursor_message_sender = self.inner().cursor_message_sender.clone();
405 cursor_message_sender
406 .send(CursorMessage::SetPosition(new_position))
407 .await
408 .context("Failed to send current mouse position to cursor renderer")?;
409
410 Ok(())
411 }
412
413 fn scale_absolute_position(
421 &self,
422 position: &Position,
423 x_range: &Range,
424 y_range: &Range,
425 ) -> Position {
426 let range_min = Position { x: x_range.min as f32, y: y_range.min as f32 };
427 let range_max = Position { x: x_range.max as f32, y: y_range.max as f32 };
428 self.max_position * ((*position - range_min) / (range_max - range_min))
429 }
430
431 async fn send_event_to_scenic(
438 &self,
439 mouse_event: &mouse_binding::MouseEvent,
440 mouse_descriptor: &mouse_binding::MouseDeviceDescriptor,
441 event_time: zx::MonotonicInstant,
442 tracing_id: u64,
443 ) -> Result<(), anyhow::Error> {
444 let injector = self.inner().injectors.get(&mouse_descriptor.device_id).cloned();
445 if let Some(injector) = injector {
446 let relative_motion = match mouse_event.location {
447 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
448 millimeters: offset_mm,
449 }) if mouse_event.phase == mouse_binding::MousePhase::Move => {
450 let offset = self.relative_movement_mm_to_phyical_pixel(offset_mm);
451 Some([offset.x, offset.y])
452 }
453 _ => None,
454 };
455 let events_to_send = vec![self.create_pointer_sample_event(
456 mouse_event,
457 event_time,
458 pointerinjector::EventPhase::Change,
459 self.inner().current_position,
460 relative_motion,
461 Some(tracing_id),
462 )];
463
464 fuchsia_trace::flow_begin!("input", "dispatch_event_to_scenic", tracing_id.into());
465
466 let _ = injector.inject_events(events_to_send);
467
468 Ok(())
469 } else {
470 Err(anyhow::format_err!(
471 "No injector found for mouse device {}.",
472 mouse_descriptor.device_id
473 ))
474 }
475 }
476
477 fn create_pointer_sample_event(
486 &self,
487 mouse_event: &mouse_binding::MouseEvent,
488 event_time: zx::MonotonicInstant,
489 phase: pointerinjector::EventPhase,
490 current_position: Position,
491 relative_motion: Option<[f32; 2]>,
492 trace_id: Option<u64>,
493 ) -> pointerinjector::Event {
494 let pointer_sample = pointerinjector::PointerSample {
495 pointer_id: Some(0),
496 phase: Some(phase),
497 position_in_viewport: Some([current_position.x, current_position.y]),
498 scroll_v: match mouse_event.wheel_delta_v {
499 Some(mouse_binding::WheelDelta {
500 raw_data: mouse_binding::RawWheelDelta::Ticks(tick),
501 ..
502 }) => Some(tick),
503 _ => None,
504 },
505 scroll_h: match mouse_event.wheel_delta_h {
506 Some(mouse_binding::WheelDelta {
507 raw_data: mouse_binding::RawWheelDelta::Ticks(tick),
508 ..
509 }) => Some(tick),
510 _ => None,
511 },
512 scroll_v_physical_pixel: match mouse_event.wheel_delta_v {
513 Some(mouse_binding::WheelDelta { physical_pixel: Some(pixel), .. }) => {
514 Some(pixel.into())
515 }
516 _ => None,
517 },
518 scroll_h_physical_pixel: match mouse_event.wheel_delta_h {
519 Some(mouse_binding::WheelDelta { physical_pixel: Some(pixel), .. }) => {
520 Some(pixel.into())
521 }
522 _ => None,
523 },
524 is_precision_scroll: match mouse_event.phase {
525 mouse_binding::MousePhase::Wheel => match mouse_event.is_precision_scroll {
526 Some(mouse_binding::PrecisionScroll::Yes) => Some(true),
527 Some(mouse_binding::PrecisionScroll::No) => Some(false),
528 None => {
529 self.metrics_logger.log_error(
530 InputPipelineErrorMetricDimensionEvent::MouseInjectorMissingIsPrecisionScroll,
531 "mouse wheel event does not have value in is_precision_scroll.");
532 None
533 }
534 },
535 _ => None,
536 },
537 pressed_buttons: Some(Vec::from_iter(mouse_event.pressed_buttons.iter().cloned())),
538 relative_motion,
539 ..Default::default()
540 };
541 pointerinjector::Event {
542 timestamp: Some(event_time.into_nanos()),
543 data: Some(pointerinjector::Data::PointerSample(pointer_sample)),
544 trace_flow_id: trace_id,
545 wake_lease: mouse_event.wake_lease.lock().take(),
546 ..Default::default()
547 }
548 }
549
550 pub async fn watch_viewport(self: Rc<Self>) {
552 let configuration_proxy = self.configuration_proxy.clone();
553 let mut viewport_stream = HangingGetStream::new(
554 configuration_proxy,
555 pointerinjector_config::SetupProxy::watch_viewport,
556 );
557 loop {
558 match viewport_stream.next().await {
559 Some(Ok(new_viewport)) => {
560 self.inner_mut().viewport = Some(new_viewport.clone());
562
563 let injectors = self.inner().injectors.values().cloned().collect::<Vec<_>>();
565 for injector in injectors {
566 let events = vec![pointerinjector::Event {
567 timestamp: Some(fuchsia_async::MonotonicInstant::now().into_nanos()),
568 data: Some(pointerinjector::Data::Viewport(new_viewport.clone())),
569 trace_flow_id: Some(fuchsia_trace::Id::random().into()),
570 ..Default::default()
571 }];
572 injector.inject_events(events).expect("Failed to inject updated viewport.");
573 }
574 }
575 Some(Err(e)) => {
576 self.metrics_logger.log_error(
577 InputPipelineErrorMetricDimensionEvent::MouseInjectorErrorWhileReadingViewportUpdate,
578 std::format!("Error while reading viewport update: {}", e));
579 return;
580 }
581 None => {
582 self.metrics_logger.log_error(
583 InputPipelineErrorMetricDimensionEvent::MouseInjectorViewportUpdateStreamTerminatedUnexpectedly,
584 "Viewport update stream terminated unexpectedly");
585 return;
586 }
587 }
588 }
589 }
590
591 fn relative_movement_mm_to_phyical_pixel(&self, movement_mm: Position) -> Position {
595 Position {
596 x: movement_mm.x * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
597 y: movement_mm.y * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
598 }
599 }
600}
601
602#[cfg(test)]
603mod tests {
604 use super::*;
605 use crate::testing_utilities::{
606 assert_handler_ignores_input_event_sequence, create_mouse_event,
607 create_mouse_event_with_handled, create_mouse_pointer_sample_event,
608 create_mouse_pointer_sample_event_phase_add,
609 create_mouse_pointer_sample_event_with_wheel_physical_pixel,
610 };
611 use assert_matches::assert_matches;
612 use futures::channel::mpsc;
613 use pretty_assertions::assert_eq;
614 use std::collections::HashSet;
615 use std::ops::Add;
616 use test_case::test_case;
617 use {
618 fidl_fuchsia_input_report as fidl_input_report,
619 fidl_fuchsia_ui_pointerinjector as pointerinjector, fuchsia_async as fasync,
620 };
621
622 const DISPLAY_WIDTH_IN_PHYSICAL_PX: f32 = 100.0;
623 const DISPLAY_HEIGHT_IN_PHYSICAL_PX: f32 = 100.0;
624 const COUNTS_PER_MM: u32 = 12;
625
626 const DESCRIPTOR: input_device::InputDeviceDescriptor =
628 input_device::InputDeviceDescriptor::Mouse(mouse_binding::MouseDeviceDescriptor {
629 device_id: 1,
630 absolute_x_range: Some(fidl_input_report::Range { min: 0, max: 100 }),
631 absolute_y_range: Some(fidl_input_report::Range { min: 0, max: 100 }),
632 wheel_v_range: Some(fidl_input_report::Axis {
633 range: fidl_input_report::Range { min: -1, max: 1 },
634 unit: fidl_input_report::Unit {
635 type_: fidl_input_report::UnitType::Other,
636 exponent: 0,
637 },
638 }),
639 wheel_h_range: Some(fidl_input_report::Axis {
640 range: fidl_input_report::Range { min: -1, max: 1 },
641 unit: fidl_input_report::Unit {
642 type_: fidl_input_report::UnitType::Other,
643 exponent: 0,
644 },
645 }),
646 buttons: None,
647 counts_per_mm: COUNTS_PER_MM,
648 });
649
650 async fn handle_configuration_request_stream(
652 stream: &mut pointerinjector_config::SetupRequestStream,
653 ) {
654 if let Some(Ok(request)) = stream.next().await {
655 match request {
656 pointerinjector_config::SetupRequest::GetViewRefs { responder, .. } => {
657 let context = fuchsia_scenic::ViewRefPair::new()
658 .expect("Failed to create viewrefpair.")
659 .view_ref;
660 let target = fuchsia_scenic::ViewRefPair::new()
661 .expect("Failed to create viewrefpair.")
662 .view_ref;
663 let _ = responder.send(context, target);
664 }
665 _ => {}
666 };
667 }
668 }
669
670 async fn handle_registry_request_stream(
673 mut stream: pointerinjector::RegistryRequestStream,
674 injector_sender: futures::channel::oneshot::Sender<pointerinjector::DeviceRequestStream>,
675 ) {
676 if let Some(request) = stream.next().await {
677 match request {
678 Ok(pointerinjector::RegistryRequest::Register {
679 config: _,
680 injector,
681 responder,
682 ..
683 }) => {
684 let injector_stream = injector.into_stream();
685 let _ = injector_sender.send(injector_stream);
686 responder.send().expect("failed to respond");
687 }
688 _ => {}
689 };
690 } else {
691 panic!("RegistryRequestStream failed.");
692 }
693 }
694
695 async fn handle_registry_request_stream2(
697 mut stream: pointerinjector::RegistryRequestStream,
698 injector_sender: mpsc::UnboundedSender<Vec<pointerinjector::Event>>,
699 ) {
700 let (injector, responder) = match stream.next().await {
701 Some(Ok(pointerinjector::RegistryRequest::Register {
702 config: _,
703 injector,
704 responder,
705 ..
706 })) => (injector, responder),
707 other => panic!("expected register request, but got {:?}", other),
708 };
709 let injector_stream: pointerinjector::DeviceRequestStream = injector.into_stream();
710 responder.send().expect("failed to respond");
711 injector_stream
712 .for_each(|request| {
713 futures::future::ready({
714 match request {
715 Ok(pointerinjector::DeviceRequest::Inject { .. }) => {
716 panic!("DeviceRequest::Inject is deprecated.");
717 }
718 Ok(pointerinjector::DeviceRequest::InjectEvents { events, .. }) => {
719 let _ = injector_sender.unbounded_send(events);
720 }
721 Err(e) => panic!("FIDL error {}", e),
722 }
723 })
724 })
725 .await;
726 }
727
728 async fn handle_device_request_stream(
731 injector_stream_receiver: futures::channel::oneshot::Receiver<
732 pointerinjector::DeviceRequestStream,
733 >,
734 expected_events: Vec<pointerinjector::Event>,
735 ) {
736 let mut injector_stream =
737 injector_stream_receiver.await.expect("Failed to get DeviceRequestStream.");
738 for expected_event in expected_events {
739 match injector_stream.next().await {
740 Some(Ok(pointerinjector::DeviceRequest::Inject { .. })) => {
741 panic!("DeviceRequest::Inject is deprecated.");
742 }
743 Some(Ok(pointerinjector::DeviceRequest::InjectEvents { events, .. })) => {
744 assert_eq!(events, vec![expected_event]);
745 }
746 Some(Err(e)) => panic!("FIDL error {}", e),
747 None => panic!("Expected another event."),
748 }
749 }
750 }
751
752 fn create_viewport(min: f32, max: f32) -> pointerinjector::Viewport {
754 pointerinjector::Viewport {
755 extents: Some([[min, min], [max, max]]),
756 viewport_to_context_transform: None,
757 ..Default::default()
758 }
759 }
760
761 #[fuchsia::test]
764 fn receives_viewport_updates() {
765 let mut exec = fasync::TestExecutor::new();
766
767 let (configuration_proxy, mut configuration_request_stream) =
769 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
770 let (injector_registry_proxy, _) =
771 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
772 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(0);
773
774 let inspector = fuchsia_inspect::Inspector::default();
775 let test_node = inspector.root().create_child("test_node");
776
777 let mouse_handler_fut = MouseInjectorHandler::new_handler(
779 configuration_proxy,
780 injector_registry_proxy,
781 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
782 sender,
783 &test_node,
784 metrics::MetricsLogger::default(),
785 );
786 let config_request_stream_fut =
787 handle_configuration_request_stream(&mut configuration_request_stream);
788 let (mouse_handler_res, _) = exec.run_singlethreaded(futures::future::join(
789 mouse_handler_fut,
790 config_request_stream_fut,
791 ));
792 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
793
794 let (injector_device_proxy, mut injector_device_request_stream) =
796 fidl::endpoints::create_proxy_and_stream::<pointerinjector::DeviceMarker>();
797 mouse_handler.inner_mut().injectors.insert(1, injector_device_proxy);
798
799 {
801 let watch_viewport_fut = mouse_handler.clone().watch_viewport();
803 futures::pin_mut!(watch_viewport_fut);
804 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
805
806 match exec.run_singlethreaded(&mut configuration_request_stream.next()) {
808 Some(Ok(pointerinjector_config::SetupRequest::WatchViewport {
809 responder, ..
810 })) => {
811 responder.send(&create_viewport(0.0, 100.0)).expect("Failed to send viewport.");
812 }
813 other => panic!("Received unexpected value: {:?}", other),
814 };
815 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
816
817 exec.run_singlethreaded(async {
819 match injector_device_request_stream.next().await {
820 Some(Ok(pointerinjector::DeviceRequest::Inject { .. })) => {
821 panic!("DeviceRequest::Inject is deprecated.");
822 }
823 Some(Ok(pointerinjector::DeviceRequest::InjectEvents { events, .. })) => {
824 assert_eq!(events.len(), 1);
825 assert!(events[0].data.is_some());
826 assert_eq!(
827 events[0].data,
828 Some(pointerinjector::Data::Viewport(create_viewport(0.0, 100.0)))
829 );
830 }
831 other => panic!("Received unexpected value: {:?}", other),
832 }
833 });
834
835 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
837
838 match exec.run_singlethreaded(&mut configuration_request_stream.next()) {
840 Some(Ok(pointerinjector_config::SetupRequest::WatchViewport {
841 responder, ..
842 })) => {
843 responder
844 .send(&create_viewport(100.0, 200.0))
845 .expect("Failed to send viewport.");
846 }
847 other => panic!("Received unexpected value: {:?}", other),
848 };
849
850 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
852 }
853
854 exec.run_singlethreaded(async {
856 match injector_device_request_stream.next().await {
857 Some(Ok(pointerinjector::DeviceRequest::Inject { .. })) => {
858 panic!("DeviceRequest::Inject is deprecated.");
859 }
860 Some(Ok(pointerinjector::DeviceRequest::InjectEvents { events, .. })) => {
861 assert_eq!(events.len(), 1);
862 assert!(events[0].data.is_some());
863 assert_eq!(
864 events[0].data,
865 Some(pointerinjector::Data::Viewport(create_viewport(100.0, 200.0)))
866 );
867 }
868 other => panic!("Received unexpected value: {:?}", other),
869 }
870 });
871
872 let expected_viewport = create_viewport(100.0, 200.0);
874 assert_eq!(mouse_handler.inner().viewport, Some(expected_viewport));
875 }
876
877 fn wheel_delta_ticks(
878 ticks: i64,
879 physical_pixel: Option<f32>,
880 ) -> Option<mouse_binding::WheelDelta> {
881 Some(mouse_binding::WheelDelta {
882 raw_data: mouse_binding::RawWheelDelta::Ticks(ticks),
883 physical_pixel,
884 })
885 }
886
887 fn wheel_delta_mm(mm: f32, physical_pixel: Option<f32>) -> Option<mouse_binding::WheelDelta> {
888 Some(mouse_binding::WheelDelta {
889 raw_data: mouse_binding::RawWheelDelta::Millimeters(mm),
890 physical_pixel,
891 })
892 }
893
894 #[test_case(
897 mouse_binding::MouseLocation::Relative(
898 mouse_binding::RelativeLocation {
899 millimeters: Position { x: 1.0, y: 2.0 }
900 }),
901 Position {
902 x: DISPLAY_WIDTH_IN_PHYSICAL_PX / 2.0
903 + 1.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
904 y: DISPLAY_HEIGHT_IN_PHYSICAL_PX / 2.0
905 + 2.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
906 },
907 [
908 1.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
909 2.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
910 ]; "Valid move event."
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 {
920 x: DISPLAY_WIDTH_IN_PHYSICAL_PX,
921 y: DISPLAY_HEIGHT_IN_PHYSICAL_PX,
922 },
923 [
924 DISPLAY_WIDTH_IN_PHYSICAL_PX + 2.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
925 DISPLAY_HEIGHT_IN_PHYSICAL_PX + 1.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
926 ]; "Move event exceeds max bounds."
927 )]
928 #[test_case(
929 mouse_binding::MouseLocation::Relative(
930 mouse_binding::RelativeLocation {
931 millimeters: Position {
932 x: -(DISPLAY_WIDTH_IN_PHYSICAL_PX / MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL + 2.0),
933 y: -(DISPLAY_HEIGHT_IN_PHYSICAL_PX / MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL + 1.0),
934 }}),
935 Position { x: 0.0, y: 0.0 },
936 [
937 -(DISPLAY_WIDTH_IN_PHYSICAL_PX + 2.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL),
938 -(DISPLAY_HEIGHT_IN_PHYSICAL_PX + 1.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL),
939 ]; "Move event exceeds min bounds."
940 )]
941 #[fuchsia::test(allow_stalls = false)]
942 async fn move_event(
943 move_location: mouse_binding::MouseLocation,
944 expected_position: Position,
945 expected_relative_motion: [f32; 2],
946 ) {
947 let (configuration_proxy, mut configuration_request_stream) =
949 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
950 let (injector_registry_proxy, injector_registry_request_stream) =
951 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
952 let config_request_stream_fut =
953 handle_configuration_request_stream(&mut configuration_request_stream);
954
955 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
957 let inspector = fuchsia_inspect::Inspector::default();
958 let test_node = inspector.root().create_child("test_node");
959 let mouse_handler_fut = MouseInjectorHandler::new_handler(
960 configuration_proxy,
961 injector_registry_proxy,
962 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
963 sender,
964 &test_node,
965 metrics::MetricsLogger::default(),
966 );
967 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
968 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
969
970 let event_time = zx::MonotonicInstant::get();
971 let input_event = create_mouse_event(
972 move_location,
973 None, None, None, mouse_binding::MousePhase::Move,
977 HashSet::new(),
978 HashSet::new(),
979 event_time,
980 &DESCRIPTOR,
981 );
982
983 let handle_event_fut = mouse_handler.handle_input_event(input_event);
985 let expected_events = vec![
986 create_mouse_pointer_sample_event_phase_add(vec![], expected_position, event_time),
987 create_mouse_pointer_sample_event(
988 pointerinjector::EventPhase::Change,
989 vec![],
990 expected_position,
991 Some(expected_relative_motion),
992 None, None, None, event_time,
996 ),
997 ];
998
999 let (injector_stream_sender, injector_stream_receiver) =
1003 futures::channel::oneshot::channel::<pointerinjector::DeviceRequestStream>();
1004 let registry_fut = handle_registry_request_stream(
1005 injector_registry_request_stream,
1006 injector_stream_sender,
1007 );
1008 let device_fut = handle_device_request_stream(injector_stream_receiver, expected_events);
1009
1010 let (handle_result, _, _) = futures::join!(handle_event_fut, registry_fut, device_fut);
1013 match receiver.next().await {
1014 Some(CursorMessage::SetPosition(position)) => {
1015 pretty_assertions::assert_eq!(position, expected_position);
1016 }
1017 Some(CursorMessage::SetVisibility(_)) => {
1018 panic!("Received unexpected cursor visibility update.")
1019 }
1020 None => panic!("Did not receive cursor update."),
1021 }
1022
1023 assert_matches!(
1025 handle_result.as_slice(),
1026 [input_device::InputEvent { handled: input_device::Handled::Yes, .. }]
1027 );
1028 }
1029
1030 #[fuchsia::test(allow_stalls = false)]
1033 async fn move_absolute_event() {
1034 const DEVICE_ID: u32 = 1;
1035
1036 let (configuration_proxy, mut configuration_request_stream) =
1038 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1039 let (injector_registry_proxy, injector_registry_request_stream) =
1040 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1041 let config_request_stream_fut =
1042 handle_configuration_request_stream(&mut configuration_request_stream);
1043
1044 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
1046 let inspector = fuchsia_inspect::Inspector::default();
1047 let test_node = inspector.root().create_child("test_node");
1048 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1049 configuration_proxy,
1050 injector_registry_proxy,
1051 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1052 sender,
1053 &test_node,
1054 metrics::MetricsLogger::default(),
1055 );
1056 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1057 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1058
1059 let cursor_location =
1075 mouse_binding::MouseLocation::Absolute(Position { x: -25.0, y: 25.0 });
1076 let event_time = zx::MonotonicInstant::get();
1077 let descriptor =
1078 input_device::InputDeviceDescriptor::Mouse(mouse_binding::MouseDeviceDescriptor {
1079 device_id: DEVICE_ID,
1080 absolute_x_range: Some(fidl_input_report::Range { min: -50, max: 50 }),
1081 absolute_y_range: Some(fidl_input_report::Range { min: -50, max: 50 }),
1082 wheel_v_range: None,
1083 wheel_h_range: None,
1084 buttons: None,
1085 counts_per_mm: COUNTS_PER_MM,
1086 });
1087 let input_event = create_mouse_event(
1088 cursor_location,
1089 None, None, None, mouse_binding::MousePhase::Move,
1093 HashSet::new(),
1094 HashSet::new(),
1095 event_time,
1096 &descriptor,
1097 );
1098
1099 let handle_event_fut = mouse_handler.handle_input_event(input_event);
1101 let expected_position = Position {
1102 x: DISPLAY_WIDTH_IN_PHYSICAL_PX * 0.25,
1103 y: DISPLAY_WIDTH_IN_PHYSICAL_PX * 0.75,
1104 };
1105 let expected_events = vec![
1106 create_mouse_pointer_sample_event_phase_add(vec![], expected_position, event_time),
1107 create_mouse_pointer_sample_event(
1108 pointerinjector::EventPhase::Change,
1109 vec![],
1110 expected_position,
1111 None, None, None, None, event_time,
1116 ),
1117 ];
1118
1119 let (injector_stream_sender, injector_stream_receiver) =
1123 futures::channel::oneshot::channel::<pointerinjector::DeviceRequestStream>();
1124 let registry_fut = handle_registry_request_stream(
1125 injector_registry_request_stream,
1126 injector_stream_sender,
1127 );
1128 let device_fut = handle_device_request_stream(injector_stream_receiver, expected_events);
1129
1130 let (handle_result, _, _) = futures::join!(handle_event_fut, registry_fut, device_fut);
1133 match receiver.next().await {
1134 Some(CursorMessage::SetPosition(position)) => {
1135 assert_eq!(position, expected_position);
1136 }
1137 Some(CursorMessage::SetVisibility(_)) => {
1138 panic!("Received unexpected cursor visibility update.")
1139 }
1140 None => panic!("Did not receive cursor update."),
1141 }
1142
1143 assert_matches!(
1145 handle_result.as_slice(),
1146 [input_device::InputEvent { handled: input_device::Handled::Yes, .. }]
1147 );
1148 }
1149
1150 #[test_case(
1152 mouse_binding::MousePhase::Down,
1153 vec![1], vec![1]; "Down event injects button press state."
1154 )]
1155 #[test_case(
1156 mouse_binding::MousePhase::Up,
1157 vec![1], vec![]; "Up event injects button press state."
1158 )]
1159 #[fuchsia::test(allow_stalls = false)]
1160 async fn button_state_event(
1161 phase: mouse_binding::MousePhase,
1162 affected_buttons: Vec<mouse_binding::MouseButton>,
1163 pressed_buttons: Vec<mouse_binding::MouseButton>,
1164 ) {
1165 let (configuration_proxy, mut configuration_request_stream) =
1167 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1168 let (injector_registry_proxy, injector_registry_request_stream) =
1169 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1170 let config_request_stream_fut =
1171 handle_configuration_request_stream(&mut configuration_request_stream);
1172
1173 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
1175 let inspector = fuchsia_inspect::Inspector::default();
1176 let test_node = inspector.root().create_child("test_node");
1177 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1178 configuration_proxy,
1179 injector_registry_proxy,
1180 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1181 sender,
1182 &test_node,
1183 metrics::MetricsLogger::default(),
1184 );
1185 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1186 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1187
1188 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
1189 let event_time = zx::MonotonicInstant::get();
1190
1191 let input_event = create_mouse_event(
1192 cursor_location,
1193 None, None, None, phase,
1197 HashSet::from_iter(affected_buttons.clone()),
1198 HashSet::from_iter(pressed_buttons.clone()),
1199 event_time,
1200 &DESCRIPTOR,
1201 );
1202
1203 let handle_event_fut = mouse_handler.handle_input_event(input_event);
1205 let expected_position = Position { x: 0.0, y: 0.0 };
1206 let expected_events = vec![
1207 create_mouse_pointer_sample_event_phase_add(
1208 pressed_buttons.clone(),
1209 expected_position,
1210 event_time,
1211 ),
1212 create_mouse_pointer_sample_event(
1213 pointerinjector::EventPhase::Change,
1214 pressed_buttons.clone(),
1215 expected_position,
1216 None, None, None, None, event_time,
1221 ),
1222 ];
1223
1224 let (injector_stream_sender, injector_stream_receiver) =
1228 futures::channel::oneshot::channel::<pointerinjector::DeviceRequestStream>();
1229 let registry_fut = handle_registry_request_stream(
1230 injector_registry_request_stream,
1231 injector_stream_sender,
1232 );
1233 let device_fut = handle_device_request_stream(injector_stream_receiver, expected_events);
1234
1235 let (handle_result, _, _) = futures::join!(handle_event_fut, registry_fut, device_fut);
1238 match receiver.next().await {
1239 Some(CursorMessage::SetPosition(position)) => {
1240 pretty_assertions::assert_eq!(position, expected_position);
1241 }
1242 Some(CursorMessage::SetVisibility(_)) => {
1243 panic!("Received unexpected cursor visibility update.")
1244 }
1245 None => panic!("Did not receive cursor update."),
1246 }
1247
1248 assert_matches!(
1250 handle_result.as_slice(),
1251 [input_device::InputEvent { handled: input_device::Handled::Yes, .. }]
1252 );
1253 }
1254
1255 #[fuchsia::test(allow_stalls = false)]
1257 async fn down_up_event() {
1258 let (configuration_proxy, mut configuration_request_stream) =
1260 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1261 let (injector_registry_proxy, injector_registry_request_stream) =
1262 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1263 let config_request_stream_fut =
1264 handle_configuration_request_stream(&mut configuration_request_stream);
1265
1266 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(2);
1270 let inspector = fuchsia_inspect::Inspector::default();
1271 let test_node = inspector.root().create_child("test_node");
1272 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1273 configuration_proxy,
1274 injector_registry_proxy,
1275 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1276 sender,
1277 &test_node,
1278 metrics::MetricsLogger::default(),
1279 );
1280 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1281 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1282
1283 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
1284 let event_time1 = zx::MonotonicInstant::get();
1285 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
1286
1287 let event1 = create_mouse_event(
1288 cursor_location,
1289 None, None, None, mouse_binding::MousePhase::Down,
1293 HashSet::from_iter(vec![1]),
1294 HashSet::from_iter(vec![1]),
1295 event_time1,
1296 &DESCRIPTOR,
1297 );
1298
1299 let event2 = create_mouse_event(
1300 cursor_location,
1301 None, None, None, mouse_binding::MousePhase::Up,
1305 HashSet::from_iter(vec![1]),
1306 HashSet::new(),
1307 event_time2,
1308 &DESCRIPTOR,
1309 );
1310
1311 let expected_position = Position { x: 0.0, y: 0.0 };
1312
1313 let (injector_stream_sender, injector_stream_receiver) =
1317 mpsc::unbounded::<Vec<pointerinjector::Event>>();
1318 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
1320 let registry_fut = handle_registry_request_stream2(
1321 injector_registry_request_stream,
1322 injector_stream_sender,
1323 );
1324
1325 let _registry_task = fasync::Task::local(registry_fut);
1327
1328 mouse_handler.clone().handle_input_event(event1).await;
1329 assert_eq!(
1330 injector_stream_receiver
1331 .next()
1332 .await
1333 .map(|events| events.into_iter().flatten().collect()),
1334 Some(vec![
1335 create_mouse_pointer_sample_event_phase_add(
1336 vec![1],
1337 expected_position,
1338 event_time1,
1339 ),
1340 create_mouse_pointer_sample_event(
1341 pointerinjector::EventPhase::Change,
1342 vec![1],
1343 expected_position,
1344 None, None, None, None, event_time1,
1349 )
1350 ])
1351 );
1352
1353 mouse_handler.clone().handle_input_event(event2).await;
1355 assert_eq!(
1356 injector_stream_receiver
1357 .next()
1358 .await
1359 .map(|events| events.into_iter().flatten().collect()),
1360 Some(vec![create_mouse_pointer_sample_event(
1361 pointerinjector::EventPhase::Change,
1362 vec![],
1363 expected_position,
1364 None, None, None, None, event_time2,
1369 )])
1370 );
1371
1372 match receiver.next().await {
1374 Some(CursorMessage::SetPosition(position)) => {
1375 assert_eq!(position, expected_position);
1376 }
1377 Some(CursorMessage::SetVisibility(_)) => {
1378 panic!("Received unexpected cursor visibility update.")
1379 }
1380 None => panic!("Did not receive cursor update."),
1381 }
1382 }
1383
1384 #[fuchsia::test(allow_stalls = false)]
1394 async fn down_down_up_up_event() {
1395 let (configuration_proxy, mut configuration_request_stream) =
1397 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1398 let (injector_registry_proxy, injector_registry_request_stream) =
1399 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1400 let config_request_stream_fut =
1401 handle_configuration_request_stream(&mut configuration_request_stream);
1402
1403 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(4);
1407 let inspector = fuchsia_inspect::Inspector::default();
1408 let test_node = inspector.root().create_child("test_node");
1409 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1410 configuration_proxy,
1411 injector_registry_proxy,
1412 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1413 sender,
1414 &test_node,
1415 metrics::MetricsLogger::default(),
1416 );
1417 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1418 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1419
1420 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
1421 let event_time1 = zx::MonotonicInstant::get();
1422 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
1423 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
1424 let event_time4 = event_time3.add(zx::MonotonicDuration::from_micros(1));
1425
1426 let event1 = create_mouse_event(
1427 cursor_location,
1428 None, None, None, mouse_binding::MousePhase::Down,
1432 HashSet::from_iter(vec![1]),
1433 HashSet::from_iter(vec![1]),
1434 event_time1,
1435 &DESCRIPTOR,
1436 );
1437 let event2 = create_mouse_event(
1438 cursor_location,
1439 None, None, None, mouse_binding::MousePhase::Down,
1443 HashSet::from_iter(vec![2]),
1444 HashSet::from_iter(vec![1, 2]),
1445 event_time2,
1446 &DESCRIPTOR,
1447 );
1448 let event3 = create_mouse_event(
1449 cursor_location,
1450 None, None, None, mouse_binding::MousePhase::Up,
1454 HashSet::from_iter(vec![1]),
1455 HashSet::from_iter(vec![2]),
1456 event_time3,
1457 &DESCRIPTOR,
1458 );
1459 let event4 = create_mouse_event(
1460 cursor_location,
1461 None, None, None, mouse_binding::MousePhase::Up,
1465 HashSet::from_iter(vec![2]),
1466 HashSet::new(),
1467 event_time4,
1468 &DESCRIPTOR,
1469 );
1470
1471 let expected_position = Position { x: 0.0, y: 0.0 };
1472
1473 let (injector_stream_sender, injector_stream_receiver) =
1477 mpsc::unbounded::<Vec<pointerinjector::Event>>();
1478 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
1480 let registry_fut = handle_registry_request_stream2(
1481 injector_registry_request_stream,
1482 injector_stream_sender,
1483 );
1484
1485 let _registry_task = fasync::Task::local(registry_fut);
1487 mouse_handler.clone().handle_input_event(event1).await;
1488 assert_eq!(
1489 injector_stream_receiver
1490 .next()
1491 .await
1492 .map(|events| events.into_iter().flatten().collect()),
1493 Some(vec![
1494 create_mouse_pointer_sample_event_phase_add(
1495 vec![1],
1496 expected_position,
1497 event_time1,
1498 ),
1499 create_mouse_pointer_sample_event(
1500 pointerinjector::EventPhase::Change,
1501 vec![1],
1502 expected_position,
1503 None, None, None, None, event_time1,
1508 )
1509 ])
1510 );
1511
1512 mouse_handler.clone().handle_input_event(event2).await;
1514 let pointer_sample_event2: Vec<_> = injector_stream_receiver
1515 .next()
1516 .await
1517 .map(|events| events.into_iter().flatten().collect())
1518 .expect("Failed to receive pointer sample event.");
1519 let expected_event_time: i64 = event_time2.into_nanos();
1520 assert_eq!(pointer_sample_event2.len(), 1);
1521
1522 match &pointer_sample_event2[0] {
1525 pointerinjector::Event {
1526 timestamp: Some(actual_event_time),
1527 data:
1528 Some(pointerinjector::Data::PointerSample(pointerinjector::PointerSample {
1529 pointer_id: Some(0),
1530 phase: Some(pointerinjector::EventPhase::Change),
1531 position_in_viewport: Some(actual_position),
1532 scroll_v: None,
1533 scroll_h: None,
1534 pressed_buttons: Some(actual_buttons),
1535 relative_motion: None,
1536 ..
1537 })),
1538 ..
1539 } => {
1540 assert_eq!(*actual_event_time, expected_event_time);
1541 assert_eq!(actual_position[0], expected_position.x);
1542 assert_eq!(actual_position[1], expected_position.y);
1543 assert_eq!(
1544 HashSet::<mouse_binding::MouseButton>::from_iter(actual_buttons.clone()),
1545 HashSet::from_iter(vec![1, 2])
1546 );
1547 }
1548 _ => panic!("Unexpected pointer sample event: {:?}", pointer_sample_event2[0]),
1549 }
1550
1551 mouse_handler.clone().handle_input_event(event3).await;
1553 assert_eq!(
1554 injector_stream_receiver
1555 .next()
1556 .await
1557 .map(|events| events.into_iter().flatten().collect()),
1558 Some(vec![create_mouse_pointer_sample_event(
1559 pointerinjector::EventPhase::Change,
1560 vec![2],
1561 expected_position,
1562 None, None, None, None, event_time3,
1567 )])
1568 );
1569
1570 mouse_handler.clone().handle_input_event(event4).await;
1572 assert_eq!(
1573 injector_stream_receiver
1574 .next()
1575 .await
1576 .map(|events| events.into_iter().flatten().collect()),
1577 Some(vec![create_mouse_pointer_sample_event(
1578 pointerinjector::EventPhase::Change,
1579 vec![],
1580 expected_position,
1581 None, None, None, None, event_time4,
1586 )])
1587 );
1588
1589 match receiver.next().await {
1591 Some(CursorMessage::SetPosition(position)) => {
1592 assert_eq!(position, expected_position);
1593 }
1594 Some(CursorMessage::SetVisibility(_)) => {
1595 panic!("Received unexpected cursor visibility update.")
1596 }
1597 None => panic!("Did not receive cursor update."),
1598 }
1599 }
1600
1601 #[fuchsia::test(allow_stalls = false)]
1603 async fn down_move_up_event() {
1604 let (configuration_proxy, mut configuration_request_stream) =
1606 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1607 let (injector_registry_proxy, injector_registry_request_stream) =
1608 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1609 let config_request_stream_fut =
1610 handle_configuration_request_stream(&mut configuration_request_stream);
1611
1612 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(3);
1616 let inspector = fuchsia_inspect::Inspector::default();
1617 let test_node = inspector.root().create_child("test_node");
1618 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1619 configuration_proxy,
1620 injector_registry_proxy,
1621 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1622 sender,
1623 &test_node,
1624 metrics::MetricsLogger::default(),
1625 );
1626 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1627 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1628
1629 let event_time1 = zx::MonotonicInstant::get();
1630 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
1631 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
1632 let zero_position = Position { x: 0.0, y: 0.0 };
1633 let expected_position = Position {
1634 x: 10.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
1635 y: 5.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
1636 };
1637 let expected_relative_motion = [
1638 10.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
1639 5.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
1640 ];
1641 let event1 = create_mouse_event(
1642 mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 }),
1643 None, None, None, mouse_binding::MousePhase::Down,
1647 HashSet::from_iter(vec![1]),
1648 HashSet::from_iter(vec![1]),
1649 event_time1,
1650 &DESCRIPTOR,
1651 );
1652 let event2 = create_mouse_event(
1653 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1654 millimeters: Position { x: 10.0, y: 5.0 },
1655 }),
1656 None, None, None, mouse_binding::MousePhase::Move,
1660 HashSet::from_iter(vec![1]),
1661 HashSet::from_iter(vec![1]),
1662 event_time2,
1663 &DESCRIPTOR,
1664 );
1665 let event3 = create_mouse_event(
1666 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1667 millimeters: Position { x: 0.0, y: 0.0 },
1668 }),
1669 None, None, None, mouse_binding::MousePhase::Up,
1673 HashSet::from_iter(vec![1]),
1674 HashSet::from_iter(vec![]),
1675 event_time3,
1676 &DESCRIPTOR,
1677 );
1678
1679 let (injector_stream_sender, injector_stream_receiver) =
1683 mpsc::unbounded::<Vec<pointerinjector::Event>>();
1684 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
1686 let registry_fut = handle_registry_request_stream2(
1687 injector_registry_request_stream,
1688 injector_stream_sender,
1689 );
1690
1691 let _registry_task = fasync::Task::local(registry_fut);
1693 mouse_handler.clone().handle_input_event(event1).await;
1694 assert_eq!(
1695 injector_stream_receiver
1696 .next()
1697 .await
1698 .map(|events| events.into_iter().flatten().collect()),
1699 Some(vec![
1700 create_mouse_pointer_sample_event_phase_add(vec![1], zero_position, event_time1,),
1701 create_mouse_pointer_sample_event(
1702 pointerinjector::EventPhase::Change,
1703 vec![1],
1704 zero_position,
1705 None, None, None, None, event_time1,
1710 )
1711 ])
1712 );
1713
1714 match receiver.next().await {
1716 Some(CursorMessage::SetPosition(position)) => {
1717 assert_eq!(position, zero_position);
1718 }
1719 Some(CursorMessage::SetVisibility(_)) => {
1720 panic!("Received unexpected cursor visibility update.")
1721 }
1722 None => panic!("Did not receive cursor update."),
1723 }
1724
1725 mouse_handler.clone().handle_input_event(event2).await;
1727 assert_eq!(
1728 injector_stream_receiver
1729 .next()
1730 .await
1731 .map(|events| events.into_iter().flatten().collect()),
1732 Some(vec![create_mouse_pointer_sample_event(
1733 pointerinjector::EventPhase::Change,
1734 vec![1],
1735 expected_position,
1736 Some(expected_relative_motion),
1737 None, None, None, event_time2,
1741 )])
1742 );
1743
1744 match receiver.next().await {
1746 Some(CursorMessage::SetPosition(position)) => {
1747 assert_eq!(position, expected_position);
1748 }
1749 Some(CursorMessage::SetVisibility(_)) => {
1750 panic!("Received unexpected cursor visibility update.")
1751 }
1752 None => panic!("Did not receive cursor update."),
1753 }
1754
1755 mouse_handler.clone().handle_input_event(event3).await;
1757 assert_eq!(
1758 injector_stream_receiver
1759 .next()
1760 .await
1761 .map(|events| events.into_iter().flatten().collect()),
1762 Some(vec![create_mouse_pointer_sample_event(
1763 pointerinjector::EventPhase::Change,
1764 vec![],
1765 expected_position,
1766 None, None, None, None, event_time3,
1771 )])
1772 );
1773
1774 match receiver.next().await {
1776 Some(CursorMessage::SetPosition(position)) => {
1777 assert_eq!(position, expected_position);
1778 }
1779 Some(CursorMessage::SetVisibility(_)) => {
1780 panic!("Received unexpected cursor visibility update.")
1781 }
1782 None => panic!("Did not receive cursor update."),
1783 }
1784 }
1785
1786 #[fuchsia::test(allow_stalls = false)]
1788 async fn handler_ignores_handled_events() {
1789 let (configuration_proxy, mut configuration_request_stream) =
1791 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1792 let (injector_registry_proxy, injector_registry_request_stream) =
1793 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1794 let config_request_stream_fut =
1795 handle_configuration_request_stream(&mut configuration_request_stream);
1796
1797 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
1799 let inspector = fuchsia_inspect::Inspector::default();
1800 let test_node = inspector.root().create_child("test_node");
1801 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1802 configuration_proxy,
1803 injector_registry_proxy,
1804 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1805 sender,
1806 &test_node,
1807 metrics::MetricsLogger::default(),
1808 );
1809 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1810 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1811
1812 let cursor_relative_position = Position { x: 50.0, y: 75.0 };
1813 let cursor_location =
1814 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1815 millimeters: Position {
1816 x: cursor_relative_position.x / COUNTS_PER_MM as f32,
1817 y: cursor_relative_position.y / COUNTS_PER_MM as f32,
1818 },
1819 });
1820 let event_time = zx::MonotonicInstant::get();
1821 let input_events = vec![create_mouse_event_with_handled(
1822 cursor_location,
1823 None, None, None, mouse_binding::MousePhase::Move,
1827 HashSet::new(),
1828 HashSet::new(),
1829 event_time,
1830 &DESCRIPTOR,
1831 input_device::Handled::Yes,
1832 )];
1833
1834 assert_handler_ignores_input_event_sequence(
1835 mouse_handler,
1836 input_events,
1837 injector_registry_request_stream,
1838 )
1839 .await;
1840
1841 assert!(receiver.next().await.is_none());
1843 }
1844
1845 fn zero_relative_location() -> mouse_binding::MouseLocation {
1846 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1847 millimeters: Position { x: 0.0, y: 0.0 },
1848 })
1849 }
1850
1851 #[test_case(
1852 create_mouse_event(
1853 zero_relative_location(),
1854 wheel_delta_ticks(1, None), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1858 HashSet::new(),
1859 HashSet::new(),
1860 zx::MonotonicInstant::ZERO,
1861 &DESCRIPTOR,
1862 ),
1863 create_mouse_pointer_sample_event(
1864 pointerinjector::EventPhase::Change,
1865 vec![],
1866 Position { x: 50.0, y: 50.0 },
1867 None, Some(1), None, Some(false), zx::MonotonicInstant::ZERO,
1872 ); "v tick scroll"
1873 )]
1874 #[test_case(
1875 create_mouse_event(
1876 zero_relative_location(),
1877 None, wheel_delta_ticks(1, None), Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1881 HashSet::new(),
1882 HashSet::new(),
1883 zx::MonotonicInstant::ZERO,
1884 &DESCRIPTOR,
1885 ),
1886 create_mouse_pointer_sample_event(
1887 pointerinjector::EventPhase::Change,
1888 vec![],
1889 Position { x: 50.0, y: 50.0 },
1890 None, None, Some(1), Some(false), zx::MonotonicInstant::ZERO,
1895 ); "h tick scroll"
1896 )]
1897 #[test_case(
1898 create_mouse_event(
1899 zero_relative_location(),
1900 wheel_delta_ticks(1, Some(120.0)), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1904 HashSet::new(),
1905 HashSet::new(),
1906 zx::MonotonicInstant::ZERO,
1907 &DESCRIPTOR,
1908 ),
1909 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
1910 pointerinjector::EventPhase::Change,
1911 vec![],
1912 Position { x: 50.0, y: 50.0 },
1913 None, Some(1), None, Some(120.0), None, Some(false), zx::MonotonicInstant::ZERO,
1920 ); "v tick scroll with physical pixel"
1921 )]
1922 #[test_case(
1923 create_mouse_event(
1924 zero_relative_location(),
1925 None, wheel_delta_ticks(1, Some(120.0)), Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1929 HashSet::new(),
1930 HashSet::new(),
1931 zx::MonotonicInstant::ZERO,
1932 &DESCRIPTOR,
1933 ),
1934 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
1935 pointerinjector::EventPhase::Change,
1936 vec![],
1937 Position { x: 50.0, y: 50.0 },
1938 None, None, Some(1), None, Some(120.0), Some(false), zx::MonotonicInstant::ZERO,
1945 ); "h tick scroll with physical pixel"
1946 )]
1947 #[test_case(
1948 create_mouse_event(
1949 zero_relative_location(),
1950 wheel_delta_mm(1.0, Some(120.0)), None, Some(mouse_binding::PrecisionScroll::Yes), mouse_binding::MousePhase::Wheel,
1954 HashSet::new(),
1955 HashSet::new(),
1956 zx::MonotonicInstant::ZERO,
1957 &DESCRIPTOR,
1958 ),
1959 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
1960 pointerinjector::EventPhase::Change,
1961 vec![],
1962 Position { x: 50.0, y: 50.0 },
1963 None, None, None, Some(120.0), None, Some(true), zx::MonotonicInstant::ZERO,
1970 ); "v mm scroll with physical pixel"
1971 )]
1972 #[test_case(
1973 create_mouse_event(
1974 zero_relative_location(),
1975 None, wheel_delta_mm(1.0, Some(120.0)), Some(mouse_binding::PrecisionScroll::Yes), mouse_binding::MousePhase::Wheel,
1979 HashSet::new(),
1980 HashSet::new(),
1981 zx::MonotonicInstant::ZERO,
1982 &DESCRIPTOR,
1983 ),
1984 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
1985 pointerinjector::EventPhase::Change,
1986 vec![],
1987 Position { x: 50.0, y: 50.0 },
1988 None, None, None, None, Some(120.0), Some(true), zx::MonotonicInstant::ZERO,
1995 ); "h mm scroll with physical pixel"
1996 )]
1997 #[fuchsia::test(allow_stalls = false)]
1999 async fn scroll(event: input_device::InputEvent, want_event: pointerinjector::Event) {
2000 let (configuration_proxy, mut configuration_request_stream) =
2002 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
2003 let (injector_registry_proxy, injector_registry_request_stream) =
2004 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
2005 let config_request_stream_fut =
2006 handle_configuration_request_stream(&mut configuration_request_stream);
2007
2008 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
2010 let inspector = fuchsia_inspect::Inspector::default();
2011 let test_node = inspector.root().create_child("test_node");
2012 let mouse_handler_fut = MouseInjectorHandler::new_handler(
2013 configuration_proxy,
2014 injector_registry_proxy,
2015 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
2016 sender,
2017 &test_node,
2018 metrics::MetricsLogger::default(),
2019 );
2020 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
2021 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
2022
2023 let (injector_stream_sender, injector_stream_receiver) =
2027 mpsc::unbounded::<Vec<pointerinjector::Event>>();
2028 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
2030 let registry_fut = handle_registry_request_stream2(
2031 injector_registry_request_stream,
2032 injector_stream_sender,
2033 );
2034
2035 let event_time = zx::MonotonicInstant::get();
2036
2037 let event = input_device::InputEvent { event_time, ..event };
2038
2039 let want_event =
2040 pointerinjector::Event { timestamp: Some(event_time.into_nanos()), ..want_event };
2041
2042 let _registry_task = fasync::Task::local(registry_fut);
2044
2045 mouse_handler.clone().handle_input_event(event).await;
2046 let got_events: Vec<_> = injector_stream_receiver
2047 .next()
2048 .await
2049 .map(|events| events.into_iter().flatten().collect())
2050 .unwrap();
2051 pretty_assertions::assert_eq!(got_events.len(), 2);
2052 assert_matches!(
2053 got_events[0],
2054 pointerinjector::Event {
2055 data: Some(pointerinjector::Data::PointerSample(pointerinjector::PointerSample {
2056 phase: Some(pointerinjector::EventPhase::Add),
2057 ..
2058 })),
2059 ..
2060 }
2061 );
2062
2063 pretty_assertions::assert_eq!(got_events[1], want_event);
2064 }
2065
2066 #[fuchsia::test(allow_stalls = false)]
2068 async fn down_scroll_up_scroll() {
2069 let (configuration_proxy, mut configuration_request_stream) =
2071 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
2072 let (injector_registry_proxy, injector_registry_request_stream) =
2073 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
2074 let config_request_stream_fut =
2075 handle_configuration_request_stream(&mut configuration_request_stream);
2076
2077 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
2079 let inspector = fuchsia_inspect::Inspector::default();
2080 let test_node = inspector.root().create_child("test_node");
2081 let mouse_handler_fut = MouseInjectorHandler::new_handler(
2082 configuration_proxy,
2083 injector_registry_proxy,
2084 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
2085 sender,
2086 &test_node,
2087 metrics::MetricsLogger::default(),
2088 );
2089 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
2090 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
2091
2092 let (injector_stream_sender, injector_stream_receiver) =
2096 mpsc::unbounded::<Vec<pointerinjector::Event>>();
2097 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
2099 let registry_fut = handle_registry_request_stream2(
2100 injector_registry_request_stream,
2101 injector_stream_sender,
2102 );
2103
2104 let event_time1 = zx::MonotonicInstant::get();
2105 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
2106 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
2107 let event_time4 = event_time3.add(zx::MonotonicDuration::from_micros(1));
2108
2109 let _registry_task = fasync::Task::local(registry_fut);
2111
2112 let zero_location =
2113 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
2114 millimeters: Position { x: 0.0, y: 0.0 },
2115 });
2116 let expected_position = Position { x: 50.0, y: 50.0 };
2117
2118 let down_event = create_mouse_event(
2119 zero_location,
2120 None, None, None, mouse_binding::MousePhase::Down,
2124 HashSet::from_iter(vec![1]),
2125 HashSet::from_iter(vec![1]),
2126 event_time1,
2127 &DESCRIPTOR,
2128 );
2129
2130 let wheel_event = create_mouse_event(
2131 zero_location,
2132 wheel_delta_ticks(1, None), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
2136 HashSet::from_iter(vec![1]),
2137 HashSet::from_iter(vec![1]),
2138 event_time2,
2139 &DESCRIPTOR,
2140 );
2141
2142 let up_event = create_mouse_event(
2143 zero_location,
2144 None,
2145 None,
2146 None, mouse_binding::MousePhase::Up,
2148 HashSet::from_iter(vec![1]),
2149 HashSet::new(),
2150 event_time3,
2151 &DESCRIPTOR,
2152 );
2153
2154 let continue_wheel_event = create_mouse_event(
2155 zero_location,
2156 wheel_delta_ticks(1, None), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
2160 HashSet::new(),
2161 HashSet::new(),
2162 event_time4,
2163 &DESCRIPTOR,
2164 );
2165
2166 mouse_handler.clone().handle_input_event(down_event).await;
2168 assert_eq!(
2169 injector_stream_receiver
2170 .next()
2171 .await
2172 .map(|events| events.into_iter().flatten().collect()),
2173 Some(vec![
2174 create_mouse_pointer_sample_event_phase_add(
2175 vec![1],
2176 expected_position,
2177 event_time1,
2178 ),
2179 create_mouse_pointer_sample_event(
2180 pointerinjector::EventPhase::Change,
2181 vec![1],
2182 expected_position,
2183 None, None, None, None, event_time1,
2188 ),
2189 ])
2190 );
2191
2192 mouse_handler.clone().handle_input_event(wheel_event).await;
2194 assert_eq!(
2195 injector_stream_receiver
2196 .next()
2197 .await
2198 .map(|events| events.into_iter().flatten().collect()),
2199 Some(vec![create_mouse_pointer_sample_event(
2200 pointerinjector::EventPhase::Change,
2201 vec![1],
2202 expected_position,
2203 None, Some(1), None, Some(false), event_time2,
2208 )])
2209 );
2210
2211 mouse_handler.clone().handle_input_event(up_event).await;
2213 assert_eq!(
2214 injector_stream_receiver
2215 .next()
2216 .await
2217 .map(|events| events.into_iter().flatten().collect()),
2218 Some(vec![create_mouse_pointer_sample_event(
2219 pointerinjector::EventPhase::Change,
2220 vec![],
2221 expected_position,
2222 None, None, None, None, event_time3,
2227 )])
2228 );
2229
2230 mouse_handler.clone().handle_input_event(continue_wheel_event).await;
2232 assert_eq!(
2233 injector_stream_receiver
2234 .next()
2235 .await
2236 .map(|events| events.into_iter().flatten().collect()),
2237 Some(vec![create_mouse_pointer_sample_event(
2238 pointerinjector::EventPhase::Change,
2239 vec![],
2240 expected_position,
2241 None, Some(1), None, Some(false), event_time4,
2246 )])
2247 );
2248 }
2249
2250 #[fuchsia::test(allow_stalls = false)]
2251 async fn mouse_injector_handler_initialized_with_inspect_node() {
2252 let (configuration_proxy, mut configuration_request_stream) =
2253 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
2254 let config_request_stream_fut =
2255 handle_configuration_request_stream(&mut configuration_request_stream);
2256 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
2257 let inspector = fuchsia_inspect::Inspector::default();
2258 let fake_handlers_node = inspector.root().create_child("input_handlers_node");
2259 let mouse_handler_fut = MouseInjectorHandler::new_with_config_proxy(
2260 configuration_proxy,
2261 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
2262 sender,
2263 &fake_handlers_node,
2264 metrics::MetricsLogger::default(),
2265 );
2266 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
2267 let _handler = mouse_handler_res.expect("Failed to create mouse handler");
2268
2269 diagnostics_assertions::assert_data_tree!(inspector, root: {
2270 input_handlers_node: {
2271 mouse_injector_handler: {
2272 events_received_count: 0u64,
2273 events_handled_count: 0u64,
2274 last_received_timestamp_ns: 0u64,
2275 "fuchsia.inspect.Health": {
2276 status: "STARTING_UP",
2277 start_timestamp_nanos: diagnostics_assertions::AnyProperty
2280 },
2281 }
2282 }
2283 });
2284 }
2285
2286 #[fuchsia::test(allow_stalls = false)]
2287 async fn mouse_injector_handler_inspect_counts_events() {
2288 let (configuration_proxy, mut configuration_request_stream) =
2290 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
2291 let (injector_registry_proxy, injector_registry_request_stream) =
2292 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
2293 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
2294
2295 let inspector = fuchsia_inspect::Inspector::default();
2296 let fake_handlers_node = inspector.root().create_child("input_handlers_node");
2297
2298 let mouse_handler_fut = MouseInjectorHandler::new_handler(
2300 configuration_proxy,
2301 injector_registry_proxy,
2302 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
2303 sender,
2304 &fake_handlers_node,
2305 metrics::MetricsLogger::default(),
2306 );
2307 let config_request_stream_fut =
2308 handle_configuration_request_stream(&mut configuration_request_stream);
2309
2310 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
2311 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
2312
2313 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
2314 let event_time1 = zx::MonotonicInstant::get();
2315 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
2316 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
2317
2318 let input_events = vec![
2319 create_mouse_event(
2320 cursor_location,
2321 None, None, None, mouse_binding::MousePhase::Down,
2325 HashSet::from_iter(vec![1]),
2326 HashSet::from_iter(vec![1]),
2327 event_time1,
2328 &DESCRIPTOR,
2329 ),
2330 create_mouse_event(
2331 cursor_location,
2332 None, None, None, mouse_binding::MousePhase::Up,
2336 HashSet::from_iter(vec![1]),
2337 HashSet::new(),
2338 event_time2,
2339 &DESCRIPTOR,
2340 ),
2341 create_mouse_event_with_handled(
2342 cursor_location,
2343 None, None, None, mouse_binding::MousePhase::Down,
2347 HashSet::from_iter(vec![1]),
2348 HashSet::from_iter(vec![1]),
2349 event_time3,
2350 &DESCRIPTOR,
2351 input_device::Handled::Yes,
2352 ),
2353 ];
2354
2355 let (injector_stream_sender, _) = mpsc::unbounded::<Vec<pointerinjector::Event>>();
2359 let registry_fut = handle_registry_request_stream2(
2360 injector_registry_request_stream,
2361 injector_stream_sender,
2362 );
2363
2364 let _registry_task = fasync::Task::local(registry_fut);
2366 for input_event in input_events {
2367 mouse_handler.clone().handle_input_event(input_event).await;
2368 }
2369
2370 let last_received_event_time: u64 = event_time2.into_nanos().try_into().unwrap();
2371
2372 diagnostics_assertions::assert_data_tree!(inspector, root: {
2373 input_handlers_node: {
2374 mouse_injector_handler: {
2375 events_received_count: 2u64,
2376 events_handled_count: 2u64,
2377 last_received_timestamp_ns: last_received_event_time,
2378 "fuchsia.inspect.Health": {
2379 status: "STARTING_UP",
2380 start_timestamp_nanos: diagnostics_assertions::AnyProperty
2383 },
2384 }
2385 }
2386 });
2387 }
2388}