| // Copyright 2018 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. |
| |
| #ifndef SRC_UI_SCENIC_LIB_GFX_ENGINE_SCENE_GRAPH_H_ |
| #define SRC_UI_SCENIC_LIB_GFX_ENGINE_SCENE_GRAPH_H_ |
| |
| #include <fuchsia/ui/focus/cpp/fidl.h> |
| #include <fuchsia/ui/views/cpp/fidl.h> |
| #include <lib/fidl/cpp/binding.h> |
| #include <lib/fidl/cpp/binding_set.h> |
| #include <lib/sys/cpp/component_context.h> |
| |
| #include <vector> |
| |
| #include "src/ui/scenic/lib/gfx/engine/view_focuser_registry.h" |
| #include "src/ui/scenic/lib/gfx/engine/view_tree.h" |
| #include "src/ui/scenic/lib/gfx/id.h" |
| #include "src/ui/scenic/lib/gfx/resources/compositor/compositor.h" |
| #include "src/ui/scenic/lib/gfx/resources/compositor/display_compositor.h" |
| |
| namespace scenic_impl { |
| namespace gfx { |
| |
| class SceneGraph; |
| using SceneGraphWeakPtr = fxl::WeakPtr<SceneGraph>; |
| |
| class View; |
| using ViewPtr = fxl::RefPtr<View>; |
| |
| // SceneGraph stores pointers to all the Compositors created with it as a constructor argument, but |
| // it does not hold ownership of them. |
| // |
| // SceneGraph is the source of truth for the tree of ViewRefs, from which a FocusChain is generated. |
| // Command processors update this tree, and the input system may read or modify the focus. |
| class SceneGraph : public fuchsia::ui::focus::FocusChainListenerRegistry, |
| public ViewFocuserRegistry { |
| public: |
| explicit SceneGraph(sys::ComponentContext* app_context); |
| |
| SceneGraphWeakPtr GetWeakPtr() { return weak_factory_.GetWeakPtr(); } |
| |
| // |
| // Compositor functions |
| // |
| |
| const std::vector<CompositorWeakPtr>& compositors() const { return compositors_; } |
| |
| // Returns the first compositor from the current compositors, or invalid |
| // WeakPtr if there are no compositors. |
| // TODO(SCN-1170): get rid of SceneGraph::first_compositor(). |
| CompositorWeakPtr first_compositor() const { |
| for (auto& compositor : compositors_) { |
| if (compositor) { |
| return compositor; |
| } |
| } |
| return Compositor::kNullWeakPtr; |
| } |
| |
| // Returns the compositor requested, or nullptr if it does not exist. |
| CompositorWeakPtr GetCompositor(GlobalId compositor_id) const; |
| |
| // |
| // View tree and focus chain functions |
| // |
| |
| // Expose view tree in a read-only manner. |
| // NOTE: Modifications are handled exclusively by SceneGraph, for correct dispatch of FIDL events. |
| const ViewTree& view_tree() const { return view_tree_; } |
| |
| // Tree topology: Enqueue transactional updates to the view tree, but do not apply them yet. |
| // Invariant: view_tree_ not modified |
| // Post: view_tree_updates_ grows by one |
| void StageViewTreeUpdates(ViewTreeUpdates updates); |
| |
| // Tree topolocy: Apply all enqueued updates to the view tree in a transactional step. |
| // Post: view_tree_ updated |
| // Post: view_tree_updates_ cleared |
| void ProcessViewTreeUpdates(); |
| |
| // Focus chain: Adjust focus in the view tree. |
| // Return kAccept if request was honored; otherwise return an error enum. |
| // Invariant: view_tree_ not modified |
| ViewTree::FocusChangeStatus RequestFocusChange(zx_koid_t requestor, zx_koid_t request); |
| |
| // |fuchsia.ui.focus.FocusChainListenerRegistry| |
| void Register( |
| fidl::InterfaceHandle<fuchsia::ui::focus::FocusChainListener> focus_chain_listener) override; |
| |
| // |
| // View functions |
| // |
| |
| // Look up the View with |view_ref| in the current scene graph; the View must |
| // already exist and attached to the scene when this function is called. |
| // |
| // Returns the ViewPtr if the View exists in scene graph; Returns nullptr, |
| // if the ViewRef doesn't refer to an existing View, or the View doesn't exist |
| // in any Scene. |
| ViewPtr LookupViewByViewRef(fuchsia::ui::views::ViewRef view_ref); |
| |
| // |
| // Focus transfer functionality |
| // |
| |
| // |ViewFocuserRegistry| |
| // A command processor, such as GFX or Flatland, may forward a view focuser to be bound here. |
| void RegisterViewFocuser( |
| SessionId session_id, |
| fidl::InterfaceRequest<fuchsia::ui::views::Focuser> view_focuser) override; |
| |
| // |ViewFocuserRegistry| |
| // Session cleanup terminates a view focuser connection and removes the binding. |
| void UnregisterViewFocuser(SessionId session_id) override; |
| |
| private: |
| // A small object that associates each Focuser request with a SessionId. |
| // Close of channel does not trigger object cleanup; instead, we rely on Session cleanup. |
| class ViewFocuserEndpoint : public fuchsia::ui::views::Focuser { |
| public: |
| ViewFocuserEndpoint(fidl::InterfaceRequest<fuchsia::ui::views::Focuser> view_focuser, |
| fit::function<void(fuchsia::ui::views::ViewRef, RequestFocusCallback)> |
| request_focus_handler); |
| ViewFocuserEndpoint(ViewFocuserEndpoint&& original); // Needed for emplace. |
| |
| // |fuchsia.ui.views.Focuser| |
| void RequestFocus(fuchsia::ui::views::ViewRef view_ref, RequestFocusCallback response) override; |
| |
| private: |
| // Capture SceneGraph* and SessionId, no explicit pointer management. |
| // Note that it does *not* capture |this|, so it's movable in the move constructor. |
| fit::function<void(fuchsia::ui::views::ViewRef, RequestFocusCallback)> request_focus_handler_; |
| fidl::Binding<fuchsia::ui::views::Focuser> endpoint_; |
| }; |
| |
| friend class Compositor; |
| |
| // SceneGraph notify us upon creation/destruction. |
| void AddCompositor(const CompositorWeakPtr& compositor); |
| void RemoveCompositor(const CompositorWeakPtr& compositor); |
| |
| // If the focus chain has changed, (1) dispatch an updated focus chain to the FocusChainListener, |
| // and (2) dispatch a FocusEvent to the clients that have gained and lost focus. |
| void MaybeDispatchFidlFocusChainAndFocusEvents(const std::vector<zx_koid_t>& old_focus_chain); |
| |
| // |
| // Fields |
| // |
| |
| std::vector<CompositorWeakPtr> compositors_; |
| |
| ViewTree view_tree_; |
| ViewTreeUpdates view_tree_updates_; |
| |
| fidl::Binding<fuchsia::ui::focus::FocusChainListenerRegistry> focus_chain_listener_registry_; |
| fuchsia::ui::focus::FocusChainListenerPtr focus_chain_listener_; |
| |
| // Lifetime of ViewFocuserEndpoint is tied to owning Session's lifetime. |
| // An early disconnect of ViewFocuserEndpoint is okay. |
| std::unordered_map<SessionId, ViewFocuserEndpoint> view_focuser_endpoints_; |
| |
| fxl::WeakPtrFactory<SceneGraph> weak_factory_; // Must be last. |
| }; |
| |
| } // namespace gfx |
| } // namespace scenic_impl |
| |
| #endif // SRC_UI_SCENIC_LIB_GFX_ENGINE_SCENE_GRAPH_H_ |