blob: ad7f356e342fe97a2535922c030db736e252d5ba [file] [log] [blame]
// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use crate::internal_message::*;
use futures::channel::mpsc::UnboundedSender;
use log::{error, info};
use {fidl_fuchsia_ui_pointer as fptr, fuchsia_async as fasync};
pub fn spawn_mouse_source_watcher(
mouse_source: fptr::MouseSourceProxy,
sender: UnboundedSender<InternalMessage>,
) {
fasync::Task::spawn(async move {
// We expect these to be received before any pointer sample events.
let mut device_info: Option<fptr::MouseDeviceInfo> = None;
let mut view_parameters: Option<fptr::ViewParameters> = None;
loop {
match mouse_source.watch().await {
Ok(events) => {
for e in events.iter() {
let timestamp = e.timestamp.unwrap();
// TODO(https://fxbug.dev/42163110): currently the API does not guarantee that the
// trace ID will be present. However, the current implementation behaves
// this way, and in the future it will also be guaranteed by the API.
let trace_flow_id = e.trace_flow_id.unwrap();
// Handle `device_info` field, if it exists.
// TODO(https://fxbug.dev/42172483): We don't use this info; currently all of the
// fields except for `id` are absent. Furthermore, the documentation is
// insufficient to understand how to handle these fields, if present.
if let Some(new_device_info) = e.device_info.clone() {
info!(
new:? = new_device_info,
replacing:? = device_info;
"Received device info",
);
device_info = Some(new_device_info);
}
// Handle `view_parameters` field, if it exists.
if let Some(new_view_parameters) = e.view_parameters.clone() {
info!(
new:? = new_view_parameters,
replacing:? = view_parameters;
"Received view parameters",
);
view_parameters = Some(new_view_parameters);
}
// Handle `pointer_sample` field, if it exists.
if let Some(fptr::MousePointerSample {
// If there are multiple mouse devices, then the device ID could be used
// to disambiguate them, but we don't worry about that case.
device_id: _,
position_in_viewport: Some(position_in_viewport),
relative_motion,
scroll_v,
scroll_h,
pressed_buttons,
..
}) = e.pointer_sample.clone()
{
// TODO(https://fxbug.dev/42172483): Relative motion is currently ignored.
if let Some(relative_motion) = &relative_motion {
info!(
"https://fxbug.dev/42172483: Relative motion ignored: {:?}",
relative_motion
);
}
// We expect `view_parameters` to have already been received before any
// pointer samples are received.
// TODO(https://fxbug.dev/42172483): We currently ignore these parameters, but real
// apps/frameworks will want to apply the `viewport_to_view_transform`
// instead of passing `position_in_viewport` through unchanged.
if let Some(_view_parameters) = &view_parameters {
if let Err(e) = sender.unbounded_send(InternalMessage::MouseEvent {
timestamp,
trace_flow_id,
position_in_viewport,
scroll_v,
scroll_h,
pressed_buttons,
}) {
error!("Failed to send MouseEvent message: {}", e);
return;
}
} else {
panic!("Expected ViewParameters before MousePointerSample");
}
}
// Handle `stream_info` field, if it exists.
if let Some(fptr::MouseEventStreamInfo { device_id, status }) =
e.stream_info.clone()
{
info!(device_id:%, status:?; "Unhandled MouseEventStreamInfo");
}
}
}
_ => {
info!("MouseSource connection closed");
return;
}
}
}
})
.detach();
}