blob: cb6716e9bd70d69e1867f79cffe2ce4ee9f36c5b [file] [log] [blame]
// Copyright 2015 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 GARNET_BIN_UI_ROOT_PRESENTER_PRESENTATION_H_
#define GARNET_BIN_UI_ROOT_PRESENTER_PRESENTATION_H_
#include <map>
#include <memory>
#include <fuchsia/math/cpp/fidl.h>
#include <fuchsia/ui/input/cpp/fidl.h>
#include <lib/fit/function.h>
#include <fuchsia/ui/policy/cpp/fidl.h>
#include <fuchsia/ui/views_v1/cpp/fidl.h>
#include "garnet/bin/ui/presentation_mode/detector.h"
#include "garnet/bin/ui/root_presenter/display_rotater.h"
#include "garnet/bin/ui/root_presenter/display_size_switcher.h"
#include "garnet/bin/ui/root_presenter/display_usage_switcher.h"
#include "garnet/bin/ui/root_presenter/displays/display_metrics.h"
#include "garnet/bin/ui/root_presenter/displays/display_model.h"
#include "garnet/bin/ui/root_presenter/perspective_demo_mode.h"
#include "garnet/bin/ui/root_presenter/presentation_switcher.h"
#include "garnet/bin/ui/root_presenter/renderer_params.h"
#include "lib/fidl/cpp/binding.h"
#include "lib/fxl/macros.h"
#include "lib/fxl/memory/weak_ptr.h"
#include "lib/ui/input/device_state.h"
#include "lib/ui/input/input_device_impl.h"
#include "lib/ui/scenic/client/resources.h"
#if defined(countof)
// Workaround for compiler error due to Zircon defining countof() as a macro.
// Redefines countof() using GLM_COUNTOF(), which currently provides a more
// sophisticated implementation anyway.
#undef countof
#include <glm/glm.hpp>
#define countof(X) GLM_COUNTOF(X)
#else
// No workaround required.
#include <glm/glm.hpp>
#endif
namespace root_presenter {
// This class creates a view tree and sets up rendering of a new scene to
// display the graphical content of the view passed to |PresentScene()|. It
// also wires up input dispatch and manages the mouse cursor.
//
// The view tree consists of a root view which is implemented by this class
// and which has the presented (content) view as its child.
//
// The scene's node tree has the following structure:
// + Scene
// + RootViewHost
// + link: root_view_host_import_token
// + RootView's view manager stub
// + link: root_view_parent_export_token
// + RootView
// + link: content_view_host_import_token
// + child: ContentViewHost
// + link: Content view's actual content
// + child: cursor 1
// + child: cursor N
class Presentation : private ::fuchsia::ui::views_v1::ViewTreeListener,
private ::fuchsia::ui::views_v1::ViewListener,
private ::fuchsia::ui::views_v1::ViewContainerListener,
private fuchsia::ui::policy::Presentation {
public:
// Callback when the presentation yields to the next/previous one.
using YieldCallback = fit::function<void(bool yield_to_next)>;
// Callback when the presentation is shut down.
using ShutdownCallback = fit::closure;
Presentation(::fuchsia::ui::views_v1::ViewManager* view_manager,
fuchsia::ui::scenic::Scenic* scenic,
scenic_lib::Session* session, RendererParams renderer_params);
~Presentation() override;
// Present the specified view.
// Invokes the callback if an error occurs.
// This method must be called at most once for the lifetime of the
// presentation.
void Present(
::fuchsia::ui::views_v1_token::ViewOwnerPtr view_owner,
fidl::InterfaceRequest<fuchsia::ui::policy::Presentation> presentation_request,
YieldCallback yield_callback, ShutdownCallback shutdown_callback);
void OnReport(uint32_t device_id, fuchsia::ui::input::InputReport report);
void OnDeviceAdded(mozart::InputDeviceImpl* input_device);
void OnDeviceRemoved(uint32_t device_id);
const scenic_lib::Layer& layer() const { return layer_; }
private:
enum SessionPresentState {
kNoPresentPending,
kPresentPending,
kPresentPendingAndSceneDirty
};
friend class DisplayRotater;
friend class DisplayUsageSwitcher;
friend class PerspectiveDemoMode;
friend class DisplaySizeSwitcher;
friend class PresentationSwitcher;
// Sets |display_metrics_| and updates view_manager and Scenic.
// Returns false if the updates were skipped (if display initialization hasn't
// happened yet).
bool ApplyDisplayModelChanges(bool print_log);
// |ViewContainerListener|:
void OnChildAttached(uint32_t child_key, ::fuchsia::ui::views_v1::ViewInfo child_view_info,
OnChildAttachedCallback callback) override;
void OnChildUnavailable(uint32_t child_key,
OnChildUnavailableCallback callback) override;
// |ViewListener|:
void OnPropertiesChanged(::fuchsia::ui::views_v1::ViewProperties properties,
OnPropertiesChangedCallback callback) override;
// |Presentation|
void EnableClipping(bool enabled) override;
// |Presentation|
void UseOrthographicView() override;
// |Presentation|
void UsePerspectiveView() override;
// |Presentation|
void SetRendererParams(
::fidl::VectorPtr<fuchsia::ui::gfx::RendererParam> params) override;
void InitializeDisplayModel(fuchsia::ui::gfx::DisplayInfo display_info);
// |Presentation|
void SetDisplayUsage(fuchsia::ui::policy::DisplayUsage usage) override;
void SetDisplayUsageWithoutApplyingChanges(fuchsia::ui::policy::DisplayUsage usage_);
// |Presentation|
void SetDisplaySizeInMm(float width_in_mm, float height_in_mm) override;
// |Presentation|
void SetDisplayRotation(float display_rotation_degrees,
bool animate) override;
// Returns false if the operation failed (e.g. the requested size is bigger
// than the actual display size).
bool SetDisplaySizeInMmWithoutApplyingChanges(float width_in_mm,
float height_in_mm,
bool print_errors);
// |Presentation|
void CaptureKeyboardEventHACK(
fuchsia::ui::input::KeyboardEvent event_to_capture,
fidl::InterfaceHandle<fuchsia::ui::policy::KeyboardCaptureListenerHACK> listener)
override;
// |Presentation|
void CapturePointerEventsHACK(
fidl::InterfaceHandle<fuchsia::ui::policy::PointerCaptureListenerHACK> listener)
override;
// |Presentation|
void GetPresentationMode(GetPresentationModeCallback callback) override;
// |Presentation|
void SetPresentationModeListener(
fidl::InterfaceHandle<fuchsia::ui::policy::PresentationModeListener> listener)
override;
void CreateViewTree(
::fuchsia::ui::views_v1_token::ViewOwnerPtr view_owner,
fidl::InterfaceRequest<fuchsia::ui::policy::Presentation> presentation_request,
fuchsia::ui::gfx::DisplayInfo display_info);
// Returns true if the event was consumed and the scene is to be invalidated.
bool GlobalHooksHandleEvent(const fuchsia::ui::input::InputEvent& event);
void OnEvent(fuchsia::ui::input::InputEvent event);
void OnSensorEvent(uint32_t device_id, fuchsia::ui::input::InputReport event);
void PresentScene();
void Shutdown();
::fuchsia::ui::views_v1::ViewManager* const view_manager_;
fuchsia::ui::scenic::Scenic* const scenic_;
scenic_lib::Session* const session_;
scenic_lib::Layer layer_;
scenic_lib::Renderer renderer_;
// TODO(MZ-254): put camera before scene.
scenic_lib::Scene scene_;
scenic_lib::Camera camera_;
scenic_lib::AmbientLight ambient_light_;
glm::vec3 light_direction_;
scenic_lib::DirectionalLight directional_light_;
scenic_lib::EntityNode root_view_host_node_;
zx::eventpair root_view_host_import_token_;
scenic_lib::ImportNode root_view_parent_node_;
zx::eventpair root_view_parent_export_token_;
scenic_lib::EntityNode content_view_host_node_;
zx::eventpair content_view_host_import_token_;
scenic_lib::RoundedRectangle cursor_shape_;
scenic_lib::Material cursor_material_;
SessionPresentState session_present_state_ = kNoPresentPending;
bool presentation_clipping_enabled_ = true;
bool display_model_initialized_ = false;
DisplayModel display_model_actual_;
DisplayModel display_model_simulated_;
// When |display_model_simulated_| or |display_rotation_desired_| changes:
// * |display_metrics_| must be recalculated.
// * |display_rotation_current_| must be updated.
// * Transforms on the scene must be updated.
// This is done by calling ApplyDisplayModelChanges().
DisplayMetrics display_metrics_;
// Expressed in degrees.
float display_rotation_desired_ = 0.f;
float display_rotation_current_ = 0.f;
::fuchsia::ui::views_v1::ViewPtr root_view_;
YieldCallback yield_callback_;
ShutdownCallback shutdown_callback_;
fuchsia::math::PointF mouse_coordinates_;
fidl::Binding<fuchsia::ui::policy::Presentation> presentation_binding_;
fidl::Binding<::fuchsia::ui::views_v1::ViewTreeListener> tree_listener_binding_;
fidl::Binding<::fuchsia::ui::views_v1::ViewContainerListener>
tree_container_listener_binding_;
fidl::Binding<::fuchsia::ui::views_v1::ViewContainerListener>
view_container_listener_binding_;
fidl::Binding<::fuchsia::ui::views_v1::ViewListener> view_listener_binding_;
::fuchsia::ui::views_v1::ViewTreePtr tree_;
::fuchsia::ui::views_v1::ViewContainerPtr tree_container_;
::fuchsia::ui::views_v1::ViewContainerPtr root_container_;
fuchsia::ui::input::InputDispatcherPtr input_dispatcher_;
// Rotates the display 180 degrees in response to events.
DisplayRotater display_rotater_;
// Toggles through different display usage values.
DisplayUsageSwitcher display_usage_switcher_;
PerspectiveDemoMode perspective_demo_mode_;
// Toggles through different display sizes.
DisplaySizeSwitcher display_size_switcher_;
// Toggles through different presentations.
PresentationSwitcher presentation_switcher_;
// Stores values that, if set, override any renderer params.
RendererParams renderer_params_override_;
struct CursorState {
bool created;
bool visible;
fuchsia::math::PointF position;
std::unique_ptr<scenic_lib::ShapeNode> node;
};
std::map<uint32_t, CursorState> cursors_;
std::map<uint32_t, std::pair<mozart::InputDeviceImpl*,
std::unique_ptr<mozart::DeviceState>>>
device_states_by_id_;
// A registry of listeners who want to be notified when their keyboard
// event happens.
struct KeyboardCaptureItem {
fuchsia::ui::input::KeyboardEvent event;
fuchsia::ui::policy::KeyboardCaptureListenerHACKPtr listener;
};
std::vector<KeyboardCaptureItem> captured_keybindings_;
// A registry of listeners who want to be notified when pointer event happens.
struct PointerCaptureItem {
fuchsia::ui::policy::PointerCaptureListenerHACKPtr listener;
};
std::vector<PointerCaptureItem> captured_pointerbindings_;
// Listener for changes in presentation mode.
fuchsia::ui::policy::PresentationModeListenerPtr presentation_mode_listener_;
// Presentation mode, based on last N measurements
fuchsia::ui::policy::PresentationMode presentation_mode_;
std::unique_ptr<presentation_mode::Detector> presentation_mode_detector_;
fxl::WeakPtrFactory<Presentation> weak_factory_;
FXL_DISALLOW_COPY_AND_ASSIGN(Presentation);
};
} // namespace root_presenter
#endif // GARNET_BIN_UI_ROOT_PRESENTER_PRESENTATION_H_