1use crate::lib::{Position, Size};
6use crate::pointerinjector_config::{
7 InjectorViewportChangeFn, InjectorViewportHangingGet, InjectorViewportPublisher,
8 InjectorViewportSpec, InjectorViewportSubscriber,
9};
10use crate::{DisplayMetrics, ViewingDistance};
11use anyhow::{Context, Error, Result};
12use async_trait::async_trait;
13use async_utils::hanging_get::server as hanging_get;
14use fidl::endpoints::{Proxy, create_proxy};
15use fidl_fuchsia_accessibility_scene as a11y_scene;
16use fidl_fuchsia_math as math;
17use fidl_fuchsia_ui_app as ui_app;
18use fidl_fuchsia_ui_composition::{self as ui_comp, ContentId, TransformId};
19use fidl_fuchsia_ui_display_singleton as singleton_display;
20use fidl_fuchsia_ui_pointerinjector_configuration::{
21 SetupRequest as PointerInjectorConfigurationSetupRequest,
22 SetupRequestStream as PointerInjectorConfigurationSetupRequestStream,
23};
24use fidl_fuchsia_ui_views as ui_views;
25use flatland_frame_scheduling_lib::*;
26use fuchsia_async::{self as fasync, TimeoutExt};
27use fuchsia_scenic as scenic;
28use fuchsia_trace as trace;
29use futures::channel::mpsc::{UnboundedReceiver, UnboundedSender, unbounded};
30use futures::channel::oneshot;
31use futures::prelude::*;
32use log::{error, info, warn};
33use math as fmath;
34use std::cell::{Cell, RefCell};
35use std::collections::VecDeque;
36use std::ffi::CStr;
37use std::process;
38use std::rc::Rc;
39use std::sync::{Arc, Weak};
40use zx;
41
42pub enum PresentationMessage {
44 RequestPresent,
46 RequestPresentWithPingback(oneshot::Sender<()>),
49}
50
51pub type PresentationSender = UnboundedSender<PresentationMessage>;
53
54pub type PresentationReceiver = UnboundedReceiver<PresentationMessage>;
56
57const _CURSOR_SIZE: (u32, u32) = (18, 29);
58const CURSOR_HOTSPOT: (u32, u32) = (2, 4);
59
60const CURSOR_SCALE_MULTIPLIER: u32 = 5;
63const CURSOR_SCALE_DIVIDER: u32 = 4;
64
65const DEFAULT_VIEW_CONNECTION_TIMEOUT: zx::MonotonicDuration =
66 zx::MonotonicDuration::from_seconds(15);
67
68fn physical_cursor_size(value: u32) -> u32 {
70 (CURSOR_SCALE_MULTIPLIER * value) / CURSOR_SCALE_DIVIDER
71}
72
73pub type FlatlandPtr = Arc<ui_comp::FlatlandProxy>;
74
75#[derive(Clone)]
76struct TransformContentIdPair {
77 transform_id: TransformId,
78 content_id: ContentId,
79}
80
81struct FlatlandInstance {
86 flatland: FlatlandPtr,
87 view_ref: ui_views::ViewRef,
88 root_transform_id: TransformId,
89 parent_viewport_watcher: ui_comp::ParentViewportWatcherProxy,
90 focuser: ui_views::FocuserProxy,
91}
92
93impl FlatlandInstance {
94 fn new(
95 flatland: ui_comp::FlatlandProxy,
96 view_creation_token: ui_views::ViewCreationToken,
97 id_generator: &mut scenic::flatland::IdGenerator,
98 ) -> Result<FlatlandInstance, Error> {
99 let (parent_viewport_watcher, parent_viewport_watcher_request) =
100 create_proxy::<ui_comp::ParentViewportWatcherMarker>();
101
102 let (focuser, focuser_request) = create_proxy::<ui_views::FocuserMarker>();
103
104 let view_bound_protocols = ui_comp::ViewBoundProtocols {
105 view_focuser: Some(focuser_request),
106 ..Default::default()
107 };
108
109 let view_identity = ui_views::ViewIdentityOnCreation::from(scenic::ViewRefPair::new()?);
110 let view_ref = scenic::duplicate_view_ref(&view_identity.view_ref)?;
111 flatland.create_view2(
112 view_creation_token,
113 view_identity,
114 view_bound_protocols,
115 parent_viewport_watcher_request,
116 )?;
117
118 let root_transform_id = id_generator.next_transform_id();
119 flatland.create_transform(&root_transform_id)?;
120 flatland.set_root_transform(&root_transform_id)?;
121 flatland.set_hit_regions(&root_transform_id, &[])?;
122
123 Ok(FlatlandInstance {
124 flatland: Arc::new(flatland),
125 view_ref,
126 root_transform_id,
127 parent_viewport_watcher,
128 focuser,
129 })
130 }
131}
132
133fn request_present_with_pingback(
134 presentation_sender: &PresentationSender,
135) -> Result<oneshot::Receiver<()>, Error> {
136 let (sender, receiver) = oneshot::channel::<()>();
137 presentation_sender.unbounded_send(PresentationMessage::RequestPresentWithPingback(sender))?;
138 Ok(receiver)
139}
140
141async fn setup_child_view(
142 parent_flatland: &FlatlandInstance,
143 viewport_creation_token: scenic::flatland::ViewportCreationToken,
144 id_generator: &mut scenic::flatland::IdGenerator,
145 client_viewport_size: math::SizeU,
146) -> Result<ui_comp::ChildViewWatcherProxy, Error> {
147 let child_viewport_transform_id = id_generator.next_transform_id();
148 let child_viewport_content_id = id_generator.next_content_id();
149
150 let (child_view_watcher, child_view_watcher_request) =
151 create_proxy::<ui_comp::ChildViewWatcherMarker>();
152
153 {
154 let flatland = &parent_flatland.flatland;
155 flatland.create_transform(&child_viewport_transform_id)?;
156 flatland.add_child(&parent_flatland.root_transform_id, &child_viewport_transform_id)?;
157
158 let link_properties = ui_comp::ViewportProperties {
159 logical_size: Some(client_viewport_size),
160 ..Default::default()
161 };
162
163 flatland.create_viewport(
164 &child_viewport_content_id,
165 viewport_creation_token,
166 &link_properties,
167 child_view_watcher_request,
168 )?;
169 flatland.set_content(&child_viewport_transform_id, &child_viewport_content_id)?;
170 }
171
172 Ok(child_view_watcher)
173}
174
175pub struct SceneManager {
222 _display: ui_comp::FlatlandDisplayProxy,
224
225 client_viewport_size: math::SizeU,
228
229 root_flatland: FlatlandInstance,
234
235 _pointerinjector_flatland: FlatlandInstance,
244
245 scene_flatland: FlatlandInstance,
249
250 context_view_ref: ui_views::ViewRef,
253 target_view_ref: ui_views::ViewRef,
254
255 root_flatland_presentation_sender: PresentationSender,
257 _pointerinjector_flatland_presentation_sender: PresentationSender,
258 scene_flatland_presentation_sender: PresentationSender,
259
260 scene_root_viewport_ids: RefCell<Option<TransformContentIdPair>>,
264
265 id_generator: RefCell<scenic::flatland::IdGenerator>,
268
269 viewport_hanging_get: Rc<RefCell<InjectorViewportHangingGet>>,
272
273 _viewport_publisher: Rc<RefCell<InjectorViewportPublisher>>,
276
277 cursor_transform_id: Option<TransformId>,
279
280 cursor_visibility: Cell<bool>,
282
283 display_metrics: DisplayMetrics,
285
286 device_pixel_ratio: f32,
290
291 set_root_view_lock: futures::lock::Mutex<()>,
293}
294
295#[async_trait(?Send)]
310pub trait SceneManagerTrait {
311 async fn set_root_view(
317 &self,
318 viewport_creation_token: ui_views::ViewportCreationToken,
319 view_ref: Option<ui_views::ViewRef>,
320 ) -> Result<(), Error>;
321
322 async fn set_root_view_deprecated(
327 &self,
328 view_provider: ui_app::ViewProviderProxy,
329 ) -> Result<ui_views::ViewRef, Error>;
330
331 fn present_root_view(&self);
333
334 fn set_cursor_position(&self, position_physical_px: Position);
346
347 fn set_cursor_visibility(&self, visible: bool);
352
353 fn get_pointerinjection_view_refs(&self) -> (ui_views::ViewRef, ui_views::ViewRef);
355
356 fn get_pointerinjection_display_size(&self) -> crate::lib::Size;
359
360 fn get_pointerinjector_viewport_watcher_subscription(&self) -> InjectorViewportSubscriber;
363
364 fn get_display_metrics(&self) -> &DisplayMetrics;
365}
366
367#[async_trait(?Send)]
368impl SceneManagerTrait for SceneManager {
369 async fn set_root_view(
375 &self,
376 viewport_creation_token: ui_views::ViewportCreationToken,
377 _view_ref: Option<ui_views::ViewRef>,
378 ) -> Result<(), Error> {
379 let _guard = self.set_root_view_lock.lock().await;
380 self.set_root_view_internal(viewport_creation_token).await.map(|_view_ref| {})
381 }
382
383 async fn set_root_view_deprecated(
388 &self,
389 view_provider: ui_app::ViewProviderProxy,
390 ) -> Result<ui_views::ViewRef, Error> {
391 let _guard = self.set_root_view_lock.lock().await;
392 let link_token_pair = scenic::flatland::ViewCreationTokenPair::new()?;
393
394 view_provider.create_view2(ui_app::CreateView2Args {
397 view_creation_token: Some(link_token_pair.view_creation_token),
398 ..Default::default()
399 })?;
400
401 self.set_root_view_internal(link_token_pair.viewport_creation_token).await
402 }
403
404 fn present_root_view(&self) {
406 self.root_flatland_presentation_sender
407 .unbounded_send(PresentationMessage::RequestPresent)
408 .expect("send failed");
409 }
410
411 fn get_pointerinjection_view_refs(&self) -> (ui_views::ViewRef, ui_views::ViewRef) {
413 (
414 scenic::duplicate_view_ref(&self.context_view_ref).expect("failed to copy ViewRef"),
415 scenic::duplicate_view_ref(&self.target_view_ref).expect("failed to copy ViewRef"),
416 )
417 }
418
419 fn set_cursor_position(&self, position_physical_px: Position) {
431 if let Some(cursor_transform_id) = self.cursor_transform_id {
432 let position_logical = position_physical_px / self.device_pixel_ratio;
433 let x =
434 position_logical.x.round() as i32 - physical_cursor_size(CURSOR_HOTSPOT.0) as i32;
435 let y =
436 position_logical.y.round() as i32 - physical_cursor_size(CURSOR_HOTSPOT.1) as i32;
437 self.root_flatland
438 .flatland
439 .set_translation(&cursor_transform_id, &fmath::Vec_ { x, y })
440 .expect("fidl error");
441 self.root_flatland_presentation_sender
442 .unbounded_send(PresentationMessage::RequestPresent)
443 .expect("send failed");
444 }
445 }
446
447 fn set_cursor_visibility(&self, visible: bool) {
452 if let Some(cursor_transform_id) = self.cursor_transform_id {
453 if self.cursor_visibility.get() != visible {
454 self.cursor_visibility.set(visible);
455 let flatland = &self.root_flatland.flatland;
456 if visible {
457 flatland
458 .add_child(&self.root_flatland.root_transform_id, &cursor_transform_id)
459 .expect("failed to add cursor to scene");
460 } else {
461 flatland
462 .remove_child(&self.root_flatland.root_transform_id, &cursor_transform_id)
463 .expect("failed to remove cursor from scene");
464 }
465 self.root_flatland_presentation_sender
466 .unbounded_send(PresentationMessage::RequestPresent)
467 .expect("send failed");
468 }
469 }
470 }
471
472 fn get_pointerinjection_display_size(&self) -> Size {
475 self.display_metrics.size_in_pixels()
477 }
478
479 fn get_pointerinjector_viewport_watcher_subscription(&self) -> InjectorViewportSubscriber {
482 self.viewport_hanging_get.borrow_mut().new_subscriber()
483 }
484
485 fn get_display_metrics(&self) -> &DisplayMetrics {
486 &self.display_metrics
487 }
488}
489
490const ROOT_VIEW_DEBUG_NAME: &str = "SceneManager Display";
491const POINTER_INJECTOR_DEBUG_NAME: &str = "SceneManager PointerInjector";
492const SCENE_DEBUG_NAME: &str = "SceneManager Scene";
493const ROOT_VIEW_PRESENT_TRACING_NAME: &CStr = c"Flatland::PerAppPresent[SceneManager Display]";
494const POINTER_INJECTOR_PRESENT_TRACING_NAME: &CStr =
495 c"Flatland::PerAppPresent[SceneManager PointerInjector]";
496const SCENE_TRACING_NAME: &CStr = c"Flatland::PerAppPresent[SceneManager Scene]";
497
498impl SceneManager {
499 #[allow(clippy::vec_init_then_push, reason = "mass allow for https://fxbug.dev/381896734")]
500 pub async fn new(
501 display: ui_comp::FlatlandDisplayProxy,
502 singleton_display_info: singleton_display::InfoProxy,
503 root_flatland: ui_comp::FlatlandProxy,
504 pointerinjector_flatland: ui_comp::FlatlandProxy,
505 scene_flatland: ui_comp::FlatlandProxy,
506 a11y_view_provider: Option<a11y_scene::ProviderProxy>,
507 display_rotation: u64,
508 display_pixel_density: Option<f32>,
509 viewing_distance: Option<ViewingDistance>,
510 ) -> Result<Self, Error> {
511 start_exit_on_scenic_closed_task(display.clone());
514
515 let mut id_generator = scenic::flatland::IdGenerator::new();
516
517 let pointerinjector_viewport_transform_id = id_generator.next_transform_id();
520 let pointerinjector_viewport_content_id = id_generator.next_content_id();
521
522 root_flatland.set_debug_name(ROOT_VIEW_DEBUG_NAME)?;
523 pointerinjector_flatland.set_debug_name(POINTER_INJECTOR_DEBUG_NAME)?;
524 scene_flatland.set_debug_name(SCENE_DEBUG_NAME)?;
525
526 let root_view_creation_pair = scenic::flatland::ViewCreationTokenPair::new()?;
527 let root_flatland = FlatlandInstance::new(
528 root_flatland,
529 root_view_creation_pair.view_creation_token,
530 &mut id_generator,
531 )?;
532
533 let pointerinjector_view_creation_pair = scenic::flatland::ViewCreationTokenPair::new()?;
534 let pointerinjector_flatland = FlatlandInstance::new(
535 pointerinjector_flatland,
536 pointerinjector_view_creation_pair.view_creation_token,
537 &mut id_generator,
538 )?;
539
540 let scene_view_creation_pair = scenic::flatland::ViewCreationTokenPair::new()?;
541 let scene_flatland = FlatlandInstance::new(
542 scene_flatland,
543 scene_view_creation_pair.view_creation_token,
544 &mut id_generator,
545 )?;
546
547 let info = singleton_display_info.get_metrics().await?;
549 let extent_in_px =
550 info.extent_in_px.ok_or_else(|| anyhow::anyhow!("Did not receive display size"))?;
551 let display_metrics = DisplayMetrics::new(
552 Size { width: extent_in_px.width as f32, height: extent_in_px.height as f32 },
553 display_pixel_density,
554 viewing_distance,
555 None,
556 );
557
558 display.set_device_pixel_ratio(&fmath::VecF {
559 x: display_metrics.pixels_per_pip(),
560 y: display_metrics.pixels_per_pip(),
561 })?;
562
563 {
565 let (_, child_view_watcher_request) = create_proxy::<ui_comp::ChildViewWatcherMarker>();
568
569 display.set_content(
570 root_view_creation_pair.viewport_creation_token,
571 child_view_watcher_request,
572 )?;
573 }
574
575 let layout_info = root_flatland.parent_viewport_watcher.get_layout().await?;
578 let root_viewport_size = layout_info
579 .logical_size
580 .ok_or_else(|| anyhow::anyhow!("Did not receive layout info from the display"))?;
581
582 let (
583 display_rotation_enum,
584 injector_viewport_translation,
585 flip_injector_viewport_dimensions,
586 ) = match display_rotation % 360 {
587 0 => Ok((ui_comp::Orientation::Ccw0Degrees, math::Vec_ { x: 0, y: 0 }, false)),
588 90 => Ok((
589 ui_comp::Orientation::Ccw270Degrees,
593 math::Vec_ { x: root_viewport_size.width as i32, y: 0 },
594 true,
595 )),
596 180 => Ok((
597 ui_comp::Orientation::Ccw180Degrees,
598 math::Vec_ {
599 x: root_viewport_size.width as i32,
600 y: root_viewport_size.height as i32,
601 },
602 false,
603 )),
604 270 => Ok((
605 ui_comp::Orientation::Ccw90Degrees,
609 math::Vec_ { x: 0, y: root_viewport_size.height as i32 },
610 true,
611 )),
612 _ => Err(anyhow::anyhow!("Invalid display rotation; must be {{0,90,180,270}}")),
613 }?;
614 let client_viewport_size = match flip_injector_viewport_dimensions {
615 true => {
616 math::SizeU { width: root_viewport_size.height, height: root_viewport_size.width }
617 }
618 false => {
619 math::SizeU { width: root_viewport_size.width, height: root_viewport_size.height }
620 }
621 };
622
623 {
625 let flatland = &root_flatland.flatland;
626 flatland.create_transform(&pointerinjector_viewport_transform_id)?;
627 flatland.add_child(
628 &root_flatland.root_transform_id,
629 &pointerinjector_viewport_transform_id,
630 )?;
631 flatland
632 .set_orientation(&pointerinjector_viewport_transform_id, display_rotation_enum)?;
633 flatland.set_translation(
634 &pointerinjector_viewport_transform_id,
635 &injector_viewport_translation,
636 )?;
637
638 let link_properties = ui_comp::ViewportProperties {
639 logical_size: Some(client_viewport_size),
640 ..Default::default()
641 };
642
643 let (_, child_view_watcher_request) = create_proxy::<ui_comp::ChildViewWatcherMarker>();
644
645 flatland.create_viewport(
646 &pointerinjector_viewport_content_id,
647 pointerinjector_view_creation_pair.viewport_creation_token,
648 &link_properties,
649 child_view_watcher_request,
650 )?;
651 flatland.set_content(
652 &pointerinjector_viewport_transform_id,
653 &pointerinjector_viewport_content_id,
654 )?;
655 }
656
657 let mut a11y_view_watcher: Option<ui_comp::ChildViewWatcherProxy> = None;
658 match a11y_view_provider {
659 Some(a11y_view_provider) => {
660 let a11y_view_creation_pair = scenic::flatland::ViewCreationTokenPair::new()?;
661
662 a11y_view_watcher = Some(
664 setup_child_view(
665 &pointerinjector_flatland,
666 a11y_view_creation_pair.viewport_creation_token,
667 &mut id_generator,
668 client_viewport_size,
669 )
670 .await?,
671 );
672
673 a11y_view_provider.create_view(
675 a11y_view_creation_pair.view_creation_token,
676 scene_view_creation_pair.viewport_creation_token,
677 )?;
678 }
679 None => {
680 let _ = setup_child_view(
682 &pointerinjector_flatland,
683 scene_view_creation_pair.viewport_creation_token,
684 &mut id_generator,
685 client_viewport_size,
686 )
687 .await?;
688 }
689 }
690
691 let (root_flatland_presentation_sender, root_receiver) = unbounded();
693 start_flatland_presentation_loop(
694 root_receiver,
695 Arc::downgrade(&root_flatland.flatland),
696 ROOT_VIEW_DEBUG_NAME.to_string(),
697 );
698 let (pointerinjector_flatland_presentation_sender, pointerinjector_receiver) = unbounded();
699 start_flatland_presentation_loop(
700 pointerinjector_receiver,
701 Arc::downgrade(&pointerinjector_flatland.flatland),
702 POINTER_INJECTOR_DEBUG_NAME.to_string(),
703 );
704 let (scene_flatland_presentation_sender, scene_receiver) = unbounded();
705 start_flatland_presentation_loop(
706 scene_receiver,
707 Arc::downgrade(&scene_flatland.flatland),
708 SCENE_DEBUG_NAME.to_string(),
709 );
710
711 let mut pingback_channels = Vec::new();
712 pingback_channels.push(request_present_with_pingback(&root_flatland_presentation_sender)?);
713 pingback_channels
714 .push(request_present_with_pingback(&pointerinjector_flatland_presentation_sender)?);
715 pingback_channels.push(request_present_with_pingback(&scene_flatland_presentation_sender)?);
716
717 if let Some(a11y_view_watcher) = a11y_view_watcher {
718 let a11y_view_status = a11y_view_watcher.get_status().await?;
720 match a11y_view_status {
721 ui_comp::ChildViewStatus::ContentHasPresented => {}
722 }
723 }
724
725 let device_pixel_ratio = display_metrics.pixels_per_pip();
727 let viewport_hanging_get: Rc<RefCell<InjectorViewportHangingGet>> =
728 create_viewport_hanging_get({
729 InjectorViewportSpec {
730 width: display_metrics.width_in_pixels() as f32,
731 height: display_metrics.height_in_pixels() as f32,
732 scale: 1. / device_pixel_ratio,
733 x_offset: 0.,
734 y_offset: 0.,
735 }
736 });
737 let viewport_publisher =
738 Rc::new(RefCell::new(viewport_hanging_get.borrow_mut().new_publisher()));
739
740 let context_view_ref = scenic::duplicate_view_ref(&root_flatland.view_ref)?;
741 let target_view_ref = scenic::duplicate_view_ref(&pointerinjector_flatland.view_ref)?;
742
743 for receiver in pingback_channels {
745 _ = receiver.await;
746 }
747
748 Ok(SceneManager {
749 _display: display,
750 client_viewport_size,
751 root_flatland,
752 _pointerinjector_flatland: pointerinjector_flatland,
753 scene_flatland,
754 context_view_ref,
755 target_view_ref,
756 root_flatland_presentation_sender,
757 _pointerinjector_flatland_presentation_sender:
758 pointerinjector_flatland_presentation_sender,
759 scene_flatland_presentation_sender,
760 scene_root_viewport_ids: RefCell::new(None),
761 id_generator: RefCell::new(id_generator),
762 viewport_hanging_get,
763 _viewport_publisher: viewport_publisher,
764 cursor_transform_id: None,
765 cursor_visibility: Cell::new(true),
766 display_metrics,
767 device_pixel_ratio,
768 set_root_view_lock: futures::lock::Mutex::new(()),
769 })
770 }
771
772 async fn set_root_view_internal(
773 &self,
774 viewport_creation_token: ui_views::ViewportCreationToken,
775 ) -> Result<ui_views::ViewRef> {
776 {
778 let mut scene_root_viewport_ids = self.scene_root_viewport_ids.borrow_mut();
779 if let Some(ids) = &*scene_root_viewport_ids {
780 let flatland = &self.scene_flatland.flatland;
781 flatland
782 .set_content(&ids.transform_id, &ContentId { value: 0 })
783 .context("could not set content")?;
784 flatland.remove_child(&self.scene_flatland.root_transform_id, &ids.transform_id)?;
785 flatland
786 .release_transform(&ids.transform_id)
787 .context("could not release transform")?;
788 let _ = flatland.release_viewport(&ids.content_id);
789 }
790 *scene_root_viewport_ids = None;
791 }
792
793 let ids = {
795 let mut id_generator = self.id_generator.borrow_mut();
796 TransformContentIdPair {
797 transform_id: id_generator.next_transform_id(),
798 content_id: id_generator.next_content_id(),
799 }
800 };
801 let (child_view_watcher, child_view_watcher_request) =
802 create_proxy::<ui_comp::ChildViewWatcherMarker>();
803 {
804 let flatland = &self.scene_flatland.flatland;
805 let viewport_properties = ui_comp::ViewportProperties {
806 logical_size: Some(self.client_viewport_size),
807 ..Default::default()
808 };
809 flatland.create_viewport(
810 &ids.content_id,
811 viewport_creation_token,
812 &viewport_properties,
813 child_view_watcher_request,
814 )?;
815 flatland.create_transform(&ids.transform_id).context("could not create transform")?;
816 flatland.add_child(&self.scene_flatland.root_transform_id, &ids.transform_id)?;
817 flatland
818 .set_content(&ids.transform_id, &ids.content_id)
819 .context("could not set content #2")?;
820 }
821 *self.scene_root_viewport_ids.borrow_mut() = Some(ids);
822
823 let mut pingback_channels = Vec::new();
827 pingback_channels.push(
828 request_present_with_pingback(&self.scene_flatland_presentation_sender)
829 .context("could not request present with pingback")?,
830 );
831
832 let _child_status = child_view_watcher
833 .get_status()
834 .on_timeout(fasync::MonotonicInstant::after(DEFAULT_VIEW_CONNECTION_TIMEOUT), || {
835 make_timeout_error("fuchsia.ui.composition.ChildViewWatcher")
836 })
837 .await
838 .context("could not call get_status")?;
839 let child_view_ref = child_view_watcher
840 .get_view_ref()
841 .on_timeout(fasync::MonotonicInstant::after(DEFAULT_VIEW_CONNECTION_TIMEOUT), || {
842 make_timeout_error("fuchsia.ui.composition.ChildViewWatcher")
843 })
844 .await
845 .context("could not get view_ref")?;
846 let child_view_ref_copy =
847 scenic::duplicate_view_ref(&child_view_ref).context("could not duplicate view_ref")?;
848
849 let request_focus_result = self
850 .root_flatland
851 .focuser
852 .request_focus(child_view_ref)
853 .on_timeout(fasync::MonotonicInstant::after(DEFAULT_VIEW_CONNECTION_TIMEOUT), || {
854 make_timeout_error("fuchsia.ui.views.Focuser")
855 })
856 .await;
857 match request_focus_result {
858 Err(e) => warn!("Request focus failed with err: {}", e),
859 Ok(Err(value)) => warn!("Request focus failed with err: {:?}", value),
860 Ok(_) => {}
861 }
862 pingback_channels.push(
863 request_present_with_pingback(&self.root_flatland_presentation_sender)
864 .context("could not request present with pingback #2")?,
865 );
866
867 for receiver in pingback_channels {
869 _ = receiver.await;
870 }
871
872 Ok(child_view_ref_copy)
873 }
874}
875
876fn make_timeout_error<T>(protocol_name: &'static str) -> Result<T, fidl::Error> {
877 Err(fidl::Error::ClientChannelClosed {
878 status: zx::Status::TIMED_OUT,
879 protocol_name,
880 epitaph: None,
881 })
882}
883
884pub fn create_viewport_hanging_get(
885 initial_spec: InjectorViewportSpec,
886) -> Rc<RefCell<InjectorViewportHangingGet>> {
887 let notify_fn: InjectorViewportChangeFn = Box::new(|viewport_spec, responder| {
888 if let Err(fidl_error) = responder.send(&(*viewport_spec).into()) {
889 info!("Viewport hanging get notification, FIDL error: {}", fidl_error);
890 }
891 true
893 });
894
895 Rc::new(RefCell::new(hanging_get::HangingGet::new(initial_spec, notify_fn)))
896}
897
898pub fn start_exit_on_scenic_closed_task(flatland_proxy: ui_comp::FlatlandDisplayProxy) {
899 fasync::Task::local(async move {
900 let _ = flatland_proxy.on_closed().await;
901 info!("Scenic died, closing SceneManager too.");
902 process::exit(1);
903 })
904 .detach()
905}
906
907pub fn start_flatland_presentation_loop(
908 mut receiver: PresentationReceiver,
909 weak_flatland: Weak<ui_comp::FlatlandProxy>,
910 debug_name: String,
911) {
912 fasync::Task::local(async move {
913 let mut present_count = 0;
914 let scheduler = ThroughputScheduler::new();
915 let mut flatland_event_stream = {
916 if let Some(flatland) = weak_flatland.upgrade() {
917 flatland.take_event_stream()
918 } else {
919 warn!(
920 "Failed to upgrade Flatand weak ref; exiting presentation loop for {debug_name}"
921 );
922 return;
923 }
924 };
925
926 let mut channels_awaiting_pingback = VecDeque::from([Vec::new()]);
927
928 loop {
929 futures::select! {
930 message = receiver.next() => {
931 match message {
932 Some(PresentationMessage::RequestPresent) => {
933 scheduler.request_present();
934 }
935 Some(PresentationMessage::RequestPresentWithPingback(channel)) => {
936 channels_awaiting_pingback.back_mut().unwrap().push(channel);
937 scheduler.request_present();
938 }
939 None => {}
940 }
941 }
942 flatland_event = flatland_event_stream.next() => {
943 match flatland_event {
944 Some(Ok(ui_comp::FlatlandEvent::OnNextFrameBegin{ values })) => {
945 trace::duration!("scene_manager", "SceneManager::OnNextFrameBegin",
946 "debug_name" => &*debug_name);
947 let credits = values
948 .additional_present_credits
949 .expect("Present credits must exist");
950 let infos = values
951 .future_presentation_infos
952 .expect("Future presentation infos must exist")
953 .iter()
954 .map(
955 |x| PresentationInfo{
956 latch_point: zx::MonotonicInstant::from_nanos(x.latch_point.unwrap()),
957 presentation_time: zx::MonotonicInstant::from_nanos(
958 x.presentation_time.unwrap())
959 })
960 .collect();
961 scheduler.on_next_frame_begin(credits, infos);
962 }
963 Some(Ok(ui_comp::FlatlandEvent::OnFramePresented{ frame_presented_info })) => {
964 trace::duration!("scene_manager", "SceneManager::OnFramePresented",
965 "debug_name" => &*debug_name);
966 let actual_presentation_time =
967 zx::MonotonicInstant::from_nanos(frame_presented_info.actual_presentation_time);
968 let presented_infos: Vec<PresentedInfo> =
969 frame_presented_info.presentation_infos
970 .into_iter()
971 .map(|x| x.into())
972 .collect();
973
974 for _ in 0..presented_infos.len() {
977 for channel in channels_awaiting_pingback.pop_back().unwrap() {
978 _ = channel.send(());
979 }
980 }
981
982 scheduler.on_frame_presented(actual_presentation_time, presented_infos);
983 }
984 Some(Ok(ui_comp::FlatlandEvent::OnError{ error })) => {
985 error!(
986 "Received FlatlandError code: {}; exiting listener loop for {debug_name}",
987 error.into_primitive()
988 );
989 return;
990 }
991 _ => {}
992 }
993 }
994 present_parameters = scheduler.wait_to_update().fuse() => {
995 trace::duration!("scene_manager", "SceneManager::Present",
996 "debug_name" => &*debug_name);
997
998 match debug_name.as_str() {
999 ROOT_VIEW_DEBUG_NAME => {
1000 trace::flow_begin!("gfx", ROOT_VIEW_PRESENT_TRACING_NAME, present_count.into());
1001 }
1002 POINTER_INJECTOR_DEBUG_NAME => {
1003 trace::flow_begin!("gfx", POINTER_INJECTOR_PRESENT_TRACING_NAME, present_count.into());
1004 }
1005 SCENE_DEBUG_NAME => {
1006 trace::flow_begin!("gfx", SCENE_TRACING_NAME, present_count.into());
1007 }
1008 _ => {
1009 warn!("SceneManager::Present with unknown debug_name {:?}", debug_name);
1010 }
1011 }
1012 present_count += 1;
1013 channels_awaiting_pingback.push_front(Vec::new());
1014 if let Some(flatland) = weak_flatland.upgrade() {
1015 flatland
1016 .present(present_parameters.into())
1017 .expect("Present failed for {debug_name}");
1018 } else {
1019 warn!(
1020 "Failed to upgrade Flatand weak ref; exiting listener loop for {debug_name}"
1021 );
1022 return;
1023 }
1024 }
1025 }
1026 }})
1027 .detach()
1028}
1029
1030pub fn handle_pointer_injector_configuration_setup_request_stream(
1031 mut request_stream: PointerInjectorConfigurationSetupRequestStream,
1032 scene_manager: Rc<dyn SceneManagerTrait>,
1033) {
1034 fasync::Task::local(async move {
1035 let subscriber = scene_manager.get_pointerinjector_viewport_watcher_subscription();
1036
1037 loop {
1038 let request = request_stream.try_next().await;
1039 match request {
1040 Ok(Some(PointerInjectorConfigurationSetupRequest::GetViewRefs { responder })) => {
1041 let (context_view_ref, target_view_ref) =
1042 scene_manager.get_pointerinjection_view_refs();
1043 if let Err(e) = responder.send(context_view_ref, target_view_ref) {
1044 warn!("Failed to send GetViewRefs() response: {}", e);
1045 }
1046 }
1047 Ok(Some(PointerInjectorConfigurationSetupRequest::WatchViewport { responder })) => {
1048 if let Err(e) = subscriber.register(responder) {
1049 warn!("Failed to register WatchViewport() subscriber: {}", e);
1050 }
1051 }
1052 Ok(None) => {
1053 return;
1054 }
1055 Err(e) => {
1056 error!("Error obtaining SetupRequest: {}", e);
1057 return;
1058 }
1059 }
1060 }
1061 })
1062 .detach()
1063}