blob: 23fd4644aa92767d68b33ced057a0109e85a562c [file] [log] [blame] [edit]
// 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_BIN_ROOT_PRESENTER_PRESENTATION_H_
#define SRC_UI_BIN_ROOT_PRESENTER_PRESENTATION_H_
// clang-format off
#include "src/ui/lib/glm_workaround/glm_workaround.h"
// clang-format on
#include <glm/ext.hpp>
#include <fuchsia/accessibility/cpp/fidl.h>
#include <fuchsia/math/cpp/fidl.h>
#include <fuchsia/ui/gfx/cpp/fidl.h>
#include <fuchsia/ui/input/cpp/fidl.h>
#include <fuchsia/ui/input2/cpp/fidl.h>
#include <fuchsia/ui/policy/cpp/fidl.h>
#include <fuchsia/ui/views/cpp/fidl.h>
#include <lib/fidl/cpp/binding.h>
#include <lib/fidl/cpp/interface_ptr_set.h>
#include <lib/fit/function.h>
#include <lib/ui/scenic/cpp/id.h>
#include <lib/ui/scenic/cpp/resources.h>
#include <map>
#include <memory>
#include "src/lib/fxl/macros.h"
#include "src/lib/fxl/memory/weak_ptr.h"
#include "src/lib/ui/input/device_state.h"
#include "src/lib/ui/input/input_device_impl.h"
#include "src/ui/bin/root_presenter/activity_notifier.h"
#include "src/ui/bin/root_presenter/displays/display_metrics.h"
#include "src/ui/bin/root_presenter/displays/display_model.h"
#include "src/ui/bin/root_presenter/media_buttons_handler.h"
#include "src/ui/bin/root_presenter/perspective_demo_mode.h"
#include "src/ui/bin/root_presenter/presentation.h"
#include "src/ui/bin/root_presenter/presentation_switcher.h"
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.
//
// The root ViewHolder has the presented (content) view as its child.
//
// The scene's node tree has the following structure:
// + Scene
// + RootNode
// + ViewHolder
// + link: Content view's actual content
// + child: cursor 1
// + child: cursor N
//
class Presentation : fuchsia::ui::policy::Presentation,
fuchsia::accessibility::MagnificationHandler {
public:
// Callback when the presentation yields to the next/previous one.
using YieldCallback = fit::function<void(bool yield_to_next)>;
Presentation(fuchsia::ui::scenic::Scenic* scenic, scenic::Session* session,
scenic::ResourceId compositor_id,
fuchsia::ui::views::ViewHolderToken view_holder_token,
fidl::InterfaceRequest<fuchsia::ui::policy::Presentation> presentation_request,
ActivityNotifier* activity_notifier, int32_t display_startup_rotation_adjustment,
YieldCallback yield_callback, MediaButtonsHandler* media_buttons_handler);
~Presentation() override;
void RegisterWithMagnifier(fuchsia::accessibility::Magnifier* magnifier);
void OnReport(uint32_t device_id, fuchsia::ui::input::InputReport report);
void OnDeviceAdded(ui_input::InputDeviceImpl* input_device);
void OnDeviceRemoved(uint32_t device_id);
const scenic::Layer& layer() const { return layer_; }
const scenic::ViewHolder& view_holder() const { return view_holder_; }
private:
enum SessionPresentState { kNoPresentPending, kPresentPending, kPresentPendingAndSceneDirty };
friend class PerspectiveDemoMode;
friend class PresentationSwitcher;
// |fuchsia::ui::policy::Presentation|
void CapturePointerEventsHACK(
fidl::InterfaceHandle<fuchsia::ui::policy::PointerCaptureListenerHACK> listener) override;
// |fuchsia::accessibility::MagnificationHandler|
// Sets the transform for screen magnification, applied after the camera projection.
void SetClipSpaceTransform(float x, float y, float scale,
SetClipSpaceTransformCallback callback) override;
// Nulls out the clip-space transform.
void ResetClipSpaceTransform();
// Transforms a device coordinate to a post-magnification coordinate by applying the inverse
// clip-space transform. This is used to render cursors at the correct location.
glm::vec2 ApplyInverseClipSpaceTransform(const glm::vec2& coordinate);
// Sets |display_metrics_| and updates Scenic. Returns false if the updates
// were skipped (if display initialization hasn't happened yet).
bool ApplyDisplayModelChanges(bool print_log, bool present_changes);
bool ApplyDisplayModelChangesHelper(bool print_log);
// Returns the raw pointer coordinates transformed by the current display
// rotation.
glm::vec2 RotatePointerCoordinates(float x, float y);
void InitializeDisplayModel(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);
// Passes the display rotation in degrees down to the scenic compositor.
void SetScenicDisplayRotation();
void PresentScene();
fuchsia::ui::scenic::Scenic* const scenic_;
scenic::Session* const session_;
scenic::ResourceId compositor_id_;
ActivityNotifier* activity_notifier_;
scenic::Layer layer_;
scenic::Renderer renderer_;
// TODO(SCN-254): put camera before scene.
scenic::Scene scene_;
scenic::Camera camera_;
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_;
// When |display_model_| 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_;
// 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_;
struct {
glm::vec2 translation;
float scale = 1;
} clip_space_transform_;
YieldCallback yield_callback_;
fuchsia::math::PointF mouse_coordinates_;
fidl::Binding<fuchsia::ui::policy::Presentation> presentation_binding_;
fidl::Binding<fuchsia::accessibility::MagnificationHandler> a11y_binding_;
PerspectiveDemoMode perspective_demo_mode_;
// 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<ui_input::InputDeviceImpl*, std::unique_ptr<ui_input::DeviceState>>>
device_states_by_id_;
// A registry of listeners who want to be notified when pointer event happens.
fidl::InterfacePtrSet<fuchsia::ui::policy::PointerCaptureListenerHACK> captured_pointerbindings_;
MediaButtonsHandler* media_buttons_handler_ = nullptr;
fxl::WeakPtrFactory<Presentation> weak_factory_;
FXL_DISALLOW_COPY_AND_ASSIGN(Presentation);
};
} // namespace root_presenter
#endif // SRC_UI_BIN_ROOT_PRESENTER_PRESENTATION_H_