1#![warn(clippy::await_holding_refcell_ref)]
6
7use crate::input_handler::{Handler, InputHandler, InputHandlerStatus};
8use crate::utils::{CursorMessage, Position, Size};
9use crate::{input_device, metrics, mouse_binding};
10use anyhow::{Context, Error, Result, anyhow};
11use async_trait::async_trait;
12use async_utils::hanging_get::client::HangingGetStream;
13use fidl::endpoints::create_proxy;
14use fidl_fuchsia_input_report::Range;
15use fuchsia_component::client::connect_to_protocol;
16use fuchsia_inspect::health::Reporter;
17use futures::SinkExt;
18use futures::channel::mpsc::Sender;
19use futures::stream::StreamExt;
20use metrics_registry::*;
21use std::cell::{Ref, RefCell, RefMut};
22use std::collections::HashMap;
23use std::rc::Rc;
24use {
25 fidl_fuchsia_ui_pointerinjector as pointerinjector,
26 fidl_fuchsia_ui_pointerinjector_configuration as pointerinjector_config,
27};
28
29const MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL: f32 = 10.0;
37
38pub struct MouseInjectorHandler {
41 mutable_state: RefCell<MutableState>,
43
44 context_view_ref: fidl_fuchsia_ui_views::ViewRef,
47
48 target_view_ref: fidl_fuchsia_ui_views::ViewRef,
51
52 max_position: Position,
55
56 injector_registry_proxy: pointerinjector::RegistryProxy,
58
59 configuration_proxy: pointerinjector_config::SetupProxy,
61
62 pub inspect_status: InputHandlerStatus,
64
65 metrics_logger: metrics::MetricsLogger,
66}
67
68struct MutableState {
69 viewport: Option<pointerinjector::Viewport>,
72
73 injectors: HashMap<u32, pointerinjector::DeviceProxy>,
75
76 current_position: Position,
78
79 cursor_message_sender: Sender<CursorMessage>,
81}
82
83impl Handler for MouseInjectorHandler {
84 fn set_handler_healthy(self: std::rc::Rc<Self>) {
85 self.inspect_status.health_node.borrow_mut().set_ok();
86 }
87
88 fn set_handler_unhealthy(self: std::rc::Rc<Self>, msg: &str) {
89 self.inspect_status.health_node.borrow_mut().set_unhealthy(msg);
90 }
91
92 fn get_name(&self) -> &'static str {
93 "MouseInjectorHandler"
94 }
95
96 fn interest(&self) -> Vec<input_device::InputEventType> {
97 vec![input_device::InputEventType::Mouse]
98 }
99}
100
101#[async_trait(?Send)]
102impl InputHandler for MouseInjectorHandler {
103 async fn handle_input_event(
104 self: Rc<Self>,
105 mut input_event: input_device::InputEvent,
106 ) -> Vec<input_device::InputEvent> {
107 fuchsia_trace::duration!("input", "mouse_injector_handler");
108 match input_event {
109 input_device::InputEvent {
110 device_event: input_device::InputDeviceEvent::Mouse(ref mouse_event),
111 device_descriptor:
112 input_device::InputDeviceDescriptor::Mouse(ref mouse_device_descriptor),
113 event_time,
114 handled: input_device::Handled::No,
115 trace_id,
116 } => {
117 fuchsia_trace::duration!("input", "mouse_injector_handler[processing]");
118 let trace_id = match trace_id {
119 Some(id) => {
120 fuchsia_trace::flow_step!("input", "event_in_input_pipeline", id.into());
121 id
122 }
123 None => fuchsia_trace::Id::random(),
124 };
125
126 self.inspect_status.count_received_event(&event_time);
127 if let Err(e) =
129 self.update_cursor_renderer(mouse_event, &mouse_device_descriptor).await
130 {
131 self.metrics_logger.log_error(
132 InputPipelineErrorMetricDimensionEvent::MouseInjectorUpdateCursorRendererFailed,
133 std::format!("update_cursor_renderer failed: {}", e));
134 }
135
136 if let Err(e) = self
138 .ensure_injector_registered(&mouse_event, &mouse_device_descriptor, event_time)
139 .await
140 {
141 self.metrics_logger.log_error(
142 InputPipelineErrorMetricDimensionEvent::MouseInjectorEnsureInjectorRegisteredFailed,
143 std::format!("ensure_injector_registered failed: {}", e));
144 }
145
146 if let Err(e) = self
148 .send_event_to_scenic(
149 &mouse_event,
150 &mouse_device_descriptor,
151 event_time,
152 trace_id.into(),
153 )
154 .await
155 {
156 self.metrics_logger.log_error(
157 InputPipelineErrorMetricDimensionEvent::MouseInjectorSendEventToScenicFailed,
158 std::format!("send_event_to_scenic failed: {}", e));
159 }
160
161 input_event.handled = input_device::Handled::Yes;
163 self.inspect_status.count_handled_event();
164 }
165 _ => {
166 self.metrics_logger.log_error(
167 InputPipelineErrorMetricDimensionEvent::HandlerReceivedUninterestedEvent,
168 std::format!("uninterested input event: {:?}", input_event.get_event_type()),
169 );
170 }
171 }
172 vec![input_event]
173 }
174}
175
176impl MouseInjectorHandler {
177 pub async fn new(
190 display_size: Size,
191 cursor_message_sender: Sender<CursorMessage>,
192 input_handlers_node: &fuchsia_inspect::Node,
193 metrics_logger: metrics::MetricsLogger,
194 ) -> Result<Rc<Self>, Error> {
195 let configuration_proxy = connect_to_protocol::<pointerinjector_config::SetupMarker>()?;
196 let injector_registry_proxy = connect_to_protocol::<pointerinjector::RegistryMarker>()?;
197
198 Self::new_handler(
199 configuration_proxy,
200 injector_registry_proxy,
201 display_size,
202 cursor_message_sender,
203 input_handlers_node,
204 metrics_logger,
205 )
206 .await
207 }
208
209 pub async fn new_with_config_proxy(
225 configuration_proxy: pointerinjector_config::SetupProxy,
226 display_size: Size,
227 cursor_message_sender: Sender<CursorMessage>,
228 input_handlers_node: &fuchsia_inspect::Node,
229 metrics_logger: metrics::MetricsLogger,
230 ) -> Result<Rc<Self>, Error> {
231 let injector_registry_proxy = connect_to_protocol::<pointerinjector::RegistryMarker>()?;
232 Self::new_handler(
233 configuration_proxy,
234 injector_registry_proxy,
235 display_size,
236 cursor_message_sender,
237 input_handlers_node,
238 metrics_logger,
239 )
240 .await
241 }
242
243 fn inner(&self) -> Ref<'_, MutableState> {
244 self.mutable_state.borrow()
245 }
246
247 fn inner_mut(&self) -> RefMut<'_, MutableState> {
248 self.mutable_state.borrow_mut()
249 }
250
251 async fn new_handler(
267 configuration_proxy: pointerinjector_config::SetupProxy,
268 injector_registry_proxy: pointerinjector::RegistryProxy,
269 display_size: Size,
270 cursor_message_sender: Sender<CursorMessage>,
271 input_handlers_node: &fuchsia_inspect::Node,
272 metrics_logger: metrics::MetricsLogger,
273 ) -> Result<Rc<Self>, Error> {
274 let (context_view_ref, target_view_ref) = configuration_proxy.get_view_refs().await?;
276 let inspect_status = InputHandlerStatus::new(
277 input_handlers_node,
278 "mouse_injector_handler",
279 false,
280 );
281 let handler = Rc::new(Self {
282 mutable_state: RefCell::new(MutableState {
283 viewport: None,
284 injectors: HashMap::new(),
285 current_position: Position {
287 x: display_size.width / 2.0,
288 y: display_size.height / 2.0,
289 },
290 cursor_message_sender,
291 }),
292 context_view_ref,
293 target_view_ref,
294 max_position: Position { x: display_size.width, y: display_size.height },
295 injector_registry_proxy,
296 configuration_proxy,
297 inspect_status,
298 metrics_logger,
299 });
300
301 Ok(handler)
302 }
303
304 async fn ensure_injector_registered(
312 self: &Rc<Self>,
313 mouse_event: &mouse_binding::MouseEvent,
314 mouse_descriptor: &mouse_binding::MouseDeviceDescriptor,
315 event_time: zx::MonotonicInstant,
316 ) -> Result<(), anyhow::Error> {
317 if self.inner().injectors.contains_key(&mouse_descriptor.device_id) {
318 return Ok(());
319 }
320
321 let (device_proxy, device_server) = create_proxy::<pointerinjector::DeviceMarker>();
323 let context = fuchsia_scenic::duplicate_view_ref(&self.context_view_ref)
324 .context("Failed to duplicate context view ref.")?;
325 let target = fuchsia_scenic::duplicate_view_ref(&self.target_view_ref)
326 .context("Failed to duplicate target view ref.")?;
327
328 let viewport = self.inner().viewport.clone();
329 let config = pointerinjector::Config {
330 device_id: Some(mouse_descriptor.device_id),
331 device_type: Some(pointerinjector::DeviceType::Mouse),
332 context: Some(pointerinjector::Context::View(context)),
333 target: Some(pointerinjector::Target::View(target)),
334 viewport,
335 dispatch_policy: Some(pointerinjector::DispatchPolicy::MouseHoverAndLatchInTarget),
336 scroll_v_range: mouse_descriptor.wheel_v_range.clone(),
337 scroll_h_range: mouse_descriptor.wheel_h_range.clone(),
338 buttons: mouse_descriptor.buttons.clone(),
339 ..Default::default()
340 };
341
342 self.injector_registry_proxy
344 .register(config, device_server)
345 .await
346 .context("Failed to register injector.")?;
347 log::info!("Registered injector with device id {:?}", mouse_descriptor.device_id);
348
349 self.inner_mut().injectors.insert(mouse_descriptor.device_id, device_proxy.clone());
351
352 let events_to_send = vec![self.create_pointer_sample_event(
354 mouse_event,
355 event_time,
356 pointerinjector::EventPhase::Add,
357 self.inner().current_position,
358 None,
359 None,
360 )];
361 device_proxy.inject_events(events_to_send).context("Failed to ADD new MouseDevice.")?;
362
363 Ok(())
364 }
365
366 async fn update_cursor_renderer(
377 &self,
378 mouse_event: &mouse_binding::MouseEvent,
379 mouse_descriptor: &mouse_binding::MouseDeviceDescriptor,
380 ) -> Result<(), anyhow::Error> {
381 let mut new_position = match (mouse_event.location, mouse_descriptor) {
382 (
383 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
384 millimeters,
385 }),
386 _,
387 ) => {
388 self.inner().current_position
389 + self.relative_movement_mm_to_phyical_pixel(millimeters)
390 }
391 (
392 mouse_binding::MouseLocation::Absolute(position),
393 mouse_binding::MouseDeviceDescriptor {
394 absolute_x_range: Some(x_range),
395 absolute_y_range: Some(y_range),
396 ..
397 },
398 ) => self.scale_absolute_position(&position, &x_range, &y_range),
399 (mouse_binding::MouseLocation::Absolute(_), _) => {
400 return Err(anyhow!(
401 "Received an Absolute mouse location without absolute device ranges."
402 ));
403 }
404 };
405 Position::clamp(&mut new_position, Position::zero(), self.max_position);
406 self.inner_mut().current_position = new_position;
407
408 let mut cursor_message_sender = self.inner().cursor_message_sender.clone();
409 cursor_message_sender
410 .send(CursorMessage::SetPosition(new_position))
411 .await
412 .context("Failed to send current mouse position to cursor renderer")?;
413
414 Ok(())
415 }
416
417 fn scale_absolute_position(
425 &self,
426 position: &Position,
427 x_range: &Range,
428 y_range: &Range,
429 ) -> Position {
430 let range_min = Position { x: x_range.min as f32, y: y_range.min as f32 };
431 let range_max = Position { x: x_range.max as f32, y: y_range.max as f32 };
432 self.max_position * ((*position - range_min) / (range_max - range_min))
433 }
434
435 async fn send_event_to_scenic(
442 &self,
443 mouse_event: &mouse_binding::MouseEvent,
444 mouse_descriptor: &mouse_binding::MouseDeviceDescriptor,
445 event_time: zx::MonotonicInstant,
446 tracing_id: u64,
447 ) -> Result<(), anyhow::Error> {
448 let injector = self.inner().injectors.get(&mouse_descriptor.device_id).cloned();
449 if let Some(injector) = injector {
450 let relative_motion = match mouse_event.location {
451 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
452 millimeters: offset_mm,
453 }) if mouse_event.phase == mouse_binding::MousePhase::Move => {
454 let offset = self.relative_movement_mm_to_phyical_pixel(offset_mm);
455 Some([offset.x, offset.y])
456 }
457 _ => None,
458 };
459 let events_to_send = vec![self.create_pointer_sample_event(
460 mouse_event,
461 event_time,
462 pointerinjector::EventPhase::Change,
463 self.inner().current_position,
464 relative_motion,
465 Some(tracing_id),
466 )];
467
468 fuchsia_trace::flow_begin!("input", "dispatch_event_to_scenic", tracing_id.into());
469
470 let _ = injector.inject_events(events_to_send);
471
472 Ok(())
473 } else {
474 Err(anyhow::format_err!(
475 "No injector found for mouse device {}.",
476 mouse_descriptor.device_id
477 ))
478 }
479 }
480
481 fn create_pointer_sample_event(
490 &self,
491 mouse_event: &mouse_binding::MouseEvent,
492 event_time: zx::MonotonicInstant,
493 phase: pointerinjector::EventPhase,
494 current_position: Position,
495 relative_motion: Option<[f32; 2]>,
496 trace_id: Option<u64>,
497 ) -> pointerinjector::Event {
498 let pointer_sample = pointerinjector::PointerSample {
499 pointer_id: Some(0),
500 phase: Some(phase),
501 position_in_viewport: Some([current_position.x, current_position.y]),
502 scroll_v: match mouse_event.wheel_delta_v {
503 Some(mouse_binding::WheelDelta {
504 raw_data: mouse_binding::RawWheelDelta::Ticks(tick),
505 ..
506 }) => Some(tick),
507 _ => None,
508 },
509 scroll_h: match mouse_event.wheel_delta_h {
510 Some(mouse_binding::WheelDelta {
511 raw_data: mouse_binding::RawWheelDelta::Ticks(tick),
512 ..
513 }) => Some(tick),
514 _ => None,
515 },
516 scroll_v_physical_pixel: match mouse_event.wheel_delta_v {
517 Some(mouse_binding::WheelDelta { physical_pixel: Some(pixel), .. }) => {
518 Some(pixel.into())
519 }
520 _ => None,
521 },
522 scroll_h_physical_pixel: match mouse_event.wheel_delta_h {
523 Some(mouse_binding::WheelDelta { physical_pixel: Some(pixel), .. }) => {
524 Some(pixel.into())
525 }
526 _ => None,
527 },
528 is_precision_scroll: match mouse_event.phase {
529 mouse_binding::MousePhase::Wheel => match mouse_event.is_precision_scroll {
530 Some(mouse_binding::PrecisionScroll::Yes) => Some(true),
531 Some(mouse_binding::PrecisionScroll::No) => Some(false),
532 None => {
533 self.metrics_logger.log_error(
534 InputPipelineErrorMetricDimensionEvent::MouseInjectorMissingIsPrecisionScroll,
535 "mouse wheel event does not have value in is_precision_scroll.");
536 None
537 }
538 },
539 _ => None,
540 },
541 pressed_buttons: Some(Vec::from_iter(mouse_event.pressed_buttons.iter().cloned())),
542 relative_motion,
543 ..Default::default()
544 };
545 pointerinjector::Event {
546 timestamp: Some(event_time.into_nanos()),
547 data: Some(pointerinjector::Data::PointerSample(pointer_sample)),
548 trace_flow_id: trace_id,
549 wake_lease: mouse_event.wake_lease.lock().take(),
550 ..Default::default()
551 }
552 }
553
554 pub async fn watch_viewport(self: Rc<Self>) {
556 let configuration_proxy = self.configuration_proxy.clone();
557 let mut viewport_stream = HangingGetStream::new(
558 configuration_proxy,
559 pointerinjector_config::SetupProxy::watch_viewport,
560 );
561 loop {
562 match viewport_stream.next().await {
563 Some(Ok(new_viewport)) => {
564 self.inner_mut().viewport = Some(new_viewport.clone());
566
567 let injectors = self.inner().injectors.values().cloned().collect::<Vec<_>>();
569 for injector in injectors {
570 let events = vec![pointerinjector::Event {
571 timestamp: Some(fuchsia_async::MonotonicInstant::now().into_nanos()),
572 data: Some(pointerinjector::Data::Viewport(new_viewport.clone())),
573 trace_flow_id: Some(fuchsia_trace::Id::random().into()),
574 ..Default::default()
575 }];
576 injector.inject_events(events).expect("Failed to inject updated viewport.");
577 }
578 }
579 Some(Err(e)) => {
580 self.metrics_logger.log_error(
581 InputPipelineErrorMetricDimensionEvent::MouseInjectorErrorWhileReadingViewportUpdate,
582 std::format!("Error while reading viewport update: {}", e));
583 return;
584 }
585 None => {
586 self.metrics_logger.log_error(
587 InputPipelineErrorMetricDimensionEvent::MouseInjectorViewportUpdateStreamTerminatedUnexpectedly,
588 "Viewport update stream terminated unexpectedly");
589 return;
590 }
591 }
592 }
593 }
594
595 fn relative_movement_mm_to_phyical_pixel(&self, movement_mm: Position) -> Position {
599 Position {
600 x: movement_mm.x * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
601 y: movement_mm.y * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
602 }
603 }
604}
605
606#[cfg(test)]
607mod tests {
608 use super::*;
609 use crate::testing_utilities::{
610 assert_handler_ignores_input_event_sequence, create_mouse_event,
611 create_mouse_event_with_handled, create_mouse_pointer_sample_event,
612 create_mouse_pointer_sample_event_phase_add,
613 create_mouse_pointer_sample_event_with_wheel_physical_pixel,
614 };
615 use assert_matches::assert_matches;
616 use futures::channel::mpsc;
617 use pretty_assertions::assert_eq;
618 use std::collections::HashSet;
619 use std::ops::Add;
620 use test_case::test_case;
621 use {
622 fidl_fuchsia_input_report as fidl_input_report,
623 fidl_fuchsia_ui_pointerinjector as pointerinjector, fuchsia_async as fasync,
624 };
625
626 const DISPLAY_WIDTH_IN_PHYSICAL_PX: f32 = 100.0;
627 const DISPLAY_HEIGHT_IN_PHYSICAL_PX: f32 = 100.0;
628 const COUNTS_PER_MM: u32 = 12;
629
630 const DESCRIPTOR: input_device::InputDeviceDescriptor =
632 input_device::InputDeviceDescriptor::Mouse(mouse_binding::MouseDeviceDescriptor {
633 device_id: 1,
634 absolute_x_range: Some(fidl_input_report::Range { min: 0, max: 100 }),
635 absolute_y_range: Some(fidl_input_report::Range { min: 0, max: 100 }),
636 wheel_v_range: Some(fidl_input_report::Axis {
637 range: fidl_input_report::Range { min: -1, max: 1 },
638 unit: fidl_input_report::Unit {
639 type_: fidl_input_report::UnitType::Other,
640 exponent: 0,
641 },
642 }),
643 wheel_h_range: Some(fidl_input_report::Axis {
644 range: fidl_input_report::Range { min: -1, max: 1 },
645 unit: fidl_input_report::Unit {
646 type_: fidl_input_report::UnitType::Other,
647 exponent: 0,
648 },
649 }),
650 buttons: None,
651 counts_per_mm: COUNTS_PER_MM,
652 });
653
654 async fn handle_configuration_request_stream(
656 stream: &mut pointerinjector_config::SetupRequestStream,
657 ) {
658 if let Some(Ok(request)) = stream.next().await {
659 match request {
660 pointerinjector_config::SetupRequest::GetViewRefs { responder, .. } => {
661 let context = fuchsia_scenic::ViewRefPair::new()
662 .expect("Failed to create viewrefpair.")
663 .view_ref;
664 let target = fuchsia_scenic::ViewRefPair::new()
665 .expect("Failed to create viewrefpair.")
666 .view_ref;
667 let _ = responder.send(context, target);
668 }
669 _ => {}
670 };
671 }
672 }
673
674 async fn handle_registry_request_stream(
677 mut stream: pointerinjector::RegistryRequestStream,
678 injector_sender: futures::channel::oneshot::Sender<pointerinjector::DeviceRequestStream>,
679 ) {
680 if let Some(request) = stream.next().await {
681 match request {
682 Ok(pointerinjector::RegistryRequest::Register {
683 config: _,
684 injector,
685 responder,
686 ..
687 }) => {
688 let injector_stream = injector.into_stream();
689 let _ = injector_sender.send(injector_stream);
690 responder.send().expect("failed to respond");
691 }
692 _ => {}
693 };
694 } else {
695 panic!("RegistryRequestStream failed.");
696 }
697 }
698
699 async fn handle_registry_request_stream2(
701 mut stream: pointerinjector::RegistryRequestStream,
702 injector_sender: mpsc::UnboundedSender<Vec<pointerinjector::Event>>,
703 ) {
704 let (injector, responder) = match stream.next().await {
705 Some(Ok(pointerinjector::RegistryRequest::Register {
706 config: _,
707 injector,
708 responder,
709 ..
710 })) => (injector, responder),
711 other => panic!("expected register request, but got {:?}", other),
712 };
713 let injector_stream: pointerinjector::DeviceRequestStream = injector.into_stream();
714 responder.send().expect("failed to respond");
715 injector_stream
716 .for_each(|request| {
717 futures::future::ready({
718 match request {
719 Ok(pointerinjector::DeviceRequest::Inject { .. }) => {
720 panic!("DeviceRequest::Inject is deprecated.");
721 }
722 Ok(pointerinjector::DeviceRequest::InjectEvents { events, .. }) => {
723 let _ = injector_sender.unbounded_send(events);
724 }
725 Err(e) => panic!("FIDL error {}", e),
726 }
727 })
728 })
729 .await;
730 }
731
732 async fn handle_device_request_stream(
735 injector_stream_receiver: futures::channel::oneshot::Receiver<
736 pointerinjector::DeviceRequestStream,
737 >,
738 expected_events: Vec<pointerinjector::Event>,
739 ) {
740 let mut injector_stream =
741 injector_stream_receiver.await.expect("Failed to get DeviceRequestStream.");
742 for expected_event in expected_events {
743 match injector_stream.next().await {
744 Some(Ok(pointerinjector::DeviceRequest::Inject { .. })) => {
745 panic!("DeviceRequest::Inject is deprecated.");
746 }
747 Some(Ok(pointerinjector::DeviceRequest::InjectEvents { events, .. })) => {
748 assert_eq!(events, vec![expected_event]);
749 }
750 Some(Err(e)) => panic!("FIDL error {}", e),
751 None => panic!("Expected another event."),
752 }
753 }
754 }
755
756 fn create_viewport(min: f32, max: f32) -> pointerinjector::Viewport {
758 pointerinjector::Viewport {
759 extents: Some([[min, min], [max, max]]),
760 viewport_to_context_transform: None,
761 ..Default::default()
762 }
763 }
764
765 #[fuchsia::test]
768 fn receives_viewport_updates() {
769 let mut exec = fasync::TestExecutor::new();
770
771 let (configuration_proxy, mut configuration_request_stream) =
773 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
774 let (injector_registry_proxy, _) =
775 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
776 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(0);
777
778 let inspector = fuchsia_inspect::Inspector::default();
779 let test_node = inspector.root().create_child("test_node");
780
781 let mouse_handler_fut = MouseInjectorHandler::new_handler(
783 configuration_proxy,
784 injector_registry_proxy,
785 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
786 sender,
787 &test_node,
788 metrics::MetricsLogger::default(),
789 );
790 let config_request_stream_fut =
791 handle_configuration_request_stream(&mut configuration_request_stream);
792 let (mouse_handler_res, _) = exec.run_singlethreaded(futures::future::join(
793 mouse_handler_fut,
794 config_request_stream_fut,
795 ));
796 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
797
798 let (injector_device_proxy, mut injector_device_request_stream) =
800 fidl::endpoints::create_proxy_and_stream::<pointerinjector::DeviceMarker>();
801 mouse_handler.inner_mut().injectors.insert(1, injector_device_proxy);
802
803 {
805 let watch_viewport_fut = mouse_handler.clone().watch_viewport();
807 futures::pin_mut!(watch_viewport_fut);
808 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
809
810 match exec.run_singlethreaded(&mut configuration_request_stream.next()) {
812 Some(Ok(pointerinjector_config::SetupRequest::WatchViewport {
813 responder, ..
814 })) => {
815 responder.send(&create_viewport(0.0, 100.0)).expect("Failed to send viewport.");
816 }
817 other => panic!("Received unexpected value: {:?}", other),
818 };
819 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
820
821 exec.run_singlethreaded(async {
823 match injector_device_request_stream.next().await {
824 Some(Ok(pointerinjector::DeviceRequest::Inject { .. })) => {
825 panic!("DeviceRequest::Inject is deprecated.");
826 }
827 Some(Ok(pointerinjector::DeviceRequest::InjectEvents { events, .. })) => {
828 assert_eq!(events.len(), 1);
829 assert!(events[0].data.is_some());
830 assert_eq!(
831 events[0].data,
832 Some(pointerinjector::Data::Viewport(create_viewport(0.0, 100.0)))
833 );
834 }
835 other => panic!("Received unexpected value: {:?}", other),
836 }
837 });
838
839 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
841
842 match exec.run_singlethreaded(&mut configuration_request_stream.next()) {
844 Some(Ok(pointerinjector_config::SetupRequest::WatchViewport {
845 responder, ..
846 })) => {
847 responder
848 .send(&create_viewport(100.0, 200.0))
849 .expect("Failed to send viewport.");
850 }
851 other => panic!("Received unexpected value: {:?}", other),
852 };
853
854 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
856 }
857
858 exec.run_singlethreaded(async {
860 match injector_device_request_stream.next().await {
861 Some(Ok(pointerinjector::DeviceRequest::Inject { .. })) => {
862 panic!("DeviceRequest::Inject is deprecated.");
863 }
864 Some(Ok(pointerinjector::DeviceRequest::InjectEvents { events, .. })) => {
865 assert_eq!(events.len(), 1);
866 assert!(events[0].data.is_some());
867 assert_eq!(
868 events[0].data,
869 Some(pointerinjector::Data::Viewport(create_viewport(100.0, 200.0)))
870 );
871 }
872 other => panic!("Received unexpected value: {:?}", other),
873 }
874 });
875
876 let expected_viewport = create_viewport(100.0, 200.0);
878 assert_eq!(mouse_handler.inner().viewport, Some(expected_viewport));
879 }
880
881 fn wheel_delta_ticks(
882 ticks: i64,
883 physical_pixel: Option<f32>,
884 ) -> Option<mouse_binding::WheelDelta> {
885 Some(mouse_binding::WheelDelta {
886 raw_data: mouse_binding::RawWheelDelta::Ticks(ticks),
887 physical_pixel,
888 })
889 }
890
891 fn wheel_delta_mm(mm: f32, physical_pixel: Option<f32>) -> Option<mouse_binding::WheelDelta> {
892 Some(mouse_binding::WheelDelta {
893 raw_data: mouse_binding::RawWheelDelta::Millimeters(mm),
894 physical_pixel,
895 })
896 }
897
898 #[test_case(
901 mouse_binding::MouseLocation::Relative(
902 mouse_binding::RelativeLocation {
903 millimeters: Position { x: 1.0, y: 2.0 }
904 }),
905 Position {
906 x: DISPLAY_WIDTH_IN_PHYSICAL_PX / 2.0
907 + 1.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
908 y: DISPLAY_HEIGHT_IN_PHYSICAL_PX / 2.0
909 + 2.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
910 },
911 [
912 1.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
913 2.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
914 ]; "Valid move event."
915 )]
916 #[test_case(
917 mouse_binding::MouseLocation::Relative(
918 mouse_binding::RelativeLocation {
919 millimeters: Position {
920 x: DISPLAY_WIDTH_IN_PHYSICAL_PX / MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL + 2.0,
921 y: DISPLAY_HEIGHT_IN_PHYSICAL_PX / MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL + 1.0,
922 }}),
923 Position {
924 x: DISPLAY_WIDTH_IN_PHYSICAL_PX,
925 y: DISPLAY_HEIGHT_IN_PHYSICAL_PX,
926 },
927 [
928 DISPLAY_WIDTH_IN_PHYSICAL_PX + 2.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
929 DISPLAY_HEIGHT_IN_PHYSICAL_PX + 1.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
930 ]; "Move event exceeds max bounds."
931 )]
932 #[test_case(
933 mouse_binding::MouseLocation::Relative(
934 mouse_binding::RelativeLocation {
935 millimeters: Position {
936 x: -(DISPLAY_WIDTH_IN_PHYSICAL_PX / MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL + 2.0),
937 y: -(DISPLAY_HEIGHT_IN_PHYSICAL_PX / MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL + 1.0),
938 }}),
939 Position { x: 0.0, y: 0.0 },
940 [
941 -(DISPLAY_WIDTH_IN_PHYSICAL_PX + 2.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL),
942 -(DISPLAY_HEIGHT_IN_PHYSICAL_PX + 1.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL),
943 ]; "Move event exceeds min bounds."
944 )]
945 #[fuchsia::test(allow_stalls = false)]
946 async fn move_event(
947 move_location: mouse_binding::MouseLocation,
948 expected_position: Position,
949 expected_relative_motion: [f32; 2],
950 ) {
951 let (configuration_proxy, mut configuration_request_stream) =
953 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
954 let (injector_registry_proxy, injector_registry_request_stream) =
955 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
956 let config_request_stream_fut =
957 handle_configuration_request_stream(&mut configuration_request_stream);
958
959 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
961 let inspector = fuchsia_inspect::Inspector::default();
962 let test_node = inspector.root().create_child("test_node");
963 let mouse_handler_fut = MouseInjectorHandler::new_handler(
964 configuration_proxy,
965 injector_registry_proxy,
966 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
967 sender,
968 &test_node,
969 metrics::MetricsLogger::default(),
970 );
971 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
972 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
973
974 let event_time = zx::MonotonicInstant::get();
975 let input_event = create_mouse_event(
976 move_location,
977 None, None, None, mouse_binding::MousePhase::Move,
981 HashSet::new(),
982 HashSet::new(),
983 event_time,
984 &DESCRIPTOR,
985 );
986
987 let handle_event_fut = mouse_handler.handle_input_event(input_event);
989 let expected_events = vec![
990 create_mouse_pointer_sample_event_phase_add(vec![], expected_position, event_time),
991 create_mouse_pointer_sample_event(
992 pointerinjector::EventPhase::Change,
993 vec![],
994 expected_position,
995 Some(expected_relative_motion),
996 None, None, None, event_time,
1000 ),
1001 ];
1002
1003 let (injector_stream_sender, injector_stream_receiver) =
1007 futures::channel::oneshot::channel::<pointerinjector::DeviceRequestStream>();
1008 let registry_fut = handle_registry_request_stream(
1009 injector_registry_request_stream,
1010 injector_stream_sender,
1011 );
1012 let device_fut = handle_device_request_stream(injector_stream_receiver, expected_events);
1013
1014 let (handle_result, _, _) = futures::join!(handle_event_fut, registry_fut, device_fut);
1017 match receiver.next().await {
1018 Some(CursorMessage::SetPosition(position)) => {
1019 pretty_assertions::assert_eq!(position, expected_position);
1020 }
1021 Some(CursorMessage::SetVisibility(_)) => {
1022 panic!("Received unexpected cursor visibility update.")
1023 }
1024 None => panic!("Did not receive cursor update."),
1025 }
1026
1027 assert_matches!(
1029 handle_result.as_slice(),
1030 [input_device::InputEvent { handled: input_device::Handled::Yes, .. }]
1031 );
1032 }
1033
1034 #[fuchsia::test(allow_stalls = false)]
1037 async fn move_absolute_event() {
1038 const DEVICE_ID: u32 = 1;
1039
1040 let (configuration_proxy, mut configuration_request_stream) =
1042 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1043 let (injector_registry_proxy, injector_registry_request_stream) =
1044 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1045 let config_request_stream_fut =
1046 handle_configuration_request_stream(&mut configuration_request_stream);
1047
1048 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
1050 let inspector = fuchsia_inspect::Inspector::default();
1051 let test_node = inspector.root().create_child("test_node");
1052 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1053 configuration_proxy,
1054 injector_registry_proxy,
1055 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1056 sender,
1057 &test_node,
1058 metrics::MetricsLogger::default(),
1059 );
1060 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1061 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1062
1063 let cursor_location =
1079 mouse_binding::MouseLocation::Absolute(Position { x: -25.0, y: 25.0 });
1080 let event_time = zx::MonotonicInstant::get();
1081 let descriptor =
1082 input_device::InputDeviceDescriptor::Mouse(mouse_binding::MouseDeviceDescriptor {
1083 device_id: DEVICE_ID,
1084 absolute_x_range: Some(fidl_input_report::Range { min: -50, max: 50 }),
1085 absolute_y_range: Some(fidl_input_report::Range { min: -50, max: 50 }),
1086 wheel_v_range: None,
1087 wheel_h_range: None,
1088 buttons: None,
1089 counts_per_mm: COUNTS_PER_MM,
1090 });
1091 let input_event = create_mouse_event(
1092 cursor_location,
1093 None, None, None, mouse_binding::MousePhase::Move,
1097 HashSet::new(),
1098 HashSet::new(),
1099 event_time,
1100 &descriptor,
1101 );
1102
1103 let handle_event_fut = mouse_handler.handle_input_event(input_event);
1105 let expected_position = Position {
1106 x: DISPLAY_WIDTH_IN_PHYSICAL_PX * 0.25,
1107 y: DISPLAY_WIDTH_IN_PHYSICAL_PX * 0.75,
1108 };
1109 let expected_events = vec![
1110 create_mouse_pointer_sample_event_phase_add(vec![], expected_position, event_time),
1111 create_mouse_pointer_sample_event(
1112 pointerinjector::EventPhase::Change,
1113 vec![],
1114 expected_position,
1115 None, None, None, None, event_time,
1120 ),
1121 ];
1122
1123 let (injector_stream_sender, injector_stream_receiver) =
1127 futures::channel::oneshot::channel::<pointerinjector::DeviceRequestStream>();
1128 let registry_fut = handle_registry_request_stream(
1129 injector_registry_request_stream,
1130 injector_stream_sender,
1131 );
1132 let device_fut = handle_device_request_stream(injector_stream_receiver, expected_events);
1133
1134 let (handle_result, _, _) = futures::join!(handle_event_fut, registry_fut, device_fut);
1137 match receiver.next().await {
1138 Some(CursorMessage::SetPosition(position)) => {
1139 assert_eq!(position, expected_position);
1140 }
1141 Some(CursorMessage::SetVisibility(_)) => {
1142 panic!("Received unexpected cursor visibility update.")
1143 }
1144 None => panic!("Did not receive cursor update."),
1145 }
1146
1147 assert_matches!(
1149 handle_result.as_slice(),
1150 [input_device::InputEvent { handled: input_device::Handled::Yes, .. }]
1151 );
1152 }
1153
1154 #[test_case(
1156 mouse_binding::MousePhase::Down,
1157 vec![1], vec![1]; "Down event injects button press state."
1158 )]
1159 #[test_case(
1160 mouse_binding::MousePhase::Up,
1161 vec![1], vec![]; "Up event injects button press state."
1162 )]
1163 #[fuchsia::test(allow_stalls = false)]
1164 async fn button_state_event(
1165 phase: mouse_binding::MousePhase,
1166 affected_buttons: Vec<mouse_binding::MouseButton>,
1167 pressed_buttons: Vec<mouse_binding::MouseButton>,
1168 ) {
1169 let (configuration_proxy, mut configuration_request_stream) =
1171 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1172 let (injector_registry_proxy, injector_registry_request_stream) =
1173 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1174 let config_request_stream_fut =
1175 handle_configuration_request_stream(&mut configuration_request_stream);
1176
1177 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
1179 let inspector = fuchsia_inspect::Inspector::default();
1180 let test_node = inspector.root().create_child("test_node");
1181 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1182 configuration_proxy,
1183 injector_registry_proxy,
1184 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1185 sender,
1186 &test_node,
1187 metrics::MetricsLogger::default(),
1188 );
1189 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1190 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1191
1192 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
1193 let event_time = zx::MonotonicInstant::get();
1194
1195 let input_event = create_mouse_event(
1196 cursor_location,
1197 None, None, None, phase,
1201 HashSet::from_iter(affected_buttons.clone()),
1202 HashSet::from_iter(pressed_buttons.clone()),
1203 event_time,
1204 &DESCRIPTOR,
1205 );
1206
1207 let handle_event_fut = mouse_handler.handle_input_event(input_event);
1209 let expected_position = Position { x: 0.0, y: 0.0 };
1210 let expected_events = vec![
1211 create_mouse_pointer_sample_event_phase_add(
1212 pressed_buttons.clone(),
1213 expected_position,
1214 event_time,
1215 ),
1216 create_mouse_pointer_sample_event(
1217 pointerinjector::EventPhase::Change,
1218 pressed_buttons.clone(),
1219 expected_position,
1220 None, None, None, None, event_time,
1225 ),
1226 ];
1227
1228 let (injector_stream_sender, injector_stream_receiver) =
1232 futures::channel::oneshot::channel::<pointerinjector::DeviceRequestStream>();
1233 let registry_fut = handle_registry_request_stream(
1234 injector_registry_request_stream,
1235 injector_stream_sender,
1236 );
1237 let device_fut = handle_device_request_stream(injector_stream_receiver, expected_events);
1238
1239 let (handle_result, _, _) = futures::join!(handle_event_fut, registry_fut, device_fut);
1242 match receiver.next().await {
1243 Some(CursorMessage::SetPosition(position)) => {
1244 pretty_assertions::assert_eq!(position, expected_position);
1245 }
1246 Some(CursorMessage::SetVisibility(_)) => {
1247 panic!("Received unexpected cursor visibility update.")
1248 }
1249 None => panic!("Did not receive cursor update."),
1250 }
1251
1252 assert_matches!(
1254 handle_result.as_slice(),
1255 [input_device::InputEvent { handled: input_device::Handled::Yes, .. }]
1256 );
1257 }
1258
1259 #[fuchsia::test(allow_stalls = false)]
1261 async fn down_up_event() {
1262 let (configuration_proxy, mut configuration_request_stream) =
1264 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1265 let (injector_registry_proxy, injector_registry_request_stream) =
1266 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1267 let config_request_stream_fut =
1268 handle_configuration_request_stream(&mut configuration_request_stream);
1269
1270 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(2);
1274 let inspector = fuchsia_inspect::Inspector::default();
1275 let test_node = inspector.root().create_child("test_node");
1276 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1277 configuration_proxy,
1278 injector_registry_proxy,
1279 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1280 sender,
1281 &test_node,
1282 metrics::MetricsLogger::default(),
1283 );
1284 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1285 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1286
1287 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
1288 let event_time1 = zx::MonotonicInstant::get();
1289 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
1290
1291 let event1 = create_mouse_event(
1292 cursor_location,
1293 None, None, None, mouse_binding::MousePhase::Down,
1297 HashSet::from_iter(vec![1]),
1298 HashSet::from_iter(vec![1]),
1299 event_time1,
1300 &DESCRIPTOR,
1301 );
1302
1303 let event2 = create_mouse_event(
1304 cursor_location,
1305 None, None, None, mouse_binding::MousePhase::Up,
1309 HashSet::from_iter(vec![1]),
1310 HashSet::new(),
1311 event_time2,
1312 &DESCRIPTOR,
1313 );
1314
1315 let expected_position = Position { x: 0.0, y: 0.0 };
1316
1317 let (injector_stream_sender, injector_stream_receiver) =
1321 mpsc::unbounded::<Vec<pointerinjector::Event>>();
1322 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
1324 let registry_fut = handle_registry_request_stream2(
1325 injector_registry_request_stream,
1326 injector_stream_sender,
1327 );
1328
1329 let _registry_task = fasync::Task::local(registry_fut);
1331
1332 mouse_handler.clone().handle_input_event(event1).await;
1333 assert_eq!(
1334 injector_stream_receiver
1335 .next()
1336 .await
1337 .map(|events| events.into_iter().flatten().collect()),
1338 Some(vec![
1339 create_mouse_pointer_sample_event_phase_add(
1340 vec![1],
1341 expected_position,
1342 event_time1,
1343 ),
1344 create_mouse_pointer_sample_event(
1345 pointerinjector::EventPhase::Change,
1346 vec![1],
1347 expected_position,
1348 None, None, None, None, event_time1,
1353 )
1354 ])
1355 );
1356
1357 mouse_handler.clone().handle_input_event(event2).await;
1359 assert_eq!(
1360 injector_stream_receiver
1361 .next()
1362 .await
1363 .map(|events| events.into_iter().flatten().collect()),
1364 Some(vec![create_mouse_pointer_sample_event(
1365 pointerinjector::EventPhase::Change,
1366 vec![],
1367 expected_position,
1368 None, None, None, None, event_time2,
1373 )])
1374 );
1375
1376 match receiver.next().await {
1378 Some(CursorMessage::SetPosition(position)) => {
1379 assert_eq!(position, expected_position);
1380 }
1381 Some(CursorMessage::SetVisibility(_)) => {
1382 panic!("Received unexpected cursor visibility update.")
1383 }
1384 None => panic!("Did not receive cursor update."),
1385 }
1386 }
1387
1388 #[fuchsia::test(allow_stalls = false)]
1398 async fn down_down_up_up_event() {
1399 let (configuration_proxy, mut configuration_request_stream) =
1401 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1402 let (injector_registry_proxy, injector_registry_request_stream) =
1403 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1404 let config_request_stream_fut =
1405 handle_configuration_request_stream(&mut configuration_request_stream);
1406
1407 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(4);
1411 let inspector = fuchsia_inspect::Inspector::default();
1412 let test_node = inspector.root().create_child("test_node");
1413 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1414 configuration_proxy,
1415 injector_registry_proxy,
1416 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1417 sender,
1418 &test_node,
1419 metrics::MetricsLogger::default(),
1420 );
1421 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1422 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1423
1424 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
1425 let event_time1 = zx::MonotonicInstant::get();
1426 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
1427 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
1428 let event_time4 = event_time3.add(zx::MonotonicDuration::from_micros(1));
1429
1430 let event1 = create_mouse_event(
1431 cursor_location,
1432 None, None, None, mouse_binding::MousePhase::Down,
1436 HashSet::from_iter(vec![1]),
1437 HashSet::from_iter(vec![1]),
1438 event_time1,
1439 &DESCRIPTOR,
1440 );
1441 let event2 = create_mouse_event(
1442 cursor_location,
1443 None, None, None, mouse_binding::MousePhase::Down,
1447 HashSet::from_iter(vec![2]),
1448 HashSet::from_iter(vec![1, 2]),
1449 event_time2,
1450 &DESCRIPTOR,
1451 );
1452 let event3 = create_mouse_event(
1453 cursor_location,
1454 None, None, None, mouse_binding::MousePhase::Up,
1458 HashSet::from_iter(vec![1]),
1459 HashSet::from_iter(vec![2]),
1460 event_time3,
1461 &DESCRIPTOR,
1462 );
1463 let event4 = create_mouse_event(
1464 cursor_location,
1465 None, None, None, mouse_binding::MousePhase::Up,
1469 HashSet::from_iter(vec![2]),
1470 HashSet::new(),
1471 event_time4,
1472 &DESCRIPTOR,
1473 );
1474
1475 let expected_position = Position { x: 0.0, y: 0.0 };
1476
1477 let (injector_stream_sender, injector_stream_receiver) =
1481 mpsc::unbounded::<Vec<pointerinjector::Event>>();
1482 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
1484 let registry_fut = handle_registry_request_stream2(
1485 injector_registry_request_stream,
1486 injector_stream_sender,
1487 );
1488
1489 let _registry_task = fasync::Task::local(registry_fut);
1491 mouse_handler.clone().handle_input_event(event1).await;
1492 assert_eq!(
1493 injector_stream_receiver
1494 .next()
1495 .await
1496 .map(|events| events.into_iter().flatten().collect()),
1497 Some(vec![
1498 create_mouse_pointer_sample_event_phase_add(
1499 vec![1],
1500 expected_position,
1501 event_time1,
1502 ),
1503 create_mouse_pointer_sample_event(
1504 pointerinjector::EventPhase::Change,
1505 vec![1],
1506 expected_position,
1507 None, None, None, None, event_time1,
1512 )
1513 ])
1514 );
1515
1516 mouse_handler.clone().handle_input_event(event2).await;
1518 let pointer_sample_event2: Vec<_> = injector_stream_receiver
1519 .next()
1520 .await
1521 .map(|events| events.into_iter().flatten().collect())
1522 .expect("Failed to receive pointer sample event.");
1523 let expected_event_time: i64 = event_time2.into_nanos();
1524 assert_eq!(pointer_sample_event2.len(), 1);
1525
1526 match &pointer_sample_event2[0] {
1529 pointerinjector::Event {
1530 timestamp: Some(actual_event_time),
1531 data:
1532 Some(pointerinjector::Data::PointerSample(pointerinjector::PointerSample {
1533 pointer_id: Some(0),
1534 phase: Some(pointerinjector::EventPhase::Change),
1535 position_in_viewport: Some(actual_position),
1536 scroll_v: None,
1537 scroll_h: None,
1538 pressed_buttons: Some(actual_buttons),
1539 relative_motion: None,
1540 ..
1541 })),
1542 ..
1543 } => {
1544 assert_eq!(*actual_event_time, expected_event_time);
1545 assert_eq!(actual_position[0], expected_position.x);
1546 assert_eq!(actual_position[1], expected_position.y);
1547 assert_eq!(
1548 HashSet::<mouse_binding::MouseButton>::from_iter(actual_buttons.clone()),
1549 HashSet::from_iter(vec![1, 2])
1550 );
1551 }
1552 _ => panic!("Unexpected pointer sample event: {:?}", pointer_sample_event2[0]),
1553 }
1554
1555 mouse_handler.clone().handle_input_event(event3).await;
1557 assert_eq!(
1558 injector_stream_receiver
1559 .next()
1560 .await
1561 .map(|events| events.into_iter().flatten().collect()),
1562 Some(vec![create_mouse_pointer_sample_event(
1563 pointerinjector::EventPhase::Change,
1564 vec![2],
1565 expected_position,
1566 None, None, None, None, event_time3,
1571 )])
1572 );
1573
1574 mouse_handler.clone().handle_input_event(event4).await;
1576 assert_eq!(
1577 injector_stream_receiver
1578 .next()
1579 .await
1580 .map(|events| events.into_iter().flatten().collect()),
1581 Some(vec![create_mouse_pointer_sample_event(
1582 pointerinjector::EventPhase::Change,
1583 vec![],
1584 expected_position,
1585 None, None, None, None, event_time4,
1590 )])
1591 );
1592
1593 match receiver.next().await {
1595 Some(CursorMessage::SetPosition(position)) => {
1596 assert_eq!(position, expected_position);
1597 }
1598 Some(CursorMessage::SetVisibility(_)) => {
1599 panic!("Received unexpected cursor visibility update.")
1600 }
1601 None => panic!("Did not receive cursor update."),
1602 }
1603 }
1604
1605 #[fuchsia::test(allow_stalls = false)]
1607 async fn down_move_up_event() {
1608 let (configuration_proxy, mut configuration_request_stream) =
1610 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1611 let (injector_registry_proxy, injector_registry_request_stream) =
1612 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1613 let config_request_stream_fut =
1614 handle_configuration_request_stream(&mut configuration_request_stream);
1615
1616 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(3);
1620 let inspector = fuchsia_inspect::Inspector::default();
1621 let test_node = inspector.root().create_child("test_node");
1622 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1623 configuration_proxy,
1624 injector_registry_proxy,
1625 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1626 sender,
1627 &test_node,
1628 metrics::MetricsLogger::default(),
1629 );
1630 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1631 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1632
1633 let event_time1 = zx::MonotonicInstant::get();
1634 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
1635 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
1636 let zero_position = Position { x: 0.0, y: 0.0 };
1637 let expected_position = Position {
1638 x: 10.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
1639 y: 5.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
1640 };
1641 let expected_relative_motion = [
1642 10.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
1643 5.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
1644 ];
1645 let event1 = create_mouse_event(
1646 mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 }),
1647 None, None, None, mouse_binding::MousePhase::Down,
1651 HashSet::from_iter(vec![1]),
1652 HashSet::from_iter(vec![1]),
1653 event_time1,
1654 &DESCRIPTOR,
1655 );
1656 let event2 = create_mouse_event(
1657 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1658 millimeters: Position { x: 10.0, y: 5.0 },
1659 }),
1660 None, None, None, mouse_binding::MousePhase::Move,
1664 HashSet::from_iter(vec![1]),
1665 HashSet::from_iter(vec![1]),
1666 event_time2,
1667 &DESCRIPTOR,
1668 );
1669 let event3 = create_mouse_event(
1670 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1671 millimeters: Position { x: 0.0, y: 0.0 },
1672 }),
1673 None, None, None, mouse_binding::MousePhase::Up,
1677 HashSet::from_iter(vec![1]),
1678 HashSet::from_iter(vec![]),
1679 event_time3,
1680 &DESCRIPTOR,
1681 );
1682
1683 let (injector_stream_sender, injector_stream_receiver) =
1687 mpsc::unbounded::<Vec<pointerinjector::Event>>();
1688 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
1690 let registry_fut = handle_registry_request_stream2(
1691 injector_registry_request_stream,
1692 injector_stream_sender,
1693 );
1694
1695 let _registry_task = fasync::Task::local(registry_fut);
1697 mouse_handler.clone().handle_input_event(event1).await;
1698 assert_eq!(
1699 injector_stream_receiver
1700 .next()
1701 .await
1702 .map(|events| events.into_iter().flatten().collect()),
1703 Some(vec![
1704 create_mouse_pointer_sample_event_phase_add(vec![1], zero_position, event_time1,),
1705 create_mouse_pointer_sample_event(
1706 pointerinjector::EventPhase::Change,
1707 vec![1],
1708 zero_position,
1709 None, None, None, None, event_time1,
1714 )
1715 ])
1716 );
1717
1718 match receiver.next().await {
1720 Some(CursorMessage::SetPosition(position)) => {
1721 assert_eq!(position, zero_position);
1722 }
1723 Some(CursorMessage::SetVisibility(_)) => {
1724 panic!("Received unexpected cursor visibility update.")
1725 }
1726 None => panic!("Did not receive cursor update."),
1727 }
1728
1729 mouse_handler.clone().handle_input_event(event2).await;
1731 assert_eq!(
1732 injector_stream_receiver
1733 .next()
1734 .await
1735 .map(|events| events.into_iter().flatten().collect()),
1736 Some(vec![create_mouse_pointer_sample_event(
1737 pointerinjector::EventPhase::Change,
1738 vec![1],
1739 expected_position,
1740 Some(expected_relative_motion),
1741 None, None, None, event_time2,
1745 )])
1746 );
1747
1748 match receiver.next().await {
1750 Some(CursorMessage::SetPosition(position)) => {
1751 assert_eq!(position, expected_position);
1752 }
1753 Some(CursorMessage::SetVisibility(_)) => {
1754 panic!("Received unexpected cursor visibility update.")
1755 }
1756 None => panic!("Did not receive cursor update."),
1757 }
1758
1759 mouse_handler.clone().handle_input_event(event3).await;
1761 assert_eq!(
1762 injector_stream_receiver
1763 .next()
1764 .await
1765 .map(|events| events.into_iter().flatten().collect()),
1766 Some(vec![create_mouse_pointer_sample_event(
1767 pointerinjector::EventPhase::Change,
1768 vec![],
1769 expected_position,
1770 None, None, None, None, event_time3,
1775 )])
1776 );
1777
1778 match receiver.next().await {
1780 Some(CursorMessage::SetPosition(position)) => {
1781 assert_eq!(position, expected_position);
1782 }
1783 Some(CursorMessage::SetVisibility(_)) => {
1784 panic!("Received unexpected cursor visibility update.")
1785 }
1786 None => panic!("Did not receive cursor update."),
1787 }
1788 }
1789
1790 #[fuchsia::test(allow_stalls = false)]
1792 async fn handler_ignores_handled_events() {
1793 let (configuration_proxy, mut configuration_request_stream) =
1795 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1796 let (injector_registry_proxy, injector_registry_request_stream) =
1797 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
1798 let config_request_stream_fut =
1799 handle_configuration_request_stream(&mut configuration_request_stream);
1800
1801 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
1803 let inspector = fuchsia_inspect::Inspector::default();
1804 let test_node = inspector.root().create_child("test_node");
1805 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1806 configuration_proxy,
1807 injector_registry_proxy,
1808 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1809 sender,
1810 &test_node,
1811 metrics::MetricsLogger::default(),
1812 );
1813 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1814 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1815
1816 let cursor_relative_position = Position { x: 50.0, y: 75.0 };
1817 let cursor_location =
1818 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1819 millimeters: Position {
1820 x: cursor_relative_position.x / COUNTS_PER_MM as f32,
1821 y: cursor_relative_position.y / COUNTS_PER_MM as f32,
1822 },
1823 });
1824 let event_time = zx::MonotonicInstant::get();
1825 let input_events = vec![create_mouse_event_with_handled(
1826 cursor_location,
1827 None, None, None, mouse_binding::MousePhase::Move,
1831 HashSet::new(),
1832 HashSet::new(),
1833 event_time,
1834 &DESCRIPTOR,
1835 input_device::Handled::Yes,
1836 )];
1837
1838 assert_handler_ignores_input_event_sequence(
1839 mouse_handler,
1840 input_events,
1841 injector_registry_request_stream,
1842 )
1843 .await;
1844
1845 assert!(receiver.next().await.is_none());
1847 }
1848
1849 fn zero_relative_location() -> mouse_binding::MouseLocation {
1850 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1851 millimeters: Position { x: 0.0, y: 0.0 },
1852 })
1853 }
1854
1855 #[test_case(
1856 create_mouse_event(
1857 zero_relative_location(),
1858 wheel_delta_ticks(1, None), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1862 HashSet::new(),
1863 HashSet::new(),
1864 zx::MonotonicInstant::ZERO,
1865 &DESCRIPTOR,
1866 ),
1867 create_mouse_pointer_sample_event(
1868 pointerinjector::EventPhase::Change,
1869 vec![],
1870 Position { x: 50.0, y: 50.0 },
1871 None, Some(1), None, Some(false), zx::MonotonicInstant::ZERO,
1876 ); "v tick scroll"
1877 )]
1878 #[test_case(
1879 create_mouse_event(
1880 zero_relative_location(),
1881 None, wheel_delta_ticks(1, None), Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1885 HashSet::new(),
1886 HashSet::new(),
1887 zx::MonotonicInstant::ZERO,
1888 &DESCRIPTOR,
1889 ),
1890 create_mouse_pointer_sample_event(
1891 pointerinjector::EventPhase::Change,
1892 vec![],
1893 Position { x: 50.0, y: 50.0 },
1894 None, None, Some(1), Some(false), zx::MonotonicInstant::ZERO,
1899 ); "h tick scroll"
1900 )]
1901 #[test_case(
1902 create_mouse_event(
1903 zero_relative_location(),
1904 wheel_delta_ticks(1, Some(120.0)), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1908 HashSet::new(),
1909 HashSet::new(),
1910 zx::MonotonicInstant::ZERO,
1911 &DESCRIPTOR,
1912 ),
1913 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
1914 pointerinjector::EventPhase::Change,
1915 vec![],
1916 Position { x: 50.0, y: 50.0 },
1917 None, Some(1), None, Some(120.0), None, Some(false), zx::MonotonicInstant::ZERO,
1924 ); "v tick scroll with physical pixel"
1925 )]
1926 #[test_case(
1927 create_mouse_event(
1928 zero_relative_location(),
1929 None, wheel_delta_ticks(1, Some(120.0)), Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1933 HashSet::new(),
1934 HashSet::new(),
1935 zx::MonotonicInstant::ZERO,
1936 &DESCRIPTOR,
1937 ),
1938 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
1939 pointerinjector::EventPhase::Change,
1940 vec![],
1941 Position { x: 50.0, y: 50.0 },
1942 None, None, Some(1), None, Some(120.0), Some(false), zx::MonotonicInstant::ZERO,
1949 ); "h tick scroll with physical pixel"
1950 )]
1951 #[test_case(
1952 create_mouse_event(
1953 zero_relative_location(),
1954 wheel_delta_mm(1.0, Some(120.0)), None, Some(mouse_binding::PrecisionScroll::Yes), mouse_binding::MousePhase::Wheel,
1958 HashSet::new(),
1959 HashSet::new(),
1960 zx::MonotonicInstant::ZERO,
1961 &DESCRIPTOR,
1962 ),
1963 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
1964 pointerinjector::EventPhase::Change,
1965 vec![],
1966 Position { x: 50.0, y: 50.0 },
1967 None, None, None, Some(120.0), None, Some(true), zx::MonotonicInstant::ZERO,
1974 ); "v mm scroll with physical pixel"
1975 )]
1976 #[test_case(
1977 create_mouse_event(
1978 zero_relative_location(),
1979 None, wheel_delta_mm(1.0, Some(120.0)), Some(mouse_binding::PrecisionScroll::Yes), mouse_binding::MousePhase::Wheel,
1983 HashSet::new(),
1984 HashSet::new(),
1985 zx::MonotonicInstant::ZERO,
1986 &DESCRIPTOR,
1987 ),
1988 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
1989 pointerinjector::EventPhase::Change,
1990 vec![],
1991 Position { x: 50.0, y: 50.0 },
1992 None, None, None, None, Some(120.0), Some(true), zx::MonotonicInstant::ZERO,
1999 ); "h mm scroll with physical pixel"
2000 )]
2001 #[fuchsia::test(allow_stalls = false)]
2003 async fn scroll(event: input_device::InputEvent, want_event: pointerinjector::Event) {
2004 let (configuration_proxy, mut configuration_request_stream) =
2006 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
2007 let (injector_registry_proxy, injector_registry_request_stream) =
2008 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
2009 let config_request_stream_fut =
2010 handle_configuration_request_stream(&mut configuration_request_stream);
2011
2012 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
2014 let inspector = fuchsia_inspect::Inspector::default();
2015 let test_node = inspector.root().create_child("test_node");
2016 let mouse_handler_fut = MouseInjectorHandler::new_handler(
2017 configuration_proxy,
2018 injector_registry_proxy,
2019 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
2020 sender,
2021 &test_node,
2022 metrics::MetricsLogger::default(),
2023 );
2024 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
2025 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
2026
2027 let (injector_stream_sender, injector_stream_receiver) =
2031 mpsc::unbounded::<Vec<pointerinjector::Event>>();
2032 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
2034 let registry_fut = handle_registry_request_stream2(
2035 injector_registry_request_stream,
2036 injector_stream_sender,
2037 );
2038
2039 let event_time = zx::MonotonicInstant::get();
2040
2041 let event = input_device::InputEvent { event_time, ..event };
2042
2043 let want_event =
2044 pointerinjector::Event { timestamp: Some(event_time.into_nanos()), ..want_event };
2045
2046 let _registry_task = fasync::Task::local(registry_fut);
2048
2049 mouse_handler.clone().handle_input_event(event).await;
2050 let got_events: Vec<_> = injector_stream_receiver
2051 .next()
2052 .await
2053 .map(|events| events.into_iter().flatten().collect())
2054 .unwrap();
2055 pretty_assertions::assert_eq!(got_events.len(), 2);
2056 assert_matches!(
2057 got_events[0],
2058 pointerinjector::Event {
2059 data: Some(pointerinjector::Data::PointerSample(pointerinjector::PointerSample {
2060 phase: Some(pointerinjector::EventPhase::Add),
2061 ..
2062 })),
2063 ..
2064 }
2065 );
2066
2067 pretty_assertions::assert_eq!(got_events[1], want_event);
2068 }
2069
2070 #[fuchsia::test(allow_stalls = false)]
2072 async fn down_scroll_up_scroll() {
2073 let (configuration_proxy, mut configuration_request_stream) =
2075 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
2076 let (injector_registry_proxy, injector_registry_request_stream) =
2077 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
2078 let config_request_stream_fut =
2079 handle_configuration_request_stream(&mut configuration_request_stream);
2080
2081 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
2083 let inspector = fuchsia_inspect::Inspector::default();
2084 let test_node = inspector.root().create_child("test_node");
2085 let mouse_handler_fut = MouseInjectorHandler::new_handler(
2086 configuration_proxy,
2087 injector_registry_proxy,
2088 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
2089 sender,
2090 &test_node,
2091 metrics::MetricsLogger::default(),
2092 );
2093 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
2094 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
2095
2096 let (injector_stream_sender, injector_stream_receiver) =
2100 mpsc::unbounded::<Vec<pointerinjector::Event>>();
2101 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
2103 let registry_fut = handle_registry_request_stream2(
2104 injector_registry_request_stream,
2105 injector_stream_sender,
2106 );
2107
2108 let event_time1 = zx::MonotonicInstant::get();
2109 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
2110 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
2111 let event_time4 = event_time3.add(zx::MonotonicDuration::from_micros(1));
2112
2113 let _registry_task = fasync::Task::local(registry_fut);
2115
2116 let zero_location =
2117 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
2118 millimeters: Position { x: 0.0, y: 0.0 },
2119 });
2120 let expected_position = Position { x: 50.0, y: 50.0 };
2121
2122 let down_event = create_mouse_event(
2123 zero_location,
2124 None, None, None, mouse_binding::MousePhase::Down,
2128 HashSet::from_iter(vec![1]),
2129 HashSet::from_iter(vec![1]),
2130 event_time1,
2131 &DESCRIPTOR,
2132 );
2133
2134 let wheel_event = create_mouse_event(
2135 zero_location,
2136 wheel_delta_ticks(1, None), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
2140 HashSet::from_iter(vec![1]),
2141 HashSet::from_iter(vec![1]),
2142 event_time2,
2143 &DESCRIPTOR,
2144 );
2145
2146 let up_event = create_mouse_event(
2147 zero_location,
2148 None,
2149 None,
2150 None, mouse_binding::MousePhase::Up,
2152 HashSet::from_iter(vec![1]),
2153 HashSet::new(),
2154 event_time3,
2155 &DESCRIPTOR,
2156 );
2157
2158 let continue_wheel_event = create_mouse_event(
2159 zero_location,
2160 wheel_delta_ticks(1, None), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
2164 HashSet::new(),
2165 HashSet::new(),
2166 event_time4,
2167 &DESCRIPTOR,
2168 );
2169
2170 mouse_handler.clone().handle_input_event(down_event).await;
2172 assert_eq!(
2173 injector_stream_receiver
2174 .next()
2175 .await
2176 .map(|events| events.into_iter().flatten().collect()),
2177 Some(vec![
2178 create_mouse_pointer_sample_event_phase_add(
2179 vec![1],
2180 expected_position,
2181 event_time1,
2182 ),
2183 create_mouse_pointer_sample_event(
2184 pointerinjector::EventPhase::Change,
2185 vec![1],
2186 expected_position,
2187 None, None, None, None, event_time1,
2192 ),
2193 ])
2194 );
2195
2196 mouse_handler.clone().handle_input_event(wheel_event).await;
2198 assert_eq!(
2199 injector_stream_receiver
2200 .next()
2201 .await
2202 .map(|events| events.into_iter().flatten().collect()),
2203 Some(vec![create_mouse_pointer_sample_event(
2204 pointerinjector::EventPhase::Change,
2205 vec![1],
2206 expected_position,
2207 None, Some(1), None, Some(false), event_time2,
2212 )])
2213 );
2214
2215 mouse_handler.clone().handle_input_event(up_event).await;
2217 assert_eq!(
2218 injector_stream_receiver
2219 .next()
2220 .await
2221 .map(|events| events.into_iter().flatten().collect()),
2222 Some(vec![create_mouse_pointer_sample_event(
2223 pointerinjector::EventPhase::Change,
2224 vec![],
2225 expected_position,
2226 None, None, None, None, event_time3,
2231 )])
2232 );
2233
2234 mouse_handler.clone().handle_input_event(continue_wheel_event).await;
2236 assert_eq!(
2237 injector_stream_receiver
2238 .next()
2239 .await
2240 .map(|events| events.into_iter().flatten().collect()),
2241 Some(vec![create_mouse_pointer_sample_event(
2242 pointerinjector::EventPhase::Change,
2243 vec![],
2244 expected_position,
2245 None, Some(1), None, Some(false), event_time4,
2250 )])
2251 );
2252 }
2253
2254 #[fuchsia::test(allow_stalls = false)]
2255 async fn mouse_injector_handler_initialized_with_inspect_node() {
2256 let (configuration_proxy, mut configuration_request_stream) =
2257 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
2258 let config_request_stream_fut =
2259 handle_configuration_request_stream(&mut configuration_request_stream);
2260 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
2261 let inspector = fuchsia_inspect::Inspector::default();
2262 let fake_handlers_node = inspector.root().create_child("input_handlers_node");
2263 let mouse_handler_fut = MouseInjectorHandler::new_with_config_proxy(
2264 configuration_proxy,
2265 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
2266 sender,
2267 &fake_handlers_node,
2268 metrics::MetricsLogger::default(),
2269 );
2270 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
2271 let _handler = mouse_handler_res.expect("Failed to create mouse handler");
2272
2273 diagnostics_assertions::assert_data_tree!(inspector, root: {
2274 input_handlers_node: {
2275 mouse_injector_handler: {
2276 events_received_count: 0u64,
2277 events_handled_count: 0u64,
2278 last_received_timestamp_ns: 0u64,
2279 "fuchsia.inspect.Health": {
2280 status: "STARTING_UP",
2281 start_timestamp_nanos: diagnostics_assertions::AnyProperty
2284 },
2285 }
2286 }
2287 });
2288 }
2289
2290 #[fuchsia::test(allow_stalls = false)]
2291 async fn mouse_injector_handler_inspect_counts_events() {
2292 let (configuration_proxy, mut configuration_request_stream) =
2294 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
2295 let (injector_registry_proxy, injector_registry_request_stream) =
2296 fidl::endpoints::create_proxy_and_stream::<pointerinjector::RegistryMarker>();
2297 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
2298
2299 let inspector = fuchsia_inspect::Inspector::default();
2300 let fake_handlers_node = inspector.root().create_child("input_handlers_node");
2301
2302 let mouse_handler_fut = MouseInjectorHandler::new_handler(
2304 configuration_proxy,
2305 injector_registry_proxy,
2306 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
2307 sender,
2308 &fake_handlers_node,
2309 metrics::MetricsLogger::default(),
2310 );
2311 let config_request_stream_fut =
2312 handle_configuration_request_stream(&mut configuration_request_stream);
2313
2314 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
2315 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
2316
2317 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
2318 let event_time1 = zx::MonotonicInstant::get();
2319 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
2320 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
2321
2322 let input_events = vec![
2323 create_mouse_event(
2324 cursor_location,
2325 None, None, None, mouse_binding::MousePhase::Down,
2329 HashSet::from_iter(vec![1]),
2330 HashSet::from_iter(vec![1]),
2331 event_time1,
2332 &DESCRIPTOR,
2333 ),
2334 create_mouse_event(
2335 cursor_location,
2336 None, None, None, mouse_binding::MousePhase::Up,
2340 HashSet::from_iter(vec![1]),
2341 HashSet::new(),
2342 event_time2,
2343 &DESCRIPTOR,
2344 ),
2345 create_mouse_event_with_handled(
2346 cursor_location,
2347 None, None, None, mouse_binding::MousePhase::Down,
2351 HashSet::from_iter(vec![1]),
2352 HashSet::from_iter(vec![1]),
2353 event_time3,
2354 &DESCRIPTOR,
2355 input_device::Handled::Yes,
2356 ),
2357 ];
2358
2359 let (injector_stream_sender, _) = mpsc::unbounded::<Vec<pointerinjector::Event>>();
2363 let registry_fut = handle_registry_request_stream2(
2364 injector_registry_request_stream,
2365 injector_stream_sender,
2366 );
2367
2368 let _registry_task = fasync::Task::local(registry_fut);
2370 for input_event in input_events {
2371 mouse_handler.clone().handle_input_event(input_event).await;
2372 }
2373
2374 let last_received_event_time: u64 = event_time2.into_nanos().try_into().unwrap();
2375
2376 diagnostics_assertions::assert_data_tree!(inspector, root: {
2377 input_handlers_node: {
2378 mouse_injector_handler: {
2379 events_received_count: 2u64,
2380 events_handled_count: 2u64,
2381 last_received_timestamp_ns: last_received_event_time,
2382 "fuchsia.inspect.Health": {
2383 status: "STARTING_UP",
2384 start_timestamp_nanos: diagnostics_assertions::AnyProperty
2387 },
2388 }
2389 }
2390 });
2391 }
2392}