1#![warn(clippy::await_holding_refcell_ref)]
6
7use crate::input_handler::{InputHandler, InputHandlerStatus};
8use crate::utils::{CursorMessage, Position, Size};
9use crate::{input_device, metrics, mouse_binding};
10use anyhow::{Context, Error, Result, anyhow};
11use async_trait::async_trait;
12use async_utils::hanging_get::client::HangingGetStream;
13use fidl::endpoints::create_proxy;
14use fidl_fuchsia_input_report::Range;
15use fuchsia_component::client::connect_to_protocol;
16use fuchsia_inspect::health::Reporter;
17use futures::SinkExt;
18use futures::channel::mpsc::Sender;
19use futures::stream::StreamExt;
20use metrics_registry::*;
21use std::cell::{Ref, RefCell, RefMut};
22use std::collections::HashMap;
23use std::rc::Rc;
24use {
25 fidl_fuchsia_ui_pointerinjector as pointerinjector,
26 fidl_fuchsia_ui_pointerinjector_configuration as pointerinjector_config,
27};
28
29const MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL: f32 = 10.0;
37
38pub struct MouseInjectorHandler {
41 mutable_state: RefCell<MutableState>,
43
44 context_view_ref: fidl_fuchsia_ui_views::ViewRef,
47
48 target_view_ref: fidl_fuchsia_ui_views::ViewRef,
51
52 max_position: Position,
55
56 injector_registry_proxy: pointerinjector::RegistryProxy,
58
59 configuration_proxy: pointerinjector_config::SetupProxy,
61
62 pub inspect_status: InputHandlerStatus,
64
65 metrics_logger: metrics::MetricsLogger,
66}
67
68struct MutableState {
69 viewport: Option<pointerinjector::Viewport>,
72
73 injectors: HashMap<u32, pointerinjector::DeviceProxy>,
75
76 current_position: Position,
78
79 cursor_message_sender: Sender<CursorMessage>,
81}
82
83#[async_trait(?Send)]
84impl InputHandler for MouseInjectorHandler {
85 async fn handle_input_event(
86 self: Rc<Self>,
87 mut input_event: input_device::InputEvent,
88 ) -> Vec<input_device::InputEvent> {
89 fuchsia_trace::duration!(c"input", c"mouse_injector_handler");
90 match input_event {
91 input_device::InputEvent {
92 device_event: input_device::InputDeviceEvent::Mouse(ref mouse_event),
93 device_descriptor:
94 input_device::InputDeviceDescriptor::Mouse(ref mouse_device_descriptor),
95 event_time,
96 handled: input_device::Handled::No,
97 trace_id,
98 } => {
99 fuchsia_trace::duration!(c"input", c"mouse_injector_handler[processing]");
100 let trace_id = match trace_id {
101 Some(id) => {
102 fuchsia_trace::flow_end!(c"input", c"event_in_input_pipeline", id.into());
103 id
104 }
105 None => fuchsia_trace::Id::random(),
106 };
107
108 self.inspect_status.count_received_event(&event_time);
109 if let Err(e) =
111 self.update_cursor_renderer(mouse_event, &mouse_device_descriptor).await
112 {
113 self.metrics_logger.log_error(
114 InputPipelineErrorMetricDimensionEvent::MouseInjectorUpdateCursorRendererFailed,
115 std::format!("update_cursor_renderer failed: {}", e));
116 }
117
118 if let Err(e) = self
120 .ensure_injector_registered(&mouse_event, &mouse_device_descriptor, event_time)
121 .await
122 {
123 self.metrics_logger.log_error(
124 InputPipelineErrorMetricDimensionEvent::MouseInjectorEnsureInjectorRegisteredFailed,
125 std::format!("ensure_injector_registered failed: {}", e));
126 }
127
128 if let Err(e) = self
130 .send_event_to_scenic(
131 &mouse_event,
132 &mouse_device_descriptor,
133 event_time,
134 trace_id.into(),
135 )
136 .await
137 {
138 self.metrics_logger.log_error(
139 InputPipelineErrorMetricDimensionEvent::MouseInjectorSendEventToScenicFailed,
140 std::format!("send_event_to_scenic failed: {}", e));
141 }
142
143 input_event.handled = input_device::Handled::Yes;
145 self.inspect_status.count_handled_event();
146 }
147 _ => {}
148 }
149 vec![input_event]
150 }
151
152 fn set_handler_healthy(self: std::rc::Rc<Self>) {
153 self.inspect_status.health_node.borrow_mut().set_ok();
154 }
155
156 fn set_handler_unhealthy(self: std::rc::Rc<Self>, msg: &str) {
157 self.inspect_status.health_node.borrow_mut().set_unhealthy(msg);
158 }
159}
160
161impl MouseInjectorHandler {
162 pub async fn new(
175 display_size: Size,
176 cursor_message_sender: Sender<CursorMessage>,
177 input_handlers_node: &fuchsia_inspect::Node,
178 metrics_logger: metrics::MetricsLogger,
179 ) -> Result<Rc<Self>, Error> {
180 let configuration_proxy = connect_to_protocol::<pointerinjector_config::SetupMarker>()?;
181 let injector_registry_proxy = connect_to_protocol::<pointerinjector::RegistryMarker>()?;
182
183 Self::new_handler(
184 configuration_proxy,
185 injector_registry_proxy,
186 display_size,
187 cursor_message_sender,
188 input_handlers_node,
189 metrics_logger,
190 )
191 .await
192 }
193
194 pub async fn new_with_config_proxy(
210 configuration_proxy: pointerinjector_config::SetupProxy,
211 display_size: Size,
212 cursor_message_sender: Sender<CursorMessage>,
213 input_handlers_node: &fuchsia_inspect::Node,
214 metrics_logger: metrics::MetricsLogger,
215 ) -> Result<Rc<Self>, Error> {
216 let injector_registry_proxy = connect_to_protocol::<pointerinjector::RegistryMarker>()?;
217 Self::new_handler(
218 configuration_proxy,
219 injector_registry_proxy,
220 display_size,
221 cursor_message_sender,
222 input_handlers_node,
223 metrics_logger,
224 )
225 .await
226 }
227
228 fn inner(&self) -> Ref<'_, MutableState> {
229 self.mutable_state.borrow()
230 }
231
232 fn inner_mut(&self) -> RefMut<'_, MutableState> {
233 self.mutable_state.borrow_mut()
234 }
235
236 async fn new_handler(
252 configuration_proxy: pointerinjector_config::SetupProxy,
253 injector_registry_proxy: pointerinjector::RegistryProxy,
254 display_size: Size,
255 cursor_message_sender: Sender<CursorMessage>,
256 input_handlers_node: &fuchsia_inspect::Node,
257 metrics_logger: metrics::MetricsLogger,
258 ) -> Result<Rc<Self>, Error> {
259 let (context_view_ref, target_view_ref) = configuration_proxy.get_view_refs().await?;
261 let inspect_status = InputHandlerStatus::new(
262 input_handlers_node,
263 "mouse_injector_handler",
264 false,
265 );
266 let handler = Rc::new(Self {
267 mutable_state: RefCell::new(MutableState {
268 viewport: None,
269 injectors: HashMap::new(),
270 current_position: Position {
272 x: display_size.width / 2.0,
273 y: display_size.height / 2.0,
274 },
275 cursor_message_sender,
276 }),
277 context_view_ref,
278 target_view_ref,
279 max_position: Position { x: display_size.width, y: display_size.height },
280 injector_registry_proxy,
281 configuration_proxy,
282 inspect_status,
283 metrics_logger,
284 });
285
286 Ok(handler)
287 }
288
289 async fn ensure_injector_registered(
297 self: &Rc<Self>,
298 mouse_event: &mouse_binding::MouseEvent,
299 mouse_descriptor: &mouse_binding::MouseDeviceDescriptor,
300 event_time: zx::MonotonicInstant,
301 ) -> Result<(), anyhow::Error> {
302 if self.inner().injectors.contains_key(&mouse_descriptor.device_id) {
303 return Ok(());
304 }
305
306 let (device_proxy, device_server) = create_proxy::<pointerinjector::DeviceMarker>();
308 let context = fuchsia_scenic::duplicate_view_ref(&self.context_view_ref)
309 .context("Failed to duplicate context view ref.")?;
310 let target = fuchsia_scenic::duplicate_view_ref(&self.target_view_ref)
311 .context("Failed to duplicate target view ref.")?;
312
313 let viewport = self.inner().viewport.clone();
314 let config = pointerinjector::Config {
315 device_id: Some(mouse_descriptor.device_id),
316 device_type: Some(pointerinjector::DeviceType::Mouse),
317 context: Some(pointerinjector::Context::View(context)),
318 target: Some(pointerinjector::Target::View(target)),
319 viewport,
320 dispatch_policy: Some(pointerinjector::DispatchPolicy::MouseHoverAndLatchInTarget),
321 scroll_v_range: mouse_descriptor.wheel_v_range.clone(),
322 scroll_h_range: mouse_descriptor.wheel_h_range.clone(),
323 buttons: mouse_descriptor.buttons.clone(),
324 ..Default::default()
325 };
326
327 self.injector_registry_proxy
329 .register(config, device_server)
330 .await
331 .context("Failed to register injector.")?;
332 log::info!("Registered injector with device id {:?}", mouse_descriptor.device_id);
333
334 self.inner_mut().injectors.insert(mouse_descriptor.device_id, device_proxy.clone());
336
337 let events_to_send = vec![self.create_pointer_sample_event(
339 mouse_event,
340 event_time,
341 pointerinjector::EventPhase::Add,
342 self.inner().current_position,
343 None,
344 None,
345 )];
346 device_proxy.inject_events(events_to_send).context("Failed to ADD new MouseDevice.")?;
347
348 Ok(())
349 }
350
351 async fn update_cursor_renderer(
362 &self,
363 mouse_event: &mouse_binding::MouseEvent,
364 mouse_descriptor: &mouse_binding::MouseDeviceDescriptor,
365 ) -> Result<(), anyhow::Error> {
366 let mut new_position = match (mouse_event.location, mouse_descriptor) {
367 (
368 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
369 millimeters,
370 }),
371 _,
372 ) => {
373 self.inner().current_position
374 + self.relative_movement_mm_to_phyical_pixel(millimeters)
375 }
376 (
377 mouse_binding::MouseLocation::Absolute(position),
378 mouse_binding::MouseDeviceDescriptor {
379 absolute_x_range: Some(x_range),
380 absolute_y_range: Some(y_range),
381 ..
382 },
383 ) => self.scale_absolute_position(&position, &x_range, &y_range),
384 (mouse_binding::MouseLocation::Absolute(_), _) => {
385 return Err(anyhow!(
386 "Received an Absolute mouse location without absolute device ranges."
387 ));
388 }
389 };
390 Position::clamp(&mut new_position, Position::zero(), self.max_position);
391 self.inner_mut().current_position = new_position;
392
393 let mut cursor_message_sender = self.inner().cursor_message_sender.clone();
394 cursor_message_sender
395 .send(CursorMessage::SetPosition(new_position))
396 .await
397 .context("Failed to send current mouse position to cursor renderer")?;
398
399 Ok(())
400 }
401
402 fn scale_absolute_position(
410 &self,
411 position: &Position,
412 x_range: &Range,
413 y_range: &Range,
414 ) -> Position {
415 let range_min = Position { x: x_range.min as f32, y: y_range.min as f32 };
416 let range_max = Position { x: x_range.max as f32, y: y_range.max as f32 };
417 self.max_position * ((*position - range_min) / (range_max - range_min))
418 }
419
420 async fn send_event_to_scenic(
427 &self,
428 mouse_event: &mouse_binding::MouseEvent,
429 mouse_descriptor: &mouse_binding::MouseDeviceDescriptor,
430 event_time: zx::MonotonicInstant,
431 tracing_id: u64,
432 ) -> Result<(), anyhow::Error> {
433 let injector = self.inner().injectors.get(&mouse_descriptor.device_id).cloned();
434 if let Some(injector) = injector {
435 let relative_motion = match mouse_event.location {
436 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
437 millimeters: offset_mm,
438 }) if mouse_event.phase == mouse_binding::MousePhase::Move => {
439 let offset = self.relative_movement_mm_to_phyical_pixel(offset_mm);
440 Some([offset.x, offset.y])
441 }
442 _ => None,
443 };
444 let events_to_send = vec![self.create_pointer_sample_event(
445 mouse_event,
446 event_time,
447 pointerinjector::EventPhase::Change,
448 self.inner().current_position,
449 relative_motion,
450 Some(tracing_id),
451 )];
452
453 fuchsia_trace::flow_begin!(c"input", c"dispatch_event_to_scenic", tracing_id.into());
454
455 let _ = injector.inject_events(events_to_send);
456
457 Ok(())
458 } else {
459 Err(anyhow::format_err!(
460 "No injector found for mouse device {}.",
461 mouse_descriptor.device_id
462 ))
463 }
464 }
465
466 fn create_pointer_sample_event(
475 &self,
476 mouse_event: &mouse_binding::MouseEvent,
477 event_time: zx::MonotonicInstant,
478 phase: pointerinjector::EventPhase,
479 current_position: Position,
480 relative_motion: Option<[f32; 2]>,
481 trace_id: Option<u64>,
482 ) -> pointerinjector::Event {
483 let pointer_sample = pointerinjector::PointerSample {
484 pointer_id: Some(0),
485 phase: Some(phase),
486 position_in_viewport: Some([current_position.x, current_position.y]),
487 scroll_v: match mouse_event.wheel_delta_v {
488 Some(mouse_binding::WheelDelta {
489 raw_data: mouse_binding::RawWheelDelta::Ticks(tick),
490 ..
491 }) => Some(tick),
492 _ => None,
493 },
494 scroll_h: match mouse_event.wheel_delta_h {
495 Some(mouse_binding::WheelDelta {
496 raw_data: mouse_binding::RawWheelDelta::Ticks(tick),
497 ..
498 }) => Some(tick),
499 _ => None,
500 },
501 scroll_v_physical_pixel: match mouse_event.wheel_delta_v {
502 Some(mouse_binding::WheelDelta { physical_pixel: Some(pixel), .. }) => {
503 Some(pixel.into())
504 }
505 _ => None,
506 },
507 scroll_h_physical_pixel: match mouse_event.wheel_delta_h {
508 Some(mouse_binding::WheelDelta { physical_pixel: Some(pixel), .. }) => {
509 Some(pixel.into())
510 }
511 _ => None,
512 },
513 is_precision_scroll: match mouse_event.phase {
514 mouse_binding::MousePhase::Wheel => match mouse_event.is_precision_scroll {
515 Some(mouse_binding::PrecisionScroll::Yes) => Some(true),
516 Some(mouse_binding::PrecisionScroll::No) => Some(false),
517 None => {
518 self.metrics_logger.log_error(
519 InputPipelineErrorMetricDimensionEvent::MouseInjectorMissingIsPrecisionScroll,
520 "mouse wheel event does not have value in is_precision_scroll.");
521 None
522 }
523 },
524 _ => None,
525 },
526 pressed_buttons: Some(Vec::from_iter(mouse_event.pressed_buttons.iter().cloned())),
527 relative_motion,
528 ..Default::default()
529 };
530 pointerinjector::Event {
531 timestamp: Some(event_time.into_nanos()),
532 data: Some(pointerinjector::Data::PointerSample(pointer_sample)),
533 trace_flow_id: trace_id,
534 wake_lease: mouse_event.wake_lease.lock().take(),
535 ..Default::default()
536 }
537 }
538
539 pub async fn watch_viewport(self: Rc<Self>) {
541 let configuration_proxy = self.configuration_proxy.clone();
542 let mut viewport_stream = HangingGetStream::new(
543 configuration_proxy,
544 pointerinjector_config::SetupProxy::watch_viewport,
545 );
546 loop {
547 match viewport_stream.next().await {
548 Some(Ok(new_viewport)) => {
549 self.inner_mut().viewport = Some(new_viewport.clone());
551
552 let injectors = self.inner().injectors.values().cloned().collect::<Vec<_>>();
554 for injector in injectors {
555 let events = vec![pointerinjector::Event {
556 timestamp: Some(fuchsia_async::MonotonicInstant::now().into_nanos()),
557 data: Some(pointerinjector::Data::Viewport(new_viewport.clone())),
558 trace_flow_id: Some(fuchsia_trace::Id::random().into()),
559 ..Default::default()
560 }];
561 injector.inject_events(events).expect("Failed to inject updated viewport.");
562 }
563 }
564 Some(Err(e)) => {
565 self.metrics_logger.log_error(
566 InputPipelineErrorMetricDimensionEvent::MouseInjectorErrorWhileReadingViewportUpdate,
567 std::format!("Error while reading viewport update: {}", e));
568 return;
569 }
570 None => {
571 self.metrics_logger.log_error(
572 InputPipelineErrorMetricDimensionEvent::MouseInjectorViewportUpdateStreamTerminatedUnexpectedly,
573 "Viewport update stream terminated unexpectedly");
574 return;
575 }
576 }
577 }
578 }
579
580 fn relative_movement_mm_to_phyical_pixel(&self, movement_mm: Position) -> Position {
584 Position {
585 x: movement_mm.x * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
586 y: movement_mm.y * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
587 }
588 }
589}
590
591#[cfg(test)]
592mod tests {
593 use super::*;
594 use crate::testing_utilities::{
595 assert_handler_ignores_input_event_sequence, create_mouse_event,
596 create_mouse_event_with_handled, create_mouse_pointer_sample_event,
597 create_mouse_pointer_sample_event_phase_add,
598 create_mouse_pointer_sample_event_with_wheel_physical_pixel,
599 };
600 use assert_matches::assert_matches;
601 use futures::channel::mpsc;
602 use pretty_assertions::assert_eq;
603 use std::collections::HashSet;
604 use std::ops::Add;
605 use test_case::test_case;
606 use {
607 fidl_fuchsia_input_report as fidl_input_report,
608 fidl_fuchsia_ui_pointerinjector as pointerinjector, fuchsia_async as fasync,
609 };
610
611 const DISPLAY_WIDTH_IN_PHYSICAL_PX: f32 = 100.0;
612 const DISPLAY_HEIGHT_IN_PHYSICAL_PX: f32 = 100.0;
613 const COUNTS_PER_MM: u32 = 12;
614
615 const DESCRIPTOR: input_device::InputDeviceDescriptor =
617 input_device::InputDeviceDescriptor::Mouse(mouse_binding::MouseDeviceDescriptor {
618 device_id: 1,
619 absolute_x_range: Some(fidl_input_report::Range { min: 0, max: 100 }),
620 absolute_y_range: Some(fidl_input_report::Range { min: 0, max: 100 }),
621 wheel_v_range: Some(fidl_input_report::Axis {
622 range: fidl_input_report::Range { min: -1, max: 1 },
623 unit: fidl_input_report::Unit {
624 type_: fidl_input_report::UnitType::Other,
625 exponent: 0,
626 },
627 }),
628 wheel_h_range: Some(fidl_input_report::Axis {
629 range: fidl_input_report::Range { min: -1, max: 1 },
630 unit: fidl_input_report::Unit {
631 type_: fidl_input_report::UnitType::Other,
632 exponent: 0,
633 },
634 }),
635 buttons: None,
636 counts_per_mm: COUNTS_PER_MM,
637 });
638
639 async fn handle_configuration_request_stream(
641 stream: &mut pointerinjector_config::SetupRequestStream,
642 ) {
643 if let Some(Ok(request)) = stream.next().await {
644 match request {
645 pointerinjector_config::SetupRequest::GetViewRefs { responder, .. } => {
646 let context = fuchsia_scenic::ViewRefPair::new()
647 .expect("Failed to create viewrefpair.")
648 .view_ref;
649 let target = fuchsia_scenic::ViewRefPair::new()
650 .expect("Failed to create viewrefpair.")
651 .view_ref;
652 let _ = responder.send(context, target);
653 }
654 _ => {}
655 };
656 }
657 }
658
659 async fn handle_registry_request_stream(
662 mut stream: pointerinjector::RegistryRequestStream,
663 injector_sender: futures::channel::oneshot::Sender<pointerinjector::DeviceRequestStream>,
664 ) {
665 if let Some(request) = stream.next().await {
666 match request {
667 Ok(pointerinjector::RegistryRequest::Register {
668 config: _,
669 injector,
670 responder,
671 ..
672 }) => {
673 let injector_stream = injector.into_stream();
674 let _ = injector_sender.send(injector_stream);
675 responder.send().expect("failed to respond");
676 }
677 _ => {}
678 };
679 } else {
680 panic!("RegistryRequestStream failed.");
681 }
682 }
683
684 async fn handle_registry_request_stream2(
686 mut stream: pointerinjector::RegistryRequestStream,
687 injector_sender: mpsc::UnboundedSender<Vec<pointerinjector::Event>>,
688 ) {
689 let (injector, responder) = match stream.next().await {
690 Some(Ok(pointerinjector::RegistryRequest::Register {
691 config: _,
692 injector,
693 responder,
694 ..
695 })) => (injector, responder),
696 other => panic!("expected register request, but got {:?}", other),
697 };
698 let injector_stream: pointerinjector::DeviceRequestStream = injector.into_stream();
699 responder.send().expect("failed to respond");
700 injector_stream
701 .for_each(|request| {
702 futures::future::ready({
703 match request {
704 Ok(pointerinjector::DeviceRequest::Inject { .. }) => {
705 panic!("DeviceRequest::Inject is deprecated.");
706 }
707 Ok(pointerinjector::DeviceRequest::InjectEvents { events, .. }) => {
708 let _ = injector_sender.unbounded_send(events);
709 }
710 Err(e) => panic!("FIDL error {}", e),
711 }
712 })
713 })
714 .await;
715 }
716
717 async fn handle_device_request_stream(
720 injector_stream_receiver: futures::channel::oneshot::Receiver<
721 pointerinjector::DeviceRequestStream,
722 >,
723 expected_events: Vec<pointerinjector::Event>,
724 ) {
725 let mut injector_stream =
726 injector_stream_receiver.await.expect("Failed to get DeviceRequestStream.");
727 for expected_event in expected_events {
728 match injector_stream.next().await {
729 Some(Ok(pointerinjector::DeviceRequest::Inject { .. })) => {
730 panic!("DeviceRequest::Inject is deprecated.");
731 }
732 Some(Ok(pointerinjector::DeviceRequest::InjectEvents { events, .. })) => {
733 assert_eq!(events, vec![expected_event]);
734 }
735 Some(Err(e)) => panic!("FIDL error {}", e),
736 None => panic!("Expected another event."),
737 }
738 }
739 }
740
741 fn create_viewport(min: f32, max: f32) -> pointerinjector::Viewport {
743 pointerinjector::Viewport {
744 extents: Some([[min, min], [max, max]]),
745 viewport_to_context_transform: None,
746 ..Default::default()
747 }
748 }
749
750 #[fuchsia::test]
753 fn receives_viewport_updates() {
754 let mut exec = fasync::TestExecutor::new();
755
756 let (configuration_proxy, mut configuration_request_stream) =
758 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
759 let (injector_registry_proxy, _) =
760 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
761 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(0);
762
763 let inspector = fuchsia_inspect::Inspector::default();
764 let test_node = inspector.root().create_child("test_node");
765
766 let mouse_handler_fut = MouseInjectorHandler::new_handler(
768 configuration_proxy,
769 injector_registry_proxy,
770 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
771 sender,
772 &test_node,
773 metrics::MetricsLogger::default(),
774 );
775 let config_request_stream_fut =
776 handle_configuration_request_stream(&mut configuration_request_stream);
777 let (mouse_handler_res, _) = exec.run_singlethreaded(futures::future::join(
778 mouse_handler_fut,
779 config_request_stream_fut,
780 ));
781 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
782
783 let (injector_device_proxy, mut injector_device_request_stream) =
785 fidl::endpoints::create_proxy_and_stream::<pointerinjector::DeviceMarker>();
786 mouse_handler.inner_mut().injectors.insert(1, injector_device_proxy);
787
788 {
790 let watch_viewport_fut = mouse_handler.clone().watch_viewport();
792 futures::pin_mut!(watch_viewport_fut);
793 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
794
795 match exec.run_singlethreaded(&mut configuration_request_stream.next()) {
797 Some(Ok(pointerinjector_config::SetupRequest::WatchViewport {
798 responder, ..
799 })) => {
800 responder.send(&create_viewport(0.0, 100.0)).expect("Failed to send viewport.");
801 }
802 other => panic!("Received unexpected value: {:?}", other),
803 };
804 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
805
806 exec.run_singlethreaded(async {
808 match injector_device_request_stream.next().await {
809 Some(Ok(pointerinjector::DeviceRequest::Inject { .. })) => {
810 panic!("DeviceRequest::Inject is deprecated.");
811 }
812 Some(Ok(pointerinjector::DeviceRequest::InjectEvents { events, .. })) => {
813 assert_eq!(events.len(), 1);
814 assert!(events[0].data.is_some());
815 assert_eq!(
816 events[0].data,
817 Some(pointerinjector::Data::Viewport(create_viewport(0.0, 100.0)))
818 );
819 }
820 other => panic!("Received unexpected value: {:?}", other),
821 }
822 });
823
824 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
826
827 match exec.run_singlethreaded(&mut configuration_request_stream.next()) {
829 Some(Ok(pointerinjector_config::SetupRequest::WatchViewport {
830 responder, ..
831 })) => {
832 responder
833 .send(&create_viewport(100.0, 200.0))
834 .expect("Failed to send viewport.");
835 }
836 other => panic!("Received unexpected value: {:?}", other),
837 };
838
839 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
841 }
842
843 exec.run_singlethreaded(async {
845 match injector_device_request_stream.next().await {
846 Some(Ok(pointerinjector::DeviceRequest::Inject { .. })) => {
847 panic!("DeviceRequest::Inject is deprecated.");
848 }
849 Some(Ok(pointerinjector::DeviceRequest::InjectEvents { events, .. })) => {
850 assert_eq!(events.len(), 1);
851 assert!(events[0].data.is_some());
852 assert_eq!(
853 events[0].data,
854 Some(pointerinjector::Data::Viewport(create_viewport(100.0, 200.0)))
855 );
856 }
857 other => panic!("Received unexpected value: {:?}", other),
858 }
859 });
860
861 let expected_viewport = create_viewport(100.0, 200.0);
863 assert_eq!(mouse_handler.inner().viewport, Some(expected_viewport));
864 }
865
866 fn wheel_delta_ticks(
867 ticks: i64,
868 physical_pixel: Option<f32>,
869 ) -> Option<mouse_binding::WheelDelta> {
870 Some(mouse_binding::WheelDelta {
871 raw_data: mouse_binding::RawWheelDelta::Ticks(ticks),
872 physical_pixel,
873 })
874 }
875
876 fn wheel_delta_mm(mm: f32, physical_pixel: Option<f32>) -> Option<mouse_binding::WheelDelta> {
877 Some(mouse_binding::WheelDelta {
878 raw_data: mouse_binding::RawWheelDelta::Millimeters(mm),
879 physical_pixel,
880 })
881 }
882
883 #[test_case(
886 mouse_binding::MouseLocation::Relative(
887 mouse_binding::RelativeLocation {
888 millimeters: Position { x: 1.0, y: 2.0 }
889 }),
890 Position {
891 x: DISPLAY_WIDTH_IN_PHYSICAL_PX / 2.0
892 + 1.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
893 y: DISPLAY_HEIGHT_IN_PHYSICAL_PX / 2.0
894 + 2.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
895 },
896 [
897 1.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
898 2.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
899 ]; "Valid move event."
900 )]
901 #[test_case(
902 mouse_binding::MouseLocation::Relative(
903 mouse_binding::RelativeLocation {
904 millimeters: Position {
905 x: DISPLAY_WIDTH_IN_PHYSICAL_PX / MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL + 2.0,
906 y: DISPLAY_HEIGHT_IN_PHYSICAL_PX / MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL + 1.0,
907 }}),
908 Position {
909 x: DISPLAY_WIDTH_IN_PHYSICAL_PX,
910 y: DISPLAY_HEIGHT_IN_PHYSICAL_PX,
911 },
912 [
913 DISPLAY_WIDTH_IN_PHYSICAL_PX + 2.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
914 DISPLAY_HEIGHT_IN_PHYSICAL_PX + 1.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
915 ]; "Move event exceeds max bounds."
916 )]
917 #[test_case(
918 mouse_binding::MouseLocation::Relative(
919 mouse_binding::RelativeLocation {
920 millimeters: Position {
921 x: -(DISPLAY_WIDTH_IN_PHYSICAL_PX / MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL + 2.0),
922 y: -(DISPLAY_HEIGHT_IN_PHYSICAL_PX / MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL + 1.0),
923 }}),
924 Position { x: 0.0, y: 0.0 },
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 min bounds."
929 )]
930 #[fuchsia::test(allow_stalls = false)]
931 async fn move_event(
932 move_location: mouse_binding::MouseLocation,
933 expected_position: Position,
934 expected_relative_motion: [f32; 2],
935 ) {
936 let (configuration_proxy, mut configuration_request_stream) =
938 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
939 let (injector_registry_proxy, injector_registry_request_stream) =
940 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
941 let config_request_stream_fut =
942 handle_configuration_request_stream(&mut configuration_request_stream);
943
944 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
946 let inspector = fuchsia_inspect::Inspector::default();
947 let test_node = inspector.root().create_child("test_node");
948 let mouse_handler_fut = MouseInjectorHandler::new_handler(
949 configuration_proxy,
950 injector_registry_proxy,
951 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
952 sender,
953 &test_node,
954 metrics::MetricsLogger::default(),
955 );
956 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
957 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
958
959 let event_time = zx::MonotonicInstant::get();
960 let input_event = create_mouse_event(
961 move_location,
962 None, None, None, mouse_binding::MousePhase::Move,
966 HashSet::new(),
967 HashSet::new(),
968 event_time,
969 &DESCRIPTOR,
970 );
971
972 let handle_event_fut = mouse_handler.handle_input_event(input_event);
974 let expected_events = vec![
975 create_mouse_pointer_sample_event_phase_add(vec![], expected_position, event_time),
976 create_mouse_pointer_sample_event(
977 pointerinjector::EventPhase::Change,
978 vec![],
979 expected_position,
980 Some(expected_relative_motion),
981 None, None, None, event_time,
985 ),
986 ];
987
988 let (injector_stream_sender, injector_stream_receiver) =
992 futures::channel::oneshot::channel::<pointerinjector::DeviceRequestStream>();
993 let registry_fut = handle_registry_request_stream(
994 injector_registry_request_stream,
995 injector_stream_sender,
996 );
997 let device_fut = handle_device_request_stream(injector_stream_receiver, expected_events);
998
999 let (handle_result, _, _) = futures::join!(handle_event_fut, registry_fut, device_fut);
1002 match receiver.next().await {
1003 Some(CursorMessage::SetPosition(position)) => {
1004 pretty_assertions::assert_eq!(position, expected_position);
1005 }
1006 Some(CursorMessage::SetVisibility(_)) => {
1007 panic!("Received unexpected cursor visibility update.")
1008 }
1009 None => panic!("Did not receive cursor update."),
1010 }
1011
1012 assert_matches!(
1014 handle_result.as_slice(),
1015 [input_device::InputEvent { handled: input_device::Handled::Yes, .. }]
1016 );
1017 }
1018
1019 #[fuchsia::test(allow_stalls = false)]
1022 async fn move_absolute_event() {
1023 const DEVICE_ID: u32 = 1;
1024
1025 let (configuration_proxy, mut configuration_request_stream) =
1027 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1028 let (injector_registry_proxy, injector_registry_request_stream) =
1029 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1030 let config_request_stream_fut =
1031 handle_configuration_request_stream(&mut configuration_request_stream);
1032
1033 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
1035 let inspector = fuchsia_inspect::Inspector::default();
1036 let test_node = inspector.root().create_child("test_node");
1037 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1038 configuration_proxy,
1039 injector_registry_proxy,
1040 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1041 sender,
1042 &test_node,
1043 metrics::MetricsLogger::default(),
1044 );
1045 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1046 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1047
1048 let cursor_location =
1064 mouse_binding::MouseLocation::Absolute(Position { x: -25.0, y: 25.0 });
1065 let event_time = zx::MonotonicInstant::get();
1066 let descriptor =
1067 input_device::InputDeviceDescriptor::Mouse(mouse_binding::MouseDeviceDescriptor {
1068 device_id: DEVICE_ID,
1069 absolute_x_range: Some(fidl_input_report::Range { min: -50, max: 50 }),
1070 absolute_y_range: Some(fidl_input_report::Range { min: -50, max: 50 }),
1071 wheel_v_range: None,
1072 wheel_h_range: None,
1073 buttons: None,
1074 counts_per_mm: COUNTS_PER_MM,
1075 });
1076 let input_event = create_mouse_event(
1077 cursor_location,
1078 None, None, None, mouse_binding::MousePhase::Move,
1082 HashSet::new(),
1083 HashSet::new(),
1084 event_time,
1085 &descriptor,
1086 );
1087
1088 let handle_event_fut = mouse_handler.handle_input_event(input_event);
1090 let expected_position = Position {
1091 x: DISPLAY_WIDTH_IN_PHYSICAL_PX * 0.25,
1092 y: DISPLAY_WIDTH_IN_PHYSICAL_PX * 0.75,
1093 };
1094 let expected_events = vec![
1095 create_mouse_pointer_sample_event_phase_add(vec![], expected_position, event_time),
1096 create_mouse_pointer_sample_event(
1097 pointerinjector::EventPhase::Change,
1098 vec![],
1099 expected_position,
1100 None, None, None, None, event_time,
1105 ),
1106 ];
1107
1108 let (injector_stream_sender, injector_stream_receiver) =
1112 futures::channel::oneshot::channel::<pointerinjector::DeviceRequestStream>();
1113 let registry_fut = handle_registry_request_stream(
1114 injector_registry_request_stream,
1115 injector_stream_sender,
1116 );
1117 let device_fut = handle_device_request_stream(injector_stream_receiver, expected_events);
1118
1119 let (handle_result, _, _) = futures::join!(handle_event_fut, registry_fut, device_fut);
1122 match receiver.next().await {
1123 Some(CursorMessage::SetPosition(position)) => {
1124 assert_eq!(position, expected_position);
1125 }
1126 Some(CursorMessage::SetVisibility(_)) => {
1127 panic!("Received unexpected cursor visibility update.")
1128 }
1129 None => panic!("Did not receive cursor update."),
1130 }
1131
1132 assert_matches!(
1134 handle_result.as_slice(),
1135 [input_device::InputEvent { handled: input_device::Handled::Yes, .. }]
1136 );
1137 }
1138
1139 #[test_case(
1141 mouse_binding::MousePhase::Down,
1142 vec![1], vec![1]; "Down event injects button press state."
1143 )]
1144 #[test_case(
1145 mouse_binding::MousePhase::Up,
1146 vec![1], vec![]; "Up event injects button press state."
1147 )]
1148 #[fuchsia::test(allow_stalls = false)]
1149 async fn button_state_event(
1150 phase: mouse_binding::MousePhase,
1151 affected_buttons: Vec<mouse_binding::MouseButton>,
1152 pressed_buttons: Vec<mouse_binding::MouseButton>,
1153 ) {
1154 let (configuration_proxy, mut configuration_request_stream) =
1156 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1157 let (injector_registry_proxy, injector_registry_request_stream) =
1158 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1159 let config_request_stream_fut =
1160 handle_configuration_request_stream(&mut configuration_request_stream);
1161
1162 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
1164 let inspector = fuchsia_inspect::Inspector::default();
1165 let test_node = inspector.root().create_child("test_node");
1166 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1167 configuration_proxy,
1168 injector_registry_proxy,
1169 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1170 sender,
1171 &test_node,
1172 metrics::MetricsLogger::default(),
1173 );
1174 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1175 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1176
1177 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
1178 let event_time = zx::MonotonicInstant::get();
1179
1180 let input_event = create_mouse_event(
1181 cursor_location,
1182 None, None, None, phase,
1186 HashSet::from_iter(affected_buttons.clone()),
1187 HashSet::from_iter(pressed_buttons.clone()),
1188 event_time,
1189 &DESCRIPTOR,
1190 );
1191
1192 let handle_event_fut = mouse_handler.handle_input_event(input_event);
1194 let expected_position = Position { x: 0.0, y: 0.0 };
1195 let expected_events = vec![
1196 create_mouse_pointer_sample_event_phase_add(
1197 pressed_buttons.clone(),
1198 expected_position,
1199 event_time,
1200 ),
1201 create_mouse_pointer_sample_event(
1202 pointerinjector::EventPhase::Change,
1203 pressed_buttons.clone(),
1204 expected_position,
1205 None, None, None, None, event_time,
1210 ),
1211 ];
1212
1213 let (injector_stream_sender, injector_stream_receiver) =
1217 futures::channel::oneshot::channel::<pointerinjector::DeviceRequestStream>();
1218 let registry_fut = handle_registry_request_stream(
1219 injector_registry_request_stream,
1220 injector_stream_sender,
1221 );
1222 let device_fut = handle_device_request_stream(injector_stream_receiver, expected_events);
1223
1224 let (handle_result, _, _) = futures::join!(handle_event_fut, registry_fut, device_fut);
1227 match receiver.next().await {
1228 Some(CursorMessage::SetPosition(position)) => {
1229 pretty_assertions::assert_eq!(position, expected_position);
1230 }
1231 Some(CursorMessage::SetVisibility(_)) => {
1232 panic!("Received unexpected cursor visibility update.")
1233 }
1234 None => panic!("Did not receive cursor update."),
1235 }
1236
1237 assert_matches!(
1239 handle_result.as_slice(),
1240 [input_device::InputEvent { handled: input_device::Handled::Yes, .. }]
1241 );
1242 }
1243
1244 #[fuchsia::test(allow_stalls = false)]
1246 async fn down_up_event() {
1247 let (configuration_proxy, mut configuration_request_stream) =
1249 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1250 let (injector_registry_proxy, injector_registry_request_stream) =
1251 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1252 let config_request_stream_fut =
1253 handle_configuration_request_stream(&mut configuration_request_stream);
1254
1255 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(2);
1259 let inspector = fuchsia_inspect::Inspector::default();
1260 let test_node = inspector.root().create_child("test_node");
1261 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1262 configuration_proxy,
1263 injector_registry_proxy,
1264 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1265 sender,
1266 &test_node,
1267 metrics::MetricsLogger::default(),
1268 );
1269 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1270 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1271
1272 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
1273 let event_time1 = zx::MonotonicInstant::get();
1274 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
1275
1276 let event1 = create_mouse_event(
1277 cursor_location,
1278 None, None, None, mouse_binding::MousePhase::Down,
1282 HashSet::from_iter(vec![1]),
1283 HashSet::from_iter(vec![1]),
1284 event_time1,
1285 &DESCRIPTOR,
1286 );
1287
1288 let event2 = create_mouse_event(
1289 cursor_location,
1290 None, None, None, mouse_binding::MousePhase::Up,
1294 HashSet::from_iter(vec![1]),
1295 HashSet::new(),
1296 event_time2,
1297 &DESCRIPTOR,
1298 );
1299
1300 let expected_position = Position { x: 0.0, y: 0.0 };
1301
1302 let (injector_stream_sender, injector_stream_receiver) =
1306 mpsc::unbounded::<Vec<pointerinjector::Event>>();
1307 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
1309 let registry_fut = handle_registry_request_stream2(
1310 injector_registry_request_stream,
1311 injector_stream_sender,
1312 );
1313
1314 let _registry_task = fasync::Task::local(registry_fut);
1316
1317 mouse_handler.clone().handle_input_event(event1).await;
1318 assert_eq!(
1319 injector_stream_receiver
1320 .next()
1321 .await
1322 .map(|events| events.into_iter().flatten().collect()),
1323 Some(vec![
1324 create_mouse_pointer_sample_event_phase_add(
1325 vec![1],
1326 expected_position,
1327 event_time1,
1328 ),
1329 create_mouse_pointer_sample_event(
1330 pointerinjector::EventPhase::Change,
1331 vec![1],
1332 expected_position,
1333 None, None, None, None, event_time1,
1338 )
1339 ])
1340 );
1341
1342 mouse_handler.clone().handle_input_event(event2).await;
1344 assert_eq!(
1345 injector_stream_receiver
1346 .next()
1347 .await
1348 .map(|events| events.into_iter().flatten().collect()),
1349 Some(vec![create_mouse_pointer_sample_event(
1350 pointerinjector::EventPhase::Change,
1351 vec![],
1352 expected_position,
1353 None, None, None, None, event_time2,
1358 )])
1359 );
1360
1361 match receiver.next().await {
1363 Some(CursorMessage::SetPosition(position)) => {
1364 assert_eq!(position, expected_position);
1365 }
1366 Some(CursorMessage::SetVisibility(_)) => {
1367 panic!("Received unexpected cursor visibility update.")
1368 }
1369 None => panic!("Did not receive cursor update."),
1370 }
1371 }
1372
1373 #[fuchsia::test(allow_stalls = false)]
1383 async fn down_down_up_up_event() {
1384 let (configuration_proxy, mut configuration_request_stream) =
1386 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1387 let (injector_registry_proxy, injector_registry_request_stream) =
1388 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1389 let config_request_stream_fut =
1390 handle_configuration_request_stream(&mut configuration_request_stream);
1391
1392 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(4);
1396 let inspector = fuchsia_inspect::Inspector::default();
1397 let test_node = inspector.root().create_child("test_node");
1398 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1399 configuration_proxy,
1400 injector_registry_proxy,
1401 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1402 sender,
1403 &test_node,
1404 metrics::MetricsLogger::default(),
1405 );
1406 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1407 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1408
1409 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
1410 let event_time1 = zx::MonotonicInstant::get();
1411 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
1412 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
1413 let event_time4 = event_time3.add(zx::MonotonicDuration::from_micros(1));
1414
1415 let event1 = create_mouse_event(
1416 cursor_location,
1417 None, None, None, mouse_binding::MousePhase::Down,
1421 HashSet::from_iter(vec![1]),
1422 HashSet::from_iter(vec![1]),
1423 event_time1,
1424 &DESCRIPTOR,
1425 );
1426 let event2 = create_mouse_event(
1427 cursor_location,
1428 None, None, None, mouse_binding::MousePhase::Down,
1432 HashSet::from_iter(vec![2]),
1433 HashSet::from_iter(vec![1, 2]),
1434 event_time2,
1435 &DESCRIPTOR,
1436 );
1437 let event3 = create_mouse_event(
1438 cursor_location,
1439 None, None, None, mouse_binding::MousePhase::Up,
1443 HashSet::from_iter(vec![1]),
1444 HashSet::from_iter(vec![2]),
1445 event_time3,
1446 &DESCRIPTOR,
1447 );
1448 let event4 = create_mouse_event(
1449 cursor_location,
1450 None, None, None, mouse_binding::MousePhase::Up,
1454 HashSet::from_iter(vec![2]),
1455 HashSet::new(),
1456 event_time4,
1457 &DESCRIPTOR,
1458 );
1459
1460 let expected_position = Position { x: 0.0, y: 0.0 };
1461
1462 let (injector_stream_sender, injector_stream_receiver) =
1466 mpsc::unbounded::<Vec<pointerinjector::Event>>();
1467 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
1469 let registry_fut = handle_registry_request_stream2(
1470 injector_registry_request_stream,
1471 injector_stream_sender,
1472 );
1473
1474 let _registry_task = fasync::Task::local(registry_fut);
1476 mouse_handler.clone().handle_input_event(event1).await;
1477 assert_eq!(
1478 injector_stream_receiver
1479 .next()
1480 .await
1481 .map(|events| events.into_iter().flatten().collect()),
1482 Some(vec![
1483 create_mouse_pointer_sample_event_phase_add(
1484 vec![1],
1485 expected_position,
1486 event_time1,
1487 ),
1488 create_mouse_pointer_sample_event(
1489 pointerinjector::EventPhase::Change,
1490 vec![1],
1491 expected_position,
1492 None, None, None, None, event_time1,
1497 )
1498 ])
1499 );
1500
1501 mouse_handler.clone().handle_input_event(event2).await;
1503 let pointer_sample_event2: Vec<_> = injector_stream_receiver
1504 .next()
1505 .await
1506 .map(|events| events.into_iter().flatten().collect())
1507 .expect("Failed to receive pointer sample event.");
1508 let expected_event_time: i64 = event_time2.into_nanos();
1509 assert_eq!(pointer_sample_event2.len(), 1);
1510
1511 match &pointer_sample_event2[0] {
1514 pointerinjector::Event {
1515 timestamp: Some(actual_event_time),
1516 data:
1517 Some(pointerinjector::Data::PointerSample(pointerinjector::PointerSample {
1518 pointer_id: Some(0),
1519 phase: Some(pointerinjector::EventPhase::Change),
1520 position_in_viewport: Some(actual_position),
1521 scroll_v: None,
1522 scroll_h: None,
1523 pressed_buttons: Some(actual_buttons),
1524 relative_motion: None,
1525 ..
1526 })),
1527 ..
1528 } => {
1529 assert_eq!(*actual_event_time, expected_event_time);
1530 assert_eq!(actual_position[0], expected_position.x);
1531 assert_eq!(actual_position[1], expected_position.y);
1532 assert_eq!(
1533 HashSet::<mouse_binding::MouseButton>::from_iter(actual_buttons.clone()),
1534 HashSet::from_iter(vec![1, 2])
1535 );
1536 }
1537 _ => panic!("Unexpected pointer sample event: {:?}", pointer_sample_event2[0]),
1538 }
1539
1540 mouse_handler.clone().handle_input_event(event3).await;
1542 assert_eq!(
1543 injector_stream_receiver
1544 .next()
1545 .await
1546 .map(|events| events.into_iter().flatten().collect()),
1547 Some(vec![create_mouse_pointer_sample_event(
1548 pointerinjector::EventPhase::Change,
1549 vec![2],
1550 expected_position,
1551 None, None, None, None, event_time3,
1556 )])
1557 );
1558
1559 mouse_handler.clone().handle_input_event(event4).await;
1561 assert_eq!(
1562 injector_stream_receiver
1563 .next()
1564 .await
1565 .map(|events| events.into_iter().flatten().collect()),
1566 Some(vec![create_mouse_pointer_sample_event(
1567 pointerinjector::EventPhase::Change,
1568 vec![],
1569 expected_position,
1570 None, None, None, None, event_time4,
1575 )])
1576 );
1577
1578 match receiver.next().await {
1580 Some(CursorMessage::SetPosition(position)) => {
1581 assert_eq!(position, expected_position);
1582 }
1583 Some(CursorMessage::SetVisibility(_)) => {
1584 panic!("Received unexpected cursor visibility update.")
1585 }
1586 None => panic!("Did not receive cursor update."),
1587 }
1588 }
1589
1590 #[fuchsia::test(allow_stalls = false)]
1592 async fn down_move_up_event() {
1593 let (configuration_proxy, mut configuration_request_stream) =
1595 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1596 let (injector_registry_proxy, injector_registry_request_stream) =
1597 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1598 let config_request_stream_fut =
1599 handle_configuration_request_stream(&mut configuration_request_stream);
1600
1601 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(3);
1605 let inspector = fuchsia_inspect::Inspector::default();
1606 let test_node = inspector.root().create_child("test_node");
1607 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1608 configuration_proxy,
1609 injector_registry_proxy,
1610 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1611 sender,
1612 &test_node,
1613 metrics::MetricsLogger::default(),
1614 );
1615 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1616 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1617
1618 let event_time1 = zx::MonotonicInstant::get();
1619 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
1620 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
1621 let zero_position = Position { x: 0.0, y: 0.0 };
1622 let expected_position = Position {
1623 x: 10.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
1624 y: 5.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
1625 };
1626 let expected_relative_motion = [
1627 10.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
1628 5.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
1629 ];
1630 let event1 = create_mouse_event(
1631 mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 }),
1632 None, None, None, mouse_binding::MousePhase::Down,
1636 HashSet::from_iter(vec![1]),
1637 HashSet::from_iter(vec![1]),
1638 event_time1,
1639 &DESCRIPTOR,
1640 );
1641 let event2 = create_mouse_event(
1642 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1643 millimeters: Position { x: 10.0, y: 5.0 },
1644 }),
1645 None, None, None, mouse_binding::MousePhase::Move,
1649 HashSet::from_iter(vec![1]),
1650 HashSet::from_iter(vec![1]),
1651 event_time2,
1652 &DESCRIPTOR,
1653 );
1654 let event3 = create_mouse_event(
1655 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1656 millimeters: Position { x: 0.0, y: 0.0 },
1657 }),
1658 None, None, None, mouse_binding::MousePhase::Up,
1662 HashSet::from_iter(vec![1]),
1663 HashSet::from_iter(vec![]),
1664 event_time3,
1665 &DESCRIPTOR,
1666 );
1667
1668 let (injector_stream_sender, injector_stream_receiver) =
1672 mpsc::unbounded::<Vec<pointerinjector::Event>>();
1673 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
1675 let registry_fut = handle_registry_request_stream2(
1676 injector_registry_request_stream,
1677 injector_stream_sender,
1678 );
1679
1680 let _registry_task = fasync::Task::local(registry_fut);
1682 mouse_handler.clone().handle_input_event(event1).await;
1683 assert_eq!(
1684 injector_stream_receiver
1685 .next()
1686 .await
1687 .map(|events| events.into_iter().flatten().collect()),
1688 Some(vec![
1689 create_mouse_pointer_sample_event_phase_add(vec![1], zero_position, event_time1,),
1690 create_mouse_pointer_sample_event(
1691 pointerinjector::EventPhase::Change,
1692 vec![1],
1693 zero_position,
1694 None, None, None, None, event_time1,
1699 )
1700 ])
1701 );
1702
1703 match receiver.next().await {
1705 Some(CursorMessage::SetPosition(position)) => {
1706 assert_eq!(position, zero_position);
1707 }
1708 Some(CursorMessage::SetVisibility(_)) => {
1709 panic!("Received unexpected cursor visibility update.")
1710 }
1711 None => panic!("Did not receive cursor update."),
1712 }
1713
1714 mouse_handler.clone().handle_input_event(event2).await;
1716 assert_eq!(
1717 injector_stream_receiver
1718 .next()
1719 .await
1720 .map(|events| events.into_iter().flatten().collect()),
1721 Some(vec![create_mouse_pointer_sample_event(
1722 pointerinjector::EventPhase::Change,
1723 vec![1],
1724 expected_position,
1725 Some(expected_relative_motion),
1726 None, None, None, event_time2,
1730 )])
1731 );
1732
1733 match receiver.next().await {
1735 Some(CursorMessage::SetPosition(position)) => {
1736 assert_eq!(position, expected_position);
1737 }
1738 Some(CursorMessage::SetVisibility(_)) => {
1739 panic!("Received unexpected cursor visibility update.")
1740 }
1741 None => panic!("Did not receive cursor update."),
1742 }
1743
1744 mouse_handler.clone().handle_input_event(event3).await;
1746 assert_eq!(
1747 injector_stream_receiver
1748 .next()
1749 .await
1750 .map(|events| events.into_iter().flatten().collect()),
1751 Some(vec![create_mouse_pointer_sample_event(
1752 pointerinjector::EventPhase::Change,
1753 vec![],
1754 expected_position,
1755 None, None, None, None, event_time3,
1760 )])
1761 );
1762
1763 match receiver.next().await {
1765 Some(CursorMessage::SetPosition(position)) => {
1766 assert_eq!(position, expected_position);
1767 }
1768 Some(CursorMessage::SetVisibility(_)) => {
1769 panic!("Received unexpected cursor visibility update.")
1770 }
1771 None => panic!("Did not receive cursor update."),
1772 }
1773 }
1774
1775 #[fuchsia::test(allow_stalls = false)]
1777 async fn handler_ignores_handled_events() {
1778 let (configuration_proxy, mut configuration_request_stream) =
1780 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1781 let (injector_registry_proxy, injector_registry_request_stream) =
1782 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1783 let config_request_stream_fut =
1784 handle_configuration_request_stream(&mut configuration_request_stream);
1785
1786 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
1788 let inspector = fuchsia_inspect::Inspector::default();
1789 let test_node = inspector.root().create_child("test_node");
1790 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1791 configuration_proxy,
1792 injector_registry_proxy,
1793 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1794 sender,
1795 &test_node,
1796 metrics::MetricsLogger::default(),
1797 );
1798 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1799 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1800
1801 let cursor_relative_position = Position { x: 50.0, y: 75.0 };
1802 let cursor_location =
1803 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1804 millimeters: Position {
1805 x: cursor_relative_position.x / COUNTS_PER_MM as f32,
1806 y: cursor_relative_position.y / COUNTS_PER_MM as f32,
1807 },
1808 });
1809 let event_time = zx::MonotonicInstant::get();
1810 let input_events = vec![create_mouse_event_with_handled(
1811 cursor_location,
1812 None, None, None, mouse_binding::MousePhase::Move,
1816 HashSet::new(),
1817 HashSet::new(),
1818 event_time,
1819 &DESCRIPTOR,
1820 input_device::Handled::Yes,
1821 )];
1822
1823 assert_handler_ignores_input_event_sequence(
1824 mouse_handler,
1825 input_events,
1826 injector_registry_request_stream,
1827 )
1828 .await;
1829
1830 assert!(receiver.next().await.is_none());
1832 }
1833
1834 fn zero_relative_location() -> mouse_binding::MouseLocation {
1835 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1836 millimeters: Position { x: 0.0, y: 0.0 },
1837 })
1838 }
1839
1840 #[test_case(
1841 create_mouse_event(
1842 zero_relative_location(),
1843 wheel_delta_ticks(1, None), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1847 HashSet::new(),
1848 HashSet::new(),
1849 zx::MonotonicInstant::ZERO,
1850 &DESCRIPTOR,
1851 ),
1852 create_mouse_pointer_sample_event(
1853 pointerinjector::EventPhase::Change,
1854 vec![],
1855 Position { x: 50.0, y: 50.0 },
1856 None, Some(1), None, Some(false), zx::MonotonicInstant::ZERO,
1861 ); "v tick scroll"
1862 )]
1863 #[test_case(
1864 create_mouse_event(
1865 zero_relative_location(),
1866 None, wheel_delta_ticks(1, None), Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1870 HashSet::new(),
1871 HashSet::new(),
1872 zx::MonotonicInstant::ZERO,
1873 &DESCRIPTOR,
1874 ),
1875 create_mouse_pointer_sample_event(
1876 pointerinjector::EventPhase::Change,
1877 vec![],
1878 Position { x: 50.0, y: 50.0 },
1879 None, None, Some(1), Some(false), zx::MonotonicInstant::ZERO,
1884 ); "h tick scroll"
1885 )]
1886 #[test_case(
1887 create_mouse_event(
1888 zero_relative_location(),
1889 wheel_delta_ticks(1, Some(120.0)), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1893 HashSet::new(),
1894 HashSet::new(),
1895 zx::MonotonicInstant::ZERO,
1896 &DESCRIPTOR,
1897 ),
1898 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
1899 pointerinjector::EventPhase::Change,
1900 vec![],
1901 Position { x: 50.0, y: 50.0 },
1902 None, Some(1), None, Some(120.0), None, Some(false), zx::MonotonicInstant::ZERO,
1909 ); "v tick scroll with physical pixel"
1910 )]
1911 #[test_case(
1912 create_mouse_event(
1913 zero_relative_location(),
1914 None, wheel_delta_ticks(1, Some(120.0)), Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1918 HashSet::new(),
1919 HashSet::new(),
1920 zx::MonotonicInstant::ZERO,
1921 &DESCRIPTOR,
1922 ),
1923 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
1924 pointerinjector::EventPhase::Change,
1925 vec![],
1926 Position { x: 50.0, y: 50.0 },
1927 None, None, Some(1), None, Some(120.0), Some(false), zx::MonotonicInstant::ZERO,
1934 ); "h tick scroll with physical pixel"
1935 )]
1936 #[test_case(
1937 create_mouse_event(
1938 zero_relative_location(),
1939 wheel_delta_mm(1.0, Some(120.0)), None, Some(mouse_binding::PrecisionScroll::Yes), mouse_binding::MousePhase::Wheel,
1943 HashSet::new(),
1944 HashSet::new(),
1945 zx::MonotonicInstant::ZERO,
1946 &DESCRIPTOR,
1947 ),
1948 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
1949 pointerinjector::EventPhase::Change,
1950 vec![],
1951 Position { x: 50.0, y: 50.0 },
1952 None, None, None, Some(120.0), None, Some(true), zx::MonotonicInstant::ZERO,
1959 ); "v mm scroll with physical pixel"
1960 )]
1961 #[test_case(
1962 create_mouse_event(
1963 zero_relative_location(),
1964 None, wheel_delta_mm(1.0, Some(120.0)), Some(mouse_binding::PrecisionScroll::Yes), mouse_binding::MousePhase::Wheel,
1968 HashSet::new(),
1969 HashSet::new(),
1970 zx::MonotonicInstant::ZERO,
1971 &DESCRIPTOR,
1972 ),
1973 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
1974 pointerinjector::EventPhase::Change,
1975 vec![],
1976 Position { x: 50.0, y: 50.0 },
1977 None, None, None, None, Some(120.0), Some(true), zx::MonotonicInstant::ZERO,
1984 ); "h mm scroll with physical pixel"
1985 )]
1986 #[fuchsia::test(allow_stalls = false)]
1988 async fn scroll(event: input_device::InputEvent, want_event: pointerinjector::Event) {
1989 let (configuration_proxy, mut configuration_request_stream) =
1991 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1992 let (injector_registry_proxy, injector_registry_request_stream) =
1993 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1994 let config_request_stream_fut =
1995 handle_configuration_request_stream(&mut configuration_request_stream);
1996
1997 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
1999 let inspector = fuchsia_inspect::Inspector::default();
2000 let test_node = inspector.root().create_child("test_node");
2001 let mouse_handler_fut = MouseInjectorHandler::new_handler(
2002 configuration_proxy,
2003 injector_registry_proxy,
2004 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
2005 sender,
2006 &test_node,
2007 metrics::MetricsLogger::default(),
2008 );
2009 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
2010 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
2011
2012 let (injector_stream_sender, injector_stream_receiver) =
2016 mpsc::unbounded::<Vec<pointerinjector::Event>>();
2017 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
2019 let registry_fut = handle_registry_request_stream2(
2020 injector_registry_request_stream,
2021 injector_stream_sender,
2022 );
2023
2024 let event_time = zx::MonotonicInstant::get();
2025
2026 let event = input_device::InputEvent { event_time, ..event };
2027
2028 let want_event =
2029 pointerinjector::Event { timestamp: Some(event_time.into_nanos()), ..want_event };
2030
2031 let _registry_task = fasync::Task::local(registry_fut);
2033
2034 mouse_handler.clone().handle_input_event(event).await;
2035 let got_events: Vec<_> = injector_stream_receiver
2036 .next()
2037 .await
2038 .map(|events| events.into_iter().flatten().collect())
2039 .unwrap();
2040 pretty_assertions::assert_eq!(got_events.len(), 2);
2041 assert_matches!(
2042 got_events[0],
2043 pointerinjector::Event {
2044 data: Some(pointerinjector::Data::PointerSample(pointerinjector::PointerSample {
2045 phase: Some(pointerinjector::EventPhase::Add),
2046 ..
2047 })),
2048 ..
2049 }
2050 );
2051
2052 pretty_assertions::assert_eq!(got_events[1], want_event);
2053 }
2054
2055 #[fuchsia::test(allow_stalls = false)]
2057 async fn down_scroll_up_scroll() {
2058 let (configuration_proxy, mut configuration_request_stream) =
2060 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
2061 let (injector_registry_proxy, injector_registry_request_stream) =
2062 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
2063 let config_request_stream_fut =
2064 handle_configuration_request_stream(&mut configuration_request_stream);
2065
2066 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
2068 let inspector = fuchsia_inspect::Inspector::default();
2069 let test_node = inspector.root().create_child("test_node");
2070 let mouse_handler_fut = MouseInjectorHandler::new_handler(
2071 configuration_proxy,
2072 injector_registry_proxy,
2073 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
2074 sender,
2075 &test_node,
2076 metrics::MetricsLogger::default(),
2077 );
2078 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
2079 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
2080
2081 let (injector_stream_sender, injector_stream_receiver) =
2085 mpsc::unbounded::<Vec<pointerinjector::Event>>();
2086 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
2088 let registry_fut = handle_registry_request_stream2(
2089 injector_registry_request_stream,
2090 injector_stream_sender,
2091 );
2092
2093 let event_time1 = zx::MonotonicInstant::get();
2094 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
2095 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
2096 let event_time4 = event_time3.add(zx::MonotonicDuration::from_micros(1));
2097
2098 let _registry_task = fasync::Task::local(registry_fut);
2100
2101 let zero_location =
2102 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
2103 millimeters: Position { x: 0.0, y: 0.0 },
2104 });
2105 let expected_position = Position { x: 50.0, y: 50.0 };
2106
2107 let down_event = create_mouse_event(
2108 zero_location,
2109 None, None, None, mouse_binding::MousePhase::Down,
2113 HashSet::from_iter(vec![1]),
2114 HashSet::from_iter(vec![1]),
2115 event_time1,
2116 &DESCRIPTOR,
2117 );
2118
2119 let wheel_event = create_mouse_event(
2120 zero_location,
2121 wheel_delta_ticks(1, None), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
2125 HashSet::from_iter(vec![1]),
2126 HashSet::from_iter(vec![1]),
2127 event_time2,
2128 &DESCRIPTOR,
2129 );
2130
2131 let up_event = create_mouse_event(
2132 zero_location,
2133 None,
2134 None,
2135 None, mouse_binding::MousePhase::Up,
2137 HashSet::from_iter(vec![1]),
2138 HashSet::new(),
2139 event_time3,
2140 &DESCRIPTOR,
2141 );
2142
2143 let continue_wheel_event = create_mouse_event(
2144 zero_location,
2145 wheel_delta_ticks(1, None), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
2149 HashSet::new(),
2150 HashSet::new(),
2151 event_time4,
2152 &DESCRIPTOR,
2153 );
2154
2155 mouse_handler.clone().handle_input_event(down_event).await;
2157 assert_eq!(
2158 injector_stream_receiver
2159 .next()
2160 .await
2161 .map(|events| events.into_iter().flatten().collect()),
2162 Some(vec![
2163 create_mouse_pointer_sample_event_phase_add(
2164 vec![1],
2165 expected_position,
2166 event_time1,
2167 ),
2168 create_mouse_pointer_sample_event(
2169 pointerinjector::EventPhase::Change,
2170 vec![1],
2171 expected_position,
2172 None, None, None, None, event_time1,
2177 ),
2178 ])
2179 );
2180
2181 mouse_handler.clone().handle_input_event(wheel_event).await;
2183 assert_eq!(
2184 injector_stream_receiver
2185 .next()
2186 .await
2187 .map(|events| events.into_iter().flatten().collect()),
2188 Some(vec![create_mouse_pointer_sample_event(
2189 pointerinjector::EventPhase::Change,
2190 vec![1],
2191 expected_position,
2192 None, Some(1), None, Some(false), event_time2,
2197 )])
2198 );
2199
2200 mouse_handler.clone().handle_input_event(up_event).await;
2202 assert_eq!(
2203 injector_stream_receiver
2204 .next()
2205 .await
2206 .map(|events| events.into_iter().flatten().collect()),
2207 Some(vec![create_mouse_pointer_sample_event(
2208 pointerinjector::EventPhase::Change,
2209 vec![],
2210 expected_position,
2211 None, None, None, None, event_time3,
2216 )])
2217 );
2218
2219 mouse_handler.clone().handle_input_event(continue_wheel_event).await;
2221 assert_eq!(
2222 injector_stream_receiver
2223 .next()
2224 .await
2225 .map(|events| events.into_iter().flatten().collect()),
2226 Some(vec![create_mouse_pointer_sample_event(
2227 pointerinjector::EventPhase::Change,
2228 vec![],
2229 expected_position,
2230 None, Some(1), None, Some(false), event_time4,
2235 )])
2236 );
2237 }
2238
2239 #[fuchsia::test(allow_stalls = false)]
2240 async fn mouse_injector_handler_initialized_with_inspect_node() {
2241 let (configuration_proxy, mut configuration_request_stream) =
2242 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
2243 let config_request_stream_fut =
2244 handle_configuration_request_stream(&mut configuration_request_stream);
2245 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
2246 let inspector = fuchsia_inspect::Inspector::default();
2247 let fake_handlers_node = inspector.root().create_child("input_handlers_node");
2248 let mouse_handler_fut = MouseInjectorHandler::new_with_config_proxy(
2249 configuration_proxy,
2250 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
2251 sender,
2252 &fake_handlers_node,
2253 metrics::MetricsLogger::default(),
2254 );
2255 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
2256 let _handler = mouse_handler_res.expect("Failed to create mouse handler");
2257
2258 diagnostics_assertions::assert_data_tree!(inspector, root: {
2259 input_handlers_node: {
2260 mouse_injector_handler: {
2261 events_received_count: 0u64,
2262 events_handled_count: 0u64,
2263 last_received_timestamp_ns: 0u64,
2264 "fuchsia.inspect.Health": {
2265 status: "STARTING_UP",
2266 start_timestamp_nanos: diagnostics_assertions::AnyProperty
2269 },
2270 }
2271 }
2272 });
2273 }
2274
2275 #[fuchsia::test(allow_stalls = false)]
2276 async fn mouse_injector_handler_inspect_counts_events() {
2277 let (configuration_proxy, mut configuration_request_stream) =
2279 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
2280 let (injector_registry_proxy, injector_registry_request_stream) =
2281 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
2282 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
2283
2284 let inspector = fuchsia_inspect::Inspector::default();
2285 let fake_handlers_node = inspector.root().create_child("input_handlers_node");
2286
2287 let mouse_handler_fut = MouseInjectorHandler::new_handler(
2289 configuration_proxy,
2290 injector_registry_proxy,
2291 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
2292 sender,
2293 &fake_handlers_node,
2294 metrics::MetricsLogger::default(),
2295 );
2296 let config_request_stream_fut =
2297 handle_configuration_request_stream(&mut configuration_request_stream);
2298
2299 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
2300 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
2301
2302 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
2303 let event_time1 = zx::MonotonicInstant::get();
2304 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
2305 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
2306
2307 let input_events = vec![
2308 create_mouse_event(
2309 cursor_location,
2310 None, None, None, mouse_binding::MousePhase::Down,
2314 HashSet::from_iter(vec![1]),
2315 HashSet::from_iter(vec![1]),
2316 event_time1,
2317 &DESCRIPTOR,
2318 ),
2319 create_mouse_event(
2320 cursor_location,
2321 None, None, None, mouse_binding::MousePhase::Up,
2325 HashSet::from_iter(vec![1]),
2326 HashSet::new(),
2327 event_time2,
2328 &DESCRIPTOR,
2329 ),
2330 create_mouse_event_with_handled(
2331 cursor_location,
2332 None, None, None, mouse_binding::MousePhase::Down,
2336 HashSet::from_iter(vec![1]),
2337 HashSet::from_iter(vec![1]),
2338 event_time3,
2339 &DESCRIPTOR,
2340 input_device::Handled::Yes,
2341 ),
2342 ];
2343
2344 let (injector_stream_sender, _) = mpsc::unbounded::<Vec<pointerinjector::Event>>();
2348 let registry_fut = handle_registry_request_stream2(
2349 injector_registry_request_stream,
2350 injector_stream_sender,
2351 );
2352
2353 let _registry_task = fasync::Task::local(registry_fut);
2355 for input_event in input_events {
2356 mouse_handler.clone().handle_input_event(input_event).await;
2357 }
2358
2359 let last_received_event_time: u64 = event_time2.into_nanos().try_into().unwrap();
2360
2361 diagnostics_assertions::assert_data_tree!(inspector, root: {
2362 input_handlers_node: {
2363 mouse_injector_handler: {
2364 events_received_count: 2u64,
2365 events_handled_count: 2u64,
2366 last_received_timestamp_ns: last_received_event_time,
2367 "fuchsia.inspect.Health": {
2368 status: "STARTING_UP",
2369 start_timestamp_nanos: diagnostics_assertions::AnyProperty
2372 },
2373 }
2374 }
2375 });
2376 }
2377}