blob: 4239a7d77425b4dfedd3eb243d6eef82431b4fc5 [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_PRESENTATION2_H_
#define GARNET_BIN_UI_ROOT_PRESENTER_PRESENTATION2_H_
#include <map>
#include <memory>
#include <fuchsia/math/cpp/fidl.h>
#include <fuchsia/ui/input/cpp/fidl.h>
#include <fuchsia/ui/policy/cpp/fidl.h>
#include <fuchsia/ui/viewsv1/cpp/fidl.h>
#include <lib/fit/function.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.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/cpp/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 root ViewHolder 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.
//
// This will eventually replace Presentation1.
//
// The root ViewHolder has the presented (content) view as its child.
//
// The scene's node tree has the following structure:
// + Scene
// + RootNode
// + ViewHolderNode
// + ViewHolder
// + link: Content view's actual content
// + child: cursor 1
// + child: cursor N
//
class Presentation2 : public Presentation {
public:
Presentation2(fuchsia::ui::scenic::Scenic* scenic, scenic::Session* session,
scenic::ResourceId compositor_id,
zx::eventpair view_holder_token, RendererParams renderer_params,
int32_t display_startup_rotation_adjustment);
~Presentation2() 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 PresentView(::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) override;
void OnDeviceAdded(mozart::InputDeviceImpl* input_device) override;
void OnDeviceRemoved(uint32_t device_id) override;
const scenic::Layer& layer() const override { return layer_; }
const YieldCallback& yield_callback() override { return yield_callback_; };
float display_rotation_desired() const override {
return display_rotation_desired_;
};
void set_display_rotation_desired(float display_rotation) override {
display_rotation_desired_ = display_rotation;
}
float display_rotation_current() const override {
return display_rotation_current_;
}
int32_t display_startup_rotation_adjustment() const override {
return display_startup_rotation_adjustment_;
}
const DisplayModel::DisplayInfo& actual_display_info() override {
return display_model_actual_.display_info();
}
const DisplayMetrics& simulated_display_metrics() const override {
return display_metrics_;
};
scenic::Camera* camera() override { return &camera_; }
private:
enum SessionPresentState {
kNoPresentPending,
kPresentPending,
kPresentPendingAndSceneDirty
};
friend class DisplayRotater;
friend class DisplayUsageSwitcher;
friend class PerspectiveDemoMode;
friend class DisplaySizeSwitcher;
friend class PresentationSwitcher;
// Used to receive a ViewDisconnected event, which causes root_presenter to
// shut down; can handle other Scenic events in the future.
void HandleScenicEvent(const fuchsia::ui::scenic::Event& event);
// Dispatches events to HandleScenicEvent(). Expected to be called on the same
// thread the Session was created on (which also creates a SessionListener),
// which is our main thread.
void HandleScenicEvents(std::vector<fuchsia::ui::scenic::Event>);
// 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, bool present_changes) override;
bool ApplyDisplayModelChangesHelper(bool print_log);
// |Presentation|
void EnableClipping(bool enabled) override;
// |Presentation|
void UseOrthographicView() override;
// |Presentation|
void UsePerspectiveView() override;
// |Presentation|
void SetRendererParams(
::std::vector<fuchsia::ui::gfx::RendererParam> params) override;
// Used internally by Presenter. Allows overriding of renderer params.
void OverrideRendererParams(RendererParams renderer_params,
bool present_changes = true) 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_) override;
// |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) override;
// |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;
// 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::scenic::Scenic* const scenic_;
scenic::Session* const session_;
scenic::ResourceId compositor_id_;
scenic::Layer layer_;
scenic::Renderer renderer_;
// TODO(MZ-254): put camera before scene.
scenic::Scene scene_;
scenic::Camera camera_;
scenic::AmbientLight ambient_light_;
glm::vec3 light_direction_;
scenic::DirectionalLight directional_light_;
scenic::EntityNode view_holder_node_;
scenic::EntityNode root_node_;
scenic::ViewHolder view_holder_;
scenic::RoundedRectangle cursor_shape_;
scenic::Material cursor_material_;
SessionPresentState session_present_state_ = kNoPresentPending;
bool display_model_initialized_ = false;
DisplayModel display_model_actual_;
DisplayModel display_model_simulated_;
// Stores values that, if set, override any renderer params.
bool presentation_clipping_enabled_ = true;
RendererParams renderer_params_override_;
// 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;
// At startup, apply a rotation defined in 90 degree increments, just once.
// Implies resizing of the presentation to adjust to rotated coordinates.
// Valid values are ... -180, -90, 0, 90, 180, ...
//
// Used when the native display orientation is reported incorrectly.
// TODO(SCN-857) - Make this less of a hack.
int32_t display_startup_rotation_adjustment_;
::fuchsia::ui::viewsv1::ViewPtr root_view_;
YieldCallback yield_callback_;
ShutdownCallback shutdown_callback_;
fuchsia::math::PointF mouse_coordinates_;
fidl::Binding<fuchsia::ui::policy::Presentation> presentation_binding_;
// 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_;
struct CursorState {
bool created;
bool visible;
fuchsia::math::PointF position;
std::unique_ptr<scenic::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<Presentation2> weak_factory_;
FXL_DISALLOW_COPY_AND_ASSIGN(Presentation2);
};
} // namespace root_presenter
#endif // GARNET_BIN_UI_ROOT_PRESENTER_PRESENTATION2_H_