1#![warn(clippy::await_holding_refcell_ref)]
6
7use crate::input_handler::{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
83impl Handler for MouseInjectorHandler {
84 fn set_handler_healthy(self: std::rc::Rc<Self>) {
85 self.inspect_status.health_node.borrow_mut().set_ok();
86 }
87
88 fn set_handler_unhealthy(self: std::rc::Rc<Self>, msg: &str) {
89 self.inspect_status.health_node.borrow_mut().set_unhealthy(msg);
90 }
91
92 fn get_name(&self) -> &'static str {
93 "MouseInjectorHandler"
94 }
95
96 fn interest(&self) -> Vec<input_device::InputEventType> {
97 vec![input_device::InputEventType::Mouse]
98 }
99}
100
101#[async_trait(?Send)]
102impl InputHandler for MouseInjectorHandler {
103 async fn handle_input_event(
104 self: Rc<Self>,
105 mut input_event: input_device::InputEvent,
106 ) -> Vec<input_device::InputEvent> {
107 fuchsia_trace::duration!("input", "mouse_injector_handler");
108 match input_event {
109 input_device::InputEvent {
110 device_event: input_device::InputDeviceEvent::Mouse(ref mouse_event),
111 device_descriptor:
112 input_device::InputDeviceDescriptor::Mouse(ref mouse_device_descriptor),
113 event_time,
114 handled: input_device::Handled::No,
115 trace_id,
116 } => {
117 fuchsia_trace::duration!("input", "mouse_injector_handler[processing]");
118 let trace_id = match trace_id {
119 Some(id) => {
120 fuchsia_trace::flow_end!("input", "event_in_input_pipeline", id.into());
121 id
122 }
123 None => fuchsia_trace::Id::random(),
124 };
125
126 self.inspect_status.count_received_event(&event_time);
127 if let Err(e) =
129 self.update_cursor_renderer(mouse_event, &mouse_device_descriptor).await
130 {
131 self.metrics_logger.log_error(
132 InputPipelineErrorMetricDimensionEvent::MouseInjectorUpdateCursorRendererFailed,
133 std::format!("update_cursor_renderer failed: {}", e));
134 }
135
136 if let Err(e) = self
138 .ensure_injector_registered(&mouse_event, &mouse_device_descriptor, event_time)
139 .await
140 {
141 self.metrics_logger.log_error(
142 InputPipelineErrorMetricDimensionEvent::MouseInjectorEnsureInjectorRegisteredFailed,
143 std::format!("ensure_injector_registered failed: {}", e));
144 }
145
146 if let Err(e) = self
148 .send_event_to_scenic(
149 &mouse_event,
150 &mouse_device_descriptor,
151 event_time,
152 trace_id.into(),
153 )
154 .await
155 {
156 self.metrics_logger.log_error(
157 InputPipelineErrorMetricDimensionEvent::MouseInjectorSendEventToScenicFailed,
158 std::format!("send_event_to_scenic failed: {}", e));
159 }
160
161 input_event.handled = input_device::Handled::Yes;
163 self.inspect_status.count_handled_event();
164 }
165 _ => {
166 log::warn!("Unhandled input event: {:?}", input_event.get_event_type());
168 }
169 }
170 vec![input_event]
171 }
172}
173
174impl MouseInjectorHandler {
175 pub async fn new(
188 display_size: Size,
189 cursor_message_sender: Sender<CursorMessage>,
190 input_handlers_node: &fuchsia_inspect::Node,
191 metrics_logger: metrics::MetricsLogger,
192 ) -> Result<Rc<Self>, Error> {
193 let configuration_proxy = connect_to_protocol::<pointerinjector_config::SetupMarker>()?;
194 let injector_registry_proxy = connect_to_protocol::<pointerinjector::RegistryMarker>()?;
195
196 Self::new_handler(
197 configuration_proxy,
198 injector_registry_proxy,
199 display_size,
200 cursor_message_sender,
201 input_handlers_node,
202 metrics_logger,
203 )
204 .await
205 }
206
207 pub async fn new_with_config_proxy(
223 configuration_proxy: pointerinjector_config::SetupProxy,
224 display_size: Size,
225 cursor_message_sender: Sender<CursorMessage>,
226 input_handlers_node: &fuchsia_inspect::Node,
227 metrics_logger: metrics::MetricsLogger,
228 ) -> Result<Rc<Self>, Error> {
229 let injector_registry_proxy = connect_to_protocol::<pointerinjector::RegistryMarker>()?;
230 Self::new_handler(
231 configuration_proxy,
232 injector_registry_proxy,
233 display_size,
234 cursor_message_sender,
235 input_handlers_node,
236 metrics_logger,
237 )
238 .await
239 }
240
241 fn inner(&self) -> Ref<'_, MutableState> {
242 self.mutable_state.borrow()
243 }
244
245 fn inner_mut(&self) -> RefMut<'_, MutableState> {
246 self.mutable_state.borrow_mut()
247 }
248
249 async fn new_handler(
265 configuration_proxy: pointerinjector_config::SetupProxy,
266 injector_registry_proxy: pointerinjector::RegistryProxy,
267 display_size: Size,
268 cursor_message_sender: Sender<CursorMessage>,
269 input_handlers_node: &fuchsia_inspect::Node,
270 metrics_logger: metrics::MetricsLogger,
271 ) -> Result<Rc<Self>, Error> {
272 let (context_view_ref, target_view_ref) = configuration_proxy.get_view_refs().await?;
274 let inspect_status = InputHandlerStatus::new(
275 input_handlers_node,
276 "mouse_injector_handler",
277 false,
278 );
279 let handler = Rc::new(Self {
280 mutable_state: RefCell::new(MutableState {
281 viewport: None,
282 injectors: HashMap::new(),
283 current_position: Position {
285 x: display_size.width / 2.0,
286 y: display_size.height / 2.0,
287 },
288 cursor_message_sender,
289 }),
290 context_view_ref,
291 target_view_ref,
292 max_position: Position { x: display_size.width, y: display_size.height },
293 injector_registry_proxy,
294 configuration_proxy,
295 inspect_status,
296 metrics_logger,
297 });
298
299 Ok(handler)
300 }
301
302 async fn ensure_injector_registered(
310 self: &Rc<Self>,
311 mouse_event: &mouse_binding::MouseEvent,
312 mouse_descriptor: &mouse_binding::MouseDeviceDescriptor,
313 event_time: zx::MonotonicInstant,
314 ) -> Result<(), anyhow::Error> {
315 if self.inner().injectors.contains_key(&mouse_descriptor.device_id) {
316 return Ok(());
317 }
318
319 let (device_proxy, device_server) = create_proxy::<pointerinjector::DeviceMarker>();
321 let context = fuchsia_scenic::duplicate_view_ref(&self.context_view_ref)
322 .context("Failed to duplicate context view ref.")?;
323 let target = fuchsia_scenic::duplicate_view_ref(&self.target_view_ref)
324 .context("Failed to duplicate target view ref.")?;
325
326 let viewport = self.inner().viewport.clone();
327 let config = pointerinjector::Config {
328 device_id: Some(mouse_descriptor.device_id),
329 device_type: Some(pointerinjector::DeviceType::Mouse),
330 context: Some(pointerinjector::Context::View(context)),
331 target: Some(pointerinjector::Target::View(target)),
332 viewport,
333 dispatch_policy: Some(pointerinjector::DispatchPolicy::MouseHoverAndLatchInTarget),
334 scroll_v_range: mouse_descriptor.wheel_v_range.clone(),
335 scroll_h_range: mouse_descriptor.wheel_h_range.clone(),
336 buttons: mouse_descriptor.buttons.clone(),
337 ..Default::default()
338 };
339
340 self.injector_registry_proxy
342 .register(config, device_server)
343 .await
344 .context("Failed to register injector.")?;
345 log::info!("Registered injector with device id {:?}", mouse_descriptor.device_id);
346
347 self.inner_mut().injectors.insert(mouse_descriptor.device_id, device_proxy.clone());
349
350 let events_to_send = vec![self.create_pointer_sample_event(
352 mouse_event,
353 event_time,
354 pointerinjector::EventPhase::Add,
355 self.inner().current_position,
356 None,
357 None,
358 )];
359 device_proxy.inject_events(events_to_send).context("Failed to ADD new MouseDevice.")?;
360
361 Ok(())
362 }
363
364 async fn update_cursor_renderer(
375 &self,
376 mouse_event: &mouse_binding::MouseEvent,
377 mouse_descriptor: &mouse_binding::MouseDeviceDescriptor,
378 ) -> Result<(), anyhow::Error> {
379 let mut new_position = match (mouse_event.location, mouse_descriptor) {
380 (
381 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
382 millimeters,
383 }),
384 _,
385 ) => {
386 self.inner().current_position
387 + self.relative_movement_mm_to_phyical_pixel(millimeters)
388 }
389 (
390 mouse_binding::MouseLocation::Absolute(position),
391 mouse_binding::MouseDeviceDescriptor {
392 absolute_x_range: Some(x_range),
393 absolute_y_range: Some(y_range),
394 ..
395 },
396 ) => self.scale_absolute_position(&position, &x_range, &y_range),
397 (mouse_binding::MouseLocation::Absolute(_), _) => {
398 return Err(anyhow!(
399 "Received an Absolute mouse location without absolute device ranges."
400 ));
401 }
402 };
403 Position::clamp(&mut new_position, Position::zero(), self.max_position);
404 self.inner_mut().current_position = new_position;
405
406 let mut cursor_message_sender = self.inner().cursor_message_sender.clone();
407 cursor_message_sender
408 .send(CursorMessage::SetPosition(new_position))
409 .await
410 .context("Failed to send current mouse position to cursor renderer")?;
411
412 Ok(())
413 }
414
415 fn scale_absolute_position(
423 &self,
424 position: &Position,
425 x_range: &Range,
426 y_range: &Range,
427 ) -> Position {
428 let range_min = Position { x: x_range.min as f32, y: y_range.min as f32 };
429 let range_max = Position { x: x_range.max as f32, y: y_range.max as f32 };
430 self.max_position * ((*position - range_min) / (range_max - range_min))
431 }
432
433 async fn send_event_to_scenic(
440 &self,
441 mouse_event: &mouse_binding::MouseEvent,
442 mouse_descriptor: &mouse_binding::MouseDeviceDescriptor,
443 event_time: zx::MonotonicInstant,
444 tracing_id: u64,
445 ) -> Result<(), anyhow::Error> {
446 let injector = self.inner().injectors.get(&mouse_descriptor.device_id).cloned();
447 if let Some(injector) = injector {
448 let relative_motion = match mouse_event.location {
449 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
450 millimeters: offset_mm,
451 }) if mouse_event.phase == mouse_binding::MousePhase::Move => {
452 let offset = self.relative_movement_mm_to_phyical_pixel(offset_mm);
453 Some([offset.x, offset.y])
454 }
455 _ => None,
456 };
457 let events_to_send = vec![self.create_pointer_sample_event(
458 mouse_event,
459 event_time,
460 pointerinjector::EventPhase::Change,
461 self.inner().current_position,
462 relative_motion,
463 Some(tracing_id),
464 )];
465
466 fuchsia_trace::flow_begin!("input", "dispatch_event_to_scenic", tracing_id.into());
467
468 let _ = injector.inject_events(events_to_send);
469
470 Ok(())
471 } else {
472 Err(anyhow::format_err!(
473 "No injector found for mouse device {}.",
474 mouse_descriptor.device_id
475 ))
476 }
477 }
478
479 fn create_pointer_sample_event(
488 &self,
489 mouse_event: &mouse_binding::MouseEvent,
490 event_time: zx::MonotonicInstant,
491 phase: pointerinjector::EventPhase,
492 current_position: Position,
493 relative_motion: Option<[f32; 2]>,
494 trace_id: Option<u64>,
495 ) -> pointerinjector::Event {
496 let pointer_sample = pointerinjector::PointerSample {
497 pointer_id: Some(0),
498 phase: Some(phase),
499 position_in_viewport: Some([current_position.x, current_position.y]),
500 scroll_v: match mouse_event.wheel_delta_v {
501 Some(mouse_binding::WheelDelta {
502 raw_data: mouse_binding::RawWheelDelta::Ticks(tick),
503 ..
504 }) => Some(tick),
505 _ => None,
506 },
507 scroll_h: match mouse_event.wheel_delta_h {
508 Some(mouse_binding::WheelDelta {
509 raw_data: mouse_binding::RawWheelDelta::Ticks(tick),
510 ..
511 }) => Some(tick),
512 _ => None,
513 },
514 scroll_v_physical_pixel: match mouse_event.wheel_delta_v {
515 Some(mouse_binding::WheelDelta { physical_pixel: Some(pixel), .. }) => {
516 Some(pixel.into())
517 }
518 _ => None,
519 },
520 scroll_h_physical_pixel: match mouse_event.wheel_delta_h {
521 Some(mouse_binding::WheelDelta { physical_pixel: Some(pixel), .. }) => {
522 Some(pixel.into())
523 }
524 _ => None,
525 },
526 is_precision_scroll: match mouse_event.phase {
527 mouse_binding::MousePhase::Wheel => match mouse_event.is_precision_scroll {
528 Some(mouse_binding::PrecisionScroll::Yes) => Some(true),
529 Some(mouse_binding::PrecisionScroll::No) => Some(false),
530 None => {
531 self.metrics_logger.log_error(
532 InputPipelineErrorMetricDimensionEvent::MouseInjectorMissingIsPrecisionScroll,
533 "mouse wheel event does not have value in is_precision_scroll.");
534 None
535 }
536 },
537 _ => None,
538 },
539 pressed_buttons: Some(Vec::from_iter(mouse_event.pressed_buttons.iter().cloned())),
540 relative_motion,
541 ..Default::default()
542 };
543 pointerinjector::Event {
544 timestamp: Some(event_time.into_nanos()),
545 data: Some(pointerinjector::Data::PointerSample(pointer_sample)),
546 trace_flow_id: trace_id,
547 wake_lease: mouse_event.wake_lease.lock().take(),
548 ..Default::default()
549 }
550 }
551
552 pub async fn watch_viewport(self: Rc<Self>) {
554 let configuration_proxy = self.configuration_proxy.clone();
555 let mut viewport_stream = HangingGetStream::new(
556 configuration_proxy,
557 pointerinjector_config::SetupProxy::watch_viewport,
558 );
559 loop {
560 match viewport_stream.next().await {
561 Some(Ok(new_viewport)) => {
562 self.inner_mut().viewport = Some(new_viewport.clone());
564
565 let injectors = self.inner().injectors.values().cloned().collect::<Vec<_>>();
567 for injector in injectors {
568 let events = vec![pointerinjector::Event {
569 timestamp: Some(fuchsia_async::MonotonicInstant::now().into_nanos()),
570 data: Some(pointerinjector::Data::Viewport(new_viewport.clone())),
571 trace_flow_id: Some(fuchsia_trace::Id::random().into()),
572 ..Default::default()
573 }];
574 injector.inject_events(events).expect("Failed to inject updated viewport.");
575 }
576 }
577 Some(Err(e)) => {
578 self.metrics_logger.log_error(
579 InputPipelineErrorMetricDimensionEvent::MouseInjectorErrorWhileReadingViewportUpdate,
580 std::format!("Error while reading viewport update: {}", e));
581 return;
582 }
583 None => {
584 self.metrics_logger.log_error(
585 InputPipelineErrorMetricDimensionEvent::MouseInjectorViewportUpdateStreamTerminatedUnexpectedly,
586 "Viewport update stream terminated unexpectedly");
587 return;
588 }
589 }
590 }
591 }
592
593 fn relative_movement_mm_to_phyical_pixel(&self, movement_mm: Position) -> Position {
597 Position {
598 x: movement_mm.x * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
599 y: movement_mm.y * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
600 }
601 }
602}
603
604#[cfg(test)]
605mod tests {
606 use super::*;
607 use crate::testing_utilities::{
608 assert_handler_ignores_input_event_sequence, create_mouse_event,
609 create_mouse_event_with_handled, create_mouse_pointer_sample_event,
610 create_mouse_pointer_sample_event_phase_add,
611 create_mouse_pointer_sample_event_with_wheel_physical_pixel,
612 };
613 use assert_matches::assert_matches;
614 use futures::channel::mpsc;
615 use pretty_assertions::assert_eq;
616 use std::collections::HashSet;
617 use std::ops::Add;
618 use test_case::test_case;
619 use {
620 fidl_fuchsia_input_report as fidl_input_report,
621 fidl_fuchsia_ui_pointerinjector as pointerinjector, fuchsia_async as fasync,
622 };
623
624 const DISPLAY_WIDTH_IN_PHYSICAL_PX: f32 = 100.0;
625 const DISPLAY_HEIGHT_IN_PHYSICAL_PX: f32 = 100.0;
626 const COUNTS_PER_MM: u32 = 12;
627
628 const DESCRIPTOR: input_device::InputDeviceDescriptor =
630 input_device::InputDeviceDescriptor::Mouse(mouse_binding::MouseDeviceDescriptor {
631 device_id: 1,
632 absolute_x_range: Some(fidl_input_report::Range { min: 0, max: 100 }),
633 absolute_y_range: Some(fidl_input_report::Range { min: 0, max: 100 }),
634 wheel_v_range: Some(fidl_input_report::Axis {
635 range: fidl_input_report::Range { min: -1, max: 1 },
636 unit: fidl_input_report::Unit {
637 type_: fidl_input_report::UnitType::Other,
638 exponent: 0,
639 },
640 }),
641 wheel_h_range: Some(fidl_input_report::Axis {
642 range: fidl_input_report::Range { min: -1, max: 1 },
643 unit: fidl_input_report::Unit {
644 type_: fidl_input_report::UnitType::Other,
645 exponent: 0,
646 },
647 }),
648 buttons: None,
649 counts_per_mm: COUNTS_PER_MM,
650 });
651
652 async fn handle_configuration_request_stream(
654 stream: &mut pointerinjector_config::SetupRequestStream,
655 ) {
656 if let Some(Ok(request)) = stream.next().await {
657 match request {
658 pointerinjector_config::SetupRequest::GetViewRefs { responder, .. } => {
659 let context = fuchsia_scenic::ViewRefPair::new()
660 .expect("Failed to create viewrefpair.")
661 .view_ref;
662 let target = fuchsia_scenic::ViewRefPair::new()
663 .expect("Failed to create viewrefpair.")
664 .view_ref;
665 let _ = responder.send(context, target);
666 }
667 _ => {}
668 };
669 }
670 }
671
672 async fn handle_registry_request_stream(
675 mut stream: pointerinjector::RegistryRequestStream,
676 injector_sender: futures::channel::oneshot::Sender<pointerinjector::DeviceRequestStream>,
677 ) {
678 if let Some(request) = stream.next().await {
679 match request {
680 Ok(pointerinjector::RegistryRequest::Register {
681 config: _,
682 injector,
683 responder,
684 ..
685 }) => {
686 let injector_stream = injector.into_stream();
687 let _ = injector_sender.send(injector_stream);
688 responder.send().expect("failed to respond");
689 }
690 _ => {}
691 };
692 } else {
693 panic!("RegistryRequestStream failed.");
694 }
695 }
696
697 async fn handle_registry_request_stream2(
699 mut stream: pointerinjector::RegistryRequestStream,
700 injector_sender: mpsc::UnboundedSender<Vec<pointerinjector::Event>>,
701 ) {
702 let (injector, responder) = match stream.next().await {
703 Some(Ok(pointerinjector::RegistryRequest::Register {
704 config: _,
705 injector,
706 responder,
707 ..
708 })) => (injector, responder),
709 other => panic!("expected register request, but got {:?}", other),
710 };
711 let injector_stream: pointerinjector::DeviceRequestStream = injector.into_stream();
712 responder.send().expect("failed to respond");
713 injector_stream
714 .for_each(|request| {
715 futures::future::ready({
716 match request {
717 Ok(pointerinjector::DeviceRequest::Inject { .. }) => {
718 panic!("DeviceRequest::Inject is deprecated.");
719 }
720 Ok(pointerinjector::DeviceRequest::InjectEvents { events, .. }) => {
721 let _ = injector_sender.unbounded_send(events);
722 }
723 Err(e) => panic!("FIDL error {}", e),
724 }
725 })
726 })
727 .await;
728 }
729
730 async fn handle_device_request_stream(
733 injector_stream_receiver: futures::channel::oneshot::Receiver<
734 pointerinjector::DeviceRequestStream,
735 >,
736 expected_events: Vec<pointerinjector::Event>,
737 ) {
738 let mut injector_stream =
739 injector_stream_receiver.await.expect("Failed to get DeviceRequestStream.");
740 for expected_event in expected_events {
741 match injector_stream.next().await {
742 Some(Ok(pointerinjector::DeviceRequest::Inject { .. })) => {
743 panic!("DeviceRequest::Inject is deprecated.");
744 }
745 Some(Ok(pointerinjector::DeviceRequest::InjectEvents { events, .. })) => {
746 assert_eq!(events, vec![expected_event]);
747 }
748 Some(Err(e)) => panic!("FIDL error {}", e),
749 None => panic!("Expected another event."),
750 }
751 }
752 }
753
754 fn create_viewport(min: f32, max: f32) -> pointerinjector::Viewport {
756 pointerinjector::Viewport {
757 extents: Some([[min, min], [max, max]]),
758 viewport_to_context_transform: None,
759 ..Default::default()
760 }
761 }
762
763 #[fuchsia::test]
766 fn receives_viewport_updates() {
767 let mut exec = fasync::TestExecutor::new();
768
769 let (configuration_proxy, mut configuration_request_stream) =
771 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
772 let (injector_registry_proxy, _) =
773 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
774 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(0);
775
776 let inspector = fuchsia_inspect::Inspector::default();
777 let test_node = inspector.root().create_child("test_node");
778
779 let mouse_handler_fut = MouseInjectorHandler::new_handler(
781 configuration_proxy,
782 injector_registry_proxy,
783 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
784 sender,
785 &test_node,
786 metrics::MetricsLogger::default(),
787 );
788 let config_request_stream_fut =
789 handle_configuration_request_stream(&mut configuration_request_stream);
790 let (mouse_handler_res, _) = exec.run_singlethreaded(futures::future::join(
791 mouse_handler_fut,
792 config_request_stream_fut,
793 ));
794 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
795
796 let (injector_device_proxy, mut injector_device_request_stream) =
798 fidl::endpoints::create_proxy_and_stream::<pointerinjector::DeviceMarker>();
799 mouse_handler.inner_mut().injectors.insert(1, injector_device_proxy);
800
801 {
803 let watch_viewport_fut = mouse_handler.clone().watch_viewport();
805 futures::pin_mut!(watch_viewport_fut);
806 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
807
808 match exec.run_singlethreaded(&mut configuration_request_stream.next()) {
810 Some(Ok(pointerinjector_config::SetupRequest::WatchViewport {
811 responder, ..
812 })) => {
813 responder.send(&create_viewport(0.0, 100.0)).expect("Failed to send viewport.");
814 }
815 other => panic!("Received unexpected value: {:?}", other),
816 };
817 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
818
819 exec.run_singlethreaded(async {
821 match injector_device_request_stream.next().await {
822 Some(Ok(pointerinjector::DeviceRequest::Inject { .. })) => {
823 panic!("DeviceRequest::Inject is deprecated.");
824 }
825 Some(Ok(pointerinjector::DeviceRequest::InjectEvents { events, .. })) => {
826 assert_eq!(events.len(), 1);
827 assert!(events[0].data.is_some());
828 assert_eq!(
829 events[0].data,
830 Some(pointerinjector::Data::Viewport(create_viewport(0.0, 100.0)))
831 );
832 }
833 other => panic!("Received unexpected value: {:?}", other),
834 }
835 });
836
837 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
839
840 match exec.run_singlethreaded(&mut configuration_request_stream.next()) {
842 Some(Ok(pointerinjector_config::SetupRequest::WatchViewport {
843 responder, ..
844 })) => {
845 responder
846 .send(&create_viewport(100.0, 200.0))
847 .expect("Failed to send viewport.");
848 }
849 other => panic!("Received unexpected value: {:?}", other),
850 };
851
852 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
854 }
855
856 exec.run_singlethreaded(async {
858 match injector_device_request_stream.next().await {
859 Some(Ok(pointerinjector::DeviceRequest::Inject { .. })) => {
860 panic!("DeviceRequest::Inject is deprecated.");
861 }
862 Some(Ok(pointerinjector::DeviceRequest::InjectEvents { events, .. })) => {
863 assert_eq!(events.len(), 1);
864 assert!(events[0].data.is_some());
865 assert_eq!(
866 events[0].data,
867 Some(pointerinjector::Data::Viewport(create_viewport(100.0, 200.0)))
868 );
869 }
870 other => panic!("Received unexpected value: {:?}", other),
871 }
872 });
873
874 let expected_viewport = create_viewport(100.0, 200.0);
876 assert_eq!(mouse_handler.inner().viewport, Some(expected_viewport));
877 }
878
879 fn wheel_delta_ticks(
880 ticks: i64,
881 physical_pixel: Option<f32>,
882 ) -> Option<mouse_binding::WheelDelta> {
883 Some(mouse_binding::WheelDelta {
884 raw_data: mouse_binding::RawWheelDelta::Ticks(ticks),
885 physical_pixel,
886 })
887 }
888
889 fn wheel_delta_mm(mm: f32, physical_pixel: Option<f32>) -> Option<mouse_binding::WheelDelta> {
890 Some(mouse_binding::WheelDelta {
891 raw_data: mouse_binding::RawWheelDelta::Millimeters(mm),
892 physical_pixel,
893 })
894 }
895
896 #[test_case(
899 mouse_binding::MouseLocation::Relative(
900 mouse_binding::RelativeLocation {
901 millimeters: Position { x: 1.0, y: 2.0 }
902 }),
903 Position {
904 x: DISPLAY_WIDTH_IN_PHYSICAL_PX / 2.0
905 + 1.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
906 y: DISPLAY_HEIGHT_IN_PHYSICAL_PX / 2.0
907 + 2.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
908 },
909 [
910 1.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
911 2.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
912 ]; "Valid move event."
913 )]
914 #[test_case(
915 mouse_binding::MouseLocation::Relative(
916 mouse_binding::RelativeLocation {
917 millimeters: Position {
918 x: DISPLAY_WIDTH_IN_PHYSICAL_PX / MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL + 2.0,
919 y: DISPLAY_HEIGHT_IN_PHYSICAL_PX / MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL + 1.0,
920 }}),
921 Position {
922 x: DISPLAY_WIDTH_IN_PHYSICAL_PX,
923 y: DISPLAY_HEIGHT_IN_PHYSICAL_PX,
924 },
925 [
926 DISPLAY_WIDTH_IN_PHYSICAL_PX + 2.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
927 DISPLAY_HEIGHT_IN_PHYSICAL_PX + 1.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
928 ]; "Move event exceeds max bounds."
929 )]
930 #[test_case(
931 mouse_binding::MouseLocation::Relative(
932 mouse_binding::RelativeLocation {
933 millimeters: Position {
934 x: -(DISPLAY_WIDTH_IN_PHYSICAL_PX / MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL + 2.0),
935 y: -(DISPLAY_HEIGHT_IN_PHYSICAL_PX / MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL + 1.0),
936 }}),
937 Position { x: 0.0, y: 0.0 },
938 [
939 -(DISPLAY_WIDTH_IN_PHYSICAL_PX + 2.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL),
940 -(DISPLAY_HEIGHT_IN_PHYSICAL_PX + 1.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL),
941 ]; "Move event exceeds min bounds."
942 )]
943 #[fuchsia::test(allow_stalls = false)]
944 async fn move_event(
945 move_location: mouse_binding::MouseLocation,
946 expected_position: Position,
947 expected_relative_motion: [f32; 2],
948 ) {
949 let (configuration_proxy, mut configuration_request_stream) =
951 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
952 let (injector_registry_proxy, injector_registry_request_stream) =
953 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
954 let config_request_stream_fut =
955 handle_configuration_request_stream(&mut configuration_request_stream);
956
957 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
959 let inspector = fuchsia_inspect::Inspector::default();
960 let test_node = inspector.root().create_child("test_node");
961 let mouse_handler_fut = MouseInjectorHandler::new_handler(
962 configuration_proxy,
963 injector_registry_proxy,
964 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
965 sender,
966 &test_node,
967 metrics::MetricsLogger::default(),
968 );
969 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
970 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
971
972 let event_time = zx::MonotonicInstant::get();
973 let input_event = create_mouse_event(
974 move_location,
975 None, None, None, mouse_binding::MousePhase::Move,
979 HashSet::new(),
980 HashSet::new(),
981 event_time,
982 &DESCRIPTOR,
983 );
984
985 let handle_event_fut = mouse_handler.handle_input_event(input_event);
987 let expected_events = vec![
988 create_mouse_pointer_sample_event_phase_add(vec![], expected_position, event_time),
989 create_mouse_pointer_sample_event(
990 pointerinjector::EventPhase::Change,
991 vec![],
992 expected_position,
993 Some(expected_relative_motion),
994 None, None, None, event_time,
998 ),
999 ];
1000
1001 let (injector_stream_sender, injector_stream_receiver) =
1005 futures::channel::oneshot::channel::<pointerinjector::DeviceRequestStream>();
1006 let registry_fut = handle_registry_request_stream(
1007 injector_registry_request_stream,
1008 injector_stream_sender,
1009 );
1010 let device_fut = handle_device_request_stream(injector_stream_receiver, expected_events);
1011
1012 let (handle_result, _, _) = futures::join!(handle_event_fut, registry_fut, device_fut);
1015 match receiver.next().await {
1016 Some(CursorMessage::SetPosition(position)) => {
1017 pretty_assertions::assert_eq!(position, expected_position);
1018 }
1019 Some(CursorMessage::SetVisibility(_)) => {
1020 panic!("Received unexpected cursor visibility update.")
1021 }
1022 None => panic!("Did not receive cursor update."),
1023 }
1024
1025 assert_matches!(
1027 handle_result.as_slice(),
1028 [input_device::InputEvent { handled: input_device::Handled::Yes, .. }]
1029 );
1030 }
1031
1032 #[fuchsia::test(allow_stalls = false)]
1035 async fn move_absolute_event() {
1036 const DEVICE_ID: u32 = 1;
1037
1038 let (configuration_proxy, mut configuration_request_stream) =
1040 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1041 let (injector_registry_proxy, injector_registry_request_stream) =
1042 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1043 let config_request_stream_fut =
1044 handle_configuration_request_stream(&mut configuration_request_stream);
1045
1046 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
1048 let inspector = fuchsia_inspect::Inspector::default();
1049 let test_node = inspector.root().create_child("test_node");
1050 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1051 configuration_proxy,
1052 injector_registry_proxy,
1053 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1054 sender,
1055 &test_node,
1056 metrics::MetricsLogger::default(),
1057 );
1058 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1059 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1060
1061 let cursor_location =
1077 mouse_binding::MouseLocation::Absolute(Position { x: -25.0, y: 25.0 });
1078 let event_time = zx::MonotonicInstant::get();
1079 let descriptor =
1080 input_device::InputDeviceDescriptor::Mouse(mouse_binding::MouseDeviceDescriptor {
1081 device_id: DEVICE_ID,
1082 absolute_x_range: Some(fidl_input_report::Range { min: -50, max: 50 }),
1083 absolute_y_range: Some(fidl_input_report::Range { min: -50, max: 50 }),
1084 wheel_v_range: None,
1085 wheel_h_range: None,
1086 buttons: None,
1087 counts_per_mm: COUNTS_PER_MM,
1088 });
1089 let input_event = create_mouse_event(
1090 cursor_location,
1091 None, None, None, mouse_binding::MousePhase::Move,
1095 HashSet::new(),
1096 HashSet::new(),
1097 event_time,
1098 &descriptor,
1099 );
1100
1101 let handle_event_fut = mouse_handler.handle_input_event(input_event);
1103 let expected_position = Position {
1104 x: DISPLAY_WIDTH_IN_PHYSICAL_PX * 0.25,
1105 y: DISPLAY_WIDTH_IN_PHYSICAL_PX * 0.75,
1106 };
1107 let expected_events = vec![
1108 create_mouse_pointer_sample_event_phase_add(vec![], expected_position, event_time),
1109 create_mouse_pointer_sample_event(
1110 pointerinjector::EventPhase::Change,
1111 vec![],
1112 expected_position,
1113 None, None, None, None, event_time,
1118 ),
1119 ];
1120
1121 let (injector_stream_sender, injector_stream_receiver) =
1125 futures::channel::oneshot::channel::<pointerinjector::DeviceRequestStream>();
1126 let registry_fut = handle_registry_request_stream(
1127 injector_registry_request_stream,
1128 injector_stream_sender,
1129 );
1130 let device_fut = handle_device_request_stream(injector_stream_receiver, expected_events);
1131
1132 let (handle_result, _, _) = futures::join!(handle_event_fut, registry_fut, device_fut);
1135 match receiver.next().await {
1136 Some(CursorMessage::SetPosition(position)) => {
1137 assert_eq!(position, expected_position);
1138 }
1139 Some(CursorMessage::SetVisibility(_)) => {
1140 panic!("Received unexpected cursor visibility update.")
1141 }
1142 None => panic!("Did not receive cursor update."),
1143 }
1144
1145 assert_matches!(
1147 handle_result.as_slice(),
1148 [input_device::InputEvent { handled: input_device::Handled::Yes, .. }]
1149 );
1150 }
1151
1152 #[test_case(
1154 mouse_binding::MousePhase::Down,
1155 vec![1], vec![1]; "Down event injects button press state."
1156 )]
1157 #[test_case(
1158 mouse_binding::MousePhase::Up,
1159 vec![1], vec![]; "Up event injects button press state."
1160 )]
1161 #[fuchsia::test(allow_stalls = false)]
1162 async fn button_state_event(
1163 phase: mouse_binding::MousePhase,
1164 affected_buttons: Vec<mouse_binding::MouseButton>,
1165 pressed_buttons: Vec<mouse_binding::MouseButton>,
1166 ) {
1167 let (configuration_proxy, mut configuration_request_stream) =
1169 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1170 let (injector_registry_proxy, injector_registry_request_stream) =
1171 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1172 let config_request_stream_fut =
1173 handle_configuration_request_stream(&mut configuration_request_stream);
1174
1175 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
1177 let inspector = fuchsia_inspect::Inspector::default();
1178 let test_node = inspector.root().create_child("test_node");
1179 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1180 configuration_proxy,
1181 injector_registry_proxy,
1182 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1183 sender,
1184 &test_node,
1185 metrics::MetricsLogger::default(),
1186 );
1187 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1188 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1189
1190 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
1191 let event_time = zx::MonotonicInstant::get();
1192
1193 let input_event = create_mouse_event(
1194 cursor_location,
1195 None, None, None, phase,
1199 HashSet::from_iter(affected_buttons.clone()),
1200 HashSet::from_iter(pressed_buttons.clone()),
1201 event_time,
1202 &DESCRIPTOR,
1203 );
1204
1205 let handle_event_fut = mouse_handler.handle_input_event(input_event);
1207 let expected_position = Position { x: 0.0, y: 0.0 };
1208 let expected_events = vec![
1209 create_mouse_pointer_sample_event_phase_add(
1210 pressed_buttons.clone(),
1211 expected_position,
1212 event_time,
1213 ),
1214 create_mouse_pointer_sample_event(
1215 pointerinjector::EventPhase::Change,
1216 pressed_buttons.clone(),
1217 expected_position,
1218 None, None, None, None, event_time,
1223 ),
1224 ];
1225
1226 let (injector_stream_sender, injector_stream_receiver) =
1230 futures::channel::oneshot::channel::<pointerinjector::DeviceRequestStream>();
1231 let registry_fut = handle_registry_request_stream(
1232 injector_registry_request_stream,
1233 injector_stream_sender,
1234 );
1235 let device_fut = handle_device_request_stream(injector_stream_receiver, expected_events);
1236
1237 let (handle_result, _, _) = futures::join!(handle_event_fut, registry_fut, device_fut);
1240 match receiver.next().await {
1241 Some(CursorMessage::SetPosition(position)) => {
1242 pretty_assertions::assert_eq!(position, expected_position);
1243 }
1244 Some(CursorMessage::SetVisibility(_)) => {
1245 panic!("Received unexpected cursor visibility update.")
1246 }
1247 None => panic!("Did not receive cursor update."),
1248 }
1249
1250 assert_matches!(
1252 handle_result.as_slice(),
1253 [input_device::InputEvent { handled: input_device::Handled::Yes, .. }]
1254 );
1255 }
1256
1257 #[fuchsia::test(allow_stalls = false)]
1259 async fn down_up_event() {
1260 let (configuration_proxy, mut configuration_request_stream) =
1262 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1263 let (injector_registry_proxy, injector_registry_request_stream) =
1264 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1265 let config_request_stream_fut =
1266 handle_configuration_request_stream(&mut configuration_request_stream);
1267
1268 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(2);
1272 let inspector = fuchsia_inspect::Inspector::default();
1273 let test_node = inspector.root().create_child("test_node");
1274 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1275 configuration_proxy,
1276 injector_registry_proxy,
1277 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1278 sender,
1279 &test_node,
1280 metrics::MetricsLogger::default(),
1281 );
1282 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1283 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1284
1285 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
1286 let event_time1 = zx::MonotonicInstant::get();
1287 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
1288
1289 let event1 = create_mouse_event(
1290 cursor_location,
1291 None, None, None, mouse_binding::MousePhase::Down,
1295 HashSet::from_iter(vec![1]),
1296 HashSet::from_iter(vec![1]),
1297 event_time1,
1298 &DESCRIPTOR,
1299 );
1300
1301 let event2 = create_mouse_event(
1302 cursor_location,
1303 None, None, None, mouse_binding::MousePhase::Up,
1307 HashSet::from_iter(vec![1]),
1308 HashSet::new(),
1309 event_time2,
1310 &DESCRIPTOR,
1311 );
1312
1313 let expected_position = Position { x: 0.0, y: 0.0 };
1314
1315 let (injector_stream_sender, injector_stream_receiver) =
1319 mpsc::unbounded::<Vec<pointerinjector::Event>>();
1320 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
1322 let registry_fut = handle_registry_request_stream2(
1323 injector_registry_request_stream,
1324 injector_stream_sender,
1325 );
1326
1327 let _registry_task = fasync::Task::local(registry_fut);
1329
1330 mouse_handler.clone().handle_input_event(event1).await;
1331 assert_eq!(
1332 injector_stream_receiver
1333 .next()
1334 .await
1335 .map(|events| events.into_iter().flatten().collect()),
1336 Some(vec![
1337 create_mouse_pointer_sample_event_phase_add(
1338 vec![1],
1339 expected_position,
1340 event_time1,
1341 ),
1342 create_mouse_pointer_sample_event(
1343 pointerinjector::EventPhase::Change,
1344 vec![1],
1345 expected_position,
1346 None, None, None, None, event_time1,
1351 )
1352 ])
1353 );
1354
1355 mouse_handler.clone().handle_input_event(event2).await;
1357 assert_eq!(
1358 injector_stream_receiver
1359 .next()
1360 .await
1361 .map(|events| events.into_iter().flatten().collect()),
1362 Some(vec![create_mouse_pointer_sample_event(
1363 pointerinjector::EventPhase::Change,
1364 vec![],
1365 expected_position,
1366 None, None, None, None, event_time2,
1371 )])
1372 );
1373
1374 match receiver.next().await {
1376 Some(CursorMessage::SetPosition(position)) => {
1377 assert_eq!(position, expected_position);
1378 }
1379 Some(CursorMessage::SetVisibility(_)) => {
1380 panic!("Received unexpected cursor visibility update.")
1381 }
1382 None => panic!("Did not receive cursor update."),
1383 }
1384 }
1385
1386 #[fuchsia::test(allow_stalls = false)]
1396 async fn down_down_up_up_event() {
1397 let (configuration_proxy, mut configuration_request_stream) =
1399 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1400 let (injector_registry_proxy, injector_registry_request_stream) =
1401 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1402 let config_request_stream_fut =
1403 handle_configuration_request_stream(&mut configuration_request_stream);
1404
1405 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(4);
1409 let inspector = fuchsia_inspect::Inspector::default();
1410 let test_node = inspector.root().create_child("test_node");
1411 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1412 configuration_proxy,
1413 injector_registry_proxy,
1414 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1415 sender,
1416 &test_node,
1417 metrics::MetricsLogger::default(),
1418 );
1419 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1420 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1421
1422 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
1423 let event_time1 = zx::MonotonicInstant::get();
1424 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
1425 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
1426 let event_time4 = event_time3.add(zx::MonotonicDuration::from_micros(1));
1427
1428 let event1 = create_mouse_event(
1429 cursor_location,
1430 None, None, None, mouse_binding::MousePhase::Down,
1434 HashSet::from_iter(vec![1]),
1435 HashSet::from_iter(vec![1]),
1436 event_time1,
1437 &DESCRIPTOR,
1438 );
1439 let event2 = create_mouse_event(
1440 cursor_location,
1441 None, None, None, mouse_binding::MousePhase::Down,
1445 HashSet::from_iter(vec![2]),
1446 HashSet::from_iter(vec![1, 2]),
1447 event_time2,
1448 &DESCRIPTOR,
1449 );
1450 let event3 = create_mouse_event(
1451 cursor_location,
1452 None, None, None, mouse_binding::MousePhase::Up,
1456 HashSet::from_iter(vec![1]),
1457 HashSet::from_iter(vec![2]),
1458 event_time3,
1459 &DESCRIPTOR,
1460 );
1461 let event4 = create_mouse_event(
1462 cursor_location,
1463 None, None, None, mouse_binding::MousePhase::Up,
1467 HashSet::from_iter(vec![2]),
1468 HashSet::new(),
1469 event_time4,
1470 &DESCRIPTOR,
1471 );
1472
1473 let expected_position = Position { x: 0.0, y: 0.0 };
1474
1475 let (injector_stream_sender, injector_stream_receiver) =
1479 mpsc::unbounded::<Vec<pointerinjector::Event>>();
1480 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
1482 let registry_fut = handle_registry_request_stream2(
1483 injector_registry_request_stream,
1484 injector_stream_sender,
1485 );
1486
1487 let _registry_task = fasync::Task::local(registry_fut);
1489 mouse_handler.clone().handle_input_event(event1).await;
1490 assert_eq!(
1491 injector_stream_receiver
1492 .next()
1493 .await
1494 .map(|events| events.into_iter().flatten().collect()),
1495 Some(vec![
1496 create_mouse_pointer_sample_event_phase_add(
1497 vec![1],
1498 expected_position,
1499 event_time1,
1500 ),
1501 create_mouse_pointer_sample_event(
1502 pointerinjector::EventPhase::Change,
1503 vec![1],
1504 expected_position,
1505 None, None, None, None, event_time1,
1510 )
1511 ])
1512 );
1513
1514 mouse_handler.clone().handle_input_event(event2).await;
1516 let pointer_sample_event2: Vec<_> = injector_stream_receiver
1517 .next()
1518 .await
1519 .map(|events| events.into_iter().flatten().collect())
1520 .expect("Failed to receive pointer sample event.");
1521 let expected_event_time: i64 = event_time2.into_nanos();
1522 assert_eq!(pointer_sample_event2.len(), 1);
1523
1524 match &pointer_sample_event2[0] {
1527 pointerinjector::Event {
1528 timestamp: Some(actual_event_time),
1529 data:
1530 Some(pointerinjector::Data::PointerSample(pointerinjector::PointerSample {
1531 pointer_id: Some(0),
1532 phase: Some(pointerinjector::EventPhase::Change),
1533 position_in_viewport: Some(actual_position),
1534 scroll_v: None,
1535 scroll_h: None,
1536 pressed_buttons: Some(actual_buttons),
1537 relative_motion: None,
1538 ..
1539 })),
1540 ..
1541 } => {
1542 assert_eq!(*actual_event_time, expected_event_time);
1543 assert_eq!(actual_position[0], expected_position.x);
1544 assert_eq!(actual_position[1], expected_position.y);
1545 assert_eq!(
1546 HashSet::<mouse_binding::MouseButton>::from_iter(actual_buttons.clone()),
1547 HashSet::from_iter(vec![1, 2])
1548 );
1549 }
1550 _ => panic!("Unexpected pointer sample event: {:?}", pointer_sample_event2[0]),
1551 }
1552
1553 mouse_handler.clone().handle_input_event(event3).await;
1555 assert_eq!(
1556 injector_stream_receiver
1557 .next()
1558 .await
1559 .map(|events| events.into_iter().flatten().collect()),
1560 Some(vec![create_mouse_pointer_sample_event(
1561 pointerinjector::EventPhase::Change,
1562 vec![2],
1563 expected_position,
1564 None, None, None, None, event_time3,
1569 )])
1570 );
1571
1572 mouse_handler.clone().handle_input_event(event4).await;
1574 assert_eq!(
1575 injector_stream_receiver
1576 .next()
1577 .await
1578 .map(|events| events.into_iter().flatten().collect()),
1579 Some(vec![create_mouse_pointer_sample_event(
1580 pointerinjector::EventPhase::Change,
1581 vec![],
1582 expected_position,
1583 None, None, None, None, event_time4,
1588 )])
1589 );
1590
1591 match receiver.next().await {
1593 Some(CursorMessage::SetPosition(position)) => {
1594 assert_eq!(position, expected_position);
1595 }
1596 Some(CursorMessage::SetVisibility(_)) => {
1597 panic!("Received unexpected cursor visibility update.")
1598 }
1599 None => panic!("Did not receive cursor update."),
1600 }
1601 }
1602
1603 #[fuchsia::test(allow_stalls = false)]
1605 async fn down_move_up_event() {
1606 let (configuration_proxy, mut configuration_request_stream) =
1608 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1609 let (injector_registry_proxy, injector_registry_request_stream) =
1610 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1611 let config_request_stream_fut =
1612 handle_configuration_request_stream(&mut configuration_request_stream);
1613
1614 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(3);
1618 let inspector = fuchsia_inspect::Inspector::default();
1619 let test_node = inspector.root().create_child("test_node");
1620 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1621 configuration_proxy,
1622 injector_registry_proxy,
1623 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1624 sender,
1625 &test_node,
1626 metrics::MetricsLogger::default(),
1627 );
1628 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1629 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1630
1631 let event_time1 = zx::MonotonicInstant::get();
1632 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
1633 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
1634 let zero_position = Position { x: 0.0, y: 0.0 };
1635 let expected_position = Position {
1636 x: 10.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
1637 y: 5.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
1638 };
1639 let expected_relative_motion = [
1640 10.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
1641 5.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
1642 ];
1643 let event1 = create_mouse_event(
1644 mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 }),
1645 None, None, None, mouse_binding::MousePhase::Down,
1649 HashSet::from_iter(vec![1]),
1650 HashSet::from_iter(vec![1]),
1651 event_time1,
1652 &DESCRIPTOR,
1653 );
1654 let event2 = create_mouse_event(
1655 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1656 millimeters: Position { x: 10.0, y: 5.0 },
1657 }),
1658 None, None, None, mouse_binding::MousePhase::Move,
1662 HashSet::from_iter(vec![1]),
1663 HashSet::from_iter(vec![1]),
1664 event_time2,
1665 &DESCRIPTOR,
1666 );
1667 let event3 = create_mouse_event(
1668 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1669 millimeters: Position { x: 0.0, y: 0.0 },
1670 }),
1671 None, None, None, mouse_binding::MousePhase::Up,
1675 HashSet::from_iter(vec![1]),
1676 HashSet::from_iter(vec![]),
1677 event_time3,
1678 &DESCRIPTOR,
1679 );
1680
1681 let (injector_stream_sender, injector_stream_receiver) =
1685 mpsc::unbounded::<Vec<pointerinjector::Event>>();
1686 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
1688 let registry_fut = handle_registry_request_stream2(
1689 injector_registry_request_stream,
1690 injector_stream_sender,
1691 );
1692
1693 let _registry_task = fasync::Task::local(registry_fut);
1695 mouse_handler.clone().handle_input_event(event1).await;
1696 assert_eq!(
1697 injector_stream_receiver
1698 .next()
1699 .await
1700 .map(|events| events.into_iter().flatten().collect()),
1701 Some(vec![
1702 create_mouse_pointer_sample_event_phase_add(vec![1], zero_position, event_time1,),
1703 create_mouse_pointer_sample_event(
1704 pointerinjector::EventPhase::Change,
1705 vec![1],
1706 zero_position,
1707 None, None, None, None, event_time1,
1712 )
1713 ])
1714 );
1715
1716 match receiver.next().await {
1718 Some(CursorMessage::SetPosition(position)) => {
1719 assert_eq!(position, zero_position);
1720 }
1721 Some(CursorMessage::SetVisibility(_)) => {
1722 panic!("Received unexpected cursor visibility update.")
1723 }
1724 None => panic!("Did not receive cursor update."),
1725 }
1726
1727 mouse_handler.clone().handle_input_event(event2).await;
1729 assert_eq!(
1730 injector_stream_receiver
1731 .next()
1732 .await
1733 .map(|events| events.into_iter().flatten().collect()),
1734 Some(vec![create_mouse_pointer_sample_event(
1735 pointerinjector::EventPhase::Change,
1736 vec![1],
1737 expected_position,
1738 Some(expected_relative_motion),
1739 None, None, None, event_time2,
1743 )])
1744 );
1745
1746 match receiver.next().await {
1748 Some(CursorMessage::SetPosition(position)) => {
1749 assert_eq!(position, expected_position);
1750 }
1751 Some(CursorMessage::SetVisibility(_)) => {
1752 panic!("Received unexpected cursor visibility update.")
1753 }
1754 None => panic!("Did not receive cursor update."),
1755 }
1756
1757 mouse_handler.clone().handle_input_event(event3).await;
1759 assert_eq!(
1760 injector_stream_receiver
1761 .next()
1762 .await
1763 .map(|events| events.into_iter().flatten().collect()),
1764 Some(vec![create_mouse_pointer_sample_event(
1765 pointerinjector::EventPhase::Change,
1766 vec![],
1767 expected_position,
1768 None, None, None, None, event_time3,
1773 )])
1774 );
1775
1776 match receiver.next().await {
1778 Some(CursorMessage::SetPosition(position)) => {
1779 assert_eq!(position, expected_position);
1780 }
1781 Some(CursorMessage::SetVisibility(_)) => {
1782 panic!("Received unexpected cursor visibility update.")
1783 }
1784 None => panic!("Did not receive cursor update."),
1785 }
1786 }
1787
1788 #[fuchsia::test(allow_stalls = false)]
1790 async fn handler_ignores_handled_events() {
1791 let (configuration_proxy, mut configuration_request_stream) =
1793 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1794 let (injector_registry_proxy, injector_registry_request_stream) =
1795 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1796 let config_request_stream_fut =
1797 handle_configuration_request_stream(&mut configuration_request_stream);
1798
1799 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
1801 let inspector = fuchsia_inspect::Inspector::default();
1802 let test_node = inspector.root().create_child("test_node");
1803 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1804 configuration_proxy,
1805 injector_registry_proxy,
1806 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1807 sender,
1808 &test_node,
1809 metrics::MetricsLogger::default(),
1810 );
1811 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1812 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1813
1814 let cursor_relative_position = Position { x: 50.0, y: 75.0 };
1815 let cursor_location =
1816 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1817 millimeters: Position {
1818 x: cursor_relative_position.x / COUNTS_PER_MM as f32,
1819 y: cursor_relative_position.y / COUNTS_PER_MM as f32,
1820 },
1821 });
1822 let event_time = zx::MonotonicInstant::get();
1823 let input_events = vec![create_mouse_event_with_handled(
1824 cursor_location,
1825 None, None, None, mouse_binding::MousePhase::Move,
1829 HashSet::new(),
1830 HashSet::new(),
1831 event_time,
1832 &DESCRIPTOR,
1833 input_device::Handled::Yes,
1834 )];
1835
1836 assert_handler_ignores_input_event_sequence(
1837 mouse_handler,
1838 input_events,
1839 injector_registry_request_stream,
1840 )
1841 .await;
1842
1843 assert!(receiver.next().await.is_none());
1845 }
1846
1847 fn zero_relative_location() -> mouse_binding::MouseLocation {
1848 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1849 millimeters: Position { x: 0.0, y: 0.0 },
1850 })
1851 }
1852
1853 #[test_case(
1854 create_mouse_event(
1855 zero_relative_location(),
1856 wheel_delta_ticks(1, None), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1860 HashSet::new(),
1861 HashSet::new(),
1862 zx::MonotonicInstant::ZERO,
1863 &DESCRIPTOR,
1864 ),
1865 create_mouse_pointer_sample_event(
1866 pointerinjector::EventPhase::Change,
1867 vec![],
1868 Position { x: 50.0, y: 50.0 },
1869 None, Some(1), None, Some(false), zx::MonotonicInstant::ZERO,
1874 ); "v tick scroll"
1875 )]
1876 #[test_case(
1877 create_mouse_event(
1878 zero_relative_location(),
1879 None, wheel_delta_ticks(1, None), Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1883 HashSet::new(),
1884 HashSet::new(),
1885 zx::MonotonicInstant::ZERO,
1886 &DESCRIPTOR,
1887 ),
1888 create_mouse_pointer_sample_event(
1889 pointerinjector::EventPhase::Change,
1890 vec![],
1891 Position { x: 50.0, y: 50.0 },
1892 None, None, Some(1), Some(false), zx::MonotonicInstant::ZERO,
1897 ); "h tick scroll"
1898 )]
1899 #[test_case(
1900 create_mouse_event(
1901 zero_relative_location(),
1902 wheel_delta_ticks(1, Some(120.0)), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1906 HashSet::new(),
1907 HashSet::new(),
1908 zx::MonotonicInstant::ZERO,
1909 &DESCRIPTOR,
1910 ),
1911 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
1912 pointerinjector::EventPhase::Change,
1913 vec![],
1914 Position { x: 50.0, y: 50.0 },
1915 None, Some(1), None, Some(120.0), None, Some(false), zx::MonotonicInstant::ZERO,
1922 ); "v tick scroll with physical pixel"
1923 )]
1924 #[test_case(
1925 create_mouse_event(
1926 zero_relative_location(),
1927 None, wheel_delta_ticks(1, Some(120.0)), Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1931 HashSet::new(),
1932 HashSet::new(),
1933 zx::MonotonicInstant::ZERO,
1934 &DESCRIPTOR,
1935 ),
1936 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
1937 pointerinjector::EventPhase::Change,
1938 vec![],
1939 Position { x: 50.0, y: 50.0 },
1940 None, None, Some(1), None, Some(120.0), Some(false), zx::MonotonicInstant::ZERO,
1947 ); "h tick scroll with physical pixel"
1948 )]
1949 #[test_case(
1950 create_mouse_event(
1951 zero_relative_location(),
1952 wheel_delta_mm(1.0, Some(120.0)), None, Some(mouse_binding::PrecisionScroll::Yes), mouse_binding::MousePhase::Wheel,
1956 HashSet::new(),
1957 HashSet::new(),
1958 zx::MonotonicInstant::ZERO,
1959 &DESCRIPTOR,
1960 ),
1961 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
1962 pointerinjector::EventPhase::Change,
1963 vec![],
1964 Position { x: 50.0, y: 50.0 },
1965 None, None, None, Some(120.0), None, Some(true), zx::MonotonicInstant::ZERO,
1972 ); "v mm scroll with physical pixel"
1973 )]
1974 #[test_case(
1975 create_mouse_event(
1976 zero_relative_location(),
1977 None, wheel_delta_mm(1.0, Some(120.0)), Some(mouse_binding::PrecisionScroll::Yes), mouse_binding::MousePhase::Wheel,
1981 HashSet::new(),
1982 HashSet::new(),
1983 zx::MonotonicInstant::ZERO,
1984 &DESCRIPTOR,
1985 ),
1986 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
1987 pointerinjector::EventPhase::Change,
1988 vec![],
1989 Position { x: 50.0, y: 50.0 },
1990 None, None, None, None, Some(120.0), Some(true), zx::MonotonicInstant::ZERO,
1997 ); "h mm scroll with physical pixel"
1998 )]
1999 #[fuchsia::test(allow_stalls = false)]
2001 async fn scroll(event: input_device::InputEvent, want_event: pointerinjector::Event) {
2002 let (configuration_proxy, mut configuration_request_stream) =
2004 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
2005 let (injector_registry_proxy, injector_registry_request_stream) =
2006 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
2007 let config_request_stream_fut =
2008 handle_configuration_request_stream(&mut configuration_request_stream);
2009
2010 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
2012 let inspector = fuchsia_inspect::Inspector::default();
2013 let test_node = inspector.root().create_child("test_node");
2014 let mouse_handler_fut = MouseInjectorHandler::new_handler(
2015 configuration_proxy,
2016 injector_registry_proxy,
2017 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
2018 sender,
2019 &test_node,
2020 metrics::MetricsLogger::default(),
2021 );
2022 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
2023 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
2024
2025 let (injector_stream_sender, injector_stream_receiver) =
2029 mpsc::unbounded::<Vec<pointerinjector::Event>>();
2030 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
2032 let registry_fut = handle_registry_request_stream2(
2033 injector_registry_request_stream,
2034 injector_stream_sender,
2035 );
2036
2037 let event_time = zx::MonotonicInstant::get();
2038
2039 let event = input_device::InputEvent { event_time, ..event };
2040
2041 let want_event =
2042 pointerinjector::Event { timestamp: Some(event_time.into_nanos()), ..want_event };
2043
2044 let _registry_task = fasync::Task::local(registry_fut);
2046
2047 mouse_handler.clone().handle_input_event(event).await;
2048 let got_events: Vec<_> = injector_stream_receiver
2049 .next()
2050 .await
2051 .map(|events| events.into_iter().flatten().collect())
2052 .unwrap();
2053 pretty_assertions::assert_eq!(got_events.len(), 2);
2054 assert_matches!(
2055 got_events[0],
2056 pointerinjector::Event {
2057 data: Some(pointerinjector::Data::PointerSample(pointerinjector::PointerSample {
2058 phase: Some(pointerinjector::EventPhase::Add),
2059 ..
2060 })),
2061 ..
2062 }
2063 );
2064
2065 pretty_assertions::assert_eq!(got_events[1], want_event);
2066 }
2067
2068 #[fuchsia::test(allow_stalls = false)]
2070 async fn down_scroll_up_scroll() {
2071 let (configuration_proxy, mut configuration_request_stream) =
2073 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
2074 let (injector_registry_proxy, injector_registry_request_stream) =
2075 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
2076 let config_request_stream_fut =
2077 handle_configuration_request_stream(&mut configuration_request_stream);
2078
2079 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
2081 let inspector = fuchsia_inspect::Inspector::default();
2082 let test_node = inspector.root().create_child("test_node");
2083 let mouse_handler_fut = MouseInjectorHandler::new_handler(
2084 configuration_proxy,
2085 injector_registry_proxy,
2086 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
2087 sender,
2088 &test_node,
2089 metrics::MetricsLogger::default(),
2090 );
2091 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
2092 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
2093
2094 let (injector_stream_sender, injector_stream_receiver) =
2098 mpsc::unbounded::<Vec<pointerinjector::Event>>();
2099 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
2101 let registry_fut = handle_registry_request_stream2(
2102 injector_registry_request_stream,
2103 injector_stream_sender,
2104 );
2105
2106 let event_time1 = zx::MonotonicInstant::get();
2107 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
2108 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
2109 let event_time4 = event_time3.add(zx::MonotonicDuration::from_micros(1));
2110
2111 let _registry_task = fasync::Task::local(registry_fut);
2113
2114 let zero_location =
2115 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
2116 millimeters: Position { x: 0.0, y: 0.0 },
2117 });
2118 let expected_position = Position { x: 50.0, y: 50.0 };
2119
2120 let down_event = create_mouse_event(
2121 zero_location,
2122 None, None, None, mouse_binding::MousePhase::Down,
2126 HashSet::from_iter(vec![1]),
2127 HashSet::from_iter(vec![1]),
2128 event_time1,
2129 &DESCRIPTOR,
2130 );
2131
2132 let wheel_event = create_mouse_event(
2133 zero_location,
2134 wheel_delta_ticks(1, None), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
2138 HashSet::from_iter(vec![1]),
2139 HashSet::from_iter(vec![1]),
2140 event_time2,
2141 &DESCRIPTOR,
2142 );
2143
2144 let up_event = create_mouse_event(
2145 zero_location,
2146 None,
2147 None,
2148 None, mouse_binding::MousePhase::Up,
2150 HashSet::from_iter(vec![1]),
2151 HashSet::new(),
2152 event_time3,
2153 &DESCRIPTOR,
2154 );
2155
2156 let continue_wheel_event = create_mouse_event(
2157 zero_location,
2158 wheel_delta_ticks(1, None), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
2162 HashSet::new(),
2163 HashSet::new(),
2164 event_time4,
2165 &DESCRIPTOR,
2166 );
2167
2168 mouse_handler.clone().handle_input_event(down_event).await;
2170 assert_eq!(
2171 injector_stream_receiver
2172 .next()
2173 .await
2174 .map(|events| events.into_iter().flatten().collect()),
2175 Some(vec![
2176 create_mouse_pointer_sample_event_phase_add(
2177 vec![1],
2178 expected_position,
2179 event_time1,
2180 ),
2181 create_mouse_pointer_sample_event(
2182 pointerinjector::EventPhase::Change,
2183 vec![1],
2184 expected_position,
2185 None, None, None, None, event_time1,
2190 ),
2191 ])
2192 );
2193
2194 mouse_handler.clone().handle_input_event(wheel_event).await;
2196 assert_eq!(
2197 injector_stream_receiver
2198 .next()
2199 .await
2200 .map(|events| events.into_iter().flatten().collect()),
2201 Some(vec![create_mouse_pointer_sample_event(
2202 pointerinjector::EventPhase::Change,
2203 vec![1],
2204 expected_position,
2205 None, Some(1), None, Some(false), event_time2,
2210 )])
2211 );
2212
2213 mouse_handler.clone().handle_input_event(up_event).await;
2215 assert_eq!(
2216 injector_stream_receiver
2217 .next()
2218 .await
2219 .map(|events| events.into_iter().flatten().collect()),
2220 Some(vec![create_mouse_pointer_sample_event(
2221 pointerinjector::EventPhase::Change,
2222 vec![],
2223 expected_position,
2224 None, None, None, None, event_time3,
2229 )])
2230 );
2231
2232 mouse_handler.clone().handle_input_event(continue_wheel_event).await;
2234 assert_eq!(
2235 injector_stream_receiver
2236 .next()
2237 .await
2238 .map(|events| events.into_iter().flatten().collect()),
2239 Some(vec![create_mouse_pointer_sample_event(
2240 pointerinjector::EventPhase::Change,
2241 vec![],
2242 expected_position,
2243 None, Some(1), None, Some(false), event_time4,
2248 )])
2249 );
2250 }
2251
2252 #[fuchsia::test(allow_stalls = false)]
2253 async fn mouse_injector_handler_initialized_with_inspect_node() {
2254 let (configuration_proxy, mut configuration_request_stream) =
2255 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
2256 let config_request_stream_fut =
2257 handle_configuration_request_stream(&mut configuration_request_stream);
2258 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
2259 let inspector = fuchsia_inspect::Inspector::default();
2260 let fake_handlers_node = inspector.root().create_child("input_handlers_node");
2261 let mouse_handler_fut = MouseInjectorHandler::new_with_config_proxy(
2262 configuration_proxy,
2263 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
2264 sender,
2265 &fake_handlers_node,
2266 metrics::MetricsLogger::default(),
2267 );
2268 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
2269 let _handler = mouse_handler_res.expect("Failed to create mouse handler");
2270
2271 diagnostics_assertions::assert_data_tree!(inspector, root: {
2272 input_handlers_node: {
2273 mouse_injector_handler: {
2274 events_received_count: 0u64,
2275 events_handled_count: 0u64,
2276 last_received_timestamp_ns: 0u64,
2277 "fuchsia.inspect.Health": {
2278 status: "STARTING_UP",
2279 start_timestamp_nanos: diagnostics_assertions::AnyProperty
2282 },
2283 }
2284 }
2285 });
2286 }
2287
2288 #[fuchsia::test(allow_stalls = false)]
2289 async fn mouse_injector_handler_inspect_counts_events() {
2290 let (configuration_proxy, mut configuration_request_stream) =
2292 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
2293 let (injector_registry_proxy, injector_registry_request_stream) =
2294 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
2295 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
2296
2297 let inspector = fuchsia_inspect::Inspector::default();
2298 let fake_handlers_node = inspector.root().create_child("input_handlers_node");
2299
2300 let mouse_handler_fut = MouseInjectorHandler::new_handler(
2302 configuration_proxy,
2303 injector_registry_proxy,
2304 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
2305 sender,
2306 &fake_handlers_node,
2307 metrics::MetricsLogger::default(),
2308 );
2309 let config_request_stream_fut =
2310 handle_configuration_request_stream(&mut configuration_request_stream);
2311
2312 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
2313 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
2314
2315 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
2316 let event_time1 = zx::MonotonicInstant::get();
2317 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
2318 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
2319
2320 let input_events = vec![
2321 create_mouse_event(
2322 cursor_location,
2323 None, None, None, mouse_binding::MousePhase::Down,
2327 HashSet::from_iter(vec![1]),
2328 HashSet::from_iter(vec![1]),
2329 event_time1,
2330 &DESCRIPTOR,
2331 ),
2332 create_mouse_event(
2333 cursor_location,
2334 None, None, None, mouse_binding::MousePhase::Up,
2338 HashSet::from_iter(vec![1]),
2339 HashSet::new(),
2340 event_time2,
2341 &DESCRIPTOR,
2342 ),
2343 create_mouse_event_with_handled(
2344 cursor_location,
2345 None, None, None, mouse_binding::MousePhase::Down,
2349 HashSet::from_iter(vec![1]),
2350 HashSet::from_iter(vec![1]),
2351 event_time3,
2352 &DESCRIPTOR,
2353 input_device::Handled::Yes,
2354 ),
2355 ];
2356
2357 let (injector_stream_sender, _) = mpsc::unbounded::<Vec<pointerinjector::Event>>();
2361 let registry_fut = handle_registry_request_stream2(
2362 injector_registry_request_stream,
2363 injector_stream_sender,
2364 );
2365
2366 let _registry_task = fasync::Task::local(registry_fut);
2368 for input_event in input_events {
2369 mouse_handler.clone().handle_input_event(input_event).await;
2370 }
2371
2372 let last_received_event_time: u64 = event_time2.into_nanos().try_into().unwrap();
2373
2374 diagnostics_assertions::assert_data_tree!(inspector, root: {
2375 input_handlers_node: {
2376 mouse_injector_handler: {
2377 events_received_count: 2u64,
2378 events_handled_count: 2u64,
2379 last_received_timestamp_ns: last_received_event_time,
2380 "fuchsia.inspect.Health": {
2381 status: "STARTING_UP",
2382 start_timestamp_nanos: diagnostics_assertions::AnyProperty
2385 },
2386 }
2387 }
2388 });
2389 }
2390}