1#![warn(clippy::await_holding_refcell_ref)]
6
7use crate::input_handler::{Handler, InputHandler, InputHandlerStatus};
8use crate::utils::{self, CursorMessage, Position, Size};
9use crate::{
10 Dispatcher, Incoming, MonotonicInstant, Transport, input_device, metrics, mouse_binding,
11};
12use anyhow::{Context, Error, Result, anyhow};
13use async_trait::async_trait;
14use async_utils::hanging_get::client::HangingGetStream;
15use fidl_fuchsia_input::Range;
16use fidl_fuchsia_ui_pointerinjector_configuration as pointerinjector_config;
17use fidl_next_fuchsia_ui_pointerinjector as pointerinjector;
18use fuchsia_inspect::health::Reporter;
19use futures::SinkExt;
20use futures::channel::mpsc::Sender;
21use futures::stream::StreamExt;
22use metrics_registry::*;
23use sorted_vec_map::SortedVecMap;
24use std::cell::{Ref, RefCell, RefMut};
25use std::rc::Rc;
26
27pub struct MouseInjectorHandler {
30 mutable_state: RefCell<MutableState>,
32
33 context_view_ref: fidl_fuchsia_ui_views::ViewRef,
36
37 target_view_ref: fidl_fuchsia_ui_views::ViewRef,
40
41 max_position: Position,
44
45 injector_registry_proxy: fidl_next::Client<pointerinjector::Registry, Transport>,
47
48 configuration_proxy: pointerinjector_config::SetupProxy,
50
51 pub inspect_status: InputHandlerStatus,
53
54 metrics_logger: metrics::MetricsLogger,
55}
56
57struct MutableState {
58 viewport: Option<pointerinjector::Viewport>,
61
62 injectors: SortedVecMap<u32, fidl_next::Client<pointerinjector::Device, Transport>>,
64
65 current_position: Position,
67
68 cursor_message_sender: Sender<CursorMessage>,
70}
71
72impl Handler for MouseInjectorHandler {
73 fn set_handler_healthy(self: std::rc::Rc<Self>) {
74 self.inspect_status.health_node.borrow_mut().set_ok();
75 }
76
77 fn set_handler_unhealthy(self: std::rc::Rc<Self>, msg: &str) {
78 self.inspect_status.health_node.borrow_mut().set_unhealthy(msg);
79 }
80
81 fn get_name(&self) -> &'static str {
82 "MouseInjectorHandler"
83 }
84
85 fn interest(&self) -> Vec<input_device::InputEventType> {
86 vec![input_device::InputEventType::Mouse]
87 }
88}
89
90#[async_trait(?Send)]
91impl InputHandler for MouseInjectorHandler {
92 async fn handle_input_event(
93 self: Rc<Self>,
94 mut input_event: input_device::InputEvent,
95 ) -> Vec<input_device::InputEvent> {
96 fuchsia_trace::duration!("input", "mouse_injector_handler");
97 match input_event {
98 input_device::InputEvent {
99 device_event: input_device::InputDeviceEvent::Mouse(ref mut mouse_event),
100 device_descriptor:
101 input_device::InputDeviceDescriptor::Mouse(ref mouse_device_descriptor),
102 event_time,
103 handled: input_device::Handled::No,
104 trace_id,
105 } => {
106 fuchsia_trace::duration!("input", "mouse_injector_handler[processing]");
107 let trace_id = match trace_id {
108 Some(id) => {
109 fuchsia_trace::flow_step!("input", "event_in_input_pipeline", id.into());
110 id
111 }
112 None => fuchsia_trace::Id::new(),
113 };
114
115 self.inspect_status.count_received_event(&event_time);
116 if let Err(e) =
118 self.update_cursor_renderer(mouse_event, &mouse_device_descriptor).await
119 {
120 self.metrics_logger.log_error(
121 InputPipelineErrorMetricDimensionEvent::MouseInjectorUpdateCursorRendererFailed,
122 std::format!("update_cursor_renderer failed: {}", e));
123 }
124
125 if let Err(e) = self
127 .ensure_injector_registered(mouse_event, &mouse_device_descriptor, event_time)
128 .await
129 {
130 self.metrics_logger.log_error(
131 InputPipelineErrorMetricDimensionEvent::MouseInjectorEnsureInjectorRegisteredFailed,
132 std::format!("ensure_injector_registered failed: {}", e));
133 }
134
135 if let Err(e) = self.send_event_to_scenic(
137 mouse_event,
138 &mouse_device_descriptor,
139 event_time,
140 trace_id.into(),
141 ) {
142 self.metrics_logger.log_error(
143 InputPipelineErrorMetricDimensionEvent::MouseInjectorSendEventToScenicFailed,
144 std::format!("send_event_to_scenic failed: {}", e));
145 }
146
147 input_event.handled = input_device::Handled::Yes;
149 self.inspect_status.count_handled_event();
150 }
151 _ => {
152 self.metrics_logger.log_error(
153 InputPipelineErrorMetricDimensionEvent::HandlerReceivedUninterestedEvent,
154 std::format!(
155 "{} uninterested input event: {:?}",
156 self.get_name(),
157 input_event.get_event_type()
158 ),
159 );
160 }
161 }
162 vec![input_event]
163 }
164}
165
166impl MouseInjectorHandler {
167 pub async fn new(
180 incoming: &Incoming,
181 display_size: Size,
182 cursor_message_sender: Sender<CursorMessage>,
183 input_handlers_node: &fuchsia_inspect::Node,
184 metrics_logger: metrics::MetricsLogger,
185 ) -> Result<Rc<Self>, Error> {
186 let configuration_proxy =
187 incoming.connect_protocol::<pointerinjector_config::SetupProxy>()?;
188 let injector_registry_proxy =
189 incoming.connect_protocol_next::<pointerinjector::Registry>()?.spawn();
190
191 Self::new_handler(
192 configuration_proxy,
193 injector_registry_proxy,
194 display_size,
195 cursor_message_sender,
196 input_handlers_node,
197 metrics_logger,
198 )
199 .await
200 }
201
202 pub async fn new_with_config_proxy(
218 incoming: &Incoming,
219 configuration_proxy: pointerinjector_config::SetupProxy,
220 display_size: Size,
221 cursor_message_sender: Sender<CursorMessage>,
222 input_handlers_node: &fuchsia_inspect::Node,
223 metrics_logger: metrics::MetricsLogger,
224 ) -> Result<Rc<Self>, Error> {
225 let injector_registry_proxy =
226 incoming.connect_protocol_next::<pointerinjector::Registry>()?.spawn();
227 Self::new_handler(
228 configuration_proxy,
229 injector_registry_proxy,
230 display_size,
231 cursor_message_sender,
232 input_handlers_node,
233 metrics_logger,
234 )
235 .await
236 }
237
238 fn inner(&self) -> Ref<'_, MutableState> {
239 self.mutable_state.borrow()
240 }
241
242 fn inner_mut(&self) -> RefMut<'_, MutableState> {
243 self.mutable_state.borrow_mut()
244 }
245
246 async fn new_handler(
262 configuration_proxy: pointerinjector_config::SetupProxy,
263 injector_registry_proxy: fidl_next::Client<pointerinjector::Registry, Transport>,
264 display_size: Size,
265 cursor_message_sender: Sender<CursorMessage>,
266 input_handlers_node: &fuchsia_inspect::Node,
267 metrics_logger: metrics::MetricsLogger,
268 ) -> Result<Rc<Self>, Error> {
269 let (context_view_ref, target_view_ref) = configuration_proxy.get_view_refs().await?;
271 let inspect_status = InputHandlerStatus::new(
272 input_handlers_node,
273 "mouse_injector_handler",
274 false,
275 );
276 let handler = Rc::new(Self {
277 mutable_state: RefCell::new(MutableState {
278 viewport: None,
279 injectors: SortedVecMap::new(),
280 current_position: Position {
282 x: display_size.width / 2.0,
283 y: display_size.height / 2.0,
284 },
285 cursor_message_sender,
286 }),
287 context_view_ref,
288 target_view_ref,
289 max_position: Position { x: display_size.width, y: display_size.height },
290 injector_registry_proxy,
291 configuration_proxy,
292 inspect_status,
293 metrics_logger,
294 });
295
296 Ok(handler)
297 }
298
299 async fn ensure_injector_registered(
307 self: &Rc<Self>,
308 mouse_event: &mut mouse_binding::MouseEvent,
309 mouse_descriptor: &mouse_binding::MouseDeviceDescriptor,
310 event_time: zx::MonotonicInstant,
311 ) -> Result<(), anyhow::Error> {
312 if self.inner().injectors.contains_key(&mouse_descriptor.device_id) {
313 return Ok(());
314 }
315
316 let (device_proxy, device_server) =
318 fidl_next::fuchsia::create_channel::<pointerinjector::Device>();
319 let device_proxy = Dispatcher::client_from_zx_channel(device_proxy).spawn();
320 let context = fuchsia_scenic::duplicate_view_ref(&self.context_view_ref)
321 .context("Failed to duplicate context view ref.")?;
322 let context = fidl_next_fuchsia_ui_views::ViewRef { reference: context.reference };
323 let target = fuchsia_scenic::duplicate_view_ref(&self.target_view_ref)
324 .context("Failed to duplicate target view ref.")?;
325 let target = fidl_next_fuchsia_ui_views::ViewRef { reference: target.reference };
326
327 let viewport = self.inner().viewport.clone();
328 let config = pointerinjector::Config {
329 device_id: Some(mouse_descriptor.device_id),
330 device_type: Some(pointerinjector::DeviceType::Mouse),
331 context: Some(pointerinjector::Context::View(context)),
332 target: Some(pointerinjector::Target::View(target)),
333 viewport,
334 dispatch_policy: Some(pointerinjector::DispatchPolicy::MouseHoverAndLatchInTarget),
335 scroll_v_range: utils::axis_to_next(mouse_descriptor.wheel_v_range.as_ref()),
336 scroll_h_range: utils::axis_to_next(mouse_descriptor.wheel_h_range.as_ref()),
337 buttons: mouse_descriptor.buttons.clone(),
338 ..Default::default()
339 };
340
341 self.injector_registry_proxy
343 .register(config, device_server)
344 .await
345 .context("Failed to register injector.")?;
346 log::info!("Registered injector with device id {:?}", mouse_descriptor.device_id);
347
348 self.inner_mut().injectors.insert(mouse_descriptor.device_id, device_proxy.clone());
350
351 let events_to_send = vec![self.create_pointer_sample_event(
353 mouse_event,
354 event_time,
355 pointerinjector::EventPhase::Add,
356 self.inner().current_position,
357 None,
358 None,
359 )];
360 device_proxy
361 .inject_events(events_to_send)
362 .send_immediately()
363 .context("Failed to ADD new MouseDevice.")?;
364
365 Ok(())
366 }
367
368 async fn update_cursor_renderer(
379 &self,
380 mouse_event: &mouse_binding::MouseEvent,
381 mouse_descriptor: &mouse_binding::MouseDeviceDescriptor,
382 ) -> Result<(), anyhow::Error> {
383 let mut new_position = match (mouse_event.location, mouse_descriptor) {
384 (
385 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation { counts }),
386 _,
387 ) => self.inner().current_position + counts,
388 (
389 mouse_binding::MouseLocation::Absolute(position),
390 mouse_binding::MouseDeviceDescriptor {
391 absolute_x_range: Some(x_range),
392 absolute_y_range: Some(y_range),
393 ..
394 },
395 ) => self.scale_absolute_position(&position, &x_range, &y_range),
396 (mouse_binding::MouseLocation::Absolute(_), _) => {
397 return Err(anyhow!(
398 "Received an Absolute mouse location without absolute device ranges."
399 ));
400 }
401 };
402 Position::clamp(&mut new_position, Position::zero(), self.max_position);
403 self.inner_mut().current_position = new_position;
404
405 let mut cursor_message_sender = self.inner().cursor_message_sender.clone();
406 cursor_message_sender
407 .send(CursorMessage::SetPosition(new_position))
408 .await
409 .context("Failed to send current mouse position to cursor renderer")?;
410
411 Ok(())
412 }
413
414 fn scale_absolute_position(
422 &self,
423 position: &Position,
424 x_range: &Range,
425 y_range: &Range,
426 ) -> Position {
427 let range_min = Position { x: x_range.min as f32, y: y_range.min as f32 };
428 let range_max = Position { x: x_range.max as f32, y: y_range.max as f32 };
429 self.max_position * ((*position - range_min) / (range_max - range_min))
430 }
431
432 fn send_event_to_scenic(
439 &self,
440 mouse_event: &mut mouse_binding::MouseEvent,
441 mouse_descriptor: &mouse_binding::MouseDeviceDescriptor,
442 event_time: zx::MonotonicInstant,
443 tracing_id: u64,
444 ) -> Result<(), anyhow::Error> {
445 let injector = self.inner().injectors.get(&mouse_descriptor.device_id).cloned();
446 if let Some(injector) = injector {
447 let relative_motion = match mouse_event.location {
448 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
449 counts: offset_counts,
450 }) if mouse_event.phase == mouse_binding::MousePhase::Move => {
451 Some([offset_counts.x, offset_counts.y])
452 }
453 _ => None,
454 };
455 let events_to_send = vec![self.create_pointer_sample_event(
456 mouse_event,
457 event_time,
458 pointerinjector::EventPhase::Change,
459 self.inner().current_position,
460 relative_motion,
461 Some(tracing_id),
462 )];
463
464 fuchsia_trace::flow_begin!("input", "dispatch_event_to_scenic", tracing_id.into());
465
466 _ = injector.inject_events(events_to_send).send_immediately();
467
468 Ok(())
469 } else {
470 Err(anyhow::format_err!(
471 "No injector found for mouse device {}.",
472 mouse_descriptor.device_id
473 ))
474 }
475 }
476
477 fn create_pointer_sample_event(
486 &self,
487 mouse_event: &mut mouse_binding::MouseEvent,
488 event_time: zx::MonotonicInstant,
489 phase: pointerinjector::EventPhase,
490 current_position: Position,
491 relative_motion: Option<[f32; 2]>,
492 trace_id: Option<u64>,
493 ) -> pointerinjector::Event {
494 let pointer_sample = pointerinjector::PointerSample {
495 pointer_id: Some(0),
496 phase: Some(phase),
497 position_in_viewport: Some([current_position.x, current_position.y]),
498 scroll_v: mouse_event.wheel_delta_v.as_ref().map(|delta| delta.ticks),
499 scroll_h: mouse_event.wheel_delta_h.as_ref().map(|delta| delta.ticks),
500 scroll_v_physical_pixel: match mouse_event.wheel_delta_v {
501 Some(mouse_binding::WheelDelta { physical_pixel: Some(pixel), .. }) => {
502 Some(pixel.into())
503 }
504 _ => None,
505 },
506 scroll_h_physical_pixel: match mouse_event.wheel_delta_h {
507 Some(mouse_binding::WheelDelta { physical_pixel: Some(pixel), .. }) => {
508 Some(pixel.into())
509 }
510 _ => None,
511 },
512 is_precision_scroll: match mouse_event.phase {
513 mouse_binding::MousePhase::Wheel => match mouse_event.is_precision_scroll {
514 Some(mouse_binding::PrecisionScroll::Yes) => Some(true),
515 Some(mouse_binding::PrecisionScroll::No) => Some(false),
516 None => {
517 self.metrics_logger.log_error(
518 InputPipelineErrorMetricDimensionEvent::MouseInjectorMissingIsPrecisionScroll,
519 "mouse wheel event does not have value in is_precision_scroll.");
520 None
521 }
522 },
523 _ => None,
524 },
525 pressed_buttons: Some(mouse_event.pressed_buttons.clone().into()),
526 relative_motion,
527 ..Default::default()
528 };
529 pointerinjector::Event {
530 timestamp: Some(event_time.into_nanos()),
531 data: Some(pointerinjector::Data::PointerSample(pointer_sample)),
532 trace_flow_id: trace_id,
533 wake_lease: mouse_event.wake_lease.take(),
534 ..Default::default()
535 }
536 }
537
538 pub async fn watch_viewport(self: Rc<Self>) {
540 let configuration_proxy = self.configuration_proxy.clone();
541 let mut viewport_stream = HangingGetStream::new(
542 configuration_proxy,
543 pointerinjector_config::SetupProxy::watch_viewport,
544 );
545 loop {
546 match viewport_stream.next().await {
547 Some(Ok(new_viewport)) => {
548 self.inner_mut().viewport = Some(utils::viewport_to_next(&new_viewport));
550
551 let injectors =
553 self.inner().injectors.iter().map(|(_, v)| v).cloned().collect::<Vec<_>>();
554 for injector in injectors {
555 let events = vec![pointerinjector::Event {
556 timestamp: Some(MonotonicInstant::now().into_nanos()),
557 data: Some(pointerinjector::Data::Viewport(utils::viewport_to_next(
558 &new_viewport,
559 ))),
560 trace_flow_id: Some(fuchsia_trace::Id::new().into()),
561 ..Default::default()
562 }];
563 injector
564 .inject_events(events)
565 .await
566 .expect("Failed to inject updated viewport.");
567 }
568 }
569 Some(Err(e)) => {
570 self.metrics_logger.log_error(
571 InputPipelineErrorMetricDimensionEvent::MouseInjectorErrorWhileReadingViewportUpdate,
572 std::format!("Error while reading viewport update: {}", e));
573 return;
574 }
575 None => {
576 self.metrics_logger.log_error(
577 InputPipelineErrorMetricDimensionEvent::MouseInjectorViewportUpdateStreamTerminatedUnexpectedly,
578 "Viewport update stream terminated unexpectedly");
579 return;
580 }
581 }
582 }
583 }
584}
585
586#[cfg(test)]
587mod tests {
588 use super::*;
589 use crate::testing_utilities::{
590 assert_handler_ignores_input_event_sequence, create_mouse_event,
591 create_mouse_event_with_handled, create_mouse_pointer_sample_event,
592 create_mouse_pointer_sample_event_phase_add,
593 create_mouse_pointer_sample_event_with_wheel_physical_pixel, next_client_old_stream,
594 };
595 use assert_matches::assert_matches;
596 use fidl_fuchsia_ui_pointerinjector as pointerinjector;
597 use fidl_next_fuchsia_ui_pointerinjector as pointerinjector_next;
598 use fuchsia_async as fasync;
599 use futures::channel::mpsc;
600 use pretty_assertions::assert_eq;
601 use sorted_vec_map::SortedVecSet;
602 use std::ops::Add;
603 use test_case::test_case;
604
605 const DISPLAY_WIDTH_IN_PHYSICAL_PX: f32 = 100.0;
606 const DISPLAY_HEIGHT_IN_PHYSICAL_PX: f32 = 100.0;
607 const DESCRIPTOR: input_device::InputDeviceDescriptor =
609 input_device::InputDeviceDescriptor::Mouse(mouse_binding::MouseDeviceDescriptor {
610 device_id: 1,
611 absolute_x_range: Some(fidl_fuchsia_input::Range { min: 0, max: 100 }),
612 absolute_y_range: Some(fidl_fuchsia_input::Range { min: 0, max: 100 }),
613 wheel_v_range: Some(fidl_fuchsia_input::Axis {
614 range: fidl_fuchsia_input::Range { min: -1, max: 1 },
615 unit: fidl_fuchsia_input::Unit {
616 type_: fidl_fuchsia_input::UnitType::Other,
617 exponent: 0,
618 },
619 }),
620 wheel_h_range: Some(fidl_fuchsia_input::Axis {
621 range: fidl_fuchsia_input::Range { min: -1, max: 1 },
622 unit: fidl_fuchsia_input::Unit {
623 type_: fidl_fuchsia_input::UnitType::Other,
624 exponent: 0,
625 },
626 }),
627 buttons: None,
628 });
629
630 async fn handle_configuration_request_stream(
632 stream: &mut pointerinjector_config::SetupRequestStream,
633 ) {
634 if let Some(Ok(request)) = stream.next().await {
635 match request {
636 pointerinjector_config::SetupRequest::GetViewRefs { responder, .. } => {
637 let context = fuchsia_scenic::ViewRefPair::new()
638 .expect("Failed to create viewrefpair.")
639 .view_ref;
640 let target = fuchsia_scenic::ViewRefPair::new()
641 .expect("Failed to create viewrefpair.")
642 .view_ref;
643 let _ = responder.send(context, target);
644 }
645 _ => {}
646 };
647 }
648 }
649
650 async fn handle_registry_request_stream(
653 mut stream: pointerinjector::RegistryRequestStream,
654 injector_sender: futures::channel::oneshot::Sender<pointerinjector::DeviceRequestStream>,
655 ) {
656 if let Some(request) = stream.next().await {
657 match request {
658 Ok(pointerinjector::RegistryRequest::Register {
659 config: _,
660 injector,
661 responder,
662 ..
663 }) => {
664 let injector_stream = injector.into_stream();
665 let _ = injector_sender.send(injector_stream);
666 responder.send().expect("failed to respond");
667 }
668 _ => {}
669 };
670 } else {
671 panic!("RegistryRequestStream failed.");
672 }
673 }
674
675 async fn handle_registry_request_stream2(
677 mut stream: pointerinjector::RegistryRequestStream,
678 injector_sender: mpsc::UnboundedSender<Vec<pointerinjector::Event>>,
679 ) {
680 let (injector, responder) = match stream.next().await {
681 Some(Ok(pointerinjector::RegistryRequest::Register {
682 config: _,
683 injector,
684 responder,
685 ..
686 })) => (injector, responder),
687 other => panic!("expected register request, but got {:?}", other),
688 };
689 let injector_stream: pointerinjector::DeviceRequestStream = injector.into_stream();
690 responder.send().expect("failed to respond");
691 injector_stream
692 .for_each(|request| {
693 futures::future::ready({
694 match request {
695 Ok(pointerinjector::DeviceRequest::Inject { .. }) => {
696 panic!("DeviceRequest::Inject is deprecated.");
697 }
698 Ok(pointerinjector::DeviceRequest::InjectEvents { events, .. }) => {
699 let _ = injector_sender.unbounded_send(events);
700 }
701 Err(e) => panic!("FIDL error {}", e),
702 }
703 })
704 })
705 .await;
706 }
707
708 async fn handle_device_request_stream(
711 injector_stream_receiver: futures::channel::oneshot::Receiver<
712 pointerinjector::DeviceRequestStream,
713 >,
714 expected_events: Vec<pointerinjector::Event>,
715 ) {
716 let mut injector_stream =
717 injector_stream_receiver.await.expect("Failed to get DeviceRequestStream.");
718 for expected_event in expected_events {
719 match injector_stream.next().await {
720 Some(Ok(pointerinjector::DeviceRequest::Inject { .. })) => {
721 panic!("DeviceRequest::Inject is deprecated.");
722 }
723 Some(Ok(pointerinjector::DeviceRequest::InjectEvents { events, .. })) => {
724 assert_eq!(events, vec![expected_event]);
725 }
726 Some(Err(e)) => panic!("FIDL error {}", e),
727 None => panic!("Expected another event."),
728 }
729 }
730 }
731
732 fn create_viewport(min: f32, max: f32) -> pointerinjector::Viewport {
734 pointerinjector::Viewport {
735 extents: Some([[min, min], [max, max]]),
736 viewport_to_context_transform: None,
737 ..Default::default()
738 }
739 }
740
741 fn create_viewport_next(min: f32, max: f32) -> pointerinjector_next::Viewport {
742 pointerinjector_next::Viewport {
743 extents: Some([[min, min], [max, max]]),
744 viewport_to_context_transform: None,
745 ..Default::default()
746 }
747 }
748
749 #[fuchsia::test]
752 fn receives_viewport_updates() {
753 let mut exec = fasync::TestExecutor::new();
754
755 let (configuration_proxy, mut configuration_request_stream) =
757 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
758 let (injector_registry_proxy, _) =
759 fidl_next::fuchsia::create_channel::<pointerinjector_next::Registry>();
760 let injector_registry_proxy =
761 Dispatcher::client_from_zx_channel(injector_registry_proxy).spawn();
762 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(0);
763
764 let inspector = fuchsia_inspect::Inspector::default();
765 let test_node = inspector.root().create_child("test_node");
766
767 let mouse_handler_fut = MouseInjectorHandler::new_handler(
769 configuration_proxy,
770 injector_registry_proxy,
771 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
772 sender,
773 &test_node,
774 metrics::MetricsLogger::default(),
775 );
776 let config_request_stream_fut =
777 handle_configuration_request_stream(&mut configuration_request_stream);
778 let (mouse_handler_res, _) = exec.run_singlethreaded(futures::future::join(
779 mouse_handler_fut,
780 config_request_stream_fut,
781 ));
782 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
783
784 let (injector_device_proxy, mut injector_device_request_stream) =
786 next_client_old_stream::<pointerinjector::DeviceMarker, pointerinjector_next::Device>();
787 mouse_handler.inner_mut().injectors.insert(1, injector_device_proxy);
788
789 {
791 let watch_viewport_fut = mouse_handler.clone().watch_viewport();
793 futures::pin_mut!(watch_viewport_fut);
794 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
795
796 match exec.run_singlethreaded(&mut configuration_request_stream.next()) {
798 Some(Ok(pointerinjector_config::SetupRequest::WatchViewport {
799 responder, ..
800 })) => {
801 responder.send(&create_viewport(0.0, 100.0)).expect("Failed to send viewport.");
802 }
803 other => panic!("Received unexpected value: {:?}", other),
804 };
805 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
806
807 exec.run_singlethreaded(async {
809 match injector_device_request_stream.next().await {
810 Some(Ok(pointerinjector::DeviceRequest::Inject { .. })) => {
811 panic!("DeviceRequest::Inject is deprecated.");
812 }
813 Some(Ok(pointerinjector::DeviceRequest::InjectEvents { events, .. })) => {
814 assert_eq!(events.len(), 1);
815 assert!(events[0].data.is_some());
816 assert_eq!(
817 events[0].data,
818 Some(pointerinjector::Data::Viewport(create_viewport(0.0, 100.0)))
819 );
820 }
821 other => panic!("Received unexpected value: {:?}", other),
822 }
823 });
824
825 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
827
828 match exec.run_singlethreaded(&mut configuration_request_stream.next()) {
830 Some(Ok(pointerinjector_config::SetupRequest::WatchViewport {
831 responder, ..
832 })) => {
833 responder
834 .send(&create_viewport(100.0, 200.0))
835 .expect("Failed to send viewport.");
836 }
837 other => panic!("Received unexpected value: {:?}", other),
838 };
839
840 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
842 }
843
844 exec.run_singlethreaded(async {
846 match injector_device_request_stream.next().await {
847 Some(Ok(pointerinjector::DeviceRequest::Inject { .. })) => {
848 panic!("DeviceRequest::Inject is deprecated.");
849 }
850 Some(Ok(pointerinjector::DeviceRequest::InjectEvents { events, .. })) => {
851 assert_eq!(events.len(), 1);
852 assert!(events[0].data.is_some());
853 assert_eq!(
854 events[0].data,
855 Some(pointerinjector::Data::Viewport(create_viewport(100.0, 200.0)))
856 );
857 }
858 other => panic!("Received unexpected value: {:?}", other),
859 }
860 });
861
862 let expected_viewport = create_viewport_next(100.0, 200.0);
864 assert_eq!(mouse_handler.inner().viewport, Some(expected_viewport));
865 }
866
867 fn wheel_delta_ticks(
868 ticks: i64,
869 physical_pixel: Option<f32>,
870 ) -> Option<mouse_binding::WheelDelta> {
871 Some(mouse_binding::WheelDelta { ticks, physical_pixel })
872 }
873
874 #[test_case(
877 mouse_binding::MouseLocation::Relative(
878 mouse_binding::RelativeLocation {
879 counts: Position { x: 10.0, y: 20.0 }
880 }),
881 Position {
882 x: DISPLAY_WIDTH_IN_PHYSICAL_PX / 2.0 + 10.0,
883 y: DISPLAY_HEIGHT_IN_PHYSICAL_PX / 2.0 + 20.0,
884 },
885 [10.0, 20.0]; "Valid move event."
886 )]
887 #[test_case(
888 mouse_binding::MouseLocation::Relative(
889 mouse_binding::RelativeLocation {
890 counts: Position {
891 x: DISPLAY_WIDTH_IN_PHYSICAL_PX + 2.0,
892 y: DISPLAY_HEIGHT_IN_PHYSICAL_PX + 1.0,
893 }}),
894 Position {
895 x: DISPLAY_WIDTH_IN_PHYSICAL_PX,
896 y: DISPLAY_HEIGHT_IN_PHYSICAL_PX,
897 },
898 [
899 DISPLAY_WIDTH_IN_PHYSICAL_PX + 2.0,
900 DISPLAY_HEIGHT_IN_PHYSICAL_PX + 1.0,
901 ]; "Move event exceeds max bounds."
902 )]
903 #[test_case(
904 mouse_binding::MouseLocation::Relative(
905 mouse_binding::RelativeLocation {
906 counts: Position {
907 x: -(DISPLAY_WIDTH_IN_PHYSICAL_PX + 2.0),
908 y: -(DISPLAY_HEIGHT_IN_PHYSICAL_PX + 1.0),
909 }}),
910 Position { x: 0.0, y: 0.0 },
911 [
912 -(DISPLAY_WIDTH_IN_PHYSICAL_PX + 2.0),
913 -(DISPLAY_HEIGHT_IN_PHYSICAL_PX + 1.0),
914 ]; "Move event exceeds min bounds."
915 )]
916 #[fuchsia::test(allow_stalls = false)]
917 async fn move_event(
918 move_location: mouse_binding::MouseLocation,
919 expected_position: Position,
920 expected_relative_motion: [f32; 2],
921 ) {
922 let (configuration_proxy, mut configuration_request_stream) =
924 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
925 let (injector_registry_proxy, injector_registry_request_stream) = next_client_old_stream::<
926 pointerinjector::RegistryMarker,
927 pointerinjector_next::Registry,
928 >();
929 let config_request_stream_fut =
930 handle_configuration_request_stream(&mut configuration_request_stream);
931
932 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
934 let inspector = fuchsia_inspect::Inspector::default();
935 let test_node = inspector.root().create_child("test_node");
936 let mouse_handler_fut = MouseInjectorHandler::new_handler(
937 configuration_proxy,
938 injector_registry_proxy,
939 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
940 sender,
941 &test_node,
942 metrics::MetricsLogger::default(),
943 );
944 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
945 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
946
947 let event_time = zx::MonotonicInstant::get();
948 let input_event = create_mouse_event(
949 move_location,
950 None, None, None, mouse_binding::MousePhase::Move,
954 SortedVecSet::new(),
955 SortedVecSet::new(),
956 event_time,
957 &DESCRIPTOR,
958 );
959
960 let handle_event_fut = mouse_handler.handle_input_event(input_event);
962 let expected_events = vec![
963 create_mouse_pointer_sample_event_phase_add(vec![], expected_position, event_time),
964 create_mouse_pointer_sample_event(
965 pointerinjector::EventPhase::Change,
966 vec![],
967 expected_position,
968 Some(expected_relative_motion),
969 None, None, None, event_time,
973 ),
974 ];
975
976 let (injector_stream_sender, injector_stream_receiver) =
980 futures::channel::oneshot::channel::<pointerinjector::DeviceRequestStream>();
981 let registry_fut = handle_registry_request_stream(
982 injector_registry_request_stream,
983 injector_stream_sender,
984 );
985 let device_fut = handle_device_request_stream(injector_stream_receiver, expected_events);
986
987 let (handle_result, _, _) = futures::join!(handle_event_fut, registry_fut, device_fut);
990 match receiver.next().await {
991 Some(CursorMessage::SetPosition(position)) => {
992 pretty_assertions::assert_eq!(position, expected_position);
993 }
994 Some(CursorMessage::SetVisibility(_)) => {
995 panic!("Received unexpected cursor visibility update.")
996 }
997 None => panic!("Did not receive cursor update."),
998 }
999
1000 assert_matches!(
1002 handle_result.as_slice(),
1003 [input_device::InputEvent { handled: input_device::Handled::Yes, .. }]
1004 );
1005 }
1006
1007 #[fuchsia::test(allow_stalls = false)]
1010 async fn move_absolute_event() {
1011 const DEVICE_ID: u32 = 1;
1012
1013 let (configuration_proxy, mut configuration_request_stream) =
1015 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1016 let (injector_registry_proxy, injector_registry_request_stream) = next_client_old_stream::<
1017 pointerinjector::RegistryMarker,
1018 pointerinjector_next::Registry,
1019 >();
1020 let config_request_stream_fut =
1021 handle_configuration_request_stream(&mut configuration_request_stream);
1022
1023 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
1025 let inspector = fuchsia_inspect::Inspector::default();
1026 let test_node = inspector.root().create_child("test_node");
1027 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1028 configuration_proxy,
1029 injector_registry_proxy,
1030 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1031 sender,
1032 &test_node,
1033 metrics::MetricsLogger::default(),
1034 );
1035 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1036 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1037
1038 let cursor_location =
1054 mouse_binding::MouseLocation::Absolute(Position { x: -25.0, y: 25.0 });
1055 let event_time = zx::MonotonicInstant::get();
1056 let descriptor =
1057 input_device::InputDeviceDescriptor::Mouse(mouse_binding::MouseDeviceDescriptor {
1058 device_id: DEVICE_ID,
1059 absolute_x_range: Some(fidl_fuchsia_input::Range { min: -50, max: 50 }),
1060 absolute_y_range: Some(fidl_fuchsia_input::Range { min: -50, max: 50 }),
1061 wheel_v_range: None,
1062 wheel_h_range: None,
1063 buttons: None,
1064 });
1065 let input_event = create_mouse_event(
1066 cursor_location,
1067 None, None, None, mouse_binding::MousePhase::Move,
1071 SortedVecSet::new(),
1072 SortedVecSet::new(),
1073 event_time,
1074 &descriptor,
1075 );
1076
1077 let handle_event_fut = mouse_handler.handle_input_event(input_event);
1079 let expected_position = Position {
1080 x: DISPLAY_WIDTH_IN_PHYSICAL_PX * 0.25,
1081 y: DISPLAY_WIDTH_IN_PHYSICAL_PX * 0.75,
1082 };
1083 let expected_events = vec![
1084 create_mouse_pointer_sample_event_phase_add(vec![], expected_position, event_time),
1085 create_mouse_pointer_sample_event(
1086 pointerinjector::EventPhase::Change,
1087 vec![],
1088 expected_position,
1089 None, None, None, None, event_time,
1094 ),
1095 ];
1096
1097 let (injector_stream_sender, injector_stream_receiver) =
1101 futures::channel::oneshot::channel::<pointerinjector::DeviceRequestStream>();
1102 let registry_fut = handle_registry_request_stream(
1103 injector_registry_request_stream,
1104 injector_stream_sender,
1105 );
1106 let device_fut = handle_device_request_stream(injector_stream_receiver, expected_events);
1107
1108 let (handle_result, _, _) = futures::join!(handle_event_fut, registry_fut, device_fut);
1111 match receiver.next().await {
1112 Some(CursorMessage::SetPosition(position)) => {
1113 assert_eq!(position, expected_position);
1114 }
1115 Some(CursorMessage::SetVisibility(_)) => {
1116 panic!("Received unexpected cursor visibility update.")
1117 }
1118 None => panic!("Did not receive cursor update."),
1119 }
1120
1121 assert_matches!(
1123 handle_result.as_slice(),
1124 [input_device::InputEvent { handled: input_device::Handled::Yes, .. }]
1125 );
1126 }
1127
1128 #[test_case(
1130 mouse_binding::MousePhase::Down,
1131 vec![1], vec![1]; "Down event injects button press state."
1132 )]
1133 #[test_case(
1134 mouse_binding::MousePhase::Up,
1135 vec![1], vec![]; "Up event injects button press state."
1136 )]
1137 #[fuchsia::test(allow_stalls = false)]
1138 async fn button_state_event(
1139 phase: mouse_binding::MousePhase,
1140 affected_buttons: Vec<mouse_binding::MouseButton>,
1141 pressed_buttons: Vec<mouse_binding::MouseButton>,
1142 ) {
1143 let (configuration_proxy, mut configuration_request_stream) =
1145 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1146 let (injector_registry_proxy, injector_registry_request_stream) = next_client_old_stream::<
1147 pointerinjector::RegistryMarker,
1148 pointerinjector_next::Registry,
1149 >();
1150 let config_request_stream_fut =
1151 handle_configuration_request_stream(&mut configuration_request_stream);
1152
1153 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
1155 let inspector = fuchsia_inspect::Inspector::default();
1156 let test_node = inspector.root().create_child("test_node");
1157 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1158 configuration_proxy,
1159 injector_registry_proxy,
1160 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1161 sender,
1162 &test_node,
1163 metrics::MetricsLogger::default(),
1164 );
1165 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1166 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1167
1168 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
1169 let event_time = zx::MonotonicInstant::get();
1170
1171 let input_event = create_mouse_event(
1172 cursor_location,
1173 None, None, None, phase,
1177 affected_buttons.clone().into(),
1178 pressed_buttons.clone().into(),
1179 event_time,
1180 &DESCRIPTOR,
1181 );
1182
1183 let handle_event_fut = mouse_handler.handle_input_event(input_event);
1185 let expected_position = Position { x: 0.0, y: 0.0 };
1186 let expected_events = vec![
1187 create_mouse_pointer_sample_event_phase_add(
1188 pressed_buttons.clone().into(),
1189 expected_position,
1190 event_time,
1191 ),
1192 create_mouse_pointer_sample_event(
1193 pointerinjector::EventPhase::Change,
1194 pressed_buttons.clone().into(),
1195 expected_position,
1196 None, None, None, None, event_time,
1201 ),
1202 ];
1203
1204 let (injector_stream_sender, injector_stream_receiver) =
1208 futures::channel::oneshot::channel::<pointerinjector::DeviceRequestStream>();
1209 let registry_fut = handle_registry_request_stream(
1210 injector_registry_request_stream,
1211 injector_stream_sender,
1212 );
1213 let device_fut = handle_device_request_stream(injector_stream_receiver, expected_events);
1214
1215 let (handle_result, _, _) = futures::join!(handle_event_fut, registry_fut, device_fut);
1218 match receiver.next().await {
1219 Some(CursorMessage::SetPosition(position)) => {
1220 pretty_assertions::assert_eq!(position, expected_position);
1221 }
1222 Some(CursorMessage::SetVisibility(_)) => {
1223 panic!("Received unexpected cursor visibility update.")
1224 }
1225 None => panic!("Did not receive cursor update."),
1226 }
1227
1228 assert_matches!(
1230 handle_result.as_slice(),
1231 [input_device::InputEvent { handled: input_device::Handled::Yes, .. }]
1232 );
1233 }
1234
1235 #[fuchsia::test(allow_stalls = false)]
1237 async fn down_up_event() {
1238 let (configuration_proxy, mut configuration_request_stream) =
1240 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1241 let (injector_registry_proxy, injector_registry_request_stream) = next_client_old_stream::<
1242 pointerinjector::RegistryMarker,
1243 pointerinjector_next::Registry,
1244 >();
1245 let config_request_stream_fut =
1246 handle_configuration_request_stream(&mut configuration_request_stream);
1247
1248 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(2);
1252 let inspector = fuchsia_inspect::Inspector::default();
1253 let test_node = inspector.root().create_child("test_node");
1254 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1255 configuration_proxy,
1256 injector_registry_proxy,
1257 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1258 sender,
1259 &test_node,
1260 metrics::MetricsLogger::default(),
1261 );
1262 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1263 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1264
1265 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
1266 let event_time1 = zx::MonotonicInstant::get();
1267 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
1268
1269 let event1 = create_mouse_event(
1270 cursor_location,
1271 None, None, None, mouse_binding::MousePhase::Down,
1275 SortedVecSet::from(vec![1]),
1276 SortedVecSet::from(vec![1]),
1277 event_time1,
1278 &DESCRIPTOR,
1279 );
1280
1281 let event2 = create_mouse_event(
1282 cursor_location,
1283 None, None, None, mouse_binding::MousePhase::Up,
1287 SortedVecSet::from(vec![1]),
1288 SortedVecSet::new(),
1289 event_time2,
1290 &DESCRIPTOR,
1291 );
1292
1293 let expected_position = Position { x: 0.0, y: 0.0 };
1294
1295 let (injector_stream_sender, injector_stream_receiver) =
1299 mpsc::unbounded::<Vec<pointerinjector::Event>>();
1300 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
1302 let registry_fut = handle_registry_request_stream2(
1303 injector_registry_request_stream,
1304 injector_stream_sender,
1305 );
1306
1307 let _registry_task = fasync::Task::local(registry_fut);
1309
1310 mouse_handler.clone().handle_input_event(event1).await;
1311 assert_eq!(
1312 injector_stream_receiver
1313 .next()
1314 .await
1315 .map(|events| events.into_iter().flatten().collect()),
1316 Some(vec![
1317 create_mouse_pointer_sample_event_phase_add(
1318 vec![1],
1319 expected_position,
1320 event_time1,
1321 ),
1322 create_mouse_pointer_sample_event(
1323 pointerinjector::EventPhase::Change,
1324 vec![1],
1325 expected_position,
1326 None, None, None, None, event_time1,
1331 )
1332 ])
1333 );
1334
1335 mouse_handler.clone().handle_input_event(event2).await;
1337 assert_eq!(
1338 injector_stream_receiver
1339 .next()
1340 .await
1341 .map(|events| events.into_iter().flatten().collect()),
1342 Some(vec![create_mouse_pointer_sample_event(
1343 pointerinjector::EventPhase::Change,
1344 vec![],
1345 expected_position,
1346 None, None, None, None, event_time2,
1351 )])
1352 );
1353
1354 match receiver.next().await {
1356 Some(CursorMessage::SetPosition(position)) => {
1357 assert_eq!(position, expected_position);
1358 }
1359 Some(CursorMessage::SetVisibility(_)) => {
1360 panic!("Received unexpected cursor visibility update.")
1361 }
1362 None => panic!("Did not receive cursor update."),
1363 }
1364 }
1365
1366 #[fuchsia::test(allow_stalls = false)]
1376 async fn down_down_up_up_event() {
1377 let (configuration_proxy, mut configuration_request_stream) =
1379 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1380 let (injector_registry_proxy, injector_registry_request_stream) = next_client_old_stream::<
1381 pointerinjector::RegistryMarker,
1382 pointerinjector_next::Registry,
1383 >();
1384 let config_request_stream_fut =
1385 handle_configuration_request_stream(&mut configuration_request_stream);
1386
1387 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(4);
1391 let inspector = fuchsia_inspect::Inspector::default();
1392 let test_node = inspector.root().create_child("test_node");
1393 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1394 configuration_proxy,
1395 injector_registry_proxy,
1396 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1397 sender,
1398 &test_node,
1399 metrics::MetricsLogger::default(),
1400 );
1401 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1402 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1403
1404 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
1405 let event_time1 = zx::MonotonicInstant::get();
1406 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
1407 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
1408 let event_time4 = event_time3.add(zx::MonotonicDuration::from_micros(1));
1409
1410 let event1 = create_mouse_event(
1411 cursor_location,
1412 None, None, None, mouse_binding::MousePhase::Down,
1416 SortedVecSet::from(vec![1]),
1417 SortedVecSet::from(vec![1]),
1418 event_time1,
1419 &DESCRIPTOR,
1420 );
1421 let event2 = create_mouse_event(
1422 cursor_location,
1423 None, None, None, mouse_binding::MousePhase::Down,
1427 SortedVecSet::from(vec![2]),
1428 SortedVecSet::from(vec![1, 2]),
1429 event_time2,
1430 &DESCRIPTOR,
1431 );
1432 let event3 = create_mouse_event(
1433 cursor_location,
1434 None, None, None, mouse_binding::MousePhase::Up,
1438 SortedVecSet::from(vec![1]),
1439 SortedVecSet::from(vec![2]),
1440 event_time3,
1441 &DESCRIPTOR,
1442 );
1443 let event4 = create_mouse_event(
1444 cursor_location,
1445 None, None, None, mouse_binding::MousePhase::Up,
1449 SortedVecSet::from(vec![2]),
1450 SortedVecSet::new(),
1451 event_time4,
1452 &DESCRIPTOR,
1453 );
1454
1455 let expected_position = Position { x: 0.0, y: 0.0 };
1456
1457 let (injector_stream_sender, injector_stream_receiver) =
1461 mpsc::unbounded::<Vec<pointerinjector::Event>>();
1462 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
1464 let registry_fut = handle_registry_request_stream2(
1465 injector_registry_request_stream,
1466 injector_stream_sender,
1467 );
1468
1469 let _registry_task = fasync::Task::local(registry_fut);
1471 mouse_handler.clone().handle_input_event(event1).await;
1472 assert_eq!(
1473 injector_stream_receiver
1474 .next()
1475 .await
1476 .map(|events| events.into_iter().flatten().collect()),
1477 Some(vec![
1478 create_mouse_pointer_sample_event_phase_add(
1479 vec![1],
1480 expected_position,
1481 event_time1,
1482 ),
1483 create_mouse_pointer_sample_event(
1484 pointerinjector::EventPhase::Change,
1485 vec![1],
1486 expected_position,
1487 None, None, None, None, event_time1,
1492 )
1493 ])
1494 );
1495
1496 mouse_handler.clone().handle_input_event(event2).await;
1498 let pointer_sample_event2: Vec<_> = injector_stream_receiver
1499 .next()
1500 .await
1501 .map(|events| events.into_iter().flatten().collect())
1502 .expect("Failed to receive pointer sample event.");
1503 let expected_event_time: i64 = event_time2.into_nanos();
1504 assert_eq!(pointer_sample_event2.len(), 1);
1505
1506 match &pointer_sample_event2[0] {
1509 pointerinjector::Event {
1510 timestamp: Some(actual_event_time),
1511 data:
1512 Some(pointerinjector::Data::PointerSample(pointerinjector::PointerSample {
1513 pointer_id: Some(0),
1514 phase: Some(pointerinjector::EventPhase::Change),
1515 position_in_viewport: Some(actual_position),
1516 scroll_v: None,
1517 scroll_h: None,
1518 pressed_buttons: Some(actual_buttons),
1519 relative_motion: None,
1520 ..
1521 })),
1522 ..
1523 } => {
1524 assert_eq!(*actual_event_time, expected_event_time);
1525 assert_eq!(actual_position[0], expected_position.x);
1526 assert_eq!(actual_position[1], expected_position.y);
1527 assert_eq!(actual_buttons.as_slice(), &[1u8, 2u8]);
1528 }
1529 _ => panic!("Unexpected pointer sample event: {:?}", pointer_sample_event2[0]),
1530 }
1531
1532 mouse_handler.clone().handle_input_event(event3).await;
1534 assert_eq!(
1535 injector_stream_receiver
1536 .next()
1537 .await
1538 .map(|events| events.into_iter().flatten().collect()),
1539 Some(vec![create_mouse_pointer_sample_event(
1540 pointerinjector::EventPhase::Change,
1541 vec![2],
1542 expected_position,
1543 None, None, None, None, event_time3,
1548 )])
1549 );
1550
1551 mouse_handler.clone().handle_input_event(event4).await;
1553 assert_eq!(
1554 injector_stream_receiver
1555 .next()
1556 .await
1557 .map(|events| events.into_iter().flatten().collect()),
1558 Some(vec![create_mouse_pointer_sample_event(
1559 pointerinjector::EventPhase::Change,
1560 vec![],
1561 expected_position,
1562 None, None, None, None, event_time4,
1567 )])
1568 );
1569
1570 match receiver.next().await {
1572 Some(CursorMessage::SetPosition(position)) => {
1573 assert_eq!(position, expected_position);
1574 }
1575 Some(CursorMessage::SetVisibility(_)) => {
1576 panic!("Received unexpected cursor visibility update.")
1577 }
1578 None => panic!("Did not receive cursor update."),
1579 }
1580 }
1581
1582 #[fuchsia::test(allow_stalls = false)]
1584 async fn down_move_up_event() {
1585 let (configuration_proxy, mut configuration_request_stream) =
1587 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1588 let (injector_registry_proxy, injector_registry_request_stream) = next_client_old_stream::<
1589 pointerinjector::RegistryMarker,
1590 pointerinjector_next::Registry,
1591 >();
1592 let config_request_stream_fut =
1593 handle_configuration_request_stream(&mut configuration_request_stream);
1594
1595 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(3);
1599 let inspector = fuchsia_inspect::Inspector::default();
1600 let test_node = inspector.root().create_child("test_node");
1601 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1602 configuration_proxy,
1603 injector_registry_proxy,
1604 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1605 sender,
1606 &test_node,
1607 metrics::MetricsLogger::default(),
1608 );
1609 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1610 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1611
1612 let event_time1 = zx::MonotonicInstant::get();
1613 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
1614 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
1615 let zero_position = Position { x: 0.0, y: 0.0 };
1616 let expected_position = Position { x: 10.0, y: 5.0 };
1617 let expected_relative_motion = [10.0, 5.0];
1618 let event1 = create_mouse_event(
1619 mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 }),
1620 None, None, None, mouse_binding::MousePhase::Down,
1624 SortedVecSet::from(vec![1]),
1625 SortedVecSet::from(vec![1]),
1626 event_time1,
1627 &DESCRIPTOR,
1628 );
1629 let event2 = create_mouse_event(
1630 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1631 counts: Position { x: 10.0, y: 5.0 },
1632 }),
1633 None, None, None, mouse_binding::MousePhase::Move,
1637 SortedVecSet::from(vec![1]),
1638 SortedVecSet::from(vec![1]),
1639 event_time2,
1640 &DESCRIPTOR,
1641 );
1642 let event3 = create_mouse_event(
1643 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1644 counts: Position { x: 0.0, y: 0.0 },
1645 }),
1646 None, None, None, mouse_binding::MousePhase::Up,
1650 SortedVecSet::from(vec![1]),
1651 SortedVecSet::new(),
1652 event_time3,
1653 &DESCRIPTOR,
1654 );
1655
1656 let (injector_stream_sender, injector_stream_receiver) =
1660 mpsc::unbounded::<Vec<pointerinjector::Event>>();
1661 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
1663 let registry_fut = handle_registry_request_stream2(
1664 injector_registry_request_stream,
1665 injector_stream_sender,
1666 );
1667
1668 let _registry_task = fasync::Task::local(registry_fut);
1670 mouse_handler.clone().handle_input_event(event1).await;
1671 assert_eq!(
1672 injector_stream_receiver
1673 .next()
1674 .await
1675 .map(|events| events.into_iter().flatten().collect()),
1676 Some(vec![
1677 create_mouse_pointer_sample_event_phase_add(vec![1], zero_position, event_time1,),
1678 create_mouse_pointer_sample_event(
1679 pointerinjector::EventPhase::Change,
1680 vec![1],
1681 zero_position,
1682 None, None, None, None, event_time1,
1687 )
1688 ])
1689 );
1690
1691 match receiver.next().await {
1693 Some(CursorMessage::SetPosition(position)) => {
1694 assert_eq!(position, zero_position);
1695 }
1696 Some(CursorMessage::SetVisibility(_)) => {
1697 panic!("Received unexpected cursor visibility update.")
1698 }
1699 None => panic!("Did not receive cursor update."),
1700 }
1701
1702 mouse_handler.clone().handle_input_event(event2).await;
1704 assert_eq!(
1705 injector_stream_receiver
1706 .next()
1707 .await
1708 .map(|events| events.into_iter().flatten().collect()),
1709 Some(vec![create_mouse_pointer_sample_event(
1710 pointerinjector::EventPhase::Change,
1711 vec![1],
1712 expected_position,
1713 Some(expected_relative_motion),
1714 None, None, None, event_time2,
1718 )])
1719 );
1720
1721 match receiver.next().await {
1723 Some(CursorMessage::SetPosition(position)) => {
1724 assert_eq!(position, expected_position);
1725 }
1726 Some(CursorMessage::SetVisibility(_)) => {
1727 panic!("Received unexpected cursor visibility update.")
1728 }
1729 None => panic!("Did not receive cursor update."),
1730 }
1731
1732 mouse_handler.clone().handle_input_event(event3).await;
1734 assert_eq!(
1735 injector_stream_receiver
1736 .next()
1737 .await
1738 .map(|events| events.into_iter().flatten().collect()),
1739 Some(vec![create_mouse_pointer_sample_event(
1740 pointerinjector::EventPhase::Change,
1741 vec![],
1742 expected_position,
1743 None, None, None, None, event_time3,
1748 )])
1749 );
1750
1751 match receiver.next().await {
1753 Some(CursorMessage::SetPosition(position)) => {
1754 assert_eq!(position, expected_position);
1755 }
1756 Some(CursorMessage::SetVisibility(_)) => {
1757 panic!("Received unexpected cursor visibility update.")
1758 }
1759 None => panic!("Did not receive cursor update."),
1760 }
1761 }
1762
1763 #[fuchsia::test(allow_stalls = false)]
1765 async fn handler_ignores_handled_events() {
1766 let (configuration_proxy, mut configuration_request_stream) =
1768 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1769 let (injector_registry_proxy, injector_registry_request_stream) = next_client_old_stream::<
1770 pointerinjector::RegistryMarker,
1771 pointerinjector_next::Registry,
1772 >();
1773 let config_request_stream_fut =
1774 handle_configuration_request_stream(&mut configuration_request_stream);
1775
1776 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
1778 let inspector = fuchsia_inspect::Inspector::default();
1779 let test_node = inspector.root().create_child("test_node");
1780 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1781 configuration_proxy,
1782 injector_registry_proxy,
1783 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1784 sender,
1785 &test_node,
1786 metrics::MetricsLogger::default(),
1787 );
1788 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1789 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1790
1791 let cursor_relative_position = Position { x: 50.0, y: 75.0 };
1792 let cursor_location =
1793 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1794 counts: Position { x: cursor_relative_position.x, y: cursor_relative_position.y },
1795 });
1796 let event_time = zx::MonotonicInstant::get();
1797 let input_events = vec![create_mouse_event_with_handled(
1798 cursor_location,
1799 None, None, None, mouse_binding::MousePhase::Move,
1803 SortedVecSet::new(),
1804 SortedVecSet::new(),
1805 event_time,
1806 &DESCRIPTOR,
1807 input_device::Handled::Yes,
1808 )];
1809
1810 assert_handler_ignores_input_event_sequence(
1811 mouse_handler,
1812 input_events,
1813 injector_registry_request_stream,
1814 )
1815 .await;
1816
1817 assert!(receiver.next().await.is_none());
1819 }
1820
1821 fn zero_relative_location() -> mouse_binding::MouseLocation {
1822 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1823 counts: Position { x: 0.0, y: 0.0 },
1824 })
1825 }
1826
1827 #[test_case(
1828 create_mouse_event(
1829 zero_relative_location(),
1830 wheel_delta_ticks(1, None), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1834 SortedVecSet::new(),
1835 SortedVecSet::new(),
1836 zx::MonotonicInstant::ZERO,
1837 &DESCRIPTOR,
1838 ),
1839 create_mouse_pointer_sample_event(
1840 pointerinjector::EventPhase::Change,
1841 vec![],
1842 Position { x: 50.0, y: 50.0 },
1843 None, Some(1), None, Some(false), zx::MonotonicInstant::ZERO,
1848 ); "v tick scroll"
1849 )]
1850 #[test_case(
1851 create_mouse_event(
1852 zero_relative_location(),
1853 None, wheel_delta_ticks(1, None), Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1857 SortedVecSet::new(),
1858 SortedVecSet::new(),
1859 zx::MonotonicInstant::ZERO,
1860 &DESCRIPTOR,
1861 ),
1862 create_mouse_pointer_sample_event(
1863 pointerinjector::EventPhase::Change,
1864 vec![],
1865 Position { x: 50.0, y: 50.0 },
1866 None, None, Some(1), Some(false), zx::MonotonicInstant::ZERO,
1871 ); "h tick scroll"
1872 )]
1873 #[test_case(
1874 create_mouse_event(
1875 zero_relative_location(),
1876 wheel_delta_ticks(1, Some(120.0)), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1880 SortedVecSet::new(),
1881 SortedVecSet::new(),
1882 zx::MonotonicInstant::ZERO,
1883 &DESCRIPTOR,
1884 ),
1885 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
1886 pointerinjector::EventPhase::Change,
1887 vec![],
1888 Position { x: 50.0, y: 50.0 },
1889 None, Some(1), None, Some(120.0), None, Some(false), zx::MonotonicInstant::ZERO,
1896 ); "v tick scroll with physical pixel"
1897 )]
1898 #[test_case(
1899 create_mouse_event(
1900 zero_relative_location(),
1901 None, wheel_delta_ticks(1, Some(120.0)), Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1905 SortedVecSet::new(),
1906 SortedVecSet::new(),
1907 zx::MonotonicInstant::ZERO,
1908 &DESCRIPTOR,
1909 ),
1910 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
1911 pointerinjector::EventPhase::Change,
1912 vec![],
1913 Position { x: 50.0, y: 50.0 },
1914 None, None, Some(1), None, Some(120.0), Some(false), zx::MonotonicInstant::ZERO,
1921 ); "h tick scroll with physical pixel"
1922 )]
1923 #[test_case(
1924 create_mouse_event(
1925 zero_relative_location(),
1926 wheel_delta_ticks(1, Some(120.0)), None, Some(mouse_binding::PrecisionScroll::Yes), mouse_binding::MousePhase::Wheel,
1930 SortedVecSet::new(),
1931 SortedVecSet::new(),
1932 zx::MonotonicInstant::ZERO,
1933 &DESCRIPTOR,
1934 ),
1935 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
1936 pointerinjector::EventPhase::Change,
1937 vec![],
1938 Position { x: 50.0, y: 50.0 },
1939 None, Some(1), None, Some(120.0), None, Some(true), zx::MonotonicInstant::ZERO,
1946 ); "v precision scroll with physical pixel"
1947 )]
1948 #[test_case(
1949 create_mouse_event(
1950 zero_relative_location(),
1951 None, wheel_delta_ticks(1, Some(120.0)), Some(mouse_binding::PrecisionScroll::Yes), mouse_binding::MousePhase::Wheel,
1955 SortedVecSet::new(),
1956 SortedVecSet::new(),
1957 zx::MonotonicInstant::ZERO,
1958 &DESCRIPTOR,
1959 ),
1960 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
1961 pointerinjector::EventPhase::Change,
1962 vec![],
1963 Position { x: 50.0, y: 50.0 },
1964 None, None, Some(1), None, Some(120.0), Some(true), zx::MonotonicInstant::ZERO,
1971 ); "h precision scroll with physical pixel"
1972 )]
1973 #[fuchsia::test(allow_stalls = false)]
1975 async fn scroll(event: input_device::InputEvent, want_event: pointerinjector::Event) {
1976 let (configuration_proxy, mut configuration_request_stream) =
1978 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1979 let (injector_registry_proxy, injector_registry_request_stream) = next_client_old_stream::<
1980 pointerinjector::RegistryMarker,
1981 pointerinjector_next::Registry,
1982 >();
1983 let config_request_stream_fut =
1984 handle_configuration_request_stream(&mut configuration_request_stream);
1985
1986 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
1988 let inspector = fuchsia_inspect::Inspector::default();
1989 let test_node = inspector.root().create_child("test_node");
1990 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1991 configuration_proxy,
1992 injector_registry_proxy,
1993 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1994 sender,
1995 &test_node,
1996 metrics::MetricsLogger::default(),
1997 );
1998 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1999 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
2000
2001 let (injector_stream_sender, injector_stream_receiver) =
2005 mpsc::unbounded::<Vec<pointerinjector::Event>>();
2006 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
2008 let registry_fut = handle_registry_request_stream2(
2009 injector_registry_request_stream,
2010 injector_stream_sender,
2011 );
2012
2013 let event_time = zx::MonotonicInstant::get();
2014
2015 let event = input_device::InputEvent { event_time, ..event };
2016
2017 let want_event =
2018 pointerinjector::Event { timestamp: Some(event_time.into_nanos()), ..want_event };
2019
2020 let _registry_task = fasync::Task::local(registry_fut);
2022
2023 mouse_handler.clone().handle_input_event(event).await;
2024 let got_events: Vec<_> = injector_stream_receiver
2025 .next()
2026 .await
2027 .map(|events| events.into_iter().flatten().collect())
2028 .unwrap();
2029 pretty_assertions::assert_eq!(got_events.len(), 2);
2030 assert_matches!(
2031 got_events[0],
2032 pointerinjector::Event {
2033 data: Some(pointerinjector::Data::PointerSample(pointerinjector::PointerSample {
2034 phase: Some(pointerinjector::EventPhase::Add),
2035 ..
2036 })),
2037 ..
2038 }
2039 );
2040
2041 pretty_assertions::assert_eq!(got_events[1], want_event);
2042 }
2043
2044 #[fuchsia::test(allow_stalls = false)]
2046 async fn down_scroll_up_scroll() {
2047 let (configuration_proxy, mut configuration_request_stream) =
2049 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
2050 let (injector_registry_proxy, injector_registry_request_stream) = next_client_old_stream::<
2051 pointerinjector::RegistryMarker,
2052 pointerinjector_next::Registry,
2053 >();
2054 let config_request_stream_fut =
2055 handle_configuration_request_stream(&mut configuration_request_stream);
2056
2057 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
2059 let inspector = fuchsia_inspect::Inspector::default();
2060 let test_node = inspector.root().create_child("test_node");
2061 let mouse_handler_fut = MouseInjectorHandler::new_handler(
2062 configuration_proxy,
2063 injector_registry_proxy,
2064 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
2065 sender,
2066 &test_node,
2067 metrics::MetricsLogger::default(),
2068 );
2069 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
2070 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
2071
2072 let (injector_stream_sender, injector_stream_receiver) =
2076 mpsc::unbounded::<Vec<pointerinjector::Event>>();
2077 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
2079 let registry_fut = handle_registry_request_stream2(
2080 injector_registry_request_stream,
2081 injector_stream_sender,
2082 );
2083
2084 let event_time1 = zx::MonotonicInstant::get();
2085 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
2086 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
2087 let event_time4 = event_time3.add(zx::MonotonicDuration::from_micros(1));
2088
2089 let _registry_task = fasync::Task::local(registry_fut);
2091
2092 let zero_location =
2093 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
2094 counts: Position { x: 0.0, y: 0.0 },
2095 });
2096 let expected_position = Position { x: 50.0, y: 50.0 };
2097
2098 let down_event = create_mouse_event(
2099 zero_location,
2100 None, None, None, mouse_binding::MousePhase::Down,
2104 SortedVecSet::from(vec![1]),
2105 SortedVecSet::from(vec![1]),
2106 event_time1,
2107 &DESCRIPTOR,
2108 );
2109
2110 let wheel_event = create_mouse_event(
2111 zero_location,
2112 wheel_delta_ticks(1, None), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
2116 SortedVecSet::from(vec![1]),
2117 SortedVecSet::from(vec![1]),
2118 event_time2,
2119 &DESCRIPTOR,
2120 );
2121
2122 let up_event = create_mouse_event(
2123 zero_location,
2124 None,
2125 None,
2126 None, mouse_binding::MousePhase::Up,
2128 SortedVecSet::from(vec![1]),
2129 SortedVecSet::new(),
2130 event_time3,
2131 &DESCRIPTOR,
2132 );
2133
2134 let continue_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 SortedVecSet::new(),
2141 SortedVecSet::new(),
2142 event_time4,
2143 &DESCRIPTOR,
2144 );
2145
2146 mouse_handler.clone().handle_input_event(down_event).await;
2148 assert_eq!(
2149 injector_stream_receiver
2150 .next()
2151 .await
2152 .map(|events| events.into_iter().flatten().collect()),
2153 Some(vec![
2154 create_mouse_pointer_sample_event_phase_add(
2155 vec![1],
2156 expected_position,
2157 event_time1,
2158 ),
2159 create_mouse_pointer_sample_event(
2160 pointerinjector::EventPhase::Change,
2161 vec![1],
2162 expected_position,
2163 None, None, None, None, event_time1,
2168 ),
2169 ])
2170 );
2171
2172 mouse_handler.clone().handle_input_event(wheel_event).await;
2174 assert_eq!(
2175 injector_stream_receiver
2176 .next()
2177 .await
2178 .map(|events| events.into_iter().flatten().collect()),
2179 Some(vec![create_mouse_pointer_sample_event(
2180 pointerinjector::EventPhase::Change,
2181 vec![1],
2182 expected_position,
2183 None, Some(1), None, Some(false), event_time2,
2188 )])
2189 );
2190
2191 mouse_handler.clone().handle_input_event(up_event).await;
2193 assert_eq!(
2194 injector_stream_receiver
2195 .next()
2196 .await
2197 .map(|events| events.into_iter().flatten().collect()),
2198 Some(vec![create_mouse_pointer_sample_event(
2199 pointerinjector::EventPhase::Change,
2200 vec![],
2201 expected_position,
2202 None, None, None, None, event_time3,
2207 )])
2208 );
2209
2210 mouse_handler.clone().handle_input_event(continue_wheel_event).await;
2212 assert_eq!(
2213 injector_stream_receiver
2214 .next()
2215 .await
2216 .map(|events| events.into_iter().flatten().collect()),
2217 Some(vec![create_mouse_pointer_sample_event(
2218 pointerinjector::EventPhase::Change,
2219 vec![],
2220 expected_position,
2221 None, Some(1), None, Some(false), event_time4,
2226 )])
2227 );
2228 }
2229
2230 #[fuchsia::test(allow_stalls = false)]
2231 async fn mouse_injector_handler_initialized_with_inspect_node() {
2232 let (configuration_proxy, mut configuration_request_stream) =
2233 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
2234 let config_request_stream_fut =
2235 handle_configuration_request_stream(&mut configuration_request_stream);
2236 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
2237 let inspector = fuchsia_inspect::Inspector::default();
2238 let fake_handlers_node = inspector.root().create_child("input_handlers_node");
2239 let incoming = Incoming::new();
2240 let mouse_handler_fut = MouseInjectorHandler::new_with_config_proxy(
2241 &incoming,
2242 configuration_proxy,
2243 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
2244 sender,
2245 &fake_handlers_node,
2246 metrics::MetricsLogger::default(),
2247 );
2248 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
2249 let _handler = mouse_handler_res.expect("Failed to create mouse handler");
2250
2251 diagnostics_assertions::assert_data_tree!(inspector, root: {
2252 input_handlers_node: {
2253 mouse_injector_handler: {
2254 events_received_count: 0u64,
2255 events_handled_count: 0u64,
2256 last_received_timestamp_ns: 0u64,
2257 "fuchsia.inspect.Health": {
2258 status: "STARTING_UP",
2259 start_timestamp_nanos: diagnostics_assertions::AnyProperty
2262 },
2263 }
2264 }
2265 });
2266 }
2267
2268 #[fuchsia::test(allow_stalls = false)]
2269 async fn mouse_injector_handler_inspect_counts_events() {
2270 let (configuration_proxy, mut configuration_request_stream) =
2272 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
2273 let (injector_registry_proxy, injector_registry_request_stream) = next_client_old_stream::<
2274 pointerinjector::RegistryMarker,
2275 pointerinjector_next::Registry,
2276 >();
2277 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
2278
2279 let inspector = fuchsia_inspect::Inspector::default();
2280 let fake_handlers_node = inspector.root().create_child("input_handlers_node");
2281
2282 let mouse_handler_fut = MouseInjectorHandler::new_handler(
2284 configuration_proxy,
2285 injector_registry_proxy,
2286 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
2287 sender,
2288 &fake_handlers_node,
2289 metrics::MetricsLogger::default(),
2290 );
2291 let config_request_stream_fut =
2292 handle_configuration_request_stream(&mut configuration_request_stream);
2293
2294 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
2295 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
2296
2297 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
2298 let event_time1 = zx::MonotonicInstant::get();
2299 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
2300 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
2301
2302 let input_events = vec![
2303 create_mouse_event(
2304 cursor_location,
2305 None, None, None, mouse_binding::MousePhase::Down,
2309 SortedVecSet::from(vec![1]),
2310 SortedVecSet::from(vec![1]),
2311 event_time1,
2312 &DESCRIPTOR,
2313 ),
2314 create_mouse_event(
2315 cursor_location,
2316 None, None, None, mouse_binding::MousePhase::Up,
2320 SortedVecSet::from(vec![1]),
2321 SortedVecSet::new(),
2322 event_time2,
2323 &DESCRIPTOR,
2324 ),
2325 create_mouse_event_with_handled(
2326 cursor_location,
2327 None, None, None, mouse_binding::MousePhase::Down,
2331 SortedVecSet::from(vec![1]),
2332 SortedVecSet::from(vec![1]),
2333 event_time3,
2334 &DESCRIPTOR,
2335 input_device::Handled::Yes,
2336 ),
2337 ];
2338
2339 let (injector_stream_sender, _) = mpsc::unbounded::<Vec<pointerinjector::Event>>();
2343 let registry_fut = handle_registry_request_stream2(
2344 injector_registry_request_stream,
2345 injector_stream_sender,
2346 );
2347
2348 let _registry_task = fasync::Task::local(registry_fut);
2350 for input_event in input_events {
2351 mouse_handler.clone().handle_input_event(input_event).await;
2352 }
2353
2354 let last_received_event_time: u64 = event_time2.into_nanos().try_into().unwrap();
2355
2356 diagnostics_assertions::assert_data_tree!(inspector, root: {
2357 input_handlers_node: {
2358 mouse_injector_handler: {
2359 events_received_count: 2u64,
2360 events_handled_count: 2u64,
2361 last_received_timestamp_ns: last_received_event_time,
2362 "fuchsia.inspect.Health": {
2363 status: "STARTING_UP",
2364 start_timestamp_nanos: diagnostics_assertions::AnyProperty
2367 },
2368 }
2369 }
2370 });
2371 }
2372}