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_report::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
27const MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL: f32 = 10.0;
35
36pub struct MouseInjectorHandler {
39 mutable_state: RefCell<MutableState>,
41
42 context_view_ref: fidl_fuchsia_ui_views::ViewRef,
45
46 target_view_ref: fidl_fuchsia_ui_views::ViewRef,
49
50 max_position: Position,
53
54 injector_registry_proxy: fidl_next::Client<pointerinjector::Registry, Transport>,
56
57 configuration_proxy: pointerinjector_config::SetupProxy,
59
60 pub inspect_status: InputHandlerStatus,
62
63 metrics_logger: metrics::MetricsLogger,
64}
65
66struct MutableState {
67 viewport: Option<pointerinjector::Viewport>,
70
71 injectors: SortedVecMap<u32, fidl_next::Client<pointerinjector::Device, Transport>>,
73
74 current_position: Position,
76
77 cursor_message_sender: Sender<CursorMessage>,
79}
80
81impl Handler for MouseInjectorHandler {
82 fn set_handler_healthy(self: std::rc::Rc<Self>) {
83 self.inspect_status.health_node.borrow_mut().set_ok();
84 }
85
86 fn set_handler_unhealthy(self: std::rc::Rc<Self>, msg: &str) {
87 self.inspect_status.health_node.borrow_mut().set_unhealthy(msg);
88 }
89
90 fn get_name(&self) -> &'static str {
91 "MouseInjectorHandler"
92 }
93
94 fn interest(&self) -> Vec<input_device::InputEventType> {
95 vec![input_device::InputEventType::Mouse]
96 }
97}
98
99#[async_trait(?Send)]
100impl InputHandler for MouseInjectorHandler {
101 async fn handle_input_event(
102 self: Rc<Self>,
103 mut input_event: input_device::InputEvent,
104 ) -> Vec<input_device::InputEvent> {
105 fuchsia_trace::duration!("input", "mouse_injector_handler");
106 match input_event {
107 input_device::InputEvent {
108 device_event: input_device::InputDeviceEvent::Mouse(ref mouse_event),
109 device_descriptor:
110 input_device::InputDeviceDescriptor::Mouse(ref mouse_device_descriptor),
111 event_time,
112 handled: input_device::Handled::No,
113 trace_id,
114 } => {
115 fuchsia_trace::duration!("input", "mouse_injector_handler[processing]");
116 let trace_id = match trace_id {
117 Some(id) => {
118 fuchsia_trace::flow_step!("input", "event_in_input_pipeline", id.into());
119 id
120 }
121 None => fuchsia_trace::Id::random(),
122 };
123
124 self.inspect_status.count_received_event(&event_time);
125 if let Err(e) =
127 self.update_cursor_renderer(mouse_event, &mouse_device_descriptor).await
128 {
129 self.metrics_logger.log_error(
130 InputPipelineErrorMetricDimensionEvent::MouseInjectorUpdateCursorRendererFailed,
131 std::format!("update_cursor_renderer failed: {}", e));
132 }
133
134 if let Err(e) = self
136 .ensure_injector_registered(&mouse_event, &mouse_device_descriptor, event_time)
137 .await
138 {
139 self.metrics_logger.log_error(
140 InputPipelineErrorMetricDimensionEvent::MouseInjectorEnsureInjectorRegisteredFailed,
141 std::format!("ensure_injector_registered failed: {}", e));
142 }
143
144 if let Err(e) = self
146 .send_event_to_scenic(
147 &mouse_event,
148 &mouse_device_descriptor,
149 event_time,
150 trace_id.into(),
151 )
152 .await
153 {
154 self.metrics_logger.log_error(
155 InputPipelineErrorMetricDimensionEvent::MouseInjectorSendEventToScenicFailed,
156 std::format!("send_event_to_scenic failed: {}", e));
157 }
158
159 input_event.handled = input_device::Handled::Yes;
161 self.inspect_status.count_handled_event();
162 }
163 _ => {
164 self.metrics_logger.log_error(
165 InputPipelineErrorMetricDimensionEvent::HandlerReceivedUninterestedEvent,
166 std::format!(
167 "{} uninterested input event: {:?}",
168 self.get_name(),
169 input_event.get_event_type()
170 ),
171 );
172 }
173 }
174 vec![input_event]
175 }
176}
177
178impl MouseInjectorHandler {
179 pub async fn new(
192 incoming: &Incoming,
193 display_size: Size,
194 cursor_message_sender: Sender<CursorMessage>,
195 input_handlers_node: &fuchsia_inspect::Node,
196 metrics_logger: metrics::MetricsLogger,
197 ) -> Result<Rc<Self>, Error> {
198 let configuration_proxy =
199 incoming.connect_protocol::<pointerinjector_config::SetupProxy>()?;
200 let injector_registry_proxy =
201 incoming.connect_protocol_next::<pointerinjector::Registry>()?.spawn();
202
203 Self::new_handler(
204 configuration_proxy,
205 injector_registry_proxy,
206 display_size,
207 cursor_message_sender,
208 input_handlers_node,
209 metrics_logger,
210 )
211 .await
212 }
213
214 pub async fn new_with_config_proxy(
230 incoming: &Incoming,
231 configuration_proxy: pointerinjector_config::SetupProxy,
232 display_size: Size,
233 cursor_message_sender: Sender<CursorMessage>,
234 input_handlers_node: &fuchsia_inspect::Node,
235 metrics_logger: metrics::MetricsLogger,
236 ) -> Result<Rc<Self>, Error> {
237 let injector_registry_proxy =
238 incoming.connect_protocol_next::<pointerinjector::Registry>()?.spawn();
239 Self::new_handler(
240 configuration_proxy,
241 injector_registry_proxy,
242 display_size,
243 cursor_message_sender,
244 input_handlers_node,
245 metrics_logger,
246 )
247 .await
248 }
249
250 fn inner(&self) -> Ref<'_, MutableState> {
251 self.mutable_state.borrow()
252 }
253
254 fn inner_mut(&self) -> RefMut<'_, MutableState> {
255 self.mutable_state.borrow_mut()
256 }
257
258 async fn new_handler(
274 configuration_proxy: pointerinjector_config::SetupProxy,
275 injector_registry_proxy: fidl_next::Client<pointerinjector::Registry, Transport>,
276 display_size: Size,
277 cursor_message_sender: Sender<CursorMessage>,
278 input_handlers_node: &fuchsia_inspect::Node,
279 metrics_logger: metrics::MetricsLogger,
280 ) -> Result<Rc<Self>, Error> {
281 let (context_view_ref, target_view_ref) = configuration_proxy.get_view_refs().await?;
283 let inspect_status = InputHandlerStatus::new(
284 input_handlers_node,
285 "mouse_injector_handler",
286 false,
287 );
288 let handler = Rc::new(Self {
289 mutable_state: RefCell::new(MutableState {
290 viewport: None,
291 injectors: SortedVecMap::new(),
292 current_position: Position {
294 x: display_size.width / 2.0,
295 y: display_size.height / 2.0,
296 },
297 cursor_message_sender,
298 }),
299 context_view_ref,
300 target_view_ref,
301 max_position: Position { x: display_size.width, y: display_size.height },
302 injector_registry_proxy,
303 configuration_proxy,
304 inspect_status,
305 metrics_logger,
306 });
307
308 Ok(handler)
309 }
310
311 async fn ensure_injector_registered(
319 self: &Rc<Self>,
320 mouse_event: &mouse_binding::MouseEvent,
321 mouse_descriptor: &mouse_binding::MouseDeviceDescriptor,
322 event_time: zx::MonotonicInstant,
323 ) -> Result<(), anyhow::Error> {
324 if self.inner().injectors.contains_key(&mouse_descriptor.device_id) {
325 return Ok(());
326 }
327
328 let (device_proxy, device_server) =
330 fidl_next::fuchsia::create_channel::<pointerinjector::Device>();
331 let device_proxy = Dispatcher::client_from_zx_channel(device_proxy).spawn();
332 let context = fuchsia_scenic::duplicate_view_ref(&self.context_view_ref)
333 .context("Failed to duplicate context view ref.")?;
334 let context = fidl_next_fuchsia_ui_views::ViewRef { reference: context.reference };
335 let target = fuchsia_scenic::duplicate_view_ref(&self.target_view_ref)
336 .context("Failed to duplicate target view ref.")?;
337 let target = fidl_next_fuchsia_ui_views::ViewRef { reference: target.reference };
338
339 let viewport = self.inner().viewport.clone();
340 let config = pointerinjector::Config {
341 device_id: Some(mouse_descriptor.device_id),
342 device_type: Some(pointerinjector::DeviceType::Mouse),
343 context: Some(pointerinjector::Context::View(context)),
344 target: Some(pointerinjector::Target::View(target)),
345 viewport,
346 dispatch_policy: Some(pointerinjector::DispatchPolicy::MouseHoverAndLatchInTarget),
347 scroll_v_range: utils::axis_to_next(mouse_descriptor.wheel_v_range.as_ref()),
348 scroll_h_range: utils::axis_to_next(mouse_descriptor.wheel_h_range.as_ref()),
349 buttons: mouse_descriptor.buttons.clone(),
350 ..Default::default()
351 };
352
353 self.injector_registry_proxy
355 .register(config, device_server)
356 .await
357 .context("Failed to register injector.")?;
358 log::info!("Registered injector with device id {:?}", mouse_descriptor.device_id);
359
360 self.inner_mut().injectors.insert(mouse_descriptor.device_id, device_proxy.clone());
362
363 let events_to_send = vec![self.create_pointer_sample_event(
365 mouse_event,
366 event_time,
367 pointerinjector::EventPhase::Add,
368 self.inner().current_position,
369 None,
370 None,
371 )];
372 device_proxy
373 .inject_events(events_to_send)
374 .send_immediately()
375 .context("Failed to ADD new MouseDevice.")?;
376
377 Ok(())
378 }
379
380 async fn update_cursor_renderer(
391 &self,
392 mouse_event: &mouse_binding::MouseEvent,
393 mouse_descriptor: &mouse_binding::MouseDeviceDescriptor,
394 ) -> Result<(), anyhow::Error> {
395 let mut new_position = match (mouse_event.location, mouse_descriptor) {
396 (
397 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
398 millimeters,
399 }),
400 _,
401 ) => {
402 self.inner().current_position
403 + self.relative_movement_mm_to_phyical_pixel(millimeters)
404 }
405 (
406 mouse_binding::MouseLocation::Absolute(position),
407 mouse_binding::MouseDeviceDescriptor {
408 absolute_x_range: Some(x_range),
409 absolute_y_range: Some(y_range),
410 ..
411 },
412 ) => self.scale_absolute_position(&position, &x_range, &y_range),
413 (mouse_binding::MouseLocation::Absolute(_), _) => {
414 return Err(anyhow!(
415 "Received an Absolute mouse location without absolute device ranges."
416 ));
417 }
418 };
419 Position::clamp(&mut new_position, Position::zero(), self.max_position);
420 self.inner_mut().current_position = new_position;
421
422 let mut cursor_message_sender = self.inner().cursor_message_sender.clone();
423 cursor_message_sender
424 .send(CursorMessage::SetPosition(new_position))
425 .await
426 .context("Failed to send current mouse position to cursor renderer")?;
427
428 Ok(())
429 }
430
431 fn scale_absolute_position(
439 &self,
440 position: &Position,
441 x_range: &Range,
442 y_range: &Range,
443 ) -> Position {
444 let range_min = Position { x: x_range.min as f32, y: y_range.min as f32 };
445 let range_max = Position { x: x_range.max as f32, y: y_range.max as f32 };
446 self.max_position * ((*position - range_min) / (range_max - range_min))
447 }
448
449 async fn send_event_to_scenic(
456 &self,
457 mouse_event: &mouse_binding::MouseEvent,
458 mouse_descriptor: &mouse_binding::MouseDeviceDescriptor,
459 event_time: zx::MonotonicInstant,
460 tracing_id: u64,
461 ) -> Result<(), anyhow::Error> {
462 let injector = self.inner().injectors.get(&mouse_descriptor.device_id).cloned();
463 if let Some(injector) = injector {
464 let relative_motion = match mouse_event.location {
465 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
466 millimeters: offset_mm,
467 }) if mouse_event.phase == mouse_binding::MousePhase::Move => {
468 let offset = self.relative_movement_mm_to_phyical_pixel(offset_mm);
469 Some([offset.x, offset.y])
470 }
471 _ => None,
472 };
473 let events_to_send = vec![self.create_pointer_sample_event(
474 mouse_event,
475 event_time,
476 pointerinjector::EventPhase::Change,
477 self.inner().current_position,
478 relative_motion,
479 Some(tracing_id),
480 )];
481
482 fuchsia_trace::flow_begin!("input", "dispatch_event_to_scenic", tracing_id.into());
483
484 _ = injector.inject_events(events_to_send).send_immediately();
485
486 Ok(())
487 } else {
488 Err(anyhow::format_err!(
489 "No injector found for mouse device {}.",
490 mouse_descriptor.device_id
491 ))
492 }
493 }
494
495 fn create_pointer_sample_event(
504 &self,
505 mouse_event: &mouse_binding::MouseEvent,
506 event_time: zx::MonotonicInstant,
507 phase: pointerinjector::EventPhase,
508 current_position: Position,
509 relative_motion: Option<[f32; 2]>,
510 trace_id: Option<u64>,
511 ) -> pointerinjector::Event {
512 let pointer_sample = pointerinjector::PointerSample {
513 pointer_id: Some(0),
514 phase: Some(phase),
515 position_in_viewport: Some([current_position.x, current_position.y]),
516 scroll_v: match mouse_event.wheel_delta_v {
517 Some(mouse_binding::WheelDelta {
518 raw_data: mouse_binding::RawWheelDelta::Ticks(tick),
519 ..
520 }) => Some(tick),
521 _ => None,
522 },
523 scroll_h: match mouse_event.wheel_delta_h {
524 Some(mouse_binding::WheelDelta {
525 raw_data: mouse_binding::RawWheelDelta::Ticks(tick),
526 ..
527 }) => Some(tick),
528 _ => None,
529 },
530 scroll_v_physical_pixel: match mouse_event.wheel_delta_v {
531 Some(mouse_binding::WheelDelta { physical_pixel: Some(pixel), .. }) => {
532 Some(pixel.into())
533 }
534 _ => None,
535 },
536 scroll_h_physical_pixel: match mouse_event.wheel_delta_h {
537 Some(mouse_binding::WheelDelta { physical_pixel: Some(pixel), .. }) => {
538 Some(pixel.into())
539 }
540 _ => None,
541 },
542 is_precision_scroll: match mouse_event.phase {
543 mouse_binding::MousePhase::Wheel => match mouse_event.is_precision_scroll {
544 Some(mouse_binding::PrecisionScroll::Yes) => Some(true),
545 Some(mouse_binding::PrecisionScroll::No) => Some(false),
546 None => {
547 self.metrics_logger.log_error(
548 InputPipelineErrorMetricDimensionEvent::MouseInjectorMissingIsPrecisionScroll,
549 "mouse wheel event does not have value in is_precision_scroll.");
550 None
551 }
552 },
553 _ => None,
554 },
555 pressed_buttons: Some(mouse_event.pressed_buttons.clone().into()),
556 relative_motion,
557 ..Default::default()
558 };
559 pointerinjector::Event {
560 timestamp: Some(event_time.into_nanos()),
561 data: Some(pointerinjector::Data::PointerSample(pointer_sample)),
562 trace_flow_id: trace_id,
563 wake_lease: mouse_event.wake_lease.lock().take(),
564 ..Default::default()
565 }
566 }
567
568 pub async fn watch_viewport(self: Rc<Self>) {
570 let configuration_proxy = self.configuration_proxy.clone();
571 let mut viewport_stream = HangingGetStream::new(
572 configuration_proxy,
573 pointerinjector_config::SetupProxy::watch_viewport,
574 );
575 loop {
576 match viewport_stream.next().await {
577 Some(Ok(new_viewport)) => {
578 self.inner_mut().viewport = Some(utils::viewport_to_next(&new_viewport));
580
581 let injectors =
583 self.inner().injectors.iter().map(|(_, v)| v).cloned().collect::<Vec<_>>();
584 for injector in injectors {
585 let events = vec![pointerinjector::Event {
586 timestamp: Some(MonotonicInstant::now().into_nanos()),
587 data: Some(pointerinjector::Data::Viewport(utils::viewport_to_next(
588 &new_viewport,
589 ))),
590 trace_flow_id: Some(fuchsia_trace::Id::random().into()),
591 ..Default::default()
592 }];
593 injector
594 .inject_events(events)
595 .await
596 .expect("Failed to inject updated viewport.");
597 }
598 }
599 Some(Err(e)) => {
600 self.metrics_logger.log_error(
601 InputPipelineErrorMetricDimensionEvent::MouseInjectorErrorWhileReadingViewportUpdate,
602 std::format!("Error while reading viewport update: {}", e));
603 return;
604 }
605 None => {
606 self.metrics_logger.log_error(
607 InputPipelineErrorMetricDimensionEvent::MouseInjectorViewportUpdateStreamTerminatedUnexpectedly,
608 "Viewport update stream terminated unexpectedly");
609 return;
610 }
611 }
612 }
613 }
614
615 fn relative_movement_mm_to_phyical_pixel(&self, movement_mm: Position) -> Position {
619 Position {
620 x: movement_mm.x * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
621 y: movement_mm.y * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
622 }
623 }
624}
625
626#[cfg(test)]
627mod tests {
628 use super::*;
629 use crate::testing_utilities::{
630 assert_handler_ignores_input_event_sequence, create_mouse_event,
631 create_mouse_event_with_handled, create_mouse_pointer_sample_event,
632 create_mouse_pointer_sample_event_phase_add,
633 create_mouse_pointer_sample_event_with_wheel_physical_pixel, next_client_old_stream,
634 };
635 use assert_matches::assert_matches;
636 use fidl_fuchsia_input_report as fidl_input_report;
637 use fidl_fuchsia_ui_pointerinjector as pointerinjector;
638 use fidl_next_fuchsia_ui_pointerinjector as pointerinjector_next;
639 use fuchsia_async as fasync;
640 use futures::channel::mpsc;
641 use pretty_assertions::assert_eq;
642 use sorted_vec_map::SortedVecSet;
643 use std::ops::Add;
644 use test_case::test_case;
645
646 const DISPLAY_WIDTH_IN_PHYSICAL_PX: f32 = 100.0;
647 const DISPLAY_HEIGHT_IN_PHYSICAL_PX: f32 = 100.0;
648 const COUNTS_PER_MM: u32 = 12;
649
650 const DESCRIPTOR: input_device::InputDeviceDescriptor =
652 input_device::InputDeviceDescriptor::Mouse(mouse_binding::MouseDeviceDescriptor {
653 device_id: 1,
654 absolute_x_range: Some(fidl_input_report::Range { min: 0, max: 100 }),
655 absolute_y_range: Some(fidl_input_report::Range { min: 0, max: 100 }),
656 wheel_v_range: Some(fidl_input_report::Axis {
657 range: fidl_input_report::Range { min: -1, max: 1 },
658 unit: fidl_input_report::Unit {
659 type_: fidl_input_report::UnitType::Other,
660 exponent: 0,
661 },
662 }),
663 wheel_h_range: Some(fidl_input_report::Axis {
664 range: fidl_input_report::Range { min: -1, max: 1 },
665 unit: fidl_input_report::Unit {
666 type_: fidl_input_report::UnitType::Other,
667 exponent: 0,
668 },
669 }),
670 buttons: None,
671 counts_per_mm: COUNTS_PER_MM,
672 });
673
674 async fn handle_configuration_request_stream(
676 stream: &mut pointerinjector_config::SetupRequestStream,
677 ) {
678 if let Some(Ok(request)) = stream.next().await {
679 match request {
680 pointerinjector_config::SetupRequest::GetViewRefs { responder, .. } => {
681 let context = fuchsia_scenic::ViewRefPair::new()
682 .expect("Failed to create viewrefpair.")
683 .view_ref;
684 let target = fuchsia_scenic::ViewRefPair::new()
685 .expect("Failed to create viewrefpair.")
686 .view_ref;
687 let _ = responder.send(context, target);
688 }
689 _ => {}
690 };
691 }
692 }
693
694 async fn handle_registry_request_stream(
697 mut stream: pointerinjector::RegistryRequestStream,
698 injector_sender: futures::channel::oneshot::Sender<pointerinjector::DeviceRequestStream>,
699 ) {
700 if let Some(request) = stream.next().await {
701 match request {
702 Ok(pointerinjector::RegistryRequest::Register {
703 config: _,
704 injector,
705 responder,
706 ..
707 }) => {
708 let injector_stream = injector.into_stream();
709 let _ = injector_sender.send(injector_stream);
710 responder.send().expect("failed to respond");
711 }
712 _ => {}
713 };
714 } else {
715 panic!("RegistryRequestStream failed.");
716 }
717 }
718
719 async fn handle_registry_request_stream2(
721 mut stream: pointerinjector::RegistryRequestStream,
722 injector_sender: mpsc::UnboundedSender<Vec<pointerinjector::Event>>,
723 ) {
724 let (injector, responder) = match stream.next().await {
725 Some(Ok(pointerinjector::RegistryRequest::Register {
726 config: _,
727 injector,
728 responder,
729 ..
730 })) => (injector, responder),
731 other => panic!("expected register request, but got {:?}", other),
732 };
733 let injector_stream: pointerinjector::DeviceRequestStream = injector.into_stream();
734 responder.send().expect("failed to respond");
735 injector_stream
736 .for_each(|request| {
737 futures::future::ready({
738 match request {
739 Ok(pointerinjector::DeviceRequest::Inject { .. }) => {
740 panic!("DeviceRequest::Inject is deprecated.");
741 }
742 Ok(pointerinjector::DeviceRequest::InjectEvents { events, .. }) => {
743 let _ = injector_sender.unbounded_send(events);
744 }
745 Err(e) => panic!("FIDL error {}", e),
746 }
747 })
748 })
749 .await;
750 }
751
752 async fn handle_device_request_stream(
755 injector_stream_receiver: futures::channel::oneshot::Receiver<
756 pointerinjector::DeviceRequestStream,
757 >,
758 expected_events: Vec<pointerinjector::Event>,
759 ) {
760 let mut injector_stream =
761 injector_stream_receiver.await.expect("Failed to get DeviceRequestStream.");
762 for expected_event in expected_events {
763 match injector_stream.next().await {
764 Some(Ok(pointerinjector::DeviceRequest::Inject { .. })) => {
765 panic!("DeviceRequest::Inject is deprecated.");
766 }
767 Some(Ok(pointerinjector::DeviceRequest::InjectEvents { events, .. })) => {
768 assert_eq!(events, vec![expected_event]);
769 }
770 Some(Err(e)) => panic!("FIDL error {}", e),
771 None => panic!("Expected another event."),
772 }
773 }
774 }
775
776 fn create_viewport(min: f32, max: f32) -> pointerinjector::Viewport {
778 pointerinjector::Viewport {
779 extents: Some([[min, min], [max, max]]),
780 viewport_to_context_transform: None,
781 ..Default::default()
782 }
783 }
784
785 fn create_viewport_next(min: f32, max: f32) -> pointerinjector_next::Viewport {
786 pointerinjector_next::Viewport {
787 extents: Some([[min, min], [max, max]]),
788 viewport_to_context_transform: None,
789 ..Default::default()
790 }
791 }
792
793 #[fuchsia::test]
796 fn receives_viewport_updates() {
797 let mut exec = fasync::TestExecutor::new();
798
799 let (configuration_proxy, mut configuration_request_stream) =
801 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
802 let (injector_registry_proxy, _) =
803 fidl_next::fuchsia::create_channel::<pointerinjector_next::Registry>();
804 let injector_registry_proxy =
805 Dispatcher::client_from_zx_channel(injector_registry_proxy).spawn();
806 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(0);
807
808 let inspector = fuchsia_inspect::Inspector::default();
809 let test_node = inspector.root().create_child("test_node");
810
811 let mouse_handler_fut = MouseInjectorHandler::new_handler(
813 configuration_proxy,
814 injector_registry_proxy,
815 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
816 sender,
817 &test_node,
818 metrics::MetricsLogger::default(),
819 );
820 let config_request_stream_fut =
821 handle_configuration_request_stream(&mut configuration_request_stream);
822 let (mouse_handler_res, _) = exec.run_singlethreaded(futures::future::join(
823 mouse_handler_fut,
824 config_request_stream_fut,
825 ));
826 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
827
828 let (injector_device_proxy, mut injector_device_request_stream) =
830 next_client_old_stream::<pointerinjector::DeviceMarker, pointerinjector_next::Device>();
831 mouse_handler.inner_mut().injectors.insert(1, injector_device_proxy);
832
833 {
835 let watch_viewport_fut = mouse_handler.clone().watch_viewport();
837 futures::pin_mut!(watch_viewport_fut);
838 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
839
840 match exec.run_singlethreaded(&mut configuration_request_stream.next()) {
842 Some(Ok(pointerinjector_config::SetupRequest::WatchViewport {
843 responder, ..
844 })) => {
845 responder.send(&create_viewport(0.0, 100.0)).expect("Failed to send viewport.");
846 }
847 other => panic!("Received unexpected value: {:?}", other),
848 };
849 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
850
851 exec.run_singlethreaded(async {
853 match injector_device_request_stream.next().await {
854 Some(Ok(pointerinjector::DeviceRequest::Inject { .. })) => {
855 panic!("DeviceRequest::Inject is deprecated.");
856 }
857 Some(Ok(pointerinjector::DeviceRequest::InjectEvents { events, .. })) => {
858 assert_eq!(events.len(), 1);
859 assert!(events[0].data.is_some());
860 assert_eq!(
861 events[0].data,
862 Some(pointerinjector::Data::Viewport(create_viewport(0.0, 100.0)))
863 );
864 }
865 other => panic!("Received unexpected value: {:?}", other),
866 }
867 });
868
869 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
871
872 match exec.run_singlethreaded(&mut configuration_request_stream.next()) {
874 Some(Ok(pointerinjector_config::SetupRequest::WatchViewport {
875 responder, ..
876 })) => {
877 responder
878 .send(&create_viewport(100.0, 200.0))
879 .expect("Failed to send viewport.");
880 }
881 other => panic!("Received unexpected value: {:?}", other),
882 };
883
884 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
886 }
887
888 exec.run_singlethreaded(async {
890 match injector_device_request_stream.next().await {
891 Some(Ok(pointerinjector::DeviceRequest::Inject { .. })) => {
892 panic!("DeviceRequest::Inject is deprecated.");
893 }
894 Some(Ok(pointerinjector::DeviceRequest::InjectEvents { events, .. })) => {
895 assert_eq!(events.len(), 1);
896 assert!(events[0].data.is_some());
897 assert_eq!(
898 events[0].data,
899 Some(pointerinjector::Data::Viewport(create_viewport(100.0, 200.0)))
900 );
901 }
902 other => panic!("Received unexpected value: {:?}", other),
903 }
904 });
905
906 let expected_viewport = create_viewport_next(100.0, 200.0);
908 assert_eq!(mouse_handler.inner().viewport, Some(expected_viewport));
909 }
910
911 fn wheel_delta_ticks(
912 ticks: i64,
913 physical_pixel: Option<f32>,
914 ) -> Option<mouse_binding::WheelDelta> {
915 Some(mouse_binding::WheelDelta {
916 raw_data: mouse_binding::RawWheelDelta::Ticks(ticks),
917 physical_pixel,
918 })
919 }
920
921 fn wheel_delta_mm(mm: f32, physical_pixel: Option<f32>) -> Option<mouse_binding::WheelDelta> {
922 Some(mouse_binding::WheelDelta {
923 raw_data: mouse_binding::RawWheelDelta::Millimeters(mm),
924 physical_pixel,
925 })
926 }
927
928 #[test_case(
931 mouse_binding::MouseLocation::Relative(
932 mouse_binding::RelativeLocation {
933 millimeters: Position { x: 1.0, y: 2.0 }
934 }),
935 Position {
936 x: DISPLAY_WIDTH_IN_PHYSICAL_PX / 2.0
937 + 1.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
938 y: DISPLAY_HEIGHT_IN_PHYSICAL_PX / 2.0
939 + 2.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
940 },
941 [
942 1.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
943 2.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
944 ]; "Valid move event."
945 )]
946 #[test_case(
947 mouse_binding::MouseLocation::Relative(
948 mouse_binding::RelativeLocation {
949 millimeters: Position {
950 x: DISPLAY_WIDTH_IN_PHYSICAL_PX / MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL + 2.0,
951 y: DISPLAY_HEIGHT_IN_PHYSICAL_PX / MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL + 1.0,
952 }}),
953 Position {
954 x: DISPLAY_WIDTH_IN_PHYSICAL_PX,
955 y: DISPLAY_HEIGHT_IN_PHYSICAL_PX,
956 },
957 [
958 DISPLAY_WIDTH_IN_PHYSICAL_PX + 2.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
959 DISPLAY_HEIGHT_IN_PHYSICAL_PX + 1.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
960 ]; "Move event exceeds max bounds."
961 )]
962 #[test_case(
963 mouse_binding::MouseLocation::Relative(
964 mouse_binding::RelativeLocation {
965 millimeters: Position {
966 x: -(DISPLAY_WIDTH_IN_PHYSICAL_PX / MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL + 2.0),
967 y: -(DISPLAY_HEIGHT_IN_PHYSICAL_PX / MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL + 1.0),
968 }}),
969 Position { x: 0.0, y: 0.0 },
970 [
971 -(DISPLAY_WIDTH_IN_PHYSICAL_PX + 2.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL),
972 -(DISPLAY_HEIGHT_IN_PHYSICAL_PX + 1.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL),
973 ]; "Move event exceeds min bounds."
974 )]
975 #[fuchsia::test(allow_stalls = false)]
976 async fn move_event(
977 move_location: mouse_binding::MouseLocation,
978 expected_position: Position,
979 expected_relative_motion: [f32; 2],
980 ) {
981 let (configuration_proxy, mut configuration_request_stream) =
983 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
984 let (injector_registry_proxy, injector_registry_request_stream) = next_client_old_stream::<
985 pointerinjector::RegistryMarker,
986 pointerinjector_next::Registry,
987 >();
988 let config_request_stream_fut =
989 handle_configuration_request_stream(&mut configuration_request_stream);
990
991 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
993 let inspector = fuchsia_inspect::Inspector::default();
994 let test_node = inspector.root().create_child("test_node");
995 let mouse_handler_fut = MouseInjectorHandler::new_handler(
996 configuration_proxy,
997 injector_registry_proxy,
998 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
999 sender,
1000 &test_node,
1001 metrics::MetricsLogger::default(),
1002 );
1003 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1004 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1005
1006 let event_time = zx::MonotonicInstant::get();
1007 let input_event = create_mouse_event(
1008 move_location,
1009 None, None, None, mouse_binding::MousePhase::Move,
1013 SortedVecSet::new(),
1014 SortedVecSet::new(),
1015 event_time,
1016 &DESCRIPTOR,
1017 );
1018
1019 let handle_event_fut = mouse_handler.handle_input_event(input_event);
1021 let expected_events = vec![
1022 create_mouse_pointer_sample_event_phase_add(vec![], expected_position, event_time),
1023 create_mouse_pointer_sample_event(
1024 pointerinjector::EventPhase::Change,
1025 vec![],
1026 expected_position,
1027 Some(expected_relative_motion),
1028 None, None, None, event_time,
1032 ),
1033 ];
1034
1035 let (injector_stream_sender, injector_stream_receiver) =
1039 futures::channel::oneshot::channel::<pointerinjector::DeviceRequestStream>();
1040 let registry_fut = handle_registry_request_stream(
1041 injector_registry_request_stream,
1042 injector_stream_sender,
1043 );
1044 let device_fut = handle_device_request_stream(injector_stream_receiver, expected_events);
1045
1046 let (handle_result, _, _) = futures::join!(handle_event_fut, registry_fut, device_fut);
1049 match receiver.next().await {
1050 Some(CursorMessage::SetPosition(position)) => {
1051 pretty_assertions::assert_eq!(position, expected_position);
1052 }
1053 Some(CursorMessage::SetVisibility(_)) => {
1054 panic!("Received unexpected cursor visibility update.")
1055 }
1056 None => panic!("Did not receive cursor update."),
1057 }
1058
1059 assert_matches!(
1061 handle_result.as_slice(),
1062 [input_device::InputEvent { handled: input_device::Handled::Yes, .. }]
1063 );
1064 }
1065
1066 #[fuchsia::test(allow_stalls = false)]
1069 async fn move_absolute_event() {
1070 const DEVICE_ID: u32 = 1;
1071
1072 let (configuration_proxy, mut configuration_request_stream) =
1074 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1075 let (injector_registry_proxy, injector_registry_request_stream) = next_client_old_stream::<
1076 pointerinjector::RegistryMarker,
1077 pointerinjector_next::Registry,
1078 >();
1079 let config_request_stream_fut =
1080 handle_configuration_request_stream(&mut configuration_request_stream);
1081
1082 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
1084 let inspector = fuchsia_inspect::Inspector::default();
1085 let test_node = inspector.root().create_child("test_node");
1086 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1087 configuration_proxy,
1088 injector_registry_proxy,
1089 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1090 sender,
1091 &test_node,
1092 metrics::MetricsLogger::default(),
1093 );
1094 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1095 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1096
1097 let cursor_location =
1113 mouse_binding::MouseLocation::Absolute(Position { x: -25.0, y: 25.0 });
1114 let event_time = zx::MonotonicInstant::get();
1115 let descriptor =
1116 input_device::InputDeviceDescriptor::Mouse(mouse_binding::MouseDeviceDescriptor {
1117 device_id: DEVICE_ID,
1118 absolute_x_range: Some(fidl_input_report::Range { min: -50, max: 50 }),
1119 absolute_y_range: Some(fidl_input_report::Range { min: -50, max: 50 }),
1120 wheel_v_range: None,
1121 wheel_h_range: None,
1122 buttons: None,
1123 counts_per_mm: COUNTS_PER_MM,
1124 });
1125 let input_event = create_mouse_event(
1126 cursor_location,
1127 None, None, None, mouse_binding::MousePhase::Move,
1131 SortedVecSet::new(),
1132 SortedVecSet::new(),
1133 event_time,
1134 &descriptor,
1135 );
1136
1137 let handle_event_fut = mouse_handler.handle_input_event(input_event);
1139 let expected_position = Position {
1140 x: DISPLAY_WIDTH_IN_PHYSICAL_PX * 0.25,
1141 y: DISPLAY_WIDTH_IN_PHYSICAL_PX * 0.75,
1142 };
1143 let expected_events = vec![
1144 create_mouse_pointer_sample_event_phase_add(vec![], expected_position, event_time),
1145 create_mouse_pointer_sample_event(
1146 pointerinjector::EventPhase::Change,
1147 vec![],
1148 expected_position,
1149 None, None, None, None, event_time,
1154 ),
1155 ];
1156
1157 let (injector_stream_sender, injector_stream_receiver) =
1161 futures::channel::oneshot::channel::<pointerinjector::DeviceRequestStream>();
1162 let registry_fut = handle_registry_request_stream(
1163 injector_registry_request_stream,
1164 injector_stream_sender,
1165 );
1166 let device_fut = handle_device_request_stream(injector_stream_receiver, expected_events);
1167
1168 let (handle_result, _, _) = futures::join!(handle_event_fut, registry_fut, device_fut);
1171 match receiver.next().await {
1172 Some(CursorMessage::SetPosition(position)) => {
1173 assert_eq!(position, expected_position);
1174 }
1175 Some(CursorMessage::SetVisibility(_)) => {
1176 panic!("Received unexpected cursor visibility update.")
1177 }
1178 None => panic!("Did not receive cursor update."),
1179 }
1180
1181 assert_matches!(
1183 handle_result.as_slice(),
1184 [input_device::InputEvent { handled: input_device::Handled::Yes, .. }]
1185 );
1186 }
1187
1188 #[test_case(
1190 mouse_binding::MousePhase::Down,
1191 vec![1], vec![1]; "Down event injects button press state."
1192 )]
1193 #[test_case(
1194 mouse_binding::MousePhase::Up,
1195 vec![1], vec![]; "Up event injects button press state."
1196 )]
1197 #[fuchsia::test(allow_stalls = false)]
1198 async fn button_state_event(
1199 phase: mouse_binding::MousePhase,
1200 affected_buttons: Vec<mouse_binding::MouseButton>,
1201 pressed_buttons: Vec<mouse_binding::MouseButton>,
1202 ) {
1203 let (configuration_proxy, mut configuration_request_stream) =
1205 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1206 let (injector_registry_proxy, injector_registry_request_stream) = next_client_old_stream::<
1207 pointerinjector::RegistryMarker,
1208 pointerinjector_next::Registry,
1209 >();
1210 let config_request_stream_fut =
1211 handle_configuration_request_stream(&mut configuration_request_stream);
1212
1213 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
1215 let inspector = fuchsia_inspect::Inspector::default();
1216 let test_node = inspector.root().create_child("test_node");
1217 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1218 configuration_proxy,
1219 injector_registry_proxy,
1220 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1221 sender,
1222 &test_node,
1223 metrics::MetricsLogger::default(),
1224 );
1225 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1226 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1227
1228 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
1229 let event_time = zx::MonotonicInstant::get();
1230
1231 let input_event = create_mouse_event(
1232 cursor_location,
1233 None, None, None, phase,
1237 affected_buttons.clone().into(),
1238 pressed_buttons.clone().into(),
1239 event_time,
1240 &DESCRIPTOR,
1241 );
1242
1243 let handle_event_fut = mouse_handler.handle_input_event(input_event);
1245 let expected_position = Position { x: 0.0, y: 0.0 };
1246 let expected_events = vec![
1247 create_mouse_pointer_sample_event_phase_add(
1248 pressed_buttons.clone().into(),
1249 expected_position,
1250 event_time,
1251 ),
1252 create_mouse_pointer_sample_event(
1253 pointerinjector::EventPhase::Change,
1254 pressed_buttons.clone().into(),
1255 expected_position,
1256 None, None, None, None, event_time,
1261 ),
1262 ];
1263
1264 let (injector_stream_sender, injector_stream_receiver) =
1268 futures::channel::oneshot::channel::<pointerinjector::DeviceRequestStream>();
1269 let registry_fut = handle_registry_request_stream(
1270 injector_registry_request_stream,
1271 injector_stream_sender,
1272 );
1273 let device_fut = handle_device_request_stream(injector_stream_receiver, expected_events);
1274
1275 let (handle_result, _, _) = futures::join!(handle_event_fut, registry_fut, device_fut);
1278 match receiver.next().await {
1279 Some(CursorMessage::SetPosition(position)) => {
1280 pretty_assertions::assert_eq!(position, expected_position);
1281 }
1282 Some(CursorMessage::SetVisibility(_)) => {
1283 panic!("Received unexpected cursor visibility update.")
1284 }
1285 None => panic!("Did not receive cursor update."),
1286 }
1287
1288 assert_matches!(
1290 handle_result.as_slice(),
1291 [input_device::InputEvent { handled: input_device::Handled::Yes, .. }]
1292 );
1293 }
1294
1295 #[fuchsia::test(allow_stalls = false)]
1297 async fn down_up_event() {
1298 let (configuration_proxy, mut configuration_request_stream) =
1300 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1301 let (injector_registry_proxy, injector_registry_request_stream) = next_client_old_stream::<
1302 pointerinjector::RegistryMarker,
1303 pointerinjector_next::Registry,
1304 >();
1305 let config_request_stream_fut =
1306 handle_configuration_request_stream(&mut configuration_request_stream);
1307
1308 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(2);
1312 let inspector = fuchsia_inspect::Inspector::default();
1313 let test_node = inspector.root().create_child("test_node");
1314 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1315 configuration_proxy,
1316 injector_registry_proxy,
1317 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1318 sender,
1319 &test_node,
1320 metrics::MetricsLogger::default(),
1321 );
1322 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1323 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1324
1325 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
1326 let event_time1 = zx::MonotonicInstant::get();
1327 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
1328
1329 let event1 = create_mouse_event(
1330 cursor_location,
1331 None, None, None, mouse_binding::MousePhase::Down,
1335 SortedVecSet::from(vec![1]),
1336 SortedVecSet::from(vec![1]),
1337 event_time1,
1338 &DESCRIPTOR,
1339 );
1340
1341 let event2 = create_mouse_event(
1342 cursor_location,
1343 None, None, None, mouse_binding::MousePhase::Up,
1347 SortedVecSet::from(vec![1]),
1348 SortedVecSet::new(),
1349 event_time2,
1350 &DESCRIPTOR,
1351 );
1352
1353 let expected_position = Position { x: 0.0, y: 0.0 };
1354
1355 let (injector_stream_sender, injector_stream_receiver) =
1359 mpsc::unbounded::<Vec<pointerinjector::Event>>();
1360 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
1362 let registry_fut = handle_registry_request_stream2(
1363 injector_registry_request_stream,
1364 injector_stream_sender,
1365 );
1366
1367 let _registry_task = fasync::Task::local(registry_fut);
1369
1370 mouse_handler.clone().handle_input_event(event1).await;
1371 assert_eq!(
1372 injector_stream_receiver
1373 .next()
1374 .await
1375 .map(|events| events.into_iter().flatten().collect()),
1376 Some(vec![
1377 create_mouse_pointer_sample_event_phase_add(
1378 vec![1],
1379 expected_position,
1380 event_time1,
1381 ),
1382 create_mouse_pointer_sample_event(
1383 pointerinjector::EventPhase::Change,
1384 vec![1],
1385 expected_position,
1386 None, None, None, None, event_time1,
1391 )
1392 ])
1393 );
1394
1395 mouse_handler.clone().handle_input_event(event2).await;
1397 assert_eq!(
1398 injector_stream_receiver
1399 .next()
1400 .await
1401 .map(|events| events.into_iter().flatten().collect()),
1402 Some(vec![create_mouse_pointer_sample_event(
1403 pointerinjector::EventPhase::Change,
1404 vec![],
1405 expected_position,
1406 None, None, None, None, event_time2,
1411 )])
1412 );
1413
1414 match receiver.next().await {
1416 Some(CursorMessage::SetPosition(position)) => {
1417 assert_eq!(position, expected_position);
1418 }
1419 Some(CursorMessage::SetVisibility(_)) => {
1420 panic!("Received unexpected cursor visibility update.")
1421 }
1422 None => panic!("Did not receive cursor update."),
1423 }
1424 }
1425
1426 #[fuchsia::test(allow_stalls = false)]
1436 async fn down_down_up_up_event() {
1437 let (configuration_proxy, mut configuration_request_stream) =
1439 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1440 let (injector_registry_proxy, injector_registry_request_stream) = next_client_old_stream::<
1441 pointerinjector::RegistryMarker,
1442 pointerinjector_next::Registry,
1443 >();
1444 let config_request_stream_fut =
1445 handle_configuration_request_stream(&mut configuration_request_stream);
1446
1447 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(4);
1451 let inspector = fuchsia_inspect::Inspector::default();
1452 let test_node = inspector.root().create_child("test_node");
1453 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1454 configuration_proxy,
1455 injector_registry_proxy,
1456 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1457 sender,
1458 &test_node,
1459 metrics::MetricsLogger::default(),
1460 );
1461 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1462 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1463
1464 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
1465 let event_time1 = zx::MonotonicInstant::get();
1466 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
1467 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
1468 let event_time4 = event_time3.add(zx::MonotonicDuration::from_micros(1));
1469
1470 let event1 = create_mouse_event(
1471 cursor_location,
1472 None, None, None, mouse_binding::MousePhase::Down,
1476 SortedVecSet::from(vec![1]),
1477 SortedVecSet::from(vec![1]),
1478 event_time1,
1479 &DESCRIPTOR,
1480 );
1481 let event2 = create_mouse_event(
1482 cursor_location,
1483 None, None, None, mouse_binding::MousePhase::Down,
1487 SortedVecSet::from(vec![2]),
1488 SortedVecSet::from(vec![1, 2]),
1489 event_time2,
1490 &DESCRIPTOR,
1491 );
1492 let event3 = create_mouse_event(
1493 cursor_location,
1494 None, None, None, mouse_binding::MousePhase::Up,
1498 SortedVecSet::from(vec![1]),
1499 SortedVecSet::from(vec![2]),
1500 event_time3,
1501 &DESCRIPTOR,
1502 );
1503 let event4 = create_mouse_event(
1504 cursor_location,
1505 None, None, None, mouse_binding::MousePhase::Up,
1509 SortedVecSet::from(vec![2]),
1510 SortedVecSet::new(),
1511 event_time4,
1512 &DESCRIPTOR,
1513 );
1514
1515 let expected_position = Position { x: 0.0, y: 0.0 };
1516
1517 let (injector_stream_sender, injector_stream_receiver) =
1521 mpsc::unbounded::<Vec<pointerinjector::Event>>();
1522 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
1524 let registry_fut = handle_registry_request_stream2(
1525 injector_registry_request_stream,
1526 injector_stream_sender,
1527 );
1528
1529 let _registry_task = fasync::Task::local(registry_fut);
1531 mouse_handler.clone().handle_input_event(event1).await;
1532 assert_eq!(
1533 injector_stream_receiver
1534 .next()
1535 .await
1536 .map(|events| events.into_iter().flatten().collect()),
1537 Some(vec![
1538 create_mouse_pointer_sample_event_phase_add(
1539 vec![1],
1540 expected_position,
1541 event_time1,
1542 ),
1543 create_mouse_pointer_sample_event(
1544 pointerinjector::EventPhase::Change,
1545 vec![1],
1546 expected_position,
1547 None, None, None, None, event_time1,
1552 )
1553 ])
1554 );
1555
1556 mouse_handler.clone().handle_input_event(event2).await;
1558 let pointer_sample_event2: Vec<_> = injector_stream_receiver
1559 .next()
1560 .await
1561 .map(|events| events.into_iter().flatten().collect())
1562 .expect("Failed to receive pointer sample event.");
1563 let expected_event_time: i64 = event_time2.into_nanos();
1564 assert_eq!(pointer_sample_event2.len(), 1);
1565
1566 match &pointer_sample_event2[0] {
1569 pointerinjector::Event {
1570 timestamp: Some(actual_event_time),
1571 data:
1572 Some(pointerinjector::Data::PointerSample(pointerinjector::PointerSample {
1573 pointer_id: Some(0),
1574 phase: Some(pointerinjector::EventPhase::Change),
1575 position_in_viewport: Some(actual_position),
1576 scroll_v: None,
1577 scroll_h: None,
1578 pressed_buttons: Some(actual_buttons),
1579 relative_motion: None,
1580 ..
1581 })),
1582 ..
1583 } => {
1584 assert_eq!(*actual_event_time, expected_event_time);
1585 assert_eq!(actual_position[0], expected_position.x);
1586 assert_eq!(actual_position[1], expected_position.y);
1587 assert_eq!(actual_buttons.as_slice(), &[1u8, 2u8]);
1588 }
1589 _ => panic!("Unexpected pointer sample event: {:?}", pointer_sample_event2[0]),
1590 }
1591
1592 mouse_handler.clone().handle_input_event(event3).await;
1594 assert_eq!(
1595 injector_stream_receiver
1596 .next()
1597 .await
1598 .map(|events| events.into_iter().flatten().collect()),
1599 Some(vec![create_mouse_pointer_sample_event(
1600 pointerinjector::EventPhase::Change,
1601 vec![2],
1602 expected_position,
1603 None, None, None, None, event_time3,
1608 )])
1609 );
1610
1611 mouse_handler.clone().handle_input_event(event4).await;
1613 assert_eq!(
1614 injector_stream_receiver
1615 .next()
1616 .await
1617 .map(|events| events.into_iter().flatten().collect()),
1618 Some(vec![create_mouse_pointer_sample_event(
1619 pointerinjector::EventPhase::Change,
1620 vec![],
1621 expected_position,
1622 None, None, None, None, event_time4,
1627 )])
1628 );
1629
1630 match receiver.next().await {
1632 Some(CursorMessage::SetPosition(position)) => {
1633 assert_eq!(position, expected_position);
1634 }
1635 Some(CursorMessage::SetVisibility(_)) => {
1636 panic!("Received unexpected cursor visibility update.")
1637 }
1638 None => panic!("Did not receive cursor update."),
1639 }
1640 }
1641
1642 #[fuchsia::test(allow_stalls = false)]
1644 async fn down_move_up_event() {
1645 let (configuration_proxy, mut configuration_request_stream) =
1647 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1648 let (injector_registry_proxy, injector_registry_request_stream) = next_client_old_stream::<
1649 pointerinjector::RegistryMarker,
1650 pointerinjector_next::Registry,
1651 >();
1652 let config_request_stream_fut =
1653 handle_configuration_request_stream(&mut configuration_request_stream);
1654
1655 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(3);
1659 let inspector = fuchsia_inspect::Inspector::default();
1660 let test_node = inspector.root().create_child("test_node");
1661 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1662 configuration_proxy,
1663 injector_registry_proxy,
1664 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1665 sender,
1666 &test_node,
1667 metrics::MetricsLogger::default(),
1668 );
1669 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1670 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1671
1672 let event_time1 = zx::MonotonicInstant::get();
1673 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
1674 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
1675 let zero_position = Position { x: 0.0, y: 0.0 };
1676 let expected_position = Position {
1677 x: 10.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
1678 y: 5.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
1679 };
1680 let expected_relative_motion = [
1681 10.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
1682 5.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
1683 ];
1684 let event1 = create_mouse_event(
1685 mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 }),
1686 None, None, None, mouse_binding::MousePhase::Down,
1690 SortedVecSet::from(vec![1]),
1691 SortedVecSet::from(vec![1]),
1692 event_time1,
1693 &DESCRIPTOR,
1694 );
1695 let event2 = create_mouse_event(
1696 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1697 millimeters: Position { x: 10.0, y: 5.0 },
1698 }),
1699 None, None, None, mouse_binding::MousePhase::Move,
1703 SortedVecSet::from(vec![1]),
1704 SortedVecSet::from(vec![1]),
1705 event_time2,
1706 &DESCRIPTOR,
1707 );
1708 let event3 = create_mouse_event(
1709 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1710 millimeters: Position { x: 0.0, y: 0.0 },
1711 }),
1712 None, None, None, mouse_binding::MousePhase::Up,
1716 SortedVecSet::from(vec![1]),
1717 SortedVecSet::new(),
1718 event_time3,
1719 &DESCRIPTOR,
1720 );
1721
1722 let (injector_stream_sender, injector_stream_receiver) =
1726 mpsc::unbounded::<Vec<pointerinjector::Event>>();
1727 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
1729 let registry_fut = handle_registry_request_stream2(
1730 injector_registry_request_stream,
1731 injector_stream_sender,
1732 );
1733
1734 let _registry_task = fasync::Task::local(registry_fut);
1736 mouse_handler.clone().handle_input_event(event1).await;
1737 assert_eq!(
1738 injector_stream_receiver
1739 .next()
1740 .await
1741 .map(|events| events.into_iter().flatten().collect()),
1742 Some(vec![
1743 create_mouse_pointer_sample_event_phase_add(vec![1], zero_position, event_time1,),
1744 create_mouse_pointer_sample_event(
1745 pointerinjector::EventPhase::Change,
1746 vec![1],
1747 zero_position,
1748 None, None, None, None, event_time1,
1753 )
1754 ])
1755 );
1756
1757 match receiver.next().await {
1759 Some(CursorMessage::SetPosition(position)) => {
1760 assert_eq!(position, zero_position);
1761 }
1762 Some(CursorMessage::SetVisibility(_)) => {
1763 panic!("Received unexpected cursor visibility update.")
1764 }
1765 None => panic!("Did not receive cursor update."),
1766 }
1767
1768 mouse_handler.clone().handle_input_event(event2).await;
1770 assert_eq!(
1771 injector_stream_receiver
1772 .next()
1773 .await
1774 .map(|events| events.into_iter().flatten().collect()),
1775 Some(vec![create_mouse_pointer_sample_event(
1776 pointerinjector::EventPhase::Change,
1777 vec![1],
1778 expected_position,
1779 Some(expected_relative_motion),
1780 None, None, None, event_time2,
1784 )])
1785 );
1786
1787 match receiver.next().await {
1789 Some(CursorMessage::SetPosition(position)) => {
1790 assert_eq!(position, expected_position);
1791 }
1792 Some(CursorMessage::SetVisibility(_)) => {
1793 panic!("Received unexpected cursor visibility update.")
1794 }
1795 None => panic!("Did not receive cursor update."),
1796 }
1797
1798 mouse_handler.clone().handle_input_event(event3).await;
1800 assert_eq!(
1801 injector_stream_receiver
1802 .next()
1803 .await
1804 .map(|events| events.into_iter().flatten().collect()),
1805 Some(vec![create_mouse_pointer_sample_event(
1806 pointerinjector::EventPhase::Change,
1807 vec![],
1808 expected_position,
1809 None, None, None, None, event_time3,
1814 )])
1815 );
1816
1817 match receiver.next().await {
1819 Some(CursorMessage::SetPosition(position)) => {
1820 assert_eq!(position, expected_position);
1821 }
1822 Some(CursorMessage::SetVisibility(_)) => {
1823 panic!("Received unexpected cursor visibility update.")
1824 }
1825 None => panic!("Did not receive cursor update."),
1826 }
1827 }
1828
1829 #[fuchsia::test(allow_stalls = false)]
1831 async fn handler_ignores_handled_events() {
1832 let (configuration_proxy, mut configuration_request_stream) =
1834 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1835 let (injector_registry_proxy, injector_registry_request_stream) = next_client_old_stream::<
1836 pointerinjector::RegistryMarker,
1837 pointerinjector_next::Registry,
1838 >();
1839 let config_request_stream_fut =
1840 handle_configuration_request_stream(&mut configuration_request_stream);
1841
1842 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
1844 let inspector = fuchsia_inspect::Inspector::default();
1845 let test_node = inspector.root().create_child("test_node");
1846 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1847 configuration_proxy,
1848 injector_registry_proxy,
1849 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1850 sender,
1851 &test_node,
1852 metrics::MetricsLogger::default(),
1853 );
1854 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1855 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1856
1857 let cursor_relative_position = Position { x: 50.0, y: 75.0 };
1858 let cursor_location =
1859 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1860 millimeters: Position {
1861 x: cursor_relative_position.x / COUNTS_PER_MM as f32,
1862 y: cursor_relative_position.y / COUNTS_PER_MM as f32,
1863 },
1864 });
1865 let event_time = zx::MonotonicInstant::get();
1866 let input_events = vec![create_mouse_event_with_handled(
1867 cursor_location,
1868 None, None, None, mouse_binding::MousePhase::Move,
1872 SortedVecSet::new(),
1873 SortedVecSet::new(),
1874 event_time,
1875 &DESCRIPTOR,
1876 input_device::Handled::Yes,
1877 )];
1878
1879 assert_handler_ignores_input_event_sequence(
1880 mouse_handler,
1881 input_events,
1882 injector_registry_request_stream,
1883 )
1884 .await;
1885
1886 assert!(receiver.next().await.is_none());
1888 }
1889
1890 fn zero_relative_location() -> mouse_binding::MouseLocation {
1891 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1892 millimeters: Position { x: 0.0, y: 0.0 },
1893 })
1894 }
1895
1896 #[test_case(
1897 create_mouse_event(
1898 zero_relative_location(),
1899 wheel_delta_ticks(1, None), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1903 SortedVecSet::new(),
1904 SortedVecSet::new(),
1905 zx::MonotonicInstant::ZERO,
1906 &DESCRIPTOR,
1907 ),
1908 create_mouse_pointer_sample_event(
1909 pointerinjector::EventPhase::Change,
1910 vec![],
1911 Position { x: 50.0, y: 50.0 },
1912 None, Some(1), None, Some(false), zx::MonotonicInstant::ZERO,
1917 ); "v tick scroll"
1918 )]
1919 #[test_case(
1920 create_mouse_event(
1921 zero_relative_location(),
1922 None, wheel_delta_ticks(1, None), Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1926 SortedVecSet::new(),
1927 SortedVecSet::new(),
1928 zx::MonotonicInstant::ZERO,
1929 &DESCRIPTOR,
1930 ),
1931 create_mouse_pointer_sample_event(
1932 pointerinjector::EventPhase::Change,
1933 vec![],
1934 Position { x: 50.0, y: 50.0 },
1935 None, None, Some(1), Some(false), zx::MonotonicInstant::ZERO,
1940 ); "h tick scroll"
1941 )]
1942 #[test_case(
1943 create_mouse_event(
1944 zero_relative_location(),
1945 wheel_delta_ticks(1, Some(120.0)), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1949 SortedVecSet::new(),
1950 SortedVecSet::new(),
1951 zx::MonotonicInstant::ZERO,
1952 &DESCRIPTOR,
1953 ),
1954 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
1955 pointerinjector::EventPhase::Change,
1956 vec![],
1957 Position { x: 50.0, y: 50.0 },
1958 None, Some(1), None, Some(120.0), None, Some(false), zx::MonotonicInstant::ZERO,
1965 ); "v tick scroll with physical pixel"
1966 )]
1967 #[test_case(
1968 create_mouse_event(
1969 zero_relative_location(),
1970 None, wheel_delta_ticks(1, Some(120.0)), Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1974 SortedVecSet::new(),
1975 SortedVecSet::new(),
1976 zx::MonotonicInstant::ZERO,
1977 &DESCRIPTOR,
1978 ),
1979 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
1980 pointerinjector::EventPhase::Change,
1981 vec![],
1982 Position { x: 50.0, y: 50.0 },
1983 None, None, Some(1), None, Some(120.0), Some(false), zx::MonotonicInstant::ZERO,
1990 ); "h tick scroll with physical pixel"
1991 )]
1992 #[test_case(
1993 create_mouse_event(
1994 zero_relative_location(),
1995 wheel_delta_mm(1.0, Some(120.0)), None, Some(mouse_binding::PrecisionScroll::Yes), mouse_binding::MousePhase::Wheel,
1999 SortedVecSet::new(),
2000 SortedVecSet::new(),
2001 zx::MonotonicInstant::ZERO,
2002 &DESCRIPTOR,
2003 ),
2004 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
2005 pointerinjector::EventPhase::Change,
2006 vec![],
2007 Position { x: 50.0, y: 50.0 },
2008 None, None, None, Some(120.0), None, Some(true), zx::MonotonicInstant::ZERO,
2015 ); "v mm scroll with physical pixel"
2016 )]
2017 #[test_case(
2018 create_mouse_event(
2019 zero_relative_location(),
2020 None, wheel_delta_mm(1.0, Some(120.0)), Some(mouse_binding::PrecisionScroll::Yes), mouse_binding::MousePhase::Wheel,
2024 SortedVecSet::new(),
2025 SortedVecSet::new(),
2026 zx::MonotonicInstant::ZERO,
2027 &DESCRIPTOR,
2028 ),
2029 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
2030 pointerinjector::EventPhase::Change,
2031 vec![],
2032 Position { x: 50.0, y: 50.0 },
2033 None, None, None, None, Some(120.0), Some(true), zx::MonotonicInstant::ZERO,
2040 ); "h mm scroll with physical pixel"
2041 )]
2042 #[fuchsia::test(allow_stalls = false)]
2044 async fn scroll(event: input_device::InputEvent, want_event: pointerinjector::Event) {
2045 let (configuration_proxy, mut configuration_request_stream) =
2047 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
2048 let (injector_registry_proxy, injector_registry_request_stream) = next_client_old_stream::<
2049 pointerinjector::RegistryMarker,
2050 pointerinjector_next::Registry,
2051 >();
2052 let config_request_stream_fut =
2053 handle_configuration_request_stream(&mut configuration_request_stream);
2054
2055 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
2057 let inspector = fuchsia_inspect::Inspector::default();
2058 let test_node = inspector.root().create_child("test_node");
2059 let mouse_handler_fut = MouseInjectorHandler::new_handler(
2060 configuration_proxy,
2061 injector_registry_proxy,
2062 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
2063 sender,
2064 &test_node,
2065 metrics::MetricsLogger::default(),
2066 );
2067 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
2068 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
2069
2070 let (injector_stream_sender, injector_stream_receiver) =
2074 mpsc::unbounded::<Vec<pointerinjector::Event>>();
2075 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
2077 let registry_fut = handle_registry_request_stream2(
2078 injector_registry_request_stream,
2079 injector_stream_sender,
2080 );
2081
2082 let event_time = zx::MonotonicInstant::get();
2083
2084 let event = input_device::InputEvent { event_time, ..event };
2085
2086 let want_event =
2087 pointerinjector::Event { timestamp: Some(event_time.into_nanos()), ..want_event };
2088
2089 let _registry_task = fasync::Task::local(registry_fut);
2091
2092 mouse_handler.clone().handle_input_event(event).await;
2093 let got_events: Vec<_> = injector_stream_receiver
2094 .next()
2095 .await
2096 .map(|events| events.into_iter().flatten().collect())
2097 .unwrap();
2098 pretty_assertions::assert_eq!(got_events.len(), 2);
2099 assert_matches!(
2100 got_events[0],
2101 pointerinjector::Event {
2102 data: Some(pointerinjector::Data::PointerSample(pointerinjector::PointerSample {
2103 phase: Some(pointerinjector::EventPhase::Add),
2104 ..
2105 })),
2106 ..
2107 }
2108 );
2109
2110 pretty_assertions::assert_eq!(got_events[1], want_event);
2111 }
2112
2113 #[fuchsia::test(allow_stalls = false)]
2115 async fn down_scroll_up_scroll() {
2116 let (configuration_proxy, mut configuration_request_stream) =
2118 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
2119 let (injector_registry_proxy, injector_registry_request_stream) = next_client_old_stream::<
2120 pointerinjector::RegistryMarker,
2121 pointerinjector_next::Registry,
2122 >();
2123 let config_request_stream_fut =
2124 handle_configuration_request_stream(&mut configuration_request_stream);
2125
2126 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
2128 let inspector = fuchsia_inspect::Inspector::default();
2129 let test_node = inspector.root().create_child("test_node");
2130 let mouse_handler_fut = MouseInjectorHandler::new_handler(
2131 configuration_proxy,
2132 injector_registry_proxy,
2133 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
2134 sender,
2135 &test_node,
2136 metrics::MetricsLogger::default(),
2137 );
2138 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
2139 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
2140
2141 let (injector_stream_sender, injector_stream_receiver) =
2145 mpsc::unbounded::<Vec<pointerinjector::Event>>();
2146 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
2148 let registry_fut = handle_registry_request_stream2(
2149 injector_registry_request_stream,
2150 injector_stream_sender,
2151 );
2152
2153 let event_time1 = zx::MonotonicInstant::get();
2154 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
2155 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
2156 let event_time4 = event_time3.add(zx::MonotonicDuration::from_micros(1));
2157
2158 let _registry_task = fasync::Task::local(registry_fut);
2160
2161 let zero_location =
2162 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
2163 millimeters: Position { x: 0.0, y: 0.0 },
2164 });
2165 let expected_position = Position { x: 50.0, y: 50.0 };
2166
2167 let down_event = create_mouse_event(
2168 zero_location,
2169 None, None, None, mouse_binding::MousePhase::Down,
2173 SortedVecSet::from(vec![1]),
2174 SortedVecSet::from(vec![1]),
2175 event_time1,
2176 &DESCRIPTOR,
2177 );
2178
2179 let wheel_event = create_mouse_event(
2180 zero_location,
2181 wheel_delta_ticks(1, None), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
2185 SortedVecSet::from(vec![1]),
2186 SortedVecSet::from(vec![1]),
2187 event_time2,
2188 &DESCRIPTOR,
2189 );
2190
2191 let up_event = create_mouse_event(
2192 zero_location,
2193 None,
2194 None,
2195 None, mouse_binding::MousePhase::Up,
2197 SortedVecSet::from(vec![1]),
2198 SortedVecSet::new(),
2199 event_time3,
2200 &DESCRIPTOR,
2201 );
2202
2203 let continue_wheel_event = create_mouse_event(
2204 zero_location,
2205 wheel_delta_ticks(1, None), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
2209 SortedVecSet::new(),
2210 SortedVecSet::new(),
2211 event_time4,
2212 &DESCRIPTOR,
2213 );
2214
2215 mouse_handler.clone().handle_input_event(down_event).await;
2217 assert_eq!(
2218 injector_stream_receiver
2219 .next()
2220 .await
2221 .map(|events| events.into_iter().flatten().collect()),
2222 Some(vec![
2223 create_mouse_pointer_sample_event_phase_add(
2224 vec![1],
2225 expected_position,
2226 event_time1,
2227 ),
2228 create_mouse_pointer_sample_event(
2229 pointerinjector::EventPhase::Change,
2230 vec![1],
2231 expected_position,
2232 None, None, None, None, event_time1,
2237 ),
2238 ])
2239 );
2240
2241 mouse_handler.clone().handle_input_event(wheel_event).await;
2243 assert_eq!(
2244 injector_stream_receiver
2245 .next()
2246 .await
2247 .map(|events| events.into_iter().flatten().collect()),
2248 Some(vec![create_mouse_pointer_sample_event(
2249 pointerinjector::EventPhase::Change,
2250 vec![1],
2251 expected_position,
2252 None, Some(1), None, Some(false), event_time2,
2257 )])
2258 );
2259
2260 mouse_handler.clone().handle_input_event(up_event).await;
2262 assert_eq!(
2263 injector_stream_receiver
2264 .next()
2265 .await
2266 .map(|events| events.into_iter().flatten().collect()),
2267 Some(vec![create_mouse_pointer_sample_event(
2268 pointerinjector::EventPhase::Change,
2269 vec![],
2270 expected_position,
2271 None, None, None, None, event_time3,
2276 )])
2277 );
2278
2279 mouse_handler.clone().handle_input_event(continue_wheel_event).await;
2281 assert_eq!(
2282 injector_stream_receiver
2283 .next()
2284 .await
2285 .map(|events| events.into_iter().flatten().collect()),
2286 Some(vec![create_mouse_pointer_sample_event(
2287 pointerinjector::EventPhase::Change,
2288 vec![],
2289 expected_position,
2290 None, Some(1), None, Some(false), event_time4,
2295 )])
2296 );
2297 }
2298
2299 #[fuchsia::test(allow_stalls = false)]
2300 async fn mouse_injector_handler_initialized_with_inspect_node() {
2301 let (configuration_proxy, mut configuration_request_stream) =
2302 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
2303 let config_request_stream_fut =
2304 handle_configuration_request_stream(&mut configuration_request_stream);
2305 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
2306 let inspector = fuchsia_inspect::Inspector::default();
2307 let fake_handlers_node = inspector.root().create_child("input_handlers_node");
2308 let incoming = Incoming::new();
2309 let mouse_handler_fut = MouseInjectorHandler::new_with_config_proxy(
2310 &incoming,
2311 configuration_proxy,
2312 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
2313 sender,
2314 &fake_handlers_node,
2315 metrics::MetricsLogger::default(),
2316 );
2317 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
2318 let _handler = mouse_handler_res.expect("Failed to create mouse handler");
2319
2320 diagnostics_assertions::assert_data_tree!(inspector, root: {
2321 input_handlers_node: {
2322 mouse_injector_handler: {
2323 events_received_count: 0u64,
2324 events_handled_count: 0u64,
2325 last_received_timestamp_ns: 0u64,
2326 "fuchsia.inspect.Health": {
2327 status: "STARTING_UP",
2328 start_timestamp_nanos: diagnostics_assertions::AnyProperty
2331 },
2332 }
2333 }
2334 });
2335 }
2336
2337 #[fuchsia::test(allow_stalls = false)]
2338 async fn mouse_injector_handler_inspect_counts_events() {
2339 let (configuration_proxy, mut configuration_request_stream) =
2341 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
2342 let (injector_registry_proxy, injector_registry_request_stream) = next_client_old_stream::<
2343 pointerinjector::RegistryMarker,
2344 pointerinjector_next::Registry,
2345 >();
2346 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
2347
2348 let inspector = fuchsia_inspect::Inspector::default();
2349 let fake_handlers_node = inspector.root().create_child("input_handlers_node");
2350
2351 let mouse_handler_fut = MouseInjectorHandler::new_handler(
2353 configuration_proxy,
2354 injector_registry_proxy,
2355 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
2356 sender,
2357 &fake_handlers_node,
2358 metrics::MetricsLogger::default(),
2359 );
2360 let config_request_stream_fut =
2361 handle_configuration_request_stream(&mut configuration_request_stream);
2362
2363 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
2364 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
2365
2366 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
2367 let event_time1 = zx::MonotonicInstant::get();
2368 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
2369 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
2370
2371 let input_events = vec![
2372 create_mouse_event(
2373 cursor_location,
2374 None, None, None, mouse_binding::MousePhase::Down,
2378 SortedVecSet::from(vec![1]),
2379 SortedVecSet::from(vec![1]),
2380 event_time1,
2381 &DESCRIPTOR,
2382 ),
2383 create_mouse_event(
2384 cursor_location,
2385 None, None, None, mouse_binding::MousePhase::Up,
2389 SortedVecSet::from(vec![1]),
2390 SortedVecSet::new(),
2391 event_time2,
2392 &DESCRIPTOR,
2393 ),
2394 create_mouse_event_with_handled(
2395 cursor_location,
2396 None, None, None, mouse_binding::MousePhase::Down,
2400 SortedVecSet::from(vec![1]),
2401 SortedVecSet::from(vec![1]),
2402 event_time3,
2403 &DESCRIPTOR,
2404 input_device::Handled::Yes,
2405 ),
2406 ];
2407
2408 let (injector_stream_sender, _) = mpsc::unbounded::<Vec<pointerinjector::Event>>();
2412 let registry_fut = handle_registry_request_stream2(
2413 injector_registry_request_stream,
2414 injector_stream_sender,
2415 );
2416
2417 let _registry_task = fasync::Task::local(registry_fut);
2419 for input_event in input_events {
2420 mouse_handler.clone().handle_input_event(input_event).await;
2421 }
2422
2423 let last_received_event_time: u64 = event_time2.into_nanos().try_into().unwrap();
2424
2425 diagnostics_assertions::assert_data_tree!(inspector, root: {
2426 input_handlers_node: {
2427 mouse_injector_handler: {
2428 events_received_count: 2u64,
2429 events_handled_count: 2u64,
2430 last_received_timestamp_ns: last_received_event_time,
2431 "fuchsia.inspect.Health": {
2432 status: "STARTING_UP",
2433 start_timestamp_nanos: diagnostics_assertions::AnyProperty
2436 },
2437 }
2438 }
2439 });
2440 }
2441}