carnelian/app/strategies/
framebuffer.rs

1// Copyright 2020 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::app::strategies::base::AppStrategy;
6use crate::app::{Config, InternalSender, MessageInternal};
7use crate::drawing::DisplayRotation;
8use crate::geometry::IntSize;
9use crate::input::report::InputReportHandler;
10use crate::input::{self, listen_for_user_input, DeviceId};
11use crate::view::strategies::base::{DisplayDirectParams, ViewStrategyParams, ViewStrategyPtr};
12use crate::view::strategies::display_direct::DisplayDirectViewStrategy;
13use crate::view::ViewKey;
14use anyhow::{anyhow, bail, Context, Error};
15use async_trait::async_trait;
16use euclid::size2;
17use fidl::endpoints::{self};
18use fidl_fuchsia_hardware_display::{
19    CoordinatorListenerMarker, CoordinatorListenerRequest, CoordinatorMarker, CoordinatorProxy,
20    ProviderOpenCoordinatorWithListenerForPrimaryRequest,
21    ProviderOpenCoordinatorWithListenerForVirtconRequest, ProviderProxy,
22    ServiceMarker as DisplayServiceMarker, VirtconMode,
23};
24use fidl_fuchsia_input_report as hid_input_report;
25use fuchsia_async::{self as fasync, DurationExt, TimeoutExt};
26use fuchsia_component::client::Service;
27use futures::channel::mpsc::UnboundedSender;
28use futures::{StreamExt, TryFutureExt};
29use keymaps::Keymap;
30use std::collections::HashMap;
31use std::fmt::Debug;
32use std::rc::Rc;
33use zx::Status;
34
35pub(crate) struct AutoRepeatContext {
36    app_sender: UnboundedSender<MessageInternal>,
37    #[allow(unused)]
38    keyboard_autorepeat_task: Option<fasync::Task<()>>,
39    repeat_interval: std::time::Duration,
40}
41
42pub(crate) trait AutoRepeatTimer {
43    fn schedule_autorepeat_timer(&mut self, device_id: &DeviceId);
44    fn continue_autorepeat_timer(&mut self, device_id: &DeviceId);
45    fn cancel_autorepeat_timer(&mut self) {}
46}
47
48impl AutoRepeatContext {
49    pub(crate) fn new(app_sender: &UnboundedSender<MessageInternal>) -> Self {
50        Self {
51            app_sender: app_sender.clone(),
52            keyboard_autorepeat_task: None,
53            repeat_interval: Config::get().keyboard_autorepeat_slow_interval,
54        }
55    }
56
57    fn schedule(&mut self, device_id: &DeviceId) {
58        let timer =
59            fasync::Timer::new(fuchsia_async::MonotonicInstant::after(self.repeat_interval.into()));
60        let app_sender = self.app_sender.clone();
61        let device_id = device_id.clone();
62        let task = fasync::Task::local(async move {
63            timer.await;
64            app_sender
65                .unbounded_send(MessageInternal::KeyboardAutoRepeat(device_id))
66                .expect("unbounded_send");
67        });
68        self.keyboard_autorepeat_task = Some(task);
69    }
70}
71
72impl AutoRepeatTimer for AutoRepeatContext {
73    fn schedule_autorepeat_timer(&mut self, device_id: &DeviceId) {
74        self.repeat_interval = Config::get().keyboard_autorepeat_slow_interval;
75        self.schedule(device_id);
76    }
77
78    fn continue_autorepeat_timer(&mut self, device_id: &DeviceId) {
79        self.repeat_interval =
80            (self.repeat_interval * 3 / 4).max(Config::get().keyboard_autorepeat_fast_interval);
81        self.schedule(device_id);
82    }
83
84    fn cancel_autorepeat_timer(&mut self) {
85        self.keyboard_autorepeat_task = None;
86    }
87}
88
89pub type CoordinatorProxyPtr = Rc<CoordinatorProxy>;
90
91/// Connects to the coordinator Provider provided by the
92/// `fuchsia.hardware.display.Service`. Watches for any available service
93/// instance for up to `timeout` (or forever if `timeout` is None).
94pub async fn connect_to_display_provider(
95    timeout: Option<zx::MonotonicDuration>,
96) -> Result<ProviderProxy, Error> {
97    let deadline = match timeout {
98        Some(timeout) => timeout.after_now(),
99        None => zx::MonotonicInstant::INFINITE.into(),
100    };
101    Service::open(DisplayServiceMarker)
102        .context("failed to open service")?
103        .watch_for_any()
104        .on_timeout(deadline, || Err(anyhow!("timed out watching for display service")))
105        .await
106        .context("failed to watch for display device")?
107        .connect_to_provider()
108        .context("failed to connect to provider")
109}
110
111pub struct DisplayCoordinator {
112    pub coordinator: CoordinatorProxyPtr,
113}
114
115impl DisplayCoordinator {
116    pub(crate) async fn open(
117        provider: ProviderProxy,
118        virtcon_mode: &Option<VirtconMode>,
119        app_sender: &UnboundedSender<MessageInternal>,
120    ) -> Result<Self, Error> {
121        let (coordinator, coordinator_server) = endpoints::create_proxy::<CoordinatorMarker>();
122        let (listener_client, mut listener_requests) =
123            endpoints::create_request_stream::<CoordinatorListenerMarker>();
124        let () = if virtcon_mode.is_some() {
125            provider
126                .open_coordinator_with_listener_for_virtcon(
127                    ProviderOpenCoordinatorWithListenerForVirtconRequest {
128                        coordinator: Some(coordinator_server),
129                        coordinator_listener: Some(listener_client),
130                        __source_breaking: fidl::marker::SourceBreaking,
131                    },
132                )
133                .await
134        } else {
135            provider
136                .open_coordinator_with_listener_for_primary(
137                    ProviderOpenCoordinatorWithListenerForPrimaryRequest {
138                        coordinator: Some(coordinator_server),
139                        coordinator_listener: Some(listener_client),
140                        __source_breaking: fidl::marker::SourceBreaking,
141                    },
142                )
143                .await
144        }
145        .context("failed to perform FIDL call")?
146        .map_err(Status::from_raw)
147        .context("failed to open display coordinator")?;
148
149        if let Some(virtcon_mode) = virtcon_mode {
150            coordinator.set_virtcon_mode(*virtcon_mode)?;
151        }
152
153        let app_sender = app_sender.clone();
154        let f = async move {
155            loop {
156                if let Some(listener_request) = listener_requests.next().await {
157                    if let Ok(listener_request) = listener_request {
158                        app_sender
159                            .unbounded_send(MessageInternal::DisplayCoordinatorListenerRequest(
160                                listener_request,
161                            ))
162                            .expect("unbounded_send");
163                    }
164                }
165            }
166        };
167        fasync::Task::local(f).detach();
168
169        Ok(Self { coordinator: Rc::new(coordinator) })
170    }
171
172    pub(crate) async fn watch_displays(app_sender: UnboundedSender<MessageInternal>) {
173        let provider = Service::open(DisplayServiceMarker)
174            .expect("open service")
175            .watch_for_any()
176            .await
177            .expect("watch for any service instance")
178            .connect_to_provider()
179            .expect("connect to provider");
180        app_sender
181            .unbounded_send(MessageInternal::NewDisplayCoordinator(provider))
182            .expect("unbounded_send");
183    }
184}
185
186pub type DisplayId = display_utils::DisplayId;
187
188#[derive(Debug)]
189pub struct DisplayInfo {
190    preferred_size: IntSize,
191    info: fidl_fuchsia_hardware_display::Info,
192}
193
194pub(crate) struct DisplayDirectAppStrategy<'a> {
195    pub display_coordinator: Option<DisplayCoordinator>,
196    pub display_rotation: DisplayRotation,
197    pub keymap: &'a Keymap<'a>,
198    pub input_report_handlers: HashMap<DeviceId, InputReportHandler<'a>>,
199    pub context: AutoRepeatContext,
200    pub app_sender: UnboundedSender<MessageInternal>,
201    pub owned: bool,
202    pub primary_display: Option<DisplayInfo>,
203    views: HashMap<DisplayId, Vec<ViewKey>>,
204}
205
206impl<'a> DisplayDirectAppStrategy<'a> {
207    pub fn new(
208        display_coordinator: Option<DisplayCoordinator>,
209        keymap: &'a Keymap<'a>,
210        app_sender: UnboundedSender<MessageInternal>,
211        app_config: &Config,
212    ) -> DisplayDirectAppStrategy<'a> {
213        DisplayDirectAppStrategy {
214            display_coordinator: display_coordinator,
215            display_rotation: app_config.display_rotation,
216            keymap,
217            input_report_handlers: HashMap::new(),
218            context: AutoRepeatContext::new(&app_sender),
219            app_sender,
220            owned: false,
221            primary_display: None,
222            views: Default::default(),
223        }
224    }
225
226    async fn handle_displays_changed(
227        &mut self,
228        added: Vec<fidl_fuchsia_hardware_display::Info>,
229        removed: Vec<fidl_fuchsia_hardware_display_types::DisplayId>,
230    ) -> Result<(), Error> {
231        let display_coordinator = self.display_coordinator.as_ref().expect("display_coordinator");
232        for display_id in removed {
233            self.views.remove(&display_id.into());
234            self.app_sender
235                .unbounded_send(MessageInternal::CloseViewsOnDisplay(display_id.into()))
236                .expect("unbounded");
237        }
238
239        for info in added {
240            // We use the preferred mode of the first display as the preferred size.
241            // This makes it more likely that input events will translate across
242            // different displays.
243            let preferred_size = self
244                .primary_display
245                .get_or_insert_with(|| {
246                    let mode = &info.modes[0];
247                    DisplayInfo {
248                        preferred_size: size2(mode.active_area.width, mode.active_area.height)
249                            .to_i32(),
250                        info: info.clone(),
251                    }
252                })
253                .preferred_size;
254            self.app_sender
255                .unbounded_send(MessageInternal::CreateView(ViewStrategyParams::DisplayDirect(
256                    DisplayDirectParams {
257                        view_key: None,
258                        coordinator: display_coordinator.coordinator.clone(),
259                        info,
260                        preferred_size,
261                    },
262                )))
263                .expect("send");
264        }
265
266        Ok(())
267    }
268}
269
270#[async_trait(?Send)]
271impl<'a> AppStrategy for DisplayDirectAppStrategy<'a> {
272    async fn create_view_strategy(
273        &mut self,
274        key: ViewKey,
275        app_sender: UnboundedSender<MessageInternal>,
276        strategy_params: ViewStrategyParams,
277    ) -> Result<ViewStrategyPtr, Error> {
278        let strategy_params = match strategy_params {
279            ViewStrategyParams::DisplayDirect(params) => params,
280            _ => bail!(
281                "Incorrect ViewStrategyParams passed to create_view_strategy for frame buffer"
282            ),
283        };
284        let views_on_display = self.views.entry(strategy_params.info.id.into()).or_default();
285        views_on_display.push(key);
286        Ok(DisplayDirectViewStrategy::new(
287            key,
288            strategy_params.coordinator,
289            app_sender.clone(),
290            strategy_params.info,
291            strategy_params.preferred_size,
292        )
293        .await?)
294    }
295
296    fn create_view_strategy_params_for_additional_view(
297        &mut self,
298        view_key: ViewKey,
299    ) -> ViewStrategyParams {
300        let primary_display = self.primary_display.as_ref().expect("primary_display");
301        ViewStrategyParams::DisplayDirect(DisplayDirectParams {
302            view_key: Some(view_key),
303            coordinator: self
304                .display_coordinator
305                .as_ref()
306                .expect("display_coordinator")
307                .coordinator
308                .clone(),
309            info: primary_display.info.clone(),
310            preferred_size: primary_display.preferred_size,
311        })
312    }
313
314    fn supports_scenic(&self) -> bool {
315        return false;
316    }
317
318    async fn post_setup(&mut self, internal_sender: &InternalSender) -> Result<(), Error> {
319        let input_report_sender = internal_sender.clone();
320        fasync::Task::local(
321            listen_for_user_input(input_report_sender)
322                .unwrap_or_else(|e: anyhow::Error| eprintln!("error: listening for input {:?}", e)),
323        )
324        .detach();
325        Ok(())
326    }
327
328    fn handle_input_report(
329        &mut self,
330        device_id: &input::DeviceId,
331        input_report: &hid_input_report::InputReport,
332    ) -> Vec<input::Event> {
333        let handler = self.input_report_handlers.get_mut(device_id).expect("input_report_handler");
334        handler.handle_input_report(device_id, input_report, &mut self.context)
335    }
336
337    fn handle_register_input_device(
338        &mut self,
339        device_id: &input::DeviceId,
340        device_descriptor: &hid_input_report::DeviceDescriptor,
341    ) {
342        let frame_buffer_size =
343            self.primary_display.as_ref().expect("primary_display").preferred_size;
344        self.input_report_handlers.insert(
345            device_id.clone(),
346            InputReportHandler::new(
347                device_id.clone(),
348                frame_buffer_size,
349                self.display_rotation,
350                device_descriptor,
351                self.keymap,
352            ),
353        );
354    }
355
356    fn handle_keyboard_autorepeat(&mut self, device_id: &input::DeviceId) -> Vec<input::Event> {
357        let handler = self.input_report_handlers.get_mut(device_id).expect("input_report_handler");
358        handler.handle_keyboard_autorepeat(device_id, &mut self.context)
359    }
360
361    async fn handle_new_display_coordinator(&mut self, provider: ProviderProxy) {
362        if self.display_coordinator.is_none() {
363            let display_coordinator =
364                DisplayCoordinator::open(provider, &Config::get().virtcon_mode, &self.app_sender)
365                    .await
366                    .expect("DisplayCoordinator::open");
367            self.display_coordinator = Some(display_coordinator);
368        }
369    }
370
371    async fn handle_display_coordinator_event(&mut self, event: CoordinatorListenerRequest) {
372        match event {
373            CoordinatorListenerRequest::OnDisplaysChanged { added, removed, control_handle: _ } => {
374                self.handle_displays_changed(added, removed)
375                    .await
376                    .expect("handle_displays_changed");
377            }
378            CoordinatorListenerRequest::OnClientOwnershipChange {
379                has_ownership,
380                control_handle: _,
381            } => {
382                self.owned = has_ownership;
383                self.app_sender
384                    .unbounded_send(MessageInternal::OwnershipChanged(has_ownership))
385                    .expect("unbounded_send");
386            }
387            CoordinatorListenerRequest::OnVsync { .. } => {
388                panic!("App strategy should not see vsync events");
389            }
390            CoordinatorListenerRequest::_UnknownMethod { ordinal, .. } => {
391                panic!("Unknown method #{:}", ordinal);
392            }
393        }
394    }
395
396    fn set_virtcon_mode(&mut self, virtcon_mode: VirtconMode) {
397        self.display_coordinator
398            .as_ref()
399            .expect("display_coordinator")
400            .coordinator
401            .set_virtcon_mode(virtcon_mode)
402            .expect("set_virtcon_mode");
403    }
404
405    fn get_focused_view_key(&self) -> Option<ViewKey> {
406        self.views.keys().next().and_then(|first_display| {
407            self.views.get(first_display).expect("first_display").last().cloned()
408        })
409    }
410
411    fn get_visible_view_key_for_display(&self, display_id: DisplayId) -> Option<ViewKey> {
412        self.views
413            .get(&display_id)
414            .and_then(|views_on_first_display| views_on_first_display.last().cloned())
415    }
416
417    fn handle_view_closed(&mut self, view_key: ViewKey) {
418        for views_on_display in self.views.values_mut() {
419            views_on_display.retain(|a_view_key| view_key != *a_view_key);
420        }
421    }
422}