blob: 5d5f9d04382c3553f070ff86a819892c2da55244 [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::*,
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::InputDeviceBinding, input_handler::InputHandler,
input_pipeline::InputPipeline, keyboard, mouse, mouse_handler, mouse_handler::MouseHandler,
shortcut_handler::ShortcutHandler, touch, touch_handler::TouchHandler,
},
scene_management::{self, FlatSceneManager, SceneManager},
};
/// 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,
) {
let input_pipeline = InputPipeline::new(
device_bindings().await,
input_handlers(scene_manager, pointer_hack_server).await,
);
input_pipeline.handle_input_events().await;
}
async fn device_bindings() -> Vec<Box<dyn InputDeviceBinding>> {
let mut bindings: Vec<Box<dyn InputDeviceBinding>> = vec![];
if let Ok(touch_bindings) = touch::all_touch_bindings().await {
let mut boxed_bindings: Vec<Box<dyn InputDeviceBinding>> = touch_bindings
.into_iter()
.map(|binding| Box::new(binding) as Box<dyn InputDeviceBinding>)
.collect();
bindings.append(&mut boxed_bindings);
}
if let Ok(mouse_bindings) = mouse::all_mouse_bindings().await {
let mut boxed_bindings: Vec<Box<dyn InputDeviceBinding>> = mouse_bindings
.into_iter()
.map(|binding| Box::new(binding) as Box<dyn InputDeviceBinding>)
.collect();
bindings.append(&mut boxed_bindings);
}
if let Ok(keyboard_bindings) = keyboard::all_keyboard_bindings().await {
let mut boxed_bindings: Vec<Box<dyn InputDeviceBinding>> = keyboard_bindings
.into_iter()
.map(|binding| Box::new(binding) as Box<dyn InputDeviceBinding>)
.collect();
bindings.append(&mut boxed_bindings);
}
bindings
}
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>>,
) {
if let Ok(touch_handler) = TouchHandler::new(
scene_manager.session.clone(),
scene_manager.compositor_id,
scene_manager.display_width as i64,
scene_manager.display_height as i64,
)
.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 mouse_handler = MouseHandler::new(
mouse_handler::CursorLocation {
x: scene_manager.display_width,
y: scene_manager.display_height,
},
Some(sender),
scene_manager.session.clone(),
scene_manager.compositor_id,
);
handlers.push(Box::new(mouse_handler));
fasync::spawn(async move {
while let Some(mouse_handler::CursorLocation { x, y }) = receiver.next().await {
scene_manager.set_cursor_location(
x / scene_manager.display_metrics.pixels_per_pip(),
y / scene_manager.display_metrics.pixels_per_pip(),
);
}
});
}
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_width,
scene_manager.display_height,
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_width,
scene_manager.display_height,
1.0 / scene_manager.display_metrics.pixels_per_pip(),
pointer_hack_server.pointer_listeners.clone(),
);
handlers.push(Box::new(touch_hack));
}