carnelian/app/strategies/
base.rs1use crate::app::strategies::flatland::FlatlandAppStrategy;
6use crate::app::strategies::framebuffer::{
7 connect_to_display_provider, DisplayCoordinator, DisplayDirectAppStrategy, DisplayId,
8};
9use crate::app::{Config, InternalSender, MessageInternal, ViewMode};
10use crate::input::{self};
11use crate::view::strategies::base::{ViewStrategyParams, ViewStrategyPtr};
12use crate::view::ViewKey;
13use anyhow::Error;
14use async_trait::async_trait;
15use fidl_fuchsia_hardware_display::{ProviderProxy, VirtconMode};
16use fidl_fuchsia_input_report as hid_input_report;
17use fuchsia_component::server::{ServiceFs, ServiceObjLocal};
18use futures::channel::mpsc::UnboundedSender;
19use keymaps::select_keymap;
20
21#[async_trait(?Send)]
26pub(crate) trait AppStrategy {
27 async fn create_view_strategy(
28 &mut self,
29 key: ViewKey,
30 app_sender: UnboundedSender<MessageInternal>,
31 strategy_params: ViewStrategyParams,
32 ) -> Result<ViewStrategyPtr, Error>;
33 #[allow(dead_code)]
34 fn supports_scenic(&self) -> bool;
35 fn create_view_for_testing(&self, _: &UnboundedSender<MessageInternal>) -> Result<(), Error> {
36 Ok(())
37 }
38 fn create_view_strategy_params_for_additional_view(
39 &mut self,
40 view_key: ViewKey,
41 ) -> ViewStrategyParams;
42 fn start_services<'a, 'b>(
43 &self,
44 _app_sender: UnboundedSender<MessageInternal>,
45 _fs: &'a mut ServiceFs<ServiceObjLocal<'b, ()>>,
46 ) -> Result<(), Error> {
47 Ok(())
48 }
49 async fn post_setup(&mut self, _internal_sender: &InternalSender) -> Result<(), Error>;
50 fn handle_input_report(
51 &mut self,
52 _device_id: &input::DeviceId,
53 _input_report: &hid_input_report::InputReport,
54 ) -> Vec<input::Event> {
55 Vec::new()
56 }
57 fn handle_keyboard_autorepeat(&mut self, _device_id: &input::DeviceId) -> Vec<input::Event> {
58 Vec::new()
59 }
60 fn handle_register_input_device(
61 &mut self,
62 _device_id: &input::DeviceId,
63 _device_descriptor: &hid_input_report::DeviceDescriptor,
64 ) {
65 }
66 async fn handle_new_display_coordinator(&mut self, _provider: ProviderProxy) {}
67 async fn handle_display_coordinator_event(
68 &mut self,
69 _event: fidl_fuchsia_hardware_display::CoordinatorListenerRequest,
70 ) {
71 }
72 fn set_virtcon_mode(&mut self, _virtcon_mode: VirtconMode) {}
73 fn handle_view_closed(&mut self, _view_key: ViewKey) {}
74 fn get_focused_view_key(&self) -> Option<ViewKey> {
75 panic!("get_focused_view_key not implemented");
76 }
77 fn get_visible_view_key_for_display(&self, _display_id: DisplayId) -> Option<ViewKey> {
78 panic!("get_visible_view_key_for_display not implemented");
79 }
80}
81
82pub(crate) type AppStrategyPtr = Box<dyn AppStrategy>;
83
84fn make_flatland_app_strategy() -> Result<AppStrategyPtr, Error> {
85 Ok::<AppStrategyPtr, Error>(Box::new(FlatlandAppStrategy {}))
86}
87
88fn make_direct_app_strategy(
89 display_coordinator: Option<DisplayCoordinator>,
90 app_config: &Config,
91 internal_sender: InternalSender,
92) -> Result<AppStrategyPtr, Error> {
93 let strat = DisplayDirectAppStrategy::new(
94 display_coordinator,
95 select_keymap(&app_config.keymap_name),
96 internal_sender,
97 &app_config,
98 );
99
100 Ok(Box::new(strat))
101}
102
103pub(crate) async fn create_app_strategy(
104 internal_sender: &InternalSender,
105) -> Result<AppStrategyPtr, Error> {
106 let app_config = Config::get();
107 match app_config.view_mode {
108 ViewMode::Auto => {
109 const TIMEOUT: zx::MonotonicDuration = zx::MonotonicDuration::from_seconds(2);
114 let display_coordinator = match connect_to_display_provider(Some(TIMEOUT)).await {
115 Ok(provider) => {
116 DisplayCoordinator::open(provider, &app_config.virtcon_mode, &internal_sender)
117 .await
118 .ok()
119 }
120 Err(error) => {
121 eprintln!(
122 "display coordinator is not available, fall back to flatland: {}",
123 error
124 );
125 None
126 }
127 };
128 if display_coordinator.is_none() {
129 make_flatland_app_strategy()
130 } else {
131 make_direct_app_strategy(display_coordinator, app_config, internal_sender.clone())
132 }
133 }
134 ViewMode::Direct => {
135 DisplayCoordinator::watch_displays(internal_sender.clone()).await;
136 make_direct_app_strategy(None, app_config, internal_sender.clone())
137 }
138 ViewMode::Hosted => make_flatland_app_strategy(),
139 }
140}