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 std::cell::{Ref, RefCell, RefMut};
24use std::collections::HashMap;
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: HashMap<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: HashMap::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(Vec::from_iter(mouse_event.pressed_buttons.iter().cloned())),
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 = self.inner().injectors.values().cloned().collect::<Vec<_>>();
583 for injector in injectors {
584 let events = vec![pointerinjector::Event {
585 timestamp: Some(MonotonicInstant::now().into_nanos()),
586 data: Some(pointerinjector::Data::Viewport(utils::viewport_to_next(
587 &new_viewport,
588 ))),
589 trace_flow_id: Some(fuchsia_trace::Id::random().into()),
590 ..Default::default()
591 }];
592 injector
593 .inject_events(events)
594 .await
595 .expect("Failed to inject updated viewport.");
596 }
597 }
598 Some(Err(e)) => {
599 self.metrics_logger.log_error(
600 InputPipelineErrorMetricDimensionEvent::MouseInjectorErrorWhileReadingViewportUpdate,
601 std::format!("Error while reading viewport update: {}", e));
602 return;
603 }
604 None => {
605 self.metrics_logger.log_error(
606 InputPipelineErrorMetricDimensionEvent::MouseInjectorViewportUpdateStreamTerminatedUnexpectedly,
607 "Viewport update stream terminated unexpectedly");
608 return;
609 }
610 }
611 }
612 }
613
614 fn relative_movement_mm_to_phyical_pixel(&self, movement_mm: Position) -> Position {
618 Position {
619 x: movement_mm.x * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
620 y: movement_mm.y * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
621 }
622 }
623}
624
625#[cfg(test)]
626mod tests {
627 use super::*;
628 use crate::testing_utilities::{
629 assert_handler_ignores_input_event_sequence, create_mouse_event,
630 create_mouse_event_with_handled, create_mouse_pointer_sample_event,
631 create_mouse_pointer_sample_event_phase_add,
632 create_mouse_pointer_sample_event_with_wheel_physical_pixel, next_client_old_stream,
633 };
634 use assert_matches::assert_matches;
635 use fidl_fuchsia_input_report as fidl_input_report;
636 use fidl_fuchsia_ui_pointerinjector as pointerinjector;
637 use fidl_next_fuchsia_ui_pointerinjector as pointerinjector_next;
638 use fuchsia_async as fasync;
639 use futures::channel::mpsc;
640 use pretty_assertions::assert_eq;
641 use std::collections::HashSet;
642 use std::ops::Add;
643 use test_case::test_case;
644
645 const DISPLAY_WIDTH_IN_PHYSICAL_PX: f32 = 100.0;
646 const DISPLAY_HEIGHT_IN_PHYSICAL_PX: f32 = 100.0;
647 const COUNTS_PER_MM: u32 = 12;
648
649 const DESCRIPTOR: input_device::InputDeviceDescriptor =
651 input_device::InputDeviceDescriptor::Mouse(mouse_binding::MouseDeviceDescriptor {
652 device_id: 1,
653 absolute_x_range: Some(fidl_input_report::Range { min: 0, max: 100 }),
654 absolute_y_range: Some(fidl_input_report::Range { min: 0, max: 100 }),
655 wheel_v_range: Some(fidl_input_report::Axis {
656 range: fidl_input_report::Range { min: -1, max: 1 },
657 unit: fidl_input_report::Unit {
658 type_: fidl_input_report::UnitType::Other,
659 exponent: 0,
660 },
661 }),
662 wheel_h_range: Some(fidl_input_report::Axis {
663 range: fidl_input_report::Range { min: -1, max: 1 },
664 unit: fidl_input_report::Unit {
665 type_: fidl_input_report::UnitType::Other,
666 exponent: 0,
667 },
668 }),
669 buttons: None,
670 counts_per_mm: COUNTS_PER_MM,
671 });
672
673 async fn handle_configuration_request_stream(
675 stream: &mut pointerinjector_config::SetupRequestStream,
676 ) {
677 if let Some(Ok(request)) = stream.next().await {
678 match request {
679 pointerinjector_config::SetupRequest::GetViewRefs { responder, .. } => {
680 let context = fuchsia_scenic::ViewRefPair::new()
681 .expect("Failed to create viewrefpair.")
682 .view_ref;
683 let target = fuchsia_scenic::ViewRefPair::new()
684 .expect("Failed to create viewrefpair.")
685 .view_ref;
686 let _ = responder.send(context, target);
687 }
688 _ => {}
689 };
690 }
691 }
692
693 async fn handle_registry_request_stream(
696 mut stream: pointerinjector::RegistryRequestStream,
697 injector_sender: futures::channel::oneshot::Sender<pointerinjector::DeviceRequestStream>,
698 ) {
699 if let Some(request) = stream.next().await {
700 match request {
701 Ok(pointerinjector::RegistryRequest::Register {
702 config: _,
703 injector,
704 responder,
705 ..
706 }) => {
707 let injector_stream = injector.into_stream();
708 let _ = injector_sender.send(injector_stream);
709 responder.send().expect("failed to respond");
710 }
711 _ => {}
712 };
713 } else {
714 panic!("RegistryRequestStream failed.");
715 }
716 }
717
718 async fn handle_registry_request_stream2(
720 mut stream: pointerinjector::RegistryRequestStream,
721 injector_sender: mpsc::UnboundedSender<Vec<pointerinjector::Event>>,
722 ) {
723 let (injector, responder) = match stream.next().await {
724 Some(Ok(pointerinjector::RegistryRequest::Register {
725 config: _,
726 injector,
727 responder,
728 ..
729 })) => (injector, responder),
730 other => panic!("expected register request, but got {:?}", other),
731 };
732 let injector_stream: pointerinjector::DeviceRequestStream = injector.into_stream();
733 responder.send().expect("failed to respond");
734 injector_stream
735 .for_each(|request| {
736 futures::future::ready({
737 match request {
738 Ok(pointerinjector::DeviceRequest::Inject { .. }) => {
739 panic!("DeviceRequest::Inject is deprecated.");
740 }
741 Ok(pointerinjector::DeviceRequest::InjectEvents { events, .. }) => {
742 let _ = injector_sender.unbounded_send(events);
743 }
744 Err(e) => panic!("FIDL error {}", e),
745 }
746 })
747 })
748 .await;
749 }
750
751 async fn handle_device_request_stream(
754 injector_stream_receiver: futures::channel::oneshot::Receiver<
755 pointerinjector::DeviceRequestStream,
756 >,
757 expected_events: Vec<pointerinjector::Event>,
758 ) {
759 let mut injector_stream =
760 injector_stream_receiver.await.expect("Failed to get DeviceRequestStream.");
761 for expected_event in expected_events {
762 match injector_stream.next().await {
763 Some(Ok(pointerinjector::DeviceRequest::Inject { .. })) => {
764 panic!("DeviceRequest::Inject is deprecated.");
765 }
766 Some(Ok(pointerinjector::DeviceRequest::InjectEvents { events, .. })) => {
767 assert_eq!(events, vec![expected_event]);
768 }
769 Some(Err(e)) => panic!("FIDL error {}", e),
770 None => panic!("Expected another event."),
771 }
772 }
773 }
774
775 fn create_viewport(min: f32, max: f32) -> pointerinjector::Viewport {
777 pointerinjector::Viewport {
778 extents: Some([[min, min], [max, max]]),
779 viewport_to_context_transform: None,
780 ..Default::default()
781 }
782 }
783
784 fn create_viewport_next(min: f32, max: f32) -> pointerinjector_next::Viewport {
785 pointerinjector_next::Viewport {
786 extents: Some([[min, min], [max, max]]),
787 viewport_to_context_transform: None,
788 ..Default::default()
789 }
790 }
791
792 #[fuchsia::test]
795 fn receives_viewport_updates() {
796 let mut exec = fasync::TestExecutor::new();
797
798 let (configuration_proxy, mut configuration_request_stream) =
800 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
801 let (injector_registry_proxy, _) =
802 fidl_next::fuchsia::create_channel::<pointerinjector_next::Registry>();
803 let injector_registry_proxy =
804 Dispatcher::client_from_zx_channel(injector_registry_proxy).spawn();
805 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(0);
806
807 let inspector = fuchsia_inspect::Inspector::default();
808 let test_node = inspector.root().create_child("test_node");
809
810 let mouse_handler_fut = MouseInjectorHandler::new_handler(
812 configuration_proxy,
813 injector_registry_proxy,
814 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
815 sender,
816 &test_node,
817 metrics::MetricsLogger::default(),
818 );
819 let config_request_stream_fut =
820 handle_configuration_request_stream(&mut configuration_request_stream);
821 let (mouse_handler_res, _) = exec.run_singlethreaded(futures::future::join(
822 mouse_handler_fut,
823 config_request_stream_fut,
824 ));
825 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
826
827 let (injector_device_proxy, mut injector_device_request_stream) =
829 next_client_old_stream::<pointerinjector::DeviceMarker, pointerinjector_next::Device>();
830 mouse_handler.inner_mut().injectors.insert(1, injector_device_proxy);
831
832 {
834 let watch_viewport_fut = mouse_handler.clone().watch_viewport();
836 futures::pin_mut!(watch_viewport_fut);
837 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
838
839 match exec.run_singlethreaded(&mut configuration_request_stream.next()) {
841 Some(Ok(pointerinjector_config::SetupRequest::WatchViewport {
842 responder, ..
843 })) => {
844 responder.send(&create_viewport(0.0, 100.0)).expect("Failed to send viewport.");
845 }
846 other => panic!("Received unexpected value: {:?}", other),
847 };
848 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
849
850 exec.run_singlethreaded(async {
852 match injector_device_request_stream.next().await {
853 Some(Ok(pointerinjector::DeviceRequest::Inject { .. })) => {
854 panic!("DeviceRequest::Inject is deprecated.");
855 }
856 Some(Ok(pointerinjector::DeviceRequest::InjectEvents { events, .. })) => {
857 assert_eq!(events.len(), 1);
858 assert!(events[0].data.is_some());
859 assert_eq!(
860 events[0].data,
861 Some(pointerinjector::Data::Viewport(create_viewport(0.0, 100.0)))
862 );
863 }
864 other => panic!("Received unexpected value: {:?}", other),
865 }
866 });
867
868 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
870
871 match exec.run_singlethreaded(&mut configuration_request_stream.next()) {
873 Some(Ok(pointerinjector_config::SetupRequest::WatchViewport {
874 responder, ..
875 })) => {
876 responder
877 .send(&create_viewport(100.0, 200.0))
878 .expect("Failed to send viewport.");
879 }
880 other => panic!("Received unexpected value: {:?}", other),
881 };
882
883 assert!(exec.run_until_stalled(&mut watch_viewport_fut).is_pending());
885 }
886
887 exec.run_singlethreaded(async {
889 match injector_device_request_stream.next().await {
890 Some(Ok(pointerinjector::DeviceRequest::Inject { .. })) => {
891 panic!("DeviceRequest::Inject is deprecated.");
892 }
893 Some(Ok(pointerinjector::DeviceRequest::InjectEvents { events, .. })) => {
894 assert_eq!(events.len(), 1);
895 assert!(events[0].data.is_some());
896 assert_eq!(
897 events[0].data,
898 Some(pointerinjector::Data::Viewport(create_viewport(100.0, 200.0)))
899 );
900 }
901 other => panic!("Received unexpected value: {:?}", other),
902 }
903 });
904
905 let expected_viewport = create_viewport_next(100.0, 200.0);
907 assert_eq!(mouse_handler.inner().viewport, Some(expected_viewport));
908 }
909
910 fn wheel_delta_ticks(
911 ticks: i64,
912 physical_pixel: Option<f32>,
913 ) -> Option<mouse_binding::WheelDelta> {
914 Some(mouse_binding::WheelDelta {
915 raw_data: mouse_binding::RawWheelDelta::Ticks(ticks),
916 physical_pixel,
917 })
918 }
919
920 fn wheel_delta_mm(mm: f32, physical_pixel: Option<f32>) -> Option<mouse_binding::WheelDelta> {
921 Some(mouse_binding::WheelDelta {
922 raw_data: mouse_binding::RawWheelDelta::Millimeters(mm),
923 physical_pixel,
924 })
925 }
926
927 #[test_case(
930 mouse_binding::MouseLocation::Relative(
931 mouse_binding::RelativeLocation {
932 millimeters: Position { x: 1.0, y: 2.0 }
933 }),
934 Position {
935 x: DISPLAY_WIDTH_IN_PHYSICAL_PX / 2.0
936 + 1.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
937 y: DISPLAY_HEIGHT_IN_PHYSICAL_PX / 2.0
938 + 2.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
939 },
940 [
941 1.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
942 2.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
943 ]; "Valid move event."
944 )]
945 #[test_case(
946 mouse_binding::MouseLocation::Relative(
947 mouse_binding::RelativeLocation {
948 millimeters: Position {
949 x: DISPLAY_WIDTH_IN_PHYSICAL_PX / MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL + 2.0,
950 y: DISPLAY_HEIGHT_IN_PHYSICAL_PX / MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL + 1.0,
951 }}),
952 Position {
953 x: DISPLAY_WIDTH_IN_PHYSICAL_PX,
954 y: DISPLAY_HEIGHT_IN_PHYSICAL_PX,
955 },
956 [
957 DISPLAY_WIDTH_IN_PHYSICAL_PX + 2.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
958 DISPLAY_HEIGHT_IN_PHYSICAL_PX + 1.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
959 ]; "Move event exceeds max bounds."
960 )]
961 #[test_case(
962 mouse_binding::MouseLocation::Relative(
963 mouse_binding::RelativeLocation {
964 millimeters: Position {
965 x: -(DISPLAY_WIDTH_IN_PHYSICAL_PX / MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL + 2.0),
966 y: -(DISPLAY_HEIGHT_IN_PHYSICAL_PX / MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL + 1.0),
967 }}),
968 Position { x: 0.0, y: 0.0 },
969 [
970 -(DISPLAY_WIDTH_IN_PHYSICAL_PX + 2.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL),
971 -(DISPLAY_HEIGHT_IN_PHYSICAL_PX + 1.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL),
972 ]; "Move event exceeds min bounds."
973 )]
974 #[fuchsia::test(allow_stalls = false)]
975 async fn move_event(
976 move_location: mouse_binding::MouseLocation,
977 expected_position: Position,
978 expected_relative_motion: [f32; 2],
979 ) {
980 let (configuration_proxy, mut configuration_request_stream) =
982 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
983 let (injector_registry_proxy, injector_registry_request_stream) = next_client_old_stream::<
984 pointerinjector::RegistryMarker,
985 pointerinjector_next::Registry,
986 >();
987 let config_request_stream_fut =
988 handle_configuration_request_stream(&mut configuration_request_stream);
989
990 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
992 let inspector = fuchsia_inspect::Inspector::default();
993 let test_node = inspector.root().create_child("test_node");
994 let mouse_handler_fut = MouseInjectorHandler::new_handler(
995 configuration_proxy,
996 injector_registry_proxy,
997 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
998 sender,
999 &test_node,
1000 metrics::MetricsLogger::default(),
1001 );
1002 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1003 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1004
1005 let event_time = zx::MonotonicInstant::get();
1006 let input_event = create_mouse_event(
1007 move_location,
1008 None, None, None, mouse_binding::MousePhase::Move,
1012 HashSet::new(),
1013 HashSet::new(),
1014 event_time,
1015 &DESCRIPTOR,
1016 );
1017
1018 let handle_event_fut = mouse_handler.handle_input_event(input_event);
1020 let expected_events = vec![
1021 create_mouse_pointer_sample_event_phase_add(vec![], expected_position, event_time),
1022 create_mouse_pointer_sample_event(
1023 pointerinjector::EventPhase::Change,
1024 vec![],
1025 expected_position,
1026 Some(expected_relative_motion),
1027 None, None, None, event_time,
1031 ),
1032 ];
1033
1034 let (injector_stream_sender, injector_stream_receiver) =
1038 futures::channel::oneshot::channel::<pointerinjector::DeviceRequestStream>();
1039 let registry_fut = handle_registry_request_stream(
1040 injector_registry_request_stream,
1041 injector_stream_sender,
1042 );
1043 let device_fut = handle_device_request_stream(injector_stream_receiver, expected_events);
1044
1045 let (handle_result, _, _) = futures::join!(handle_event_fut, registry_fut, device_fut);
1048 match receiver.next().await {
1049 Some(CursorMessage::SetPosition(position)) => {
1050 pretty_assertions::assert_eq!(position, expected_position);
1051 }
1052 Some(CursorMessage::SetVisibility(_)) => {
1053 panic!("Received unexpected cursor visibility update.")
1054 }
1055 None => panic!("Did not receive cursor update."),
1056 }
1057
1058 assert_matches!(
1060 handle_result.as_slice(),
1061 [input_device::InputEvent { handled: input_device::Handled::Yes, .. }]
1062 );
1063 }
1064
1065 #[fuchsia::test(allow_stalls = false)]
1068 async fn move_absolute_event() {
1069 const DEVICE_ID: u32 = 1;
1070
1071 let (configuration_proxy, mut configuration_request_stream) =
1073 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1074 let (injector_registry_proxy, injector_registry_request_stream) = next_client_old_stream::<
1075 pointerinjector::RegistryMarker,
1076 pointerinjector_next::Registry,
1077 >();
1078 let config_request_stream_fut =
1079 handle_configuration_request_stream(&mut configuration_request_stream);
1080
1081 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
1083 let inspector = fuchsia_inspect::Inspector::default();
1084 let test_node = inspector.root().create_child("test_node");
1085 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1086 configuration_proxy,
1087 injector_registry_proxy,
1088 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1089 sender,
1090 &test_node,
1091 metrics::MetricsLogger::default(),
1092 );
1093 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1094 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1095
1096 let cursor_location =
1112 mouse_binding::MouseLocation::Absolute(Position { x: -25.0, y: 25.0 });
1113 let event_time = zx::MonotonicInstant::get();
1114 let descriptor =
1115 input_device::InputDeviceDescriptor::Mouse(mouse_binding::MouseDeviceDescriptor {
1116 device_id: DEVICE_ID,
1117 absolute_x_range: Some(fidl_input_report::Range { min: -50, max: 50 }),
1118 absolute_y_range: Some(fidl_input_report::Range { min: -50, max: 50 }),
1119 wheel_v_range: None,
1120 wheel_h_range: None,
1121 buttons: None,
1122 counts_per_mm: COUNTS_PER_MM,
1123 });
1124 let input_event = create_mouse_event(
1125 cursor_location,
1126 None, None, None, mouse_binding::MousePhase::Move,
1130 HashSet::new(),
1131 HashSet::new(),
1132 event_time,
1133 &descriptor,
1134 );
1135
1136 let handle_event_fut = mouse_handler.handle_input_event(input_event);
1138 let expected_position = Position {
1139 x: DISPLAY_WIDTH_IN_PHYSICAL_PX * 0.25,
1140 y: DISPLAY_WIDTH_IN_PHYSICAL_PX * 0.75,
1141 };
1142 let expected_events = vec![
1143 create_mouse_pointer_sample_event_phase_add(vec![], expected_position, event_time),
1144 create_mouse_pointer_sample_event(
1145 pointerinjector::EventPhase::Change,
1146 vec![],
1147 expected_position,
1148 None, None, None, None, event_time,
1153 ),
1154 ];
1155
1156 let (injector_stream_sender, injector_stream_receiver) =
1160 futures::channel::oneshot::channel::<pointerinjector::DeviceRequestStream>();
1161 let registry_fut = handle_registry_request_stream(
1162 injector_registry_request_stream,
1163 injector_stream_sender,
1164 );
1165 let device_fut = handle_device_request_stream(injector_stream_receiver, expected_events);
1166
1167 let (handle_result, _, _) = futures::join!(handle_event_fut, registry_fut, device_fut);
1170 match receiver.next().await {
1171 Some(CursorMessage::SetPosition(position)) => {
1172 assert_eq!(position, expected_position);
1173 }
1174 Some(CursorMessage::SetVisibility(_)) => {
1175 panic!("Received unexpected cursor visibility update.")
1176 }
1177 None => panic!("Did not receive cursor update."),
1178 }
1179
1180 assert_matches!(
1182 handle_result.as_slice(),
1183 [input_device::InputEvent { handled: input_device::Handled::Yes, .. }]
1184 );
1185 }
1186
1187 #[test_case(
1189 mouse_binding::MousePhase::Down,
1190 vec![1], vec![1]; "Down event injects button press state."
1191 )]
1192 #[test_case(
1193 mouse_binding::MousePhase::Up,
1194 vec![1], vec![]; "Up event injects button press state."
1195 )]
1196 #[fuchsia::test(allow_stalls = false)]
1197 async fn button_state_event(
1198 phase: mouse_binding::MousePhase,
1199 affected_buttons: Vec<mouse_binding::MouseButton>,
1200 pressed_buttons: Vec<mouse_binding::MouseButton>,
1201 ) {
1202 let (configuration_proxy, mut configuration_request_stream) =
1204 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1205 let (injector_registry_proxy, injector_registry_request_stream) = next_client_old_stream::<
1206 pointerinjector::RegistryMarker,
1207 pointerinjector_next::Registry,
1208 >();
1209 let config_request_stream_fut =
1210 handle_configuration_request_stream(&mut configuration_request_stream);
1211
1212 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
1214 let inspector = fuchsia_inspect::Inspector::default();
1215 let test_node = inspector.root().create_child("test_node");
1216 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1217 configuration_proxy,
1218 injector_registry_proxy,
1219 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1220 sender,
1221 &test_node,
1222 metrics::MetricsLogger::default(),
1223 );
1224 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1225 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1226
1227 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
1228 let event_time = zx::MonotonicInstant::get();
1229
1230 let input_event = create_mouse_event(
1231 cursor_location,
1232 None, None, None, phase,
1236 HashSet::from_iter(affected_buttons.clone()),
1237 HashSet::from_iter(pressed_buttons.clone()),
1238 event_time,
1239 &DESCRIPTOR,
1240 );
1241
1242 let handle_event_fut = mouse_handler.handle_input_event(input_event);
1244 let expected_position = Position { x: 0.0, y: 0.0 };
1245 let expected_events = vec![
1246 create_mouse_pointer_sample_event_phase_add(
1247 pressed_buttons.clone(),
1248 expected_position,
1249 event_time,
1250 ),
1251 create_mouse_pointer_sample_event(
1252 pointerinjector::EventPhase::Change,
1253 pressed_buttons.clone(),
1254 expected_position,
1255 None, None, None, None, event_time,
1260 ),
1261 ];
1262
1263 let (injector_stream_sender, injector_stream_receiver) =
1267 futures::channel::oneshot::channel::<pointerinjector::DeviceRequestStream>();
1268 let registry_fut = handle_registry_request_stream(
1269 injector_registry_request_stream,
1270 injector_stream_sender,
1271 );
1272 let device_fut = handle_device_request_stream(injector_stream_receiver, expected_events);
1273
1274 let (handle_result, _, _) = futures::join!(handle_event_fut, registry_fut, device_fut);
1277 match receiver.next().await {
1278 Some(CursorMessage::SetPosition(position)) => {
1279 pretty_assertions::assert_eq!(position, expected_position);
1280 }
1281 Some(CursorMessage::SetVisibility(_)) => {
1282 panic!("Received unexpected cursor visibility update.")
1283 }
1284 None => panic!("Did not receive cursor update."),
1285 }
1286
1287 assert_matches!(
1289 handle_result.as_slice(),
1290 [input_device::InputEvent { handled: input_device::Handled::Yes, .. }]
1291 );
1292 }
1293
1294 #[fuchsia::test(allow_stalls = false)]
1296 async fn down_up_event() {
1297 let (configuration_proxy, mut configuration_request_stream) =
1299 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1300 let (injector_registry_proxy, injector_registry_request_stream) = next_client_old_stream::<
1301 pointerinjector::RegistryMarker,
1302 pointerinjector_next::Registry,
1303 >();
1304 let config_request_stream_fut =
1305 handle_configuration_request_stream(&mut configuration_request_stream);
1306
1307 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(2);
1311 let inspector = fuchsia_inspect::Inspector::default();
1312 let test_node = inspector.root().create_child("test_node");
1313 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1314 configuration_proxy,
1315 injector_registry_proxy,
1316 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1317 sender,
1318 &test_node,
1319 metrics::MetricsLogger::default(),
1320 );
1321 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1322 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1323
1324 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
1325 let event_time1 = zx::MonotonicInstant::get();
1326 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
1327
1328 let event1 = create_mouse_event(
1329 cursor_location,
1330 None, None, None, mouse_binding::MousePhase::Down,
1334 HashSet::from_iter(vec![1]),
1335 HashSet::from_iter(vec![1]),
1336 event_time1,
1337 &DESCRIPTOR,
1338 );
1339
1340 let event2 = create_mouse_event(
1341 cursor_location,
1342 None, None, None, mouse_binding::MousePhase::Up,
1346 HashSet::from_iter(vec![1]),
1347 HashSet::new(),
1348 event_time2,
1349 &DESCRIPTOR,
1350 );
1351
1352 let expected_position = Position { x: 0.0, y: 0.0 };
1353
1354 let (injector_stream_sender, injector_stream_receiver) =
1358 mpsc::unbounded::<Vec<pointerinjector::Event>>();
1359 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
1361 let registry_fut = handle_registry_request_stream2(
1362 injector_registry_request_stream,
1363 injector_stream_sender,
1364 );
1365
1366 let _registry_task = fasync::Task::local(registry_fut);
1368
1369 mouse_handler.clone().handle_input_event(event1).await;
1370 assert_eq!(
1371 injector_stream_receiver
1372 .next()
1373 .await
1374 .map(|events| events.into_iter().flatten().collect()),
1375 Some(vec![
1376 create_mouse_pointer_sample_event_phase_add(
1377 vec![1],
1378 expected_position,
1379 event_time1,
1380 ),
1381 create_mouse_pointer_sample_event(
1382 pointerinjector::EventPhase::Change,
1383 vec![1],
1384 expected_position,
1385 None, None, None, None, event_time1,
1390 )
1391 ])
1392 );
1393
1394 mouse_handler.clone().handle_input_event(event2).await;
1396 assert_eq!(
1397 injector_stream_receiver
1398 .next()
1399 .await
1400 .map(|events| events.into_iter().flatten().collect()),
1401 Some(vec![create_mouse_pointer_sample_event(
1402 pointerinjector::EventPhase::Change,
1403 vec![],
1404 expected_position,
1405 None, None, None, None, event_time2,
1410 )])
1411 );
1412
1413 match receiver.next().await {
1415 Some(CursorMessage::SetPosition(position)) => {
1416 assert_eq!(position, expected_position);
1417 }
1418 Some(CursorMessage::SetVisibility(_)) => {
1419 panic!("Received unexpected cursor visibility update.")
1420 }
1421 None => panic!("Did not receive cursor update."),
1422 }
1423 }
1424
1425 #[fuchsia::test(allow_stalls = false)]
1435 async fn down_down_up_up_event() {
1436 let (configuration_proxy, mut configuration_request_stream) =
1438 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1439 let (injector_registry_proxy, injector_registry_request_stream) = next_client_old_stream::<
1440 pointerinjector::RegistryMarker,
1441 pointerinjector_next::Registry,
1442 >();
1443 let config_request_stream_fut =
1444 handle_configuration_request_stream(&mut configuration_request_stream);
1445
1446 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(4);
1450 let inspector = fuchsia_inspect::Inspector::default();
1451 let test_node = inspector.root().create_child("test_node");
1452 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1453 configuration_proxy,
1454 injector_registry_proxy,
1455 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1456 sender,
1457 &test_node,
1458 metrics::MetricsLogger::default(),
1459 );
1460 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1461 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1462
1463 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
1464 let event_time1 = zx::MonotonicInstant::get();
1465 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
1466 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
1467 let event_time4 = event_time3.add(zx::MonotonicDuration::from_micros(1));
1468
1469 let event1 = create_mouse_event(
1470 cursor_location,
1471 None, None, None, mouse_binding::MousePhase::Down,
1475 HashSet::from_iter(vec![1]),
1476 HashSet::from_iter(vec![1]),
1477 event_time1,
1478 &DESCRIPTOR,
1479 );
1480 let event2 = create_mouse_event(
1481 cursor_location,
1482 None, None, None, mouse_binding::MousePhase::Down,
1486 HashSet::from_iter(vec![2]),
1487 HashSet::from_iter(vec![1, 2]),
1488 event_time2,
1489 &DESCRIPTOR,
1490 );
1491 let event3 = create_mouse_event(
1492 cursor_location,
1493 None, None, None, mouse_binding::MousePhase::Up,
1497 HashSet::from_iter(vec![1]),
1498 HashSet::from_iter(vec![2]),
1499 event_time3,
1500 &DESCRIPTOR,
1501 );
1502 let event4 = create_mouse_event(
1503 cursor_location,
1504 None, None, None, mouse_binding::MousePhase::Up,
1508 HashSet::from_iter(vec![2]),
1509 HashSet::new(),
1510 event_time4,
1511 &DESCRIPTOR,
1512 );
1513
1514 let expected_position = Position { x: 0.0, y: 0.0 };
1515
1516 let (injector_stream_sender, injector_stream_receiver) =
1520 mpsc::unbounded::<Vec<pointerinjector::Event>>();
1521 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
1523 let registry_fut = handle_registry_request_stream2(
1524 injector_registry_request_stream,
1525 injector_stream_sender,
1526 );
1527
1528 let _registry_task = fasync::Task::local(registry_fut);
1530 mouse_handler.clone().handle_input_event(event1).await;
1531 assert_eq!(
1532 injector_stream_receiver
1533 .next()
1534 .await
1535 .map(|events| events.into_iter().flatten().collect()),
1536 Some(vec![
1537 create_mouse_pointer_sample_event_phase_add(
1538 vec![1],
1539 expected_position,
1540 event_time1,
1541 ),
1542 create_mouse_pointer_sample_event(
1543 pointerinjector::EventPhase::Change,
1544 vec![1],
1545 expected_position,
1546 None, None, None, None, event_time1,
1551 )
1552 ])
1553 );
1554
1555 mouse_handler.clone().handle_input_event(event2).await;
1557 let pointer_sample_event2: Vec<_> = injector_stream_receiver
1558 .next()
1559 .await
1560 .map(|events| events.into_iter().flatten().collect())
1561 .expect("Failed to receive pointer sample event.");
1562 let expected_event_time: i64 = event_time2.into_nanos();
1563 assert_eq!(pointer_sample_event2.len(), 1);
1564
1565 match &pointer_sample_event2[0] {
1568 pointerinjector::Event {
1569 timestamp: Some(actual_event_time),
1570 data:
1571 Some(pointerinjector::Data::PointerSample(pointerinjector::PointerSample {
1572 pointer_id: Some(0),
1573 phase: Some(pointerinjector::EventPhase::Change),
1574 position_in_viewport: Some(actual_position),
1575 scroll_v: None,
1576 scroll_h: None,
1577 pressed_buttons: Some(actual_buttons),
1578 relative_motion: None,
1579 ..
1580 })),
1581 ..
1582 } => {
1583 assert_eq!(*actual_event_time, expected_event_time);
1584 assert_eq!(actual_position[0], expected_position.x);
1585 assert_eq!(actual_position[1], expected_position.y);
1586 assert_eq!(
1587 HashSet::<mouse_binding::MouseButton>::from_iter(actual_buttons.clone()),
1588 HashSet::from_iter(vec![1, 2])
1589 );
1590 }
1591 _ => panic!("Unexpected pointer sample event: {:?}", pointer_sample_event2[0]),
1592 }
1593
1594 mouse_handler.clone().handle_input_event(event3).await;
1596 assert_eq!(
1597 injector_stream_receiver
1598 .next()
1599 .await
1600 .map(|events| events.into_iter().flatten().collect()),
1601 Some(vec![create_mouse_pointer_sample_event(
1602 pointerinjector::EventPhase::Change,
1603 vec![2],
1604 expected_position,
1605 None, None, None, None, event_time3,
1610 )])
1611 );
1612
1613 mouse_handler.clone().handle_input_event(event4).await;
1615 assert_eq!(
1616 injector_stream_receiver
1617 .next()
1618 .await
1619 .map(|events| events.into_iter().flatten().collect()),
1620 Some(vec![create_mouse_pointer_sample_event(
1621 pointerinjector::EventPhase::Change,
1622 vec![],
1623 expected_position,
1624 None, None, None, None, event_time4,
1629 )])
1630 );
1631
1632 match receiver.next().await {
1634 Some(CursorMessage::SetPosition(position)) => {
1635 assert_eq!(position, expected_position);
1636 }
1637 Some(CursorMessage::SetVisibility(_)) => {
1638 panic!("Received unexpected cursor visibility update.")
1639 }
1640 None => panic!("Did not receive cursor update."),
1641 }
1642 }
1643
1644 #[fuchsia::test(allow_stalls = false)]
1646 async fn down_move_up_event() {
1647 let (configuration_proxy, mut configuration_request_stream) =
1649 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1650 let (injector_registry_proxy, injector_registry_request_stream) = next_client_old_stream::<
1651 pointerinjector::RegistryMarker,
1652 pointerinjector_next::Registry,
1653 >();
1654 let config_request_stream_fut =
1655 handle_configuration_request_stream(&mut configuration_request_stream);
1656
1657 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(3);
1661 let inspector = fuchsia_inspect::Inspector::default();
1662 let test_node = inspector.root().create_child("test_node");
1663 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1664 configuration_proxy,
1665 injector_registry_proxy,
1666 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1667 sender,
1668 &test_node,
1669 metrics::MetricsLogger::default(),
1670 );
1671 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1672 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1673
1674 let event_time1 = zx::MonotonicInstant::get();
1675 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
1676 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
1677 let zero_position = Position { x: 0.0, y: 0.0 };
1678 let expected_position = Position {
1679 x: 10.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
1680 y: 5.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
1681 };
1682 let expected_relative_motion = [
1683 10.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
1684 5.0 * MOUSE_DISTANCE_IN_MM_TO_DISPLAY_LOGICAL_PIXEL,
1685 ];
1686 let event1 = create_mouse_event(
1687 mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 }),
1688 None, None, None, mouse_binding::MousePhase::Down,
1692 HashSet::from_iter(vec![1]),
1693 HashSet::from_iter(vec![1]),
1694 event_time1,
1695 &DESCRIPTOR,
1696 );
1697 let event2 = create_mouse_event(
1698 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1699 millimeters: Position { x: 10.0, y: 5.0 },
1700 }),
1701 None, None, None, mouse_binding::MousePhase::Move,
1705 HashSet::from_iter(vec![1]),
1706 HashSet::from_iter(vec![1]),
1707 event_time2,
1708 &DESCRIPTOR,
1709 );
1710 let event3 = create_mouse_event(
1711 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1712 millimeters: Position { x: 0.0, y: 0.0 },
1713 }),
1714 None, None, None, mouse_binding::MousePhase::Up,
1718 HashSet::from_iter(vec![1]),
1719 HashSet::from_iter(vec![]),
1720 event_time3,
1721 &DESCRIPTOR,
1722 );
1723
1724 let (injector_stream_sender, injector_stream_receiver) =
1728 mpsc::unbounded::<Vec<pointerinjector::Event>>();
1729 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
1731 let registry_fut = handle_registry_request_stream2(
1732 injector_registry_request_stream,
1733 injector_stream_sender,
1734 );
1735
1736 let _registry_task = fasync::Task::local(registry_fut);
1738 mouse_handler.clone().handle_input_event(event1).await;
1739 assert_eq!(
1740 injector_stream_receiver
1741 .next()
1742 .await
1743 .map(|events| events.into_iter().flatten().collect()),
1744 Some(vec![
1745 create_mouse_pointer_sample_event_phase_add(vec![1], zero_position, event_time1,),
1746 create_mouse_pointer_sample_event(
1747 pointerinjector::EventPhase::Change,
1748 vec![1],
1749 zero_position,
1750 None, None, None, None, event_time1,
1755 )
1756 ])
1757 );
1758
1759 match receiver.next().await {
1761 Some(CursorMessage::SetPosition(position)) => {
1762 assert_eq!(position, zero_position);
1763 }
1764 Some(CursorMessage::SetVisibility(_)) => {
1765 panic!("Received unexpected cursor visibility update.")
1766 }
1767 None => panic!("Did not receive cursor update."),
1768 }
1769
1770 mouse_handler.clone().handle_input_event(event2).await;
1772 assert_eq!(
1773 injector_stream_receiver
1774 .next()
1775 .await
1776 .map(|events| events.into_iter().flatten().collect()),
1777 Some(vec![create_mouse_pointer_sample_event(
1778 pointerinjector::EventPhase::Change,
1779 vec![1],
1780 expected_position,
1781 Some(expected_relative_motion),
1782 None, None, None, event_time2,
1786 )])
1787 );
1788
1789 match receiver.next().await {
1791 Some(CursorMessage::SetPosition(position)) => {
1792 assert_eq!(position, expected_position);
1793 }
1794 Some(CursorMessage::SetVisibility(_)) => {
1795 panic!("Received unexpected cursor visibility update.")
1796 }
1797 None => panic!("Did not receive cursor update."),
1798 }
1799
1800 mouse_handler.clone().handle_input_event(event3).await;
1802 assert_eq!(
1803 injector_stream_receiver
1804 .next()
1805 .await
1806 .map(|events| events.into_iter().flatten().collect()),
1807 Some(vec![create_mouse_pointer_sample_event(
1808 pointerinjector::EventPhase::Change,
1809 vec![],
1810 expected_position,
1811 None, None, None, None, event_time3,
1816 )])
1817 );
1818
1819 match receiver.next().await {
1821 Some(CursorMessage::SetPosition(position)) => {
1822 assert_eq!(position, expected_position);
1823 }
1824 Some(CursorMessage::SetVisibility(_)) => {
1825 panic!("Received unexpected cursor visibility update.")
1826 }
1827 None => panic!("Did not receive cursor update."),
1828 }
1829 }
1830
1831 #[fuchsia::test(allow_stalls = false)]
1833 async fn handler_ignores_handled_events() {
1834 let (configuration_proxy, mut configuration_request_stream) =
1836 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
1837 let (injector_registry_proxy, injector_registry_request_stream) = next_client_old_stream::<
1838 pointerinjector::RegistryMarker,
1839 pointerinjector_next::Registry,
1840 >();
1841 let config_request_stream_fut =
1842 handle_configuration_request_stream(&mut configuration_request_stream);
1843
1844 let (sender, mut receiver) = futures::channel::mpsc::channel::<CursorMessage>(1);
1846 let inspector = fuchsia_inspect::Inspector::default();
1847 let test_node = inspector.root().create_child("test_node");
1848 let mouse_handler_fut = MouseInjectorHandler::new_handler(
1849 configuration_proxy,
1850 injector_registry_proxy,
1851 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
1852 sender,
1853 &test_node,
1854 metrics::MetricsLogger::default(),
1855 );
1856 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
1857 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
1858
1859 let cursor_relative_position = Position { x: 50.0, y: 75.0 };
1860 let cursor_location =
1861 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1862 millimeters: Position {
1863 x: cursor_relative_position.x / COUNTS_PER_MM as f32,
1864 y: cursor_relative_position.y / COUNTS_PER_MM as f32,
1865 },
1866 });
1867 let event_time = zx::MonotonicInstant::get();
1868 let input_events = vec![create_mouse_event_with_handled(
1869 cursor_location,
1870 None, None, None, mouse_binding::MousePhase::Move,
1874 HashSet::new(),
1875 HashSet::new(),
1876 event_time,
1877 &DESCRIPTOR,
1878 input_device::Handled::Yes,
1879 )];
1880
1881 assert_handler_ignores_input_event_sequence(
1882 mouse_handler,
1883 input_events,
1884 injector_registry_request_stream,
1885 )
1886 .await;
1887
1888 assert!(receiver.next().await.is_none());
1890 }
1891
1892 fn zero_relative_location() -> mouse_binding::MouseLocation {
1893 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
1894 millimeters: Position { x: 0.0, y: 0.0 },
1895 })
1896 }
1897
1898 #[test_case(
1899 create_mouse_event(
1900 zero_relative_location(),
1901 wheel_delta_ticks(1, None), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1905 HashSet::new(),
1906 HashSet::new(),
1907 zx::MonotonicInstant::ZERO,
1908 &DESCRIPTOR,
1909 ),
1910 create_mouse_pointer_sample_event(
1911 pointerinjector::EventPhase::Change,
1912 vec![],
1913 Position { x: 50.0, y: 50.0 },
1914 None, Some(1), None, Some(false), zx::MonotonicInstant::ZERO,
1919 ); "v tick scroll"
1920 )]
1921 #[test_case(
1922 create_mouse_event(
1923 zero_relative_location(),
1924 None, wheel_delta_ticks(1, None), Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1928 HashSet::new(),
1929 HashSet::new(),
1930 zx::MonotonicInstant::ZERO,
1931 &DESCRIPTOR,
1932 ),
1933 create_mouse_pointer_sample_event(
1934 pointerinjector::EventPhase::Change,
1935 vec![],
1936 Position { x: 50.0, y: 50.0 },
1937 None, None, Some(1), Some(false), zx::MonotonicInstant::ZERO,
1942 ); "h tick scroll"
1943 )]
1944 #[test_case(
1945 create_mouse_event(
1946 zero_relative_location(),
1947 wheel_delta_ticks(1, Some(120.0)), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1951 HashSet::new(),
1952 HashSet::new(),
1953 zx::MonotonicInstant::ZERO,
1954 &DESCRIPTOR,
1955 ),
1956 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
1957 pointerinjector::EventPhase::Change,
1958 vec![],
1959 Position { x: 50.0, y: 50.0 },
1960 None, Some(1), None, Some(120.0), None, Some(false), zx::MonotonicInstant::ZERO,
1967 ); "v tick scroll with physical pixel"
1968 )]
1969 #[test_case(
1970 create_mouse_event(
1971 zero_relative_location(),
1972 None, wheel_delta_ticks(1, Some(120.0)), Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
1976 HashSet::new(),
1977 HashSet::new(),
1978 zx::MonotonicInstant::ZERO,
1979 &DESCRIPTOR,
1980 ),
1981 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
1982 pointerinjector::EventPhase::Change,
1983 vec![],
1984 Position { x: 50.0, y: 50.0 },
1985 None, None, Some(1), None, Some(120.0), Some(false), zx::MonotonicInstant::ZERO,
1992 ); "h tick scroll with physical pixel"
1993 )]
1994 #[test_case(
1995 create_mouse_event(
1996 zero_relative_location(),
1997 wheel_delta_mm(1.0, Some(120.0)), None, Some(mouse_binding::PrecisionScroll::Yes), mouse_binding::MousePhase::Wheel,
2001 HashSet::new(),
2002 HashSet::new(),
2003 zx::MonotonicInstant::ZERO,
2004 &DESCRIPTOR,
2005 ),
2006 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
2007 pointerinjector::EventPhase::Change,
2008 vec![],
2009 Position { x: 50.0, y: 50.0 },
2010 None, None, None, Some(120.0), None, Some(true), zx::MonotonicInstant::ZERO,
2017 ); "v mm scroll with physical pixel"
2018 )]
2019 #[test_case(
2020 create_mouse_event(
2021 zero_relative_location(),
2022 None, wheel_delta_mm(1.0, Some(120.0)), Some(mouse_binding::PrecisionScroll::Yes), mouse_binding::MousePhase::Wheel,
2026 HashSet::new(),
2027 HashSet::new(),
2028 zx::MonotonicInstant::ZERO,
2029 &DESCRIPTOR,
2030 ),
2031 create_mouse_pointer_sample_event_with_wheel_physical_pixel(
2032 pointerinjector::EventPhase::Change,
2033 vec![],
2034 Position { x: 50.0, y: 50.0 },
2035 None, None, None, None, Some(120.0), Some(true), zx::MonotonicInstant::ZERO,
2042 ); "h mm scroll with physical pixel"
2043 )]
2044 #[fuchsia::test(allow_stalls = false)]
2046 async fn scroll(event: input_device::InputEvent, want_event: pointerinjector::Event) {
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_time = zx::MonotonicInstant::get();
2085
2086 let event = input_device::InputEvent { event_time, ..event };
2087
2088 let want_event =
2089 pointerinjector::Event { timestamp: Some(event_time.into_nanos()), ..want_event };
2090
2091 let _registry_task = fasync::Task::local(registry_fut);
2093
2094 mouse_handler.clone().handle_input_event(event).await;
2095 let got_events: Vec<_> = injector_stream_receiver
2096 .next()
2097 .await
2098 .map(|events| events.into_iter().flatten().collect())
2099 .unwrap();
2100 pretty_assertions::assert_eq!(got_events.len(), 2);
2101 assert_matches!(
2102 got_events[0],
2103 pointerinjector::Event {
2104 data: Some(pointerinjector::Data::PointerSample(pointerinjector::PointerSample {
2105 phase: Some(pointerinjector::EventPhase::Add),
2106 ..
2107 })),
2108 ..
2109 }
2110 );
2111
2112 pretty_assertions::assert_eq!(got_events[1], want_event);
2113 }
2114
2115 #[fuchsia::test(allow_stalls = false)]
2117 async fn down_scroll_up_scroll() {
2118 let (configuration_proxy, mut configuration_request_stream) =
2120 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
2121 let (injector_registry_proxy, injector_registry_request_stream) = next_client_old_stream::<
2122 pointerinjector::RegistryMarker,
2123 pointerinjector_next::Registry,
2124 >();
2125 let config_request_stream_fut =
2126 handle_configuration_request_stream(&mut configuration_request_stream);
2127
2128 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
2130 let inspector = fuchsia_inspect::Inspector::default();
2131 let test_node = inspector.root().create_child("test_node");
2132 let mouse_handler_fut = MouseInjectorHandler::new_handler(
2133 configuration_proxy,
2134 injector_registry_proxy,
2135 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
2136 sender,
2137 &test_node,
2138 metrics::MetricsLogger::default(),
2139 );
2140 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
2141 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
2142
2143 let (injector_stream_sender, injector_stream_receiver) =
2147 mpsc::unbounded::<Vec<pointerinjector::Event>>();
2148 let mut injector_stream_receiver = injector_stream_receiver.ready_chunks(2);
2150 let registry_fut = handle_registry_request_stream2(
2151 injector_registry_request_stream,
2152 injector_stream_sender,
2153 );
2154
2155 let event_time1 = zx::MonotonicInstant::get();
2156 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
2157 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
2158 let event_time4 = event_time3.add(zx::MonotonicDuration::from_micros(1));
2159
2160 let _registry_task = fasync::Task::local(registry_fut);
2162
2163 let zero_location =
2164 mouse_binding::MouseLocation::Relative(mouse_binding::RelativeLocation {
2165 millimeters: Position { x: 0.0, y: 0.0 },
2166 });
2167 let expected_position = Position { x: 50.0, y: 50.0 };
2168
2169 let down_event = create_mouse_event(
2170 zero_location,
2171 None, None, None, mouse_binding::MousePhase::Down,
2175 HashSet::from_iter(vec![1]),
2176 HashSet::from_iter(vec![1]),
2177 event_time1,
2178 &DESCRIPTOR,
2179 );
2180
2181 let wheel_event = create_mouse_event(
2182 zero_location,
2183 wheel_delta_ticks(1, None), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
2187 HashSet::from_iter(vec![1]),
2188 HashSet::from_iter(vec![1]),
2189 event_time2,
2190 &DESCRIPTOR,
2191 );
2192
2193 let up_event = create_mouse_event(
2194 zero_location,
2195 None,
2196 None,
2197 None, mouse_binding::MousePhase::Up,
2199 HashSet::from_iter(vec![1]),
2200 HashSet::new(),
2201 event_time3,
2202 &DESCRIPTOR,
2203 );
2204
2205 let continue_wheel_event = create_mouse_event(
2206 zero_location,
2207 wheel_delta_ticks(1, None), None, Some(mouse_binding::PrecisionScroll::No), mouse_binding::MousePhase::Wheel,
2211 HashSet::new(),
2212 HashSet::new(),
2213 event_time4,
2214 &DESCRIPTOR,
2215 );
2216
2217 mouse_handler.clone().handle_input_event(down_event).await;
2219 assert_eq!(
2220 injector_stream_receiver
2221 .next()
2222 .await
2223 .map(|events| events.into_iter().flatten().collect()),
2224 Some(vec![
2225 create_mouse_pointer_sample_event_phase_add(
2226 vec![1],
2227 expected_position,
2228 event_time1,
2229 ),
2230 create_mouse_pointer_sample_event(
2231 pointerinjector::EventPhase::Change,
2232 vec![1],
2233 expected_position,
2234 None, None, None, None, event_time1,
2239 ),
2240 ])
2241 );
2242
2243 mouse_handler.clone().handle_input_event(wheel_event).await;
2245 assert_eq!(
2246 injector_stream_receiver
2247 .next()
2248 .await
2249 .map(|events| events.into_iter().flatten().collect()),
2250 Some(vec![create_mouse_pointer_sample_event(
2251 pointerinjector::EventPhase::Change,
2252 vec![1],
2253 expected_position,
2254 None, Some(1), None, Some(false), event_time2,
2259 )])
2260 );
2261
2262 mouse_handler.clone().handle_input_event(up_event).await;
2264 assert_eq!(
2265 injector_stream_receiver
2266 .next()
2267 .await
2268 .map(|events| events.into_iter().flatten().collect()),
2269 Some(vec![create_mouse_pointer_sample_event(
2270 pointerinjector::EventPhase::Change,
2271 vec![],
2272 expected_position,
2273 None, None, None, None, event_time3,
2278 )])
2279 );
2280
2281 mouse_handler.clone().handle_input_event(continue_wheel_event).await;
2283 assert_eq!(
2284 injector_stream_receiver
2285 .next()
2286 .await
2287 .map(|events| events.into_iter().flatten().collect()),
2288 Some(vec![create_mouse_pointer_sample_event(
2289 pointerinjector::EventPhase::Change,
2290 vec![],
2291 expected_position,
2292 None, Some(1), None, Some(false), event_time4,
2297 )])
2298 );
2299 }
2300
2301 #[fuchsia::test(allow_stalls = false)]
2302 async fn mouse_injector_handler_initialized_with_inspect_node() {
2303 let (configuration_proxy, mut configuration_request_stream) =
2304 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
2305 let config_request_stream_fut =
2306 handle_configuration_request_stream(&mut configuration_request_stream);
2307 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
2308 let inspector = fuchsia_inspect::Inspector::default();
2309 let fake_handlers_node = inspector.root().create_child("input_handlers_node");
2310 let incoming = Incoming::new();
2311 let mouse_handler_fut = MouseInjectorHandler::new_with_config_proxy(
2312 &incoming,
2313 configuration_proxy,
2314 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
2315 sender,
2316 &fake_handlers_node,
2317 metrics::MetricsLogger::default(),
2318 );
2319 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
2320 let _handler = mouse_handler_res.expect("Failed to create mouse handler");
2321
2322 diagnostics_assertions::assert_data_tree!(inspector, root: {
2323 input_handlers_node: {
2324 mouse_injector_handler: {
2325 events_received_count: 0u64,
2326 events_handled_count: 0u64,
2327 last_received_timestamp_ns: 0u64,
2328 "fuchsia.inspect.Health": {
2329 status: "STARTING_UP",
2330 start_timestamp_nanos: diagnostics_assertions::AnyProperty
2333 },
2334 }
2335 }
2336 });
2337 }
2338
2339 #[fuchsia::test(allow_stalls = false)]
2340 async fn mouse_injector_handler_inspect_counts_events() {
2341 let (configuration_proxy, mut configuration_request_stream) =
2343 fidl::endpoints::create_proxy_and_stream::<pointerinjector_config::SetupMarker>();
2344 let (injector_registry_proxy, injector_registry_request_stream) = next_client_old_stream::<
2345 pointerinjector::RegistryMarker,
2346 pointerinjector_next::Registry,
2347 >();
2348 let (sender, _) = futures::channel::mpsc::channel::<CursorMessage>(1);
2349
2350 let inspector = fuchsia_inspect::Inspector::default();
2351 let fake_handlers_node = inspector.root().create_child("input_handlers_node");
2352
2353 let mouse_handler_fut = MouseInjectorHandler::new_handler(
2355 configuration_proxy,
2356 injector_registry_proxy,
2357 Size { width: DISPLAY_WIDTH_IN_PHYSICAL_PX, height: DISPLAY_HEIGHT_IN_PHYSICAL_PX },
2358 sender,
2359 &fake_handlers_node,
2360 metrics::MetricsLogger::default(),
2361 );
2362 let config_request_stream_fut =
2363 handle_configuration_request_stream(&mut configuration_request_stream);
2364
2365 let (mouse_handler_res, _) = futures::join!(mouse_handler_fut, config_request_stream_fut);
2366 let mouse_handler = mouse_handler_res.expect("Failed to create mouse handler");
2367
2368 let cursor_location = mouse_binding::MouseLocation::Absolute(Position { x: 0.0, y: 0.0 });
2369 let event_time1 = zx::MonotonicInstant::get();
2370 let event_time2 = event_time1.add(zx::MonotonicDuration::from_micros(1));
2371 let event_time3 = event_time2.add(zx::MonotonicDuration::from_micros(1));
2372
2373 let input_events = vec![
2374 create_mouse_event(
2375 cursor_location,
2376 None, None, None, mouse_binding::MousePhase::Down,
2380 HashSet::from_iter(vec![1]),
2381 HashSet::from_iter(vec![1]),
2382 event_time1,
2383 &DESCRIPTOR,
2384 ),
2385 create_mouse_event(
2386 cursor_location,
2387 None, None, None, mouse_binding::MousePhase::Up,
2391 HashSet::from_iter(vec![1]),
2392 HashSet::new(),
2393 event_time2,
2394 &DESCRIPTOR,
2395 ),
2396 create_mouse_event_with_handled(
2397 cursor_location,
2398 None, None, None, mouse_binding::MousePhase::Down,
2402 HashSet::from_iter(vec![1]),
2403 HashSet::from_iter(vec![1]),
2404 event_time3,
2405 &DESCRIPTOR,
2406 input_device::Handled::Yes,
2407 ),
2408 ];
2409
2410 let (injector_stream_sender, _) = mpsc::unbounded::<Vec<pointerinjector::Event>>();
2414 let registry_fut = handle_registry_request_stream2(
2415 injector_registry_request_stream,
2416 injector_stream_sender,
2417 );
2418
2419 let _registry_task = fasync::Task::local(registry_fut);
2421 for input_event in input_events {
2422 mouse_handler.clone().handle_input_event(input_event).await;
2423 }
2424
2425 let last_received_event_time: u64 = event_time2.into_nanos().try_into().unwrap();
2426
2427 diagnostics_assertions::assert_data_tree!(inspector, root: {
2428 input_handlers_node: {
2429 mouse_injector_handler: {
2430 events_received_count: 2u64,
2431 events_handled_count: 2u64,
2432 last_received_timestamp_ns: last_received_event_time,
2433 "fuchsia.inspect.Health": {
2434 status: "STARTING_UP",
2435 start_timestamp_nanos: diagnostics_assertions::AnyProperty
2438 },
2439 }
2440 }
2441 });
2442 }
2443}