| # Session roles and responsibilities, by example |
| |
| The session component encapsulate a product experience, within a component |
| topology. It launches all of the product-specific components (directly or |
| indirectly), manages the lifecycle of those components, and manages the flow of |
| control and information between the product-specific components (such as |
| user-facing apps) and device-specific components (such as input devices, audio, |
| and a display, if any). |
| |
| The following sections demonstrate how a session author might implement some of |
| these responsibilities. |
| |
| ## Presenting an element's view {#presenting-an-elements-view} |
| |
| In the following example, a session forwards an [`Element`'s] view to a |
| [`GraphicalPresenter`], by calling `PresentView()` with a [`ViewSpec`]. The |
| `ViewSpec` includes the duplicated [`ViewRef`] \(a sharable handle to the |
| `Element`'s View), and an optional set of initial, product-specific |
| [`Annotation`s]. |
| |
| The component that implements the Graphical Presenter role knows how to open |
| the view on a connected display. |
| |
| ```rust |
| fn present_view_for_element( |
| graphical_presenter: &GraphicalPresenterProxy, |
| element: &Element |
| ) -> Result<ViewControllerProxy, Error> { |
| let view_provider = element.connect_to_service::<ViewProviderMarker>()?; |
| let token_pair = scenic::ViewTokenPair::new()?; |
| let scenic::ViewRefPair { |
| mut control_ref, |
| mut view_ref |
| } = scenic::ViewRefPair::new()?; |
| let view_ref_dup = fuchsia_scenic::duplicate_view_ref(&view_ref)?; |
| |
| view_provider.create_view_with_view_ref( |
| token_pair.view_token.value, |
| &mut control_ref, |
| &mut view_ref, |
| )?; |
| |
| let annotations = element.get_annotations()?; |
| |
| let view_spec = ViewSpec { |
| view_holder_token: Some(token_pair.view_holder_token), |
| view_ref: Some(view_ref_dup), |
| annotations: Some(annotations), |
| ..ViewSpec::EMPTY |
| }; |
| |
| let (view_controller_proxy, server_end) = create_proxy::<ViewControllerMarker>()?; |
| graphical_presenter.present_view(view_spec, Some(server_end))?; |
| |
| Ok(view_controller_proxy) |
| } |
| ``` |
| |
| [`Annotation`s]: /docs/glossary.md#element-annotation |
| [`Element`'s]: /docs/glossary.md#element |
| [`GraphicalPresenter`]: /docs/glossary.md#graphical-presenter |
| [`ViewRef`]: /docs/glossary.md#view-ref |
| [`ViewSpec`]: /docs/glossary.md#view-spec |
| |
| ## Handling input {#handling-input} |
| |
| In the following example, if the `MouseHandler` detects a mouse-typed input |
| event, the handler sends the event to Scenic and returns an empty vector. On all |
| other types of input events, the `MouseHandler` returns a vector containing the |
| [`InputEvent`] for the next [`InputHandler`] to process. |
| |
| ```rust |
| #[async_trait] |
| impl InputHandler for MouseHandler { |
| async fn handle_input_event( |
| &mut self, |
| input_event: InputEvent, |
| ) -> Vec<InputEvent> { |
| match input_event { |
| InputEvent { |
| device_event: InputDeviceEvent::Mouse(mouse_event), |
| device_descriptor: InputDeviceDescriptor::Mouse(mouse_descriptor), |
| } => { |
| // ... Handler specific details |
| self.send_events_to_scenic(...)).await; |
| vec![] // InputEvent is consumed because it was sent to Scenic |
| } |
| _ => vec![input_event], // InputEvent is returned for the next InputHanlder |
| } |
| } |
| } |
| ``` |
| |
| [`InputEvent`]: /docs/glossary.md#input-pipeline-input-event |
| [`InputHandler`]: /docs/glossary.md#input-pipeline-input-handler |