blob: ebc484c47712a5d6a777712ce83d6c0827241ab0 [file] [log] [blame]
// Copyright 2019 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::mouse_pointer_hack::*,
crate::pointer_hack_server::PointerHackServer,
crate::touch_pointer_hack::*,
anyhow::{Context, Error},
fidl_fuchsia_ui_shortcut as ui_shortcut, fuchsia_async as fasync,
fuchsia_component::client::connect_to_service,
futures::StreamExt,
input::{
ime_handler::ImeHandler, input_device, input_handler::InputHandler,
input_pipeline::InputPipeline, mouse_handler::MouseHandler,
shortcut_handler::ShortcutHandler, touch_handler::TouchHandler, Position, Size,
},
scene_management::{self, FlatSceneManager, SceneManager, ScreenCoordinates},
};
/// Begins handling input events. The returned future will complete when
/// input events are no longer being handled.
///
/// # Parameters
/// - `scene_manager`: The scene manager used by the session.
/// - `pointer_hack_server`: The pointer hack server, used to fetch listeners for pointer
/// hack input handlers.
pub async fn handle_input(
scene_manager: FlatSceneManager,
pointer_hack_server: &PointerHackServer,
) -> Result<(), Error> {
let input_pipeline = InputPipeline::new(
vec![
input_device::InputDeviceType::Mouse,
input_device::InputDeviceType::Touch,
input_device::InputDeviceType::Keyboard,
],
input_handlers(scene_manager, pointer_hack_server).await,
)
.await
.context("Failed to create InputPipeline.")?;
input_pipeline.handle_input_events().await;
Ok(())
}
async fn input_handlers(
scene_manager: FlatSceneManager,
pointer_hack_server: &PointerHackServer,
) -> Vec<Box<dyn InputHandler>> {
let mut handlers: Vec<Box<dyn InputHandler>> = vec![];
// Touch and mouse hack handlers are inserted first.
add_touch_hack(&scene_manager, &pointer_hack_server, &mut handlers).await;
add_mouse_hack(&scene_manager, &pointer_hack_server, &mut handlers).await;
// Shortcut needs to go before IME.
add_shortcut_handler(&mut handlers).await;
add_ime(&scene_manager, &mut handlers).await;
add_touch_handler(&scene_manager, &mut handlers).await;
add_mouse_handler(scene_manager, &mut handlers).await;
handlers
}
async fn add_shortcut_handler(handlers: &mut Vec<Box<dyn InputHandler>>) {
if let Ok(manager) = connect_to_service::<ui_shortcut::ManagerMarker>() {
if let Ok(shortcut_handler) = ShortcutHandler::new(manager) {
handlers.push(Box::new(shortcut_handler));
}
}
}
async fn add_ime(scene_manager: &FlatSceneManager, handlers: &mut Vec<Box<dyn InputHandler>>) {
if let Ok(ime_handler) =
ImeHandler::new(scene_manager.session.clone(), scene_manager.compositor_id).await
{
handlers.push(Box::new(ime_handler));
}
}
async fn add_touch_handler(
scene_manager: &FlatSceneManager,
handlers: &mut Vec<Box<dyn InputHandler>>,
) {
let (width_pixels, height_pixels) = scene_manager.display_size.pixels();
if let Ok(touch_handler) = TouchHandler::new(
scene_manager.session.clone(),
scene_manager.compositor_id,
Size { width: width_pixels, height: height_pixels },
)
.await
{
handlers.push(Box::new(touch_handler));
}
}
async fn add_mouse_handler(
mut scene_manager: FlatSceneManager,
handlers: &mut Vec<Box<dyn InputHandler>>,
) {
let (sender, mut receiver) = futures::channel::mpsc::channel(0);
let (width_pixels, height_pixels) = scene_manager.display_size.pixels();
let mouse_handler = MouseHandler::new(
Position { x: width_pixels, y: height_pixels },
Some(sender),
scene_manager.session.clone(),
scene_manager.compositor_id,
);
handlers.push(Box::new(mouse_handler));
fasync::spawn(async move {
while let Some(Position { x, y }) = receiver.next().await {
let screen_coordinates =
ScreenCoordinates::from_pixels(x, y, scene_manager.display_metrics);
scene_manager.set_cursor_location(screen_coordinates);
}
});
}
async fn add_mouse_hack(
scene_manager: &FlatSceneManager,
pointer_hack_server: &PointerHackServer,
handlers: &mut Vec<Box<dyn InputHandler>>,
) {
let mouse_hack = MousePointerHack::new(
scene_manager.display_size.size(),
1.0 / scene_manager.display_metrics.pixels_per_pip(),
pointer_hack_server.pointer_listeners.clone(),
);
handlers.push(Box::new(mouse_hack));
}
async fn add_touch_hack(
scene_manager: &FlatSceneManager,
pointer_hack_server: &PointerHackServer,
handlers: &mut Vec<Box<dyn InputHandler>>,
) {
let touch_hack = TouchPointerHack::new(
scene_manager.display_size.size(),
1.0 / scene_manager.display_metrics.pixels_per_pip(),
pointer_hack_server.pointer_listeners.clone(),
);
handlers.push(Box::new(touch_hack));
}