blob: e1f0a61b5465fd8ceeb4ed2b478e0c6afe072406 [file] [log] [blame]
// Copyright 2020 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::{
app::{
strategies::base::AppStrategy, Config, FrameBufferPtr, InternalSender, MessageInternal,
RenderOptions,
},
drawing::DisplayRotation,
geometry::IntSize,
input::{self, listen_for_user_input, report::InputReportHandler, DeviceId},
view::{
strategies::{
base::{ViewStrategyParams, ViewStrategyPtr},
framebuffer::FrameBufferViewStrategy,
},
ViewKey,
},
};
use anyhow::{bail, Error};
use async_trait::async_trait;
use euclid::size2;
use fidl_fuchsia_input_report as hid_input_report;
use fidl_fuchsia_ui_scenic::ScenicProxy;
use fuchsia_async::{self as fasync};
use futures::{channel::mpsc::UnboundedSender, TryFutureExt};
use keymaps::Keymap;
use std::collections::HashMap;
pub(crate) struct AutoRepeatContext {
app_sender: UnboundedSender<MessageInternal>,
view_id: ViewKey,
#[allow(unused)]
keyboard_autorepeat_task: Option<fasync::Task<()>>,
repeat_interval: std::time::Duration,
}
pub(crate) trait AutoRepeatTimer {
fn schedule_autorepeat_timer(&mut self, device_id: &DeviceId);
fn continue_autorepeat_timer(&mut self, device_id: &DeviceId);
fn cancel_autorepeat_timer(&mut self) {}
}
impl AutoRepeatContext {
pub(crate) fn new(app_sender: &UnboundedSender<MessageInternal>, view_id: ViewKey) -> Self {
Self {
app_sender: app_sender.clone(),
view_id,
keyboard_autorepeat_task: None,
repeat_interval: Config::get().keyboard_autorepeat_slow_interval,
}
}
fn schedule(&mut self, device_id: &DeviceId) {
let timer = fasync::Timer::new(fuchsia_async::Time::after(self.repeat_interval.into()));
let app_sender = self.app_sender.clone();
let device_id = device_id.clone();
let view_id = self.view_id;
let task = fasync::Task::local(async move {
timer.await;
app_sender
.unbounded_send(MessageInternal::KeyboardAutoRepeat(device_id, view_id))
.expect("unbounded_send");
});
self.keyboard_autorepeat_task = Some(task);
}
}
impl AutoRepeatTimer for AutoRepeatContext {
fn schedule_autorepeat_timer(&mut self, device_id: &DeviceId) {
self.repeat_interval = Config::get().keyboard_autorepeat_slow_interval;
self.schedule(device_id);
}
fn continue_autorepeat_timer(&mut self, device_id: &DeviceId) {
self.repeat_interval =
(self.repeat_interval * 3 / 4).max(Config::get().keyboard_autorepeat_fast_interval);
self.schedule(device_id);
}
fn cancel_autorepeat_timer(&mut self) {
let task = self.keyboard_autorepeat_task.take();
if let Some(task) = task {
fasync::Task::local(async move {
task.cancel().await;
})
.detach();
}
}
}
pub(crate) struct FrameBufferAppStrategy<'a> {
pub frame_buffer: FrameBufferPtr,
pub display_rotation: DisplayRotation,
pub keymap: &'a Keymap<'a>,
pub view_key: ViewKey,
pub input_report_handlers: HashMap<DeviceId, InputReportHandler<'a>>,
pub context: AutoRepeatContext,
}
#[async_trait(?Send)]
impl<'a> AppStrategy for FrameBufferAppStrategy<'a> {
async fn create_view_strategy(
&self,
key: ViewKey,
render_options: RenderOptions,
app_sender: UnboundedSender<MessageInternal>,
strategy_params: ViewStrategyParams,
) -> Result<ViewStrategyPtr, Error> {
let strategy_params = match strategy_params {
ViewStrategyParams::FrameBuffer(params) => params,
_ => bail!(
"Incorrect ViewStrategyParams passed to create_view_strategy for frame buffer"
),
};
let strat_ptr = FrameBufferViewStrategy::new(
key,
strategy_params.display_rotation,
render_options,
&strategy_params.size,
strategy_params.pixel_format,
app_sender.clone(),
strategy_params.frame_buffer.clone(),
strategy_params.display_resource_release_delay,
)
.await?;
Ok(strat_ptr)
}
fn supports_scenic(&self) -> bool {
return false;
}
fn get_scenic_proxy(&self) -> Option<&ScenicProxy> {
return None;
}
fn get_frame_buffer_size(&self) -> Option<IntSize> {
let config = self.frame_buffer.borrow().get_config();
Some(size2(config.width as i32, config.height as i32))
}
fn get_pixel_size(&self) -> u32 {
let config = self.frame_buffer.borrow().get_config();
config.pixel_size_bytes
}
fn get_pixel_format(&self) -> fuchsia_framebuffer::PixelFormat {
let config = self.frame_buffer.borrow().get_config();
config.format
}
fn get_linear_stride_bytes(&self) -> u32 {
let config = self.frame_buffer.borrow().get_config();
config.linear_stride_bytes() as u32
}
fn get_frame_buffer(&self) -> Option<FrameBufferPtr> {
Some(self.frame_buffer.clone())
}
async fn post_setup(
&mut self,
_pixel_format: fuchsia_framebuffer::PixelFormat,
internal_sender: &InternalSender,
) -> Result<(), Error> {
let view_key = self.view_key;
let input_report_sender = internal_sender.clone();
fasync::Task::local(
listen_for_user_input(view_key, input_report_sender)
.unwrap_or_else(|e: anyhow::Error| eprintln!("error: listening for input {:?}", e)),
)
.detach();
Ok(())
}
fn handle_input_report(
&mut self,
device_id: &input::DeviceId,
input_report: &hid_input_report::InputReport,
) -> Vec<input::Event> {
let handler = self.input_report_handlers.get_mut(device_id).expect("input_report_handler");
handler.handle_input_report(device_id, input_report, &mut self.context)
}
fn handle_register_input_device(
&mut self,
device_id: &input::DeviceId,
device_descriptor: &hid_input_report::DeviceDescriptor,
) {
let frame_buffer_size = self.get_frame_buffer_size().expect("frame_buffer_size");
self.input_report_handlers.insert(
device_id.clone(),
InputReportHandler::new(
device_id.clone(),
frame_buffer_size,
self.display_rotation,
device_descriptor,
self.keymap,
),
);
}
fn handle_keyboard_autorepeat(&mut self, device_id: &input::DeviceId) -> Vec<input::Event> {
let handler = self.input_report_handlers.get_mut(device_id).expect("input_report_handler");
handler.handle_keyboard_autorepeat(device_id, &mut self.context)
}
}