1#![warn(clippy::await_holding_refcell_ref)]
6
7use crate::input_handler::{Handler, InputHandler, InputHandlerStatus};
8use crate::utils::{CursorMessage, Position, Size};
9use crate::{Incoming, MonotonicInstant, 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 fidl_fuchsia_ui_pointerinjector as pointerinjector;
16use fidl_fuchsia_ui_pointerinjector_configuration as pointerinjector_config;
17use fuchsia_inspect::health::Reporter;
18use futures::SinkExt;
19use futures::channel::mpsc::Sender;
20use futures::stream::StreamExt;
21use metrics_registry::*;
22use std::cell::{Ref, RefCell, RefMut};
23use std::collections::HashMap;
24use std::rc::Rc;
25
26const MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL: f32 = 10.0;
34
35pub struct MouseInjectorHandler {
38 mutable_state: RefCell<MutableState>,
40
41 context_view_ref: fidl_fuchsia_ui_views::ViewRef,
44
45 target_view_ref: fidl_fuchsia_ui_views::ViewRef,
48
49 max_position: Position,
52
53 injector_registry_proxy: pointerinjector::RegistryProxy,
55
56 configuration_proxy: pointerinjector_config::SetupProxy,
58
59 pub inspect_status: InputHandlerStatus,
61
62 metrics_logger: metrics::MetricsLogger,
63}
64
65struct MutableState {
66 viewport: Option<pointerinjector::Viewport>,
69
70 injectors: HashMap<u32, pointerinjector::DeviceProxy>,
72
73 current_position: Position,
75
76 cursor_message_sender: Sender<CursorMessage>,
78}
79
80impl Handler for MouseInjectorHandler {
81 fn set_handler_healthy(self: std::rc::Rc<Self>) {
82 self.inspect_status.health_node.borrow_mut().set_ok();
83 }
84
85 fn set_handler_unhealthy(self: std::rc::Rc<Self>, msg: &str) {
86 self.inspect_status.health_node.borrow_mut().set_unhealthy(msg);
87 }
88
89 fn get_name(&self) -> &'static str {
90 "MouseInjectorHandler"
91 }
92
93 fn interest(&self) -> Vec<input_device::InputEventType> {
94 vec![input_device::InputEventType::Mouse]
95 }
96}
97
98#[async_trait(?Send)]
99impl InputHandler for MouseInjectorHandler {
100 async fn handle_input_event(
101 self: Rc<Self>,
102 mut input_event: input_device::InputEvent,
103 ) -> Vec<input_device::InputEvent> {
104 fuchsia_trace::duration!("input", "mouse_injector_handler");
105 match input_event {
106 input_device::InputEvent {
107 device_event: input_device::InputDeviceEvent::Mouse(ref mouse_event),
108 device_descriptor:
109 input_device::InputDeviceDescriptor::Mouse(ref mouse_device_descriptor),
110 event_time,
111 handled: input_device::Handled::No,
112 trace_id,
113 } => {
114 fuchsia_trace::duration!("input", "mouse_injector_handler[processing]");
115 let trace_id = match trace_id {
116 Some(id) => {
117 fuchsia_trace::flow_step!("input", "event_in_input_pipeline", id.into());
118 id
119 }
120 None => fuchsia_trace::Id::random(),
121 };
122
123 self.inspect_status.count_received_event(&event_time);
124 if let Err(e) =
126 self.update_cursor_renderer(mouse_event, &mouse_device_descriptor).await
127 {
128 self.metrics_logger.log_error(
129 InputPipelineErrorMetricDimensionEvent::MouseInjectorUpdateCursorRendererFailed,
130 std::format!("update_cursor_renderer failed: {}", e));
131 }
132
133 if let Err(e) = self
135 .ensure_injector_registered(&mouse_event, &mouse_device_descriptor, event_time)
136 .await
137 {
138 self.metrics_logger.log_error(
139 InputPipelineErrorMetricDimensionEvent::MouseInjectorEnsureInjectorRegisteredFailed,
140 std::format!("ensure_injector_registered failed: {}", e));
141 }
142
143 if let Err(e) = self
145 .send_event_to_scenic(
146 &mouse_event,
147 &mouse_device_descriptor,
148 event_time,
149 trace_id.into(),
150 )
151 .await
152 {
153 self.metrics_logger.log_error(
154 InputPipelineErrorMetricDimensionEvent::MouseInjectorSendEventToScenicFailed,
155 std::format!("send_event_to_scenic failed: {}", e));
156 }
157
158 input_event.handled = input_device::Handled::Yes;
160 self.inspect_status.count_handled_event();
161 }
162 _ => {
163 self.metrics_logger.log_error(
164 InputPipelineErrorMetricDimensionEvent::HandlerReceivedUninterestedEvent,
165 std::format!(
166 "{} uninterested input event: {:?}",
167 self.get_name(),
168 input_event.get_event_type()
169 ),
170 );
171 }
172 }
173 vec![input_event]
174 }
175}
176
177impl MouseInjectorHandler {
178 pub async fn new(
191 incoming: &Incoming,
192 display_size: Size,
193 cursor_message_sender: Sender<CursorMessage>,
194 input_handlers_node: &fuchsia_inspect::Node,
195 metrics_logger: metrics::MetricsLogger,
196 ) -> Result<Rc<Self>, Error> {
197 let configuration_proxy =
198 incoming.connect_protocol::<pointerinjector_config::SetupProxy>()?;
199 let injector_registry_proxy =
200 incoming.connect_protocol::<pointerinjector::RegistryProxy>()?;
201
202 Self::new_handler(
203 configuration_proxy,
204 injector_registry_proxy,
205 display_size,
206 cursor_message_sender,
207 input_handlers_node,
208 metrics_logger,
209 )
210 .await
211 }
212
213 pub async fn new_with_config_proxy(
229 incoming: &Incoming,
230 configuration_proxy: pointerinjector_config::SetupProxy,
231 display_size: Size,
232 cursor_message_sender: Sender<CursorMessage>,
233 input_handlers_node: &fuchsia_inspect::Node,
234 metrics_logger: metrics::MetricsLogger,
235 ) -> Result<Rc<Self>, Error> {
236 let injector_registry_proxy =
237 incoming.connect_protocol::<pointerinjector::RegistryProxy>()?;
238 Self::new_handler(
239 configuration_proxy,
240 injector_registry_proxy,
241 display_size,
242 cursor_message_sender,
243 input_handlers_node,
244 metrics_logger,
245 )
246 .await
247 }
248
249 fn inner(&self) -> Ref<'_, MutableState> {
250 self.mutable_state.borrow()
251 }
252
253 fn inner_mut(&self) -> RefMut<'_, MutableState> {
254 self.mutable_state.borrow_mut()
255 }
256
257 async fn new_handler(
273 configuration_proxy: pointerinjector_config::SetupProxy,
274 injector_registry_proxy: pointerinjector::RegistryProxy,
275 display_size: Size,
276 cursor_message_sender: Sender<CursorMessage>,
277 input_handlers_node: &fuchsia_inspect::Node,
278 metrics_logger: metrics::MetricsLogger,
279 ) -> Result<Rc<Self>, Error> {
280 let (context_view_ref, target_view_ref) = configuration_proxy.get_view_refs().await?;
282 let inspect_status = InputHandlerStatus::new(
283 input_handlers_node,
284 "mouse_injector_handler",
285 false,
286 );
287 let handler = Rc::new(Self {
288 mutable_state: RefCell::new(MutableState {
289 viewport: None,
290 injectors: HashMap::new(),
291 current_position: Position {
293 x: display_size.width / 2.0,
294 y: display_size.height / 2.0,
295 },
296 cursor_message_sender,
297 }),
298 context_view_ref,
299 target_view_ref,
300 max_position: Position { x: display_size.width, y: display_size.height },
301 injector_registry_proxy,
302 configuration_proxy,
303 inspect_status,
304 metrics_logger,
305 });
306
307 Ok(handler)
308 }
309
310 async fn ensure_injector_registered(
318 self: &Rc<Self>,
319 mouse_event: &mouse_binding::MouseEvent,
320 mouse_descriptor: &mouse_binding::MouseDeviceDescriptor,
321 event_time: zx::MonotonicInstant,
322 ) -> Result<(), anyhow::Error> {
323 if self.inner().injectors.contains_key(&mouse_descriptor.device_id) {
324 return Ok(());
325 }
326
327 let (device_proxy, device_server) = create_proxy::<pointerinjector::DeviceMarker>();
329 let context = fuchsia_scenic::duplicate_view_ref(&self.context_view_ref)
330 .context("Failed to duplicate context view ref.")?;
331 let target = fuchsia_scenic::duplicate_view_ref(&self.target_view_ref)
332 .context("Failed to duplicate target view ref.")?;
333
334 let viewport = self.inner().viewport.clone();
335 let config = pointerinjector::Config {
336 device_id: Some(mouse_descriptor.device_id),
337 device_type: Some(pointerinjector::DeviceType::Mouse),
338 context: Some(pointerinjector::Context::View(context)),
339 target: Some(pointerinjector::Target::View(target)),
340 viewport,
341 dispatch_policy: Some(pointerinjector::DispatchPolicy::MouseHoverAndLatchInTarget),
342 scroll_v_range: mouse_descriptor.wheel_v_range.clone(),
343 scroll_h_range: mouse_descriptor.wheel_h_range.clone(),
344 buttons: mouse_descriptor.buttons.clone(),
345 ..Default::default()
346 };
347
348 self.injector_registry_proxy
350 .register(config, device_server)
351 .await
352 .context("Failed to register injector.")?;
353 log::info!("Registered injector with device id {:?}", mouse_descriptor.device_id);
354
355 self.inner_mut().injectors.insert(mouse_descriptor.device_id, device_proxy.clone());
357
358 let events_to_send = vec![self.create_pointer_sample_event(
360 mouse_event,
361 event_time,
362 pointerinjector::EventPhase::Add,
363 self.inner().current_position,
364 None,
365 None,
366 )];
367 device_proxy.inject_events(events_to_send).context("Failed to ADD new MouseDevice.")?;
368
369 Ok(())
370 }
371
372 async fn update_cursor_renderer(
383 &self,
384 mouse_event: &mouse_binding::MouseEvent,
385 mouse_descriptor: &mouse_binding::MouseDeviceDescriptor,
386 ) -> Result<(), anyhow::Error> {
387 let mut new_position = match (mouse_event.location, mouse_descriptor) {
388 (
389 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
390 millimeters,
391 }),
392 _,
393 ) => {
394 self.inner().current_position
395 + self.relative_movement_mm_to_phyical_pixel(millimeters)
396 }
397 (
398 mouse_binding::MouseLocation::Absolute(position),
399 mouse_binding::MouseDeviceDescriptor {
400 absolute_x_range: Some(x_range),
401 absolute_y_range: Some(y_range),
402 ..
403 },
404 ) => self.scale_absolute_position(&position, &x_range, &y_range),
405 (mouse_binding::MouseLocation::Absolute(_), _) => {
406 return Err(anyhow!(
407 "Received an Absolute mouse location without absolute device ranges."
408 ));
409 }
410 };
411 Position::clamp(&mut new_position, Position::zero(), self.max_position);
412 self.inner_mut().current_position = new_position;
413
414 let mut cursor_message_sender = self.inner().cursor_message_sender.clone();
415 cursor_message_sender
416 .send(CursorMessage::SetPosition(new_position))
417 .await
418 .context("Failed to send current mouse position to cursor renderer")?;
419
420 Ok(())
421 }
422
423 fn scale_absolute_position(
431 &self,
432 position: &Position,
433 x_range: &Range,
434 y_range: &Range,
435 ) -> Position {
436 let range_min = Position { x: x_range.min as f32, y: y_range.min as f32 };
437 let range_max = Position { x: x_range.max as f32, y: y_range.max as f32 };
438 self.max_position * ((*position - range_min) / (range_max - range_min))
439 }
440
441 async fn send_event_to_scenic(
448 &self,
449 mouse_event: &mouse_binding::MouseEvent,
450 mouse_descriptor: &mouse_binding::MouseDeviceDescriptor,
451 event_time: zx::MonotonicInstant,
452 tracing_id: u64,
453 ) -> Result<(), anyhow::Error> {
454 let injector = self.inner().injectors.get(&mouse_descriptor.device_id).cloned();
455 if let Some(injector) = injector {
456 let relative_motion = match mouse_event.location {
457 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
458 millimeters: offset_mm,
459 }) if mouse_event.phase == mouse_binding::MousePhase::Move => {
460 let offset = self.relative_movement_mm_to_phyical_pixel(offset_mm);
461 Some([offset.x, offset.y])
462 }
463 _ => None,
464 };
465 let events_to_send = vec![self.create_pointer_sample_event(
466 mouse_event,
467 event_time,
468 pointerinjector::EventPhase::Change,
469 self.inner().current_position,
470 relative_motion,
471 Some(tracing_id),
472 )];
473
474 fuchsia_trace::flow_begin!("input", "dispatch_event_to_scenic", tracing_id.into());
475
476 let _ = injector.inject_events(events_to_send);
477
478 Ok(())
479 } else {
480 Err(anyhow::format_err!(
481 "No injector found for mouse device {}.",
482 mouse_descriptor.device_id
483 ))
484 }
485 }
486
487 fn create_pointer_sample_event(
496 &self,
497 mouse_event: &mouse_binding::MouseEvent,
498 event_time: zx::MonotonicInstant,
499 phase: pointerinjector::EventPhase,
500 current_position: Position,
501 relative_motion: Option<[f32; 2]>,
502 trace_id: Option<u64>,
503 ) -> pointerinjector::Event {
504 let pointer_sample = pointerinjector::PointerSample {
505 pointer_id: Some(0),
506 phase: Some(phase),
507 position_in_viewport: Some([current_position.x, current_position.y]),
508 scroll_v: match mouse_event.wheel_delta_v {
509 Some(mouse_binding::WheelDelta {
510 raw_data: mouse_binding::RawWheelDelta::Ticks(tick),
511 ..
512 }) => Some(tick),
513 _ => None,
514 },
515 scroll_h: match mouse_event.wheel_delta_h {
516 Some(mouse_binding::WheelDelta {
517 raw_data: mouse_binding::RawWheelDelta::Ticks(tick),
518 ..
519 }) => Some(tick),
520 _ => None,
521 },
522 scroll_v_physical_pixel: match mouse_event.wheel_delta_v {
523 Some(mouse_binding::WheelDelta { physical_pixel: Some(pixel), .. }) => {
524 Some(pixel.into())
525 }
526 _ => None,
527 },
528 scroll_h_physical_pixel: match mouse_event.wheel_delta_h {
529 Some(mouse_binding::WheelDelta { physical_pixel: Some(pixel), .. }) => {
530 Some(pixel.into())
531 }
532 _ => None,
533 },
534 is_precision_scroll: match mouse_event.phase {
535 mouse_binding::MousePhase::Wheel => match mouse_event.is_precision_scroll {
536 Some(mouse_binding::PrecisionScroll::Yes) => Some(true),
537 Some(mouse_binding::PrecisionScroll::No) => Some(false),
538 None => {
539 self.metrics_logger.log_error(
540 InputPipelineErrorMetricDimensionEvent::MouseInjectorMissingIsPrecisionScroll,
541 "mouse wheel event does not have value in is_precision_scroll.");
542 None
543 }
544 },
545 _ => None,
546 },
547 pressed_buttons: Some(Vec::from_iter(mouse_event.pressed_buttons.iter().cloned())),
548 relative_motion,
549 ..Default::default()
550 };
551 pointerinjector::Event {
552 timestamp: Some(event_time.into_nanos()),
553 data: Some(pointerinjector::Data::PointerSample(pointer_sample)),
554 trace_flow_id: trace_id,
555 wake_lease: mouse_event.wake_lease.lock().take(),
556 ..Default::default()
557 }
558 }
559
560 pub async fn watch_viewport(self: Rc<Self>) {
562 let configuration_proxy = self.configuration_proxy.clone();
563 let mut viewport_stream = HangingGetStream::new(
564 configuration_proxy,
565 pointerinjector_config::SetupProxy::watch_viewport,
566 );
567 loop {
568 match viewport_stream.next().await {
569 Some(Ok(new_viewport)) => {
570 self.inner_mut().viewport = Some(new_viewport.clone());
572
573 let injectors = self.inner().injectors.values().cloned().collect::<Vec<_>>();
575 for injector in injectors {
576 let events = vec![pointerinjector::Event {
577 timestamp: Some(MonotonicInstant::now().into_nanos()),
578 data: Some(pointerinjector::Data::Viewport(new_viewport.clone())),
579 trace_flow_id: Some(fuchsia_trace::Id::random().into()),
580 ..Default::default()
581 }];
582 injector.inject_events(events).expect("Failed to inject updated viewport.");
583 }
584 }
585 Some(Err(e)) => {
586 self.metrics_logger.log_error(
587 InputPipelineErrorMetricDimensionEvent::MouseInjectorErrorWhileReadingViewportUpdate,
588 std::format!("Error while reading viewport update: {}", e));
589 return;
590 }
591 None => {
592 self.metrics_logger.log_error(
593 InputPipelineErrorMetricDimensionEvent::MouseInjectorViewportUpdateStreamTerminatedUnexpectedly,
594 "Viewport update stream terminated unexpectedly");
595 return;
596 }
597 }
598 }
599 }
600
601 fn relative_movement_mm_to_phyical_pixel(&self, movement_mm: Position) -> Position {
605 Position {
606 x: movement_mm.x * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
607 y: movement_mm.y * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
608 }
609 }
610}
611
612#[cfg(test)]
613mod tests {
614 use super::*;
615 use crate::testing_utilities::{
616 assert_handler_ignores_input_event_sequence, create_mouse_event,
617 create_mouse_event_with_handled, create_mouse_pointer_sample_event,
618 create_mouse_pointer_sample_event_phase_add,
619 create_mouse_pointer_sample_event_with_wheel_physical_pixel,
620 };
621 use assert_matches::assert_matches;
622 use fidl_fuchsia_input_report as fidl_input_report;
623 use fidl_fuchsia_ui_pointerinjector as pointerinjector;
624 use fuchsia_async as fasync;
625 use futures::channel::mpsc;
626 use pretty_assertions::assert_eq;
627 use std::collections::HashSet;
628 use std::ops::Add;
629 use test_case::test_case;
630
631 const DISPLAY_WIDTH_IN_PHYSICAL_PX: f32 = 100.0;
632 const DISPLAY_HEIGHT_IN_PHYSICAL_PX: f32 = 100.0;
633 const COUNTS_PER_MM: u32 = 12;
634
635 const DESCRIPTOR: input_device::InputDeviceDescriptor =
637 input_device::InputDeviceDescriptor::Mouse(mouse_binding::MouseDeviceDescriptor {
638 device_id: 1,
639 absolute_x_range: Some(fidl_input_report::Range { min: 0, max: 100 }),
640 absolute_y_range: Some(fidl_input_report::Range { min: 0, max: 100 }),
641 wheel_v_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 wheel_h_range: Some(fidl_input_report::Axis {
649 range: fidl_input_report::Range { min: -1, max: 1 },
650 unit: fidl_input_report::Unit {
651 type_: fidl_input_report::UnitType::Other,
652 exponent: 0,
653 },
654 }),
655 buttons: None,
656 counts_per_mm: COUNTS_PER_MM,
657 });
658
659 async fn handle_configuration_request_stream(
661 stream: &mut pointerinjector_config::SetupRequestStream,
662 ) {
663 if let Some(Ok(request)) = stream.next().await {
664 match request {
665 pointerinjector_config::SetupRequest::GetViewRefs { responder, .. } => {
666 let context = fuchsia_scenic::ViewRefPair::new()
667 .expect("Failed to create viewrefpair.")
668 .view_ref;
669 let target = fuchsia_scenic::ViewRefPair::new()
670 .expect("Failed to create viewrefpair.")
671 .view_ref;
672 let _ = responder.send(context, target);
673 }
674 _ => {}
675 };
676 }
677 }
678
679 async fn handle_registry_request_stream(
682 mut stream: pointerinjector::RegistryRequestStream,
683 injector_sender: futures::channel::oneshot::Sender<pointerinjector::DeviceRequestStream>,
684 ) {
685 if let Some(request) = stream.next().await {
686 match request {
687 Ok(pointerinjector::RegistryRequest::Register {
688 config: _,
689 injector,
690 responder,
691 ..
692 }) => {
693 let injector_stream = injector.into_stream();
694 let _ = injector_sender.send(injector_stream);
695 responder.send().expect("failed to respond");
696 }
697 _ => {}
698 };
699 } else {
700 panic!("RegistryRequestStream failed.");
701 }
702 }
703
704 async fn handle_registry_request_stream2(
706 mut stream: pointerinjector::RegistryRequestStream,
707 injector_sender: mpsc::UnboundedSender<Vec<pointerinjector::Event>>,
708 ) {
709 let (injector, responder) = match stream.next().await {
710 Some(Ok(pointerinjector::RegistryRequest::Register {
711 config: _,
712 injector,
713 responder,
714 ..
715 })) => (injector, responder),
716 other => panic!("expected register request, but got {:?}", other),
717 };
718 let injector_stream: pointerinjector::DeviceRequestStream = injector.into_stream();
719 responder.send().expect("failed to respond");
720 injector_stream
721 .for_each(|request| {
722 futures::future::ready({
723 match request {
724 Ok(pointerinjector::DeviceRequest::Inject { .. }) => {
725 panic!("DeviceRequest::Inject is deprecated.");
726 }
727 Ok(pointerinjector::DeviceRequest::InjectEvents { events, .. }) => {
728 let _ = injector_sender.unbounded_send(events);
729 }
730 Err(e) => panic!("FIDL error {}", e),
731 }
732 })
733 })
734 .await;
735 }
736
737 async fn handle_device_request_stream(
740 injector_stream_receiver: futures::channel::oneshot::Receiver<
741 pointerinjector::DeviceRequestStream,
742 >,
743 expected_events: Vec<pointerinjector::Event>,
744 ) {
745 let mut injector_stream =
746 injector_stream_receiver.await.expect("Failed to get DeviceRequestStream.");
747 for expected_event in expected_events {
748 match injector_stream.next().await {
749 Some(Ok(pointerinjector::DeviceRequest::Inject { .. })) => {
750 panic!("DeviceRequest::Inject is deprecated.");
751 }
752 Some(Ok(pointerinjector::DeviceRequest::InjectEvents { events, .. })) => {
753 assert_eq!(events, vec![expected_event]);
754 }
755 Some(Err(e)) => panic!("FIDL error {}", e),
756 None => panic!("Expected another event."),
757 }
758 }
759 }
760
761 fn create_viewport(min: f32, max: f32) -> pointerinjector::Viewport {
763 pointerinjector::Viewport {
764 extents: Some([[min, min], [max, max]]),
765 viewport_to_context_transform: None,
766 ..Default::default()
767 }
768 }
769
770 #[fuchsia::test]
773 fn receives_viewport_updates() {
774 let mut exec = fasync::TestExecutor::new();
775
776 let (configuration_proxy, mut configuration_request_stream) =
778 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
779 let (injector_registry_proxy, _) =
780 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
781 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(0);
782
783 let inspector = fuchsia_inspect::Inspector::default();
784 let test_node = inspector.root().create_child("test_node");
785
786 let mouse_handler_fut = MouseInjectorHandler::new_handler(
788 configuration_proxy,
789 injector_registry_proxy,
790 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
791 sender,
792 &test_node,
793 metrics::MetricsLogger::default(),
794 );
795 let config_request_stream_fut =
796 handle_configuration_request_stream(&mut configuration_request_stream);
797 let (mouse_handler_res, _) = exec.run_singlethreaded(futures::future::join(
798 mouse_handler_fut,
799 config_request_stream_fut,
800 ));
801 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
802
803 let (injector_device_proxy, mut injector_device_request_stream) =
805 fidl::endpoints::create_proxy_and_stream::<pointerinjector::DeviceMarker>();
806 mouse_handler.inner_mut().injectors.insert(1, injector_device_proxy);
807
808 {
810 let watch_viewport_fut = mouse_handler.clone().watch_viewport();
812 futures::pin_mut!(watch_viewport_fut);
813 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
814
815 match exec.run_singlethreaded(&mut configuration_request_stream.next()) {
817 Some(Ok(pointerinjector_config::SetupRequest::WatchViewport {
818 responder, ..
819 })) => {
820 responder.send(&create_viewport(0.0, 100.0)).expect("Failed to send viewport.");
821 }
822 other => panic!("Received unexpected value: {:?}", other),
823 };
824 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
825
826 exec.run_singlethreaded(async {
828 match injector_device_request_stream.next().await {
829 Some(Ok(pointerinjector::DeviceRequest::Inject { .. })) => {
830 panic!("DeviceRequest::Inject is deprecated.");
831 }
832 Some(Ok(pointerinjector::DeviceRequest::InjectEvents { events, .. })) => {
833 assert_eq!(events.len(), 1);
834 assert!(events[0].data.is_some());
835 assert_eq!(
836 events[0].data,
837 Some(pointerinjector::Data::Viewport(create_viewport(0.0, 100.0)))
838 );
839 }
840 other => panic!("Received unexpected value: {:?}", other),
841 }
842 });
843
844 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
846
847 match exec.run_singlethreaded(&mut configuration_request_stream.next()) {
849 Some(Ok(pointerinjector_config::SetupRequest::WatchViewport {
850 responder, ..
851 })) => {
852 responder
853 .send(&create_viewport(100.0, 200.0))
854 .expect("Failed to send viewport.");
855 }
856 other => panic!("Received unexpected value: {:?}", other),
857 };
858
859 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
861 }
862
863 exec.run_singlethreaded(async {
865 match injector_device_request_stream.next().await {
866 Some(Ok(pointerinjector::DeviceRequest::Inject { .. })) => {
867 panic!("DeviceRequest::Inject is deprecated.");
868 }
869 Some(Ok(pointerinjector::DeviceRequest::InjectEvents { events, .. })) => {
870 assert_eq!(events.len(), 1);
871 assert!(events[0].data.is_some());
872 assert_eq!(
873 events[0].data,
874 Some(pointerinjector::Data::Viewport(create_viewport(100.0, 200.0)))
875 );
876 }
877 other => panic!("Received unexpected value: {:?}", other),
878 }
879 });
880
881 let expected_viewport = create_viewport(100.0, 200.0);
883 assert_eq!(mouse_handler.inner().viewport, Some(expected_viewport));
884 }
885
886 fn wheel_delta_ticks(
887 ticks: i64,
888 physical_pixel: Option<f32>,
889 ) -> Option<mouse_binding::WheelDelta> {
890 Some(mouse_binding::WheelDelta {
891 raw_data: mouse_binding::RawWheelDelta::Ticks(ticks),
892 physical_pixel,
893 })
894 }
895
896 fn wheel_delta_mm(mm: f32, physical_pixel: Option<f32>) -> Option<mouse_binding::WheelDelta> {
897 Some(mouse_binding::WheelDelta {
898 raw_data: mouse_binding::RawWheelDelta::Millimeters(mm),
899 physical_pixel,
900 })
901 }
902
903 #[test_case(
906 mouse_binding::MouseLocation::Relative(
907 mouse_binding::RelativeLocation {
908 millimeters: Position { x: 1.0, y: 2.0 }
909 }),
910 Position {
911 x: DISPLAY_WIDTH_IN_PHYSICAL_PX / 2.0
912 + 1.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
913 y: DISPLAY_HEIGHT_IN_PHYSICAL_PX / 2.0
914 + 2.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
915 },
916 [
917 1.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
918 2.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
919 ]; "Valid move event."
920 )]
921 #[test_case(
922 mouse_binding::MouseLocation::Relative(
923 mouse_binding::RelativeLocation {
924 millimeters: Position {
925 x: DISPLAY_WIDTH_IN_PHYSICAL_PX / MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL + 2.0,
926 y: DISPLAY_HEIGHT_IN_PHYSICAL_PX / MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL + 1.0,
927 }}),
928 Position {
929 x: DISPLAY_WIDTH_IN_PHYSICAL_PX,
930 y: DISPLAY_HEIGHT_IN_PHYSICAL_PX,
931 },
932 [
933 DISPLAY_WIDTH_IN_PHYSICAL_PX + 2.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
934 DISPLAY_HEIGHT_IN_PHYSICAL_PX + 1.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
935 ]; "Move event exceeds max bounds."
936 )]
937 #[test_case(
938 mouse_binding::MouseLocation::Relative(
939 mouse_binding::RelativeLocation {
940 millimeters: Position {
941 x: -(DISPLAY_WIDTH_IN_PHYSICAL_PX / MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL + 2.0),
942 y: -(DISPLAY_HEIGHT_IN_PHYSICAL_PX / MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL + 1.0),
943 }}),
944 Position { x: 0.0, y: 0.0 },
945 [
946 -(DISPLAY_WIDTH_IN_PHYSICAL_PX + 2.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL),
947 -(DISPLAY_HEIGHT_IN_PHYSICAL_PX + 1.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL),
948 ]; "Move event exceeds min bounds."
949 )]
950 #[fuchsia::test(allow_stalls = false)]
951 async fn move_event(
952 move_location: mouse_binding::MouseLocation,
953 expected_position: Position,
954 expected_relative_motion: [f32; 2],
955 ) {
956 let (configuration_proxy, mut configuration_request_stream) =
958 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
959 let (injector_registry_proxy, injector_registry_request_stream) =
960 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
961 let config_request_stream_fut =
962 handle_configuration_request_stream(&mut configuration_request_stream);
963
964 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
966 let inspector = fuchsia_inspect::Inspector::default();
967 let test_node = inspector.root().create_child("test_node");
968 let mouse_handler_fut = MouseInjectorHandler::new_handler(
969 configuration_proxy,
970 injector_registry_proxy,
971 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
972 sender,
973 &test_node,
974 metrics::MetricsLogger::default(),
975 );
976 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
977 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
978
979 let event_time = zx::MonotonicInstant::get();
980 let input_event = create_mouse_event(
981 move_location,
982 None, None, None, mouse_binding::MousePhase::Move,
986 HashSet::new(),
987 HashSet::new(),
988 event_time,
989 &DESCRIPTOR,
990 );
991
992 let handle_event_fut = mouse_handler.handle_input_event(input_event);
994 let expected_events = vec![
995 create_mouse_pointer_sample_event_phase_add(vec![], expected_position, event_time),
996 create_mouse_pointer_sample_event(
997 pointerinjector::EventPhase::Change,
998 vec![],
999 expected_position,
1000 Some(expected_relative_motion),
1001 None, None, None, event_time,
1005 ),
1006 ];
1007
1008 let (injector_stream_sender, injector_stream_receiver) =
1012 futures::channel::oneshot::channel::<pointerinjector::DeviceRequestStream>();
1013 let registry_fut = handle_registry_request_stream(
1014 injector_registry_request_stream,
1015 injector_stream_sender,
1016 );
1017 let device_fut = handle_device_request_stream(injector_stream_receiver, expected_events);
1018
1019 let (handle_result, _, _) = futures::join!(handle_event_fut, registry_fut, device_fut);
1022 match receiver.next().await {
1023 Some(CursorMessage::SetPosition(position)) => {
1024 pretty_assertions::assert_eq!(position, expected_position);
1025 }
1026 Some(CursorMessage::SetVisibility(_)) => {
1027 panic!("Received unexpected cursor visibility update.")
1028 }
1029 None => panic!("Did not receive cursor update."),
1030 }
1031
1032 assert_matches!(
1034 handle_result.as_slice(),
1035 [input_device::InputEvent { handled: input_device::Handled::Yes, .. }]
1036 );
1037 }
1038
1039 #[fuchsia::test(allow_stalls = false)]
1042 async fn move_absolute_event() {
1043 const DEVICE_ID: u32 = 1;
1044
1045 let (configuration_proxy, mut configuration_request_stream) =
1047 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1048 let (injector_registry_proxy, injector_registry_request_stream) =
1049 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1050 let config_request_stream_fut =
1051 handle_configuration_request_stream(&mut configuration_request_stream);
1052
1053 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
1055 let inspector = fuchsia_inspect::Inspector::default();
1056 let test_node = inspector.root().create_child("test_node");
1057 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1058 configuration_proxy,
1059 injector_registry_proxy,
1060 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1061 sender,
1062 &test_node,
1063 metrics::MetricsLogger::default(),
1064 );
1065 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1066 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1067
1068 let cursor_location =
1084 mouse_binding::MouseLocation::Absolute(Position { x: -25.0, y: 25.0 });
1085 let event_time = zx::MonotonicInstant::get();
1086 let descriptor =
1087 input_device::InputDeviceDescriptor::Mouse(mouse_binding::MouseDeviceDescriptor {
1088 device_id: DEVICE_ID,
1089 absolute_x_range: Some(fidl_input_report::Range { min: -50, max: 50 }),
1090 absolute_y_range: Some(fidl_input_report::Range { min: -50, max: 50 }),
1091 wheel_v_range: None,
1092 wheel_h_range: None,
1093 buttons: None,
1094 counts_per_mm: COUNTS_PER_MM,
1095 });
1096 let input_event = create_mouse_event(
1097 cursor_location,
1098 None, None, None, mouse_binding::MousePhase::Move,
1102 HashSet::new(),
1103 HashSet::new(),
1104 event_time,
1105 &descriptor,
1106 );
1107
1108 let handle_event_fut = mouse_handler.handle_input_event(input_event);
1110 let expected_position = Position {
1111 x: DISPLAY_WIDTH_IN_PHYSICAL_PX * 0.25,
1112 y: DISPLAY_WIDTH_IN_PHYSICAL_PX * 0.75,
1113 };
1114 let expected_events = vec![
1115 create_mouse_pointer_sample_event_phase_add(vec![], expected_position, event_time),
1116 create_mouse_pointer_sample_event(
1117 pointerinjector::EventPhase::Change,
1118 vec![],
1119 expected_position,
1120 None, None, None, None, event_time,
1125 ),
1126 ];
1127
1128 let (injector_stream_sender, injector_stream_receiver) =
1132 futures::channel::oneshot::channel::<pointerinjector::DeviceRequestStream>();
1133 let registry_fut = handle_registry_request_stream(
1134 injector_registry_request_stream,
1135 injector_stream_sender,
1136 );
1137 let device_fut = handle_device_request_stream(injector_stream_receiver, expected_events);
1138
1139 let (handle_result, _, _) = futures::join!(handle_event_fut, registry_fut, device_fut);
1142 match receiver.next().await {
1143 Some(CursorMessage::SetPosition(position)) => {
1144 assert_eq!(position, expected_position);
1145 }
1146 Some(CursorMessage::SetVisibility(_)) => {
1147 panic!("Received unexpected cursor visibility update.")
1148 }
1149 None => panic!("Did not receive cursor update."),
1150 }
1151
1152 assert_matches!(
1154 handle_result.as_slice(),
1155 [input_device::InputEvent { handled: input_device::Handled::Yes, .. }]
1156 );
1157 }
1158
1159 #[test_case(
1161 mouse_binding::MousePhase::Down,
1162 vec![1], vec![1]; "Down event injects button press state."
1163 )]
1164 #[test_case(
1165 mouse_binding::MousePhase::Up,
1166 vec![1], vec![]; "Up event injects button press state."
1167 )]
1168 #[fuchsia::test(allow_stalls = false)]
1169 async fn button_state_event(
1170 phase: mouse_binding::MousePhase,
1171 affected_buttons: Vec<mouse_binding::MouseButton>,
1172 pressed_buttons: Vec<mouse_binding::MouseButton>,
1173 ) {
1174 let (configuration_proxy, mut configuration_request_stream) =
1176 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1177 let (injector_registry_proxy, injector_registry_request_stream) =
1178 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1179 let config_request_stream_fut =
1180 handle_configuration_request_stream(&mut configuration_request_stream);
1181
1182 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
1184 let inspector = fuchsia_inspect::Inspector::default();
1185 let test_node = inspector.root().create_child("test_node");
1186 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1187 configuration_proxy,
1188 injector_registry_proxy,
1189 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1190 sender,
1191 &test_node,
1192 metrics::MetricsLogger::default(),
1193 );
1194 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1195 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1196
1197 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
1198 let event_time = zx::MonotonicInstant::get();
1199
1200 let input_event = create_mouse_event(
1201 cursor_location,
1202 None, None, None, phase,
1206 HashSet::from_iter(affected_buttons.clone()),
1207 HashSet::from_iter(pressed_buttons.clone()),
1208 event_time,
1209 &DESCRIPTOR,
1210 );
1211
1212 let handle_event_fut = mouse_handler.handle_input_event(input_event);
1214 let expected_position = Position { x: 0.0, y: 0.0 };
1215 let expected_events = vec![
1216 create_mouse_pointer_sample_event_phase_add(
1217 pressed_buttons.clone(),
1218 expected_position,
1219 event_time,
1220 ),
1221 create_mouse_pointer_sample_event(
1222 pointerinjector::EventPhase::Change,
1223 pressed_buttons.clone(),
1224 expected_position,
1225 None, None, None, None, event_time,
1230 ),
1231 ];
1232
1233 let (injector_stream_sender, injector_stream_receiver) =
1237 futures::channel::oneshot::channel::<pointerinjector::DeviceRequestStream>();
1238 let registry_fut = handle_registry_request_stream(
1239 injector_registry_request_stream,
1240 injector_stream_sender,
1241 );
1242 let device_fut = handle_device_request_stream(injector_stream_receiver, expected_events);
1243
1244 let (handle_result, _, _) = futures::join!(handle_event_fut, registry_fut, device_fut);
1247 match receiver.next().await {
1248 Some(CursorMessage::SetPosition(position)) => {
1249 pretty_assertions::assert_eq!(position, expected_position);
1250 }
1251 Some(CursorMessage::SetVisibility(_)) => {
1252 panic!("Received unexpected cursor visibility update.")
1253 }
1254 None => panic!("Did not receive cursor update."),
1255 }
1256
1257 assert_matches!(
1259 handle_result.as_slice(),
1260 [input_device::InputEvent { handled: input_device::Handled::Yes, .. }]
1261 );
1262 }
1263
1264 #[fuchsia::test(allow_stalls = false)]
1266 async fn down_up_event() {
1267 let (configuration_proxy, mut configuration_request_stream) =
1269 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1270 let (injector_registry_proxy, injector_registry_request_stream) =
1271 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1272 let config_request_stream_fut =
1273 handle_configuration_request_stream(&mut configuration_request_stream);
1274
1275 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(2);
1279 let inspector = fuchsia_inspect::Inspector::default();
1280 let test_node = inspector.root().create_child("test_node");
1281 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1282 configuration_proxy,
1283 injector_registry_proxy,
1284 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1285 sender,
1286 &test_node,
1287 metrics::MetricsLogger::default(),
1288 );
1289 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1290 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1291
1292 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
1293 let event_time1 = zx::MonotonicInstant::get();
1294 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
1295
1296 let event1 = create_mouse_event(
1297 cursor_location,
1298 None, None, None, mouse_binding::MousePhase::Down,
1302 HashSet::from_iter(vec![1]),
1303 HashSet::from_iter(vec![1]),
1304 event_time1,
1305 &DESCRIPTOR,
1306 );
1307
1308 let event2 = create_mouse_event(
1309 cursor_location,
1310 None, None, None, mouse_binding::MousePhase::Up,
1314 HashSet::from_iter(vec![1]),
1315 HashSet::new(),
1316 event_time2,
1317 &DESCRIPTOR,
1318 );
1319
1320 let expected_position = Position { x: 0.0, y: 0.0 };
1321
1322 let (injector_stream_sender, injector_stream_receiver) =
1326 mpsc::unbounded::<Vec<pointerinjector::Event>>();
1327 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
1329 let registry_fut = handle_registry_request_stream2(
1330 injector_registry_request_stream,
1331 injector_stream_sender,
1332 );
1333
1334 let _registry_task = fasync::Task::local(registry_fut);
1336
1337 mouse_handler.clone().handle_input_event(event1).await;
1338 assert_eq!(
1339 injector_stream_receiver
1340 .next()
1341 .await
1342 .map(|events| events.into_iter().flatten().collect()),
1343 Some(vec![
1344 create_mouse_pointer_sample_event_phase_add(
1345 vec![1],
1346 expected_position,
1347 event_time1,
1348 ),
1349 create_mouse_pointer_sample_event(
1350 pointerinjector::EventPhase::Change,
1351 vec![1],
1352 expected_position,
1353 None, None, None, None, event_time1,
1358 )
1359 ])
1360 );
1361
1362 mouse_handler.clone().handle_input_event(event2).await;
1364 assert_eq!(
1365 injector_stream_receiver
1366 .next()
1367 .await
1368 .map(|events| events.into_iter().flatten().collect()),
1369 Some(vec![create_mouse_pointer_sample_event(
1370 pointerinjector::EventPhase::Change,
1371 vec![],
1372 expected_position,
1373 None, None, None, None, event_time2,
1378 )])
1379 );
1380
1381 match receiver.next().await {
1383 Some(CursorMessage::SetPosition(position)) => {
1384 assert_eq!(position, expected_position);
1385 }
1386 Some(CursorMessage::SetVisibility(_)) => {
1387 panic!("Received unexpected cursor visibility update.")
1388 }
1389 None => panic!("Did not receive cursor update."),
1390 }
1391 }
1392
1393 #[fuchsia::test(allow_stalls = false)]
1403 async fn down_down_up_up_event() {
1404 let (configuration_proxy, mut configuration_request_stream) =
1406 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1407 let (injector_registry_proxy, injector_registry_request_stream) =
1408 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1409 let config_request_stream_fut =
1410 handle_configuration_request_stream(&mut configuration_request_stream);
1411
1412 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(4);
1416 let inspector = fuchsia_inspect::Inspector::default();
1417 let test_node = inspector.root().create_child("test_node");
1418 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1419 configuration_proxy,
1420 injector_registry_proxy,
1421 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1422 sender,
1423 &test_node,
1424 metrics::MetricsLogger::default(),
1425 );
1426 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1427 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1428
1429 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
1430 let event_time1 = zx::MonotonicInstant::get();
1431 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
1432 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
1433 let event_time4 = event_time3.add(zx::MonotonicDuration::from_micros(1));
1434
1435 let event1 = create_mouse_event(
1436 cursor_location,
1437 None, None, None, mouse_binding::MousePhase::Down,
1441 HashSet::from_iter(vec![1]),
1442 HashSet::from_iter(vec![1]),
1443 event_time1,
1444 &DESCRIPTOR,
1445 );
1446 let event2 = create_mouse_event(
1447 cursor_location,
1448 None, None, None, mouse_binding::MousePhase::Down,
1452 HashSet::from_iter(vec![2]),
1453 HashSet::from_iter(vec![1, 2]),
1454 event_time2,
1455 &DESCRIPTOR,
1456 );
1457 let event3 = create_mouse_event(
1458 cursor_location,
1459 None, None, None, mouse_binding::MousePhase::Up,
1463 HashSet::from_iter(vec![1]),
1464 HashSet::from_iter(vec![2]),
1465 event_time3,
1466 &DESCRIPTOR,
1467 );
1468 let event4 = create_mouse_event(
1469 cursor_location,
1470 None, None, None, mouse_binding::MousePhase::Up,
1474 HashSet::from_iter(vec![2]),
1475 HashSet::new(),
1476 event_time4,
1477 &DESCRIPTOR,
1478 );
1479
1480 let expected_position = Position { x: 0.0, y: 0.0 };
1481
1482 let (injector_stream_sender, injector_stream_receiver) =
1486 mpsc::unbounded::<Vec<pointerinjector::Event>>();
1487 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
1489 let registry_fut = handle_registry_request_stream2(
1490 injector_registry_request_stream,
1491 injector_stream_sender,
1492 );
1493
1494 let _registry_task = fasync::Task::local(registry_fut);
1496 mouse_handler.clone().handle_input_event(event1).await;
1497 assert_eq!(
1498 injector_stream_receiver
1499 .next()
1500 .await
1501 .map(|events| events.into_iter().flatten().collect()),
1502 Some(vec![
1503 create_mouse_pointer_sample_event_phase_add(
1504 vec![1],
1505 expected_position,
1506 event_time1,
1507 ),
1508 create_mouse_pointer_sample_event(
1509 pointerinjector::EventPhase::Change,
1510 vec![1],
1511 expected_position,
1512 None, None, None, None, event_time1,
1517 )
1518 ])
1519 );
1520
1521 mouse_handler.clone().handle_input_event(event2).await;
1523 let pointer_sample_event2: Vec<_> = injector_stream_receiver
1524 .next()
1525 .await
1526 .map(|events| events.into_iter().flatten().collect())
1527 .expect("Failed to receive pointer sample event.");
1528 let expected_event_time: i64 = event_time2.into_nanos();
1529 assert_eq!(pointer_sample_event2.len(), 1);
1530
1531 match &pointer_sample_event2[0] {
1534 pointerinjector::Event {
1535 timestamp: Some(actual_event_time),
1536 data:
1537 Some(pointerinjector::Data::PointerSample(pointerinjector::PointerSample {
1538 pointer_id: Some(0),
1539 phase: Some(pointerinjector::EventPhase::Change),
1540 position_in_viewport: Some(actual_position),
1541 scroll_v: None,
1542 scroll_h: None,
1543 pressed_buttons: Some(actual_buttons),
1544 relative_motion: None,
1545 ..
1546 })),
1547 ..
1548 } => {
1549 assert_eq!(*actual_event_time, expected_event_time);
1550 assert_eq!(actual_position[0], expected_position.x);
1551 assert_eq!(actual_position[1], expected_position.y);
1552 assert_eq!(
1553 HashSet::<mouse_binding::MouseButton>::from_iter(actual_buttons.clone()),
1554 HashSet::from_iter(vec![1, 2])
1555 );
1556 }
1557 _ => panic!("Unexpected pointer sample event: {:?}", pointer_sample_event2[0]),
1558 }
1559
1560 mouse_handler.clone().handle_input_event(event3).await;
1562 assert_eq!(
1563 injector_stream_receiver
1564 .next()
1565 .await
1566 .map(|events| events.into_iter().flatten().collect()),
1567 Some(vec![create_mouse_pointer_sample_event(
1568 pointerinjector::EventPhase::Change,
1569 vec![2],
1570 expected_position,
1571 None, None, None, None, event_time3,
1576 )])
1577 );
1578
1579 mouse_handler.clone().handle_input_event(event4).await;
1581 assert_eq!(
1582 injector_stream_receiver
1583 .next()
1584 .await
1585 .map(|events| events.into_iter().flatten().collect()),
1586 Some(vec![create_mouse_pointer_sample_event(
1587 pointerinjector::EventPhase::Change,
1588 vec![],
1589 expected_position,
1590 None, None, None, None, event_time4,
1595 )])
1596 );
1597
1598 match receiver.next().await {
1600 Some(CursorMessage::SetPosition(position)) => {
1601 assert_eq!(position, expected_position);
1602 }
1603 Some(CursorMessage::SetVisibility(_)) => {
1604 panic!("Received unexpected cursor visibility update.")
1605 }
1606 None => panic!("Did not receive cursor update."),
1607 }
1608 }
1609
1610 #[fuchsia::test(allow_stalls = false)]
1612 async fn down_move_up_event() {
1613 let (configuration_proxy, mut configuration_request_stream) =
1615 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1616 let (injector_registry_proxy, injector_registry_request_stream) =
1617 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1618 let config_request_stream_fut =
1619 handle_configuration_request_stream(&mut configuration_request_stream);
1620
1621 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(3);
1625 let inspector = fuchsia_inspect::Inspector::default();
1626 let test_node = inspector.root().create_child("test_node");
1627 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1628 configuration_proxy,
1629 injector_registry_proxy,
1630 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1631 sender,
1632 &test_node,
1633 metrics::MetricsLogger::default(),
1634 );
1635 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1636 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1637
1638 let event_time1 = zx::MonotonicInstant::get();
1639 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
1640 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
1641 let zero_position = Position { x: 0.0, y: 0.0 };
1642 let expected_position = Position {
1643 x: 10.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
1644 y: 5.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
1645 };
1646 let expected_relative_motion = [
1647 10.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
1648 5.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
1649 ];
1650 let event1 = create_mouse_event(
1651 mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 }),
1652 None, None, None, mouse_binding::MousePhase::Down,
1656 HashSet::from_iter(vec![1]),
1657 HashSet::from_iter(vec![1]),
1658 event_time1,
1659 &DESCRIPTOR,
1660 );
1661 let event2 = create_mouse_event(
1662 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1663 millimeters: Position { x: 10.0, y: 5.0 },
1664 }),
1665 None, None, None, mouse_binding::MousePhase::Move,
1669 HashSet::from_iter(vec![1]),
1670 HashSet::from_iter(vec![1]),
1671 event_time2,
1672 &DESCRIPTOR,
1673 );
1674 let event3 = create_mouse_event(
1675 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1676 millimeters: Position { x: 0.0, y: 0.0 },
1677 }),
1678 None, None, None, mouse_binding::MousePhase::Up,
1682 HashSet::from_iter(vec![1]),
1683 HashSet::from_iter(vec![]),
1684 event_time3,
1685 &DESCRIPTOR,
1686 );
1687
1688 let (injector_stream_sender, injector_stream_receiver) =
1692 mpsc::unbounded::<Vec<pointerinjector::Event>>();
1693 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
1695 let registry_fut = handle_registry_request_stream2(
1696 injector_registry_request_stream,
1697 injector_stream_sender,
1698 );
1699
1700 let _registry_task = fasync::Task::local(registry_fut);
1702 mouse_handler.clone().handle_input_event(event1).await;
1703 assert_eq!(
1704 injector_stream_receiver
1705 .next()
1706 .await
1707 .map(|events| events.into_iter().flatten().collect()),
1708 Some(vec![
1709 create_mouse_pointer_sample_event_phase_add(vec![1], zero_position, event_time1,),
1710 create_mouse_pointer_sample_event(
1711 pointerinjector::EventPhase::Change,
1712 vec![1],
1713 zero_position,
1714 None, None, None, None, event_time1,
1719 )
1720 ])
1721 );
1722
1723 match receiver.next().await {
1725 Some(CursorMessage::SetPosition(position)) => {
1726 assert_eq!(position, zero_position);
1727 }
1728 Some(CursorMessage::SetVisibility(_)) => {
1729 panic!("Received unexpected cursor visibility update.")
1730 }
1731 None => panic!("Did not receive cursor update."),
1732 }
1733
1734 mouse_handler.clone().handle_input_event(event2).await;
1736 assert_eq!(
1737 injector_stream_receiver
1738 .next()
1739 .await
1740 .map(|events| events.into_iter().flatten().collect()),
1741 Some(vec![create_mouse_pointer_sample_event(
1742 pointerinjector::EventPhase::Change,
1743 vec![1],
1744 expected_position,
1745 Some(expected_relative_motion),
1746 None, None, None, event_time2,
1750 )])
1751 );
1752
1753 match receiver.next().await {
1755 Some(CursorMessage::SetPosition(position)) => {
1756 assert_eq!(position, expected_position);
1757 }
1758 Some(CursorMessage::SetVisibility(_)) => {
1759 panic!("Received unexpected cursor visibility update.")
1760 }
1761 None => panic!("Did not receive cursor update."),
1762 }
1763
1764 mouse_handler.clone().handle_input_event(event3).await;
1766 assert_eq!(
1767 injector_stream_receiver
1768 .next()
1769 .await
1770 .map(|events| events.into_iter().flatten().collect()),
1771 Some(vec![create_mouse_pointer_sample_event(
1772 pointerinjector::EventPhase::Change,
1773 vec![],
1774 expected_position,
1775 None, None, None, None, event_time3,
1780 )])
1781 );
1782
1783 match receiver.next().await {
1785 Some(CursorMessage::SetPosition(position)) => {
1786 assert_eq!(position, expected_position);
1787 }
1788 Some(CursorMessage::SetVisibility(_)) => {
1789 panic!("Received unexpected cursor visibility update.")
1790 }
1791 None => panic!("Did not receive cursor update."),
1792 }
1793 }
1794
1795 #[fuchsia::test(allow_stalls = false)]
1797 async fn handler_ignores_handled_events() {
1798 let (configuration_proxy, mut configuration_request_stream) =
1800 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1801 let (injector_registry_proxy, injector_registry_request_stream) =
1802 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1803 let config_request_stream_fut =
1804 handle_configuration_request_stream(&mut configuration_request_stream);
1805
1806 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
1808 let inspector = fuchsia_inspect::Inspector::default();
1809 let test_node = inspector.root().create_child("test_node");
1810 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1811 configuration_proxy,
1812 injector_registry_proxy,
1813 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1814 sender,
1815 &test_node,
1816 metrics::MetricsLogger::default(),
1817 );
1818 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1819 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1820
1821 let cursor_relative_position = Position { x: 50.0, y: 75.0 };
1822 let cursor_location =
1823 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1824 millimeters: Position {
1825 x: cursor_relative_position.x / COUNTS_PER_MM as f32,
1826 y: cursor_relative_position.y / COUNTS_PER_MM as f32,
1827 },
1828 });
1829 let event_time = zx::MonotonicInstant::get();
1830 let input_events = vec![create_mouse_event_with_handled(
1831 cursor_location,
1832 None, None, None, mouse_binding::MousePhase::Move,
1836 HashSet::new(),
1837 HashSet::new(),
1838 event_time,
1839 &DESCRIPTOR,
1840 input_device::Handled::Yes,
1841 )];
1842
1843 assert_handler_ignores_input_event_sequence(
1844 mouse_handler,
1845 input_events,
1846 injector_registry_request_stream,
1847 )
1848 .await;
1849
1850 assert!(receiver.next().await.is_none());
1852 }
1853
1854 fn zero_relative_location() -> mouse_binding::MouseLocation {
1855 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1856 millimeters: Position { x: 0.0, y: 0.0 },
1857 })
1858 }
1859
1860 #[test_case(
1861 create_mouse_event(
1862 zero_relative_location(),
1863 wheel_delta_ticks(1, None), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1867 HashSet::new(),
1868 HashSet::new(),
1869 zx::MonotonicInstant::ZERO,
1870 &DESCRIPTOR,
1871 ),
1872 create_mouse_pointer_sample_event(
1873 pointerinjector::EventPhase::Change,
1874 vec![],
1875 Position { x: 50.0, y: 50.0 },
1876 None, Some(1), None, Some(false), zx::MonotonicInstant::ZERO,
1881 ); "v tick scroll"
1882 )]
1883 #[test_case(
1884 create_mouse_event(
1885 zero_relative_location(),
1886 None, wheel_delta_ticks(1, None), Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1890 HashSet::new(),
1891 HashSet::new(),
1892 zx::MonotonicInstant::ZERO,
1893 &DESCRIPTOR,
1894 ),
1895 create_mouse_pointer_sample_event(
1896 pointerinjector::EventPhase::Change,
1897 vec![],
1898 Position { x: 50.0, y: 50.0 },
1899 None, None, Some(1), Some(false), zx::MonotonicInstant::ZERO,
1904 ); "h tick scroll"
1905 )]
1906 #[test_case(
1907 create_mouse_event(
1908 zero_relative_location(),
1909 wheel_delta_ticks(1, Some(120.0)), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1913 HashSet::new(),
1914 HashSet::new(),
1915 zx::MonotonicInstant::ZERO,
1916 &DESCRIPTOR,
1917 ),
1918 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
1919 pointerinjector::EventPhase::Change,
1920 vec![],
1921 Position { x: 50.0, y: 50.0 },
1922 None, Some(1), None, Some(120.0), None, Some(false), zx::MonotonicInstant::ZERO,
1929 ); "v tick scroll with physical pixel"
1930 )]
1931 #[test_case(
1932 create_mouse_event(
1933 zero_relative_location(),
1934 None, wheel_delta_ticks(1, Some(120.0)), Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1938 HashSet::new(),
1939 HashSet::new(),
1940 zx::MonotonicInstant::ZERO,
1941 &DESCRIPTOR,
1942 ),
1943 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
1944 pointerinjector::EventPhase::Change,
1945 vec![],
1946 Position { x: 50.0, y: 50.0 },
1947 None, None, Some(1), None, Some(120.0), Some(false), zx::MonotonicInstant::ZERO,
1954 ); "h tick scroll with physical pixel"
1955 )]
1956 #[test_case(
1957 create_mouse_event(
1958 zero_relative_location(),
1959 wheel_delta_mm(1.0, Some(120.0)), None, Some(mouse_binding::PrecisionScroll::Yes), mouse_binding::MousePhase::Wheel,
1963 HashSet::new(),
1964 HashSet::new(),
1965 zx::MonotonicInstant::ZERO,
1966 &DESCRIPTOR,
1967 ),
1968 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
1969 pointerinjector::EventPhase::Change,
1970 vec![],
1971 Position { x: 50.0, y: 50.0 },
1972 None, None, None, Some(120.0), None, Some(true), zx::MonotonicInstant::ZERO,
1979 ); "v mm scroll with physical pixel"
1980 )]
1981 #[test_case(
1982 create_mouse_event(
1983 zero_relative_location(),
1984 None, wheel_delta_mm(1.0, Some(120.0)), Some(mouse_binding::PrecisionScroll::Yes), mouse_binding::MousePhase::Wheel,
1988 HashSet::new(),
1989 HashSet::new(),
1990 zx::MonotonicInstant::ZERO,
1991 &DESCRIPTOR,
1992 ),
1993 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
1994 pointerinjector::EventPhase::Change,
1995 vec![],
1996 Position { x: 50.0, y: 50.0 },
1997 None, None, None, None, Some(120.0), Some(true), zx::MonotonicInstant::ZERO,
2004 ); "h mm scroll with physical pixel"
2005 )]
2006 #[fuchsia::test(allow_stalls = false)]
2008 async fn scroll(event: input_device::InputEvent, want_event: pointerinjector::Event) {
2009 let (configuration_proxy, mut configuration_request_stream) =
2011 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
2012 let (injector_registry_proxy, injector_registry_request_stream) =
2013 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
2014 let config_request_stream_fut =
2015 handle_configuration_request_stream(&mut configuration_request_stream);
2016
2017 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
2019 let inspector = fuchsia_inspect::Inspector::default();
2020 let test_node = inspector.root().create_child("test_node");
2021 let mouse_handler_fut = MouseInjectorHandler::new_handler(
2022 configuration_proxy,
2023 injector_registry_proxy,
2024 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
2025 sender,
2026 &test_node,
2027 metrics::MetricsLogger::default(),
2028 );
2029 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
2030 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
2031
2032 let (injector_stream_sender, injector_stream_receiver) =
2036 mpsc::unbounded::<Vec<pointerinjector::Event>>();
2037 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
2039 let registry_fut = handle_registry_request_stream2(
2040 injector_registry_request_stream,
2041 injector_stream_sender,
2042 );
2043
2044 let event_time = zx::MonotonicInstant::get();
2045
2046 let event = input_device::InputEvent { event_time, ..event };
2047
2048 let want_event =
2049 pointerinjector::Event { timestamp: Some(event_time.into_nanos()), ..want_event };
2050
2051 let _registry_task = fasync::Task::local(registry_fut);
2053
2054 mouse_handler.clone().handle_input_event(event).await;
2055 let got_events: Vec<_> = injector_stream_receiver
2056 .next()
2057 .await
2058 .map(|events| events.into_iter().flatten().collect())
2059 .unwrap();
2060 pretty_assertions::assert_eq!(got_events.len(), 2);
2061 assert_matches!(
2062 got_events[0],
2063 pointerinjector::Event {
2064 data: Some(pointerinjector::Data::PointerSample(pointerinjector::PointerSample {
2065 phase: Some(pointerinjector::EventPhase::Add),
2066 ..
2067 })),
2068 ..
2069 }
2070 );
2071
2072 pretty_assertions::assert_eq!(got_events[1], want_event);
2073 }
2074
2075 #[fuchsia::test(allow_stalls = false)]
2077 async fn down_scroll_up_scroll() {
2078 let (configuration_proxy, mut configuration_request_stream) =
2080 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
2081 let (injector_registry_proxy, injector_registry_request_stream) =
2082 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
2083 let config_request_stream_fut =
2084 handle_configuration_request_stream(&mut configuration_request_stream);
2085
2086 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
2088 let inspector = fuchsia_inspect::Inspector::default();
2089 let test_node = inspector.root().create_child("test_node");
2090 let mouse_handler_fut = MouseInjectorHandler::new_handler(
2091 configuration_proxy,
2092 injector_registry_proxy,
2093 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
2094 sender,
2095 &test_node,
2096 metrics::MetricsLogger::default(),
2097 );
2098 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
2099 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
2100
2101 let (injector_stream_sender, injector_stream_receiver) =
2105 mpsc::unbounded::<Vec<pointerinjector::Event>>();
2106 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
2108 let registry_fut = handle_registry_request_stream2(
2109 injector_registry_request_stream,
2110 injector_stream_sender,
2111 );
2112
2113 let event_time1 = zx::MonotonicInstant::get();
2114 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
2115 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
2116 let event_time4 = event_time3.add(zx::MonotonicDuration::from_micros(1));
2117
2118 let _registry_task = fasync::Task::local(registry_fut);
2120
2121 let zero_location =
2122 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
2123 millimeters: Position { x: 0.0, y: 0.0 },
2124 });
2125 let expected_position = Position { x: 50.0, y: 50.0 };
2126
2127 let down_event = create_mouse_event(
2128 zero_location,
2129 None, None, None, mouse_binding::MousePhase::Down,
2133 HashSet::from_iter(vec![1]),
2134 HashSet::from_iter(vec![1]),
2135 event_time1,
2136 &DESCRIPTOR,
2137 );
2138
2139 let wheel_event = create_mouse_event(
2140 zero_location,
2141 wheel_delta_ticks(1, None), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
2145 HashSet::from_iter(vec![1]),
2146 HashSet::from_iter(vec![1]),
2147 event_time2,
2148 &DESCRIPTOR,
2149 );
2150
2151 let up_event = create_mouse_event(
2152 zero_location,
2153 None,
2154 None,
2155 None, mouse_binding::MousePhase::Up,
2157 HashSet::from_iter(vec![1]),
2158 HashSet::new(),
2159 event_time3,
2160 &DESCRIPTOR,
2161 );
2162
2163 let continue_wheel_event = create_mouse_event(
2164 zero_location,
2165 wheel_delta_ticks(1, None), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
2169 HashSet::new(),
2170 HashSet::new(),
2171 event_time4,
2172 &DESCRIPTOR,
2173 );
2174
2175 mouse_handler.clone().handle_input_event(down_event).await;
2177 assert_eq!(
2178 injector_stream_receiver
2179 .next()
2180 .await
2181 .map(|events| events.into_iter().flatten().collect()),
2182 Some(vec![
2183 create_mouse_pointer_sample_event_phase_add(
2184 vec![1],
2185 expected_position,
2186 event_time1,
2187 ),
2188 create_mouse_pointer_sample_event(
2189 pointerinjector::EventPhase::Change,
2190 vec![1],
2191 expected_position,
2192 None, None, None, None, event_time1,
2197 ),
2198 ])
2199 );
2200
2201 mouse_handler.clone().handle_input_event(wheel_event).await;
2203 assert_eq!(
2204 injector_stream_receiver
2205 .next()
2206 .await
2207 .map(|events| events.into_iter().flatten().collect()),
2208 Some(vec![create_mouse_pointer_sample_event(
2209 pointerinjector::EventPhase::Change,
2210 vec![1],
2211 expected_position,
2212 None, Some(1), None, Some(false), event_time2,
2217 )])
2218 );
2219
2220 mouse_handler.clone().handle_input_event(up_event).await;
2222 assert_eq!(
2223 injector_stream_receiver
2224 .next()
2225 .await
2226 .map(|events| events.into_iter().flatten().collect()),
2227 Some(vec![create_mouse_pointer_sample_event(
2228 pointerinjector::EventPhase::Change,
2229 vec![],
2230 expected_position,
2231 None, None, None, None, event_time3,
2236 )])
2237 );
2238
2239 mouse_handler.clone().handle_input_event(continue_wheel_event).await;
2241 assert_eq!(
2242 injector_stream_receiver
2243 .next()
2244 .await
2245 .map(|events| events.into_iter().flatten().collect()),
2246 Some(vec![create_mouse_pointer_sample_event(
2247 pointerinjector::EventPhase::Change,
2248 vec![],
2249 expected_position,
2250 None, Some(1), None, Some(false), event_time4,
2255 )])
2256 );
2257 }
2258
2259 #[fuchsia::test(allow_stalls = false)]
2260 async fn mouse_injector_handler_initialized_with_inspect_node() {
2261 let (configuration_proxy, mut configuration_request_stream) =
2262 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
2263 let config_request_stream_fut =
2264 handle_configuration_request_stream(&mut configuration_request_stream);
2265 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
2266 let inspector = fuchsia_inspect::Inspector::default();
2267 let fake_handlers_node = inspector.root().create_child("input_handlers_node");
2268 let incoming = Incoming::new();
2269 let mouse_handler_fut = MouseInjectorHandler::new_with_config_proxy(
2270 &incoming,
2271 configuration_proxy,
2272 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
2273 sender,
2274 &fake_handlers_node,
2275 metrics::MetricsLogger::default(),
2276 );
2277 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
2278 let _handler = mouse_handler_res.expect("Failed to create mouse handler");
2279
2280 diagnostics_assertions::assert_data_tree!(inspector, root: {
2281 input_handlers_node: {
2282 mouse_injector_handler: {
2283 events_received_count: 0u64,
2284 events_handled_count: 0u64,
2285 last_received_timestamp_ns: 0u64,
2286 "fuchsia.inspect.Health": {
2287 status: "STARTING_UP",
2288 start_timestamp_nanos: diagnostics_assertions::AnyProperty
2291 },
2292 }
2293 }
2294 });
2295 }
2296
2297 #[fuchsia::test(allow_stalls = false)]
2298 async fn mouse_injector_handler_inspect_counts_events() {
2299 let (configuration_proxy, mut configuration_request_stream) =
2301 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
2302 let (injector_registry_proxy, injector_registry_request_stream) =
2303 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
2304 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
2305
2306 let inspector = fuchsia_inspect::Inspector::default();
2307 let fake_handlers_node = inspector.root().create_child("input_handlers_node");
2308
2309 let mouse_handler_fut = MouseInjectorHandler::new_handler(
2311 configuration_proxy,
2312 injector_registry_proxy,
2313 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
2314 sender,
2315 &fake_handlers_node,
2316 metrics::MetricsLogger::default(),
2317 );
2318 let config_request_stream_fut =
2319 handle_configuration_request_stream(&mut configuration_request_stream);
2320
2321 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
2322 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
2323
2324 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
2325 let event_time1 = zx::MonotonicInstant::get();
2326 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
2327 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
2328
2329 let input_events = vec![
2330 create_mouse_event(
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_time1,
2339 &DESCRIPTOR,
2340 ),
2341 create_mouse_event(
2342 cursor_location,
2343 None, None, None, mouse_binding::MousePhase::Up,
2347 HashSet::from_iter(vec![1]),
2348 HashSet::new(),
2349 event_time2,
2350 &DESCRIPTOR,
2351 ),
2352 create_mouse_event_with_handled(
2353 cursor_location,
2354 None, None, None, mouse_binding::MousePhase::Down,
2358 HashSet::from_iter(vec![1]),
2359 HashSet::from_iter(vec![1]),
2360 event_time3,
2361 &DESCRIPTOR,
2362 input_device::Handled::Yes,
2363 ),
2364 ];
2365
2366 let (injector_stream_sender, _) = mpsc::unbounded::<Vec<pointerinjector::Event>>();
2370 let registry_fut = handle_registry_request_stream2(
2371 injector_registry_request_stream,
2372 injector_stream_sender,
2373 );
2374
2375 let _registry_task = fasync::Task::local(registry_fut);
2377 for input_event in input_events {
2378 mouse_handler.clone().handle_input_event(input_event).await;
2379 }
2380
2381 let last_received_event_time: u64 = event_time2.into_nanos().try_into().unwrap();
2382
2383 diagnostics_assertions::assert_data_tree!(inspector, root: {
2384 input_handlers_node: {
2385 mouse_injector_handler: {
2386 events_received_count: 2u64,
2387 events_handled_count: 2u64,
2388 last_received_timestamp_ns: last_received_event_time,
2389 "fuchsia.inspect.Health": {
2390 status: "STARTING_UP",
2391 start_timestamp_nanos: diagnostics_assertions::AnyProperty
2394 },
2395 }
2396 }
2397 });
2398 }
2399}