blob: 4b282760aab8aec82bac44c2a96e84511cc4e991 [file] [log] [blame]
// 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 GARNET_LIB_UI_SCENIC_SCENIC_H_
#define GARNET_LIB_UI_SCENIC_SCENIC_H_
#include <fuchsia/ui/scenic/cpp/fidl.h>
#include <lib/fit/function.h>
#include <set>
#include "garnet/lib/ui/scenic/session.h"
#include "garnet/lib/ui/scenic/system.h"
#include "lib/fidl/cpp/binding_set.h"
#include "lib/fxl/macros.h"
namespace scenic_impl {
class Clock;
// A Scenic instance has two main areas of responsibility:
// - manage Session lifecycles
// - provide a host environment for Services
class Scenic : public fuchsia::ui::scenic::Scenic {
public:
explicit Scenic(component::StartupContext* app_context,
fit::closure quit_callback);
~Scenic();
// Create and register a new system of the specified type. At most one System
// with a given TypeId may be registered.
template <typename SystemT, typename... Args>
SystemT* RegisterSystem(Args&&... args);
// Called by Session when it needs to close itself.
void CloseSession(Session* session);
// |fuchsia::ui::scenic::Scenic|
void CreateSession(
::fidl::InterfaceRequest<fuchsia::ui::scenic::Session> session,
::fidl::InterfaceHandle<fuchsia::ui::scenic::SessionListener> listener)
override;
component::StartupContext* app_context() const { return app_context_; }
size_t num_sessions() { return num_sessions_; }
private:
void CreateSessionImmediately(
::fidl::InterfaceRequest<fuchsia::ui::scenic::Session> session_request,
::fidl::InterfaceHandle<fuchsia::ui::scenic::SessionListener> listener);
// If a System is not initially initialized, this method will be called when
// it is ready.
void OnSystemInitialized(System* system);
void GetDisplayInfo(
fuchsia::ui::scenic::Scenic::GetDisplayInfoCallback callback) override;
void TakeScreenshot(
fuchsia::ui::scenic::Scenic::TakeScreenshotCallback callback) override;
void GetDisplayOwnershipEvent(
fuchsia::ui::scenic::Scenic::GetDisplayOwnershipEventCallback callback)
override;
component::StartupContext* const app_context_;
fit::closure quit_callback_;
// Registered systems, indexed by their TypeId. These slots could be null,
// indicating the System is not available or supported.
std::array<std::unique_ptr<System>, System::TypeId::kMaxSystems> systems_;
// List of systems that are waiting to be initialized; we can't create
// sessions until this is empty.
std::set<System*> uninitialized_systems_;
// Closures that will be run when all systems are initialized.
std::vector<fit::closure> run_after_all_systems_initialized_;
// Session bindings rely on setup of systems_; order matters.
fidl::BindingSet<fuchsia::ui::scenic::Session, std::unique_ptr<Session>>
session_bindings_;
fidl::BindingSet<fuchsia::ui::scenic::Scenic> scenic_bindings_;
size_t next_session_id_ = 1;
size_t num_sessions_ = 0;
FXL_DISALLOW_COPY_AND_ASSIGN(Scenic);
};
template <typename SystemT, typename... Args>
SystemT* Scenic::RegisterSystem(Args&&... args) {
FXL_DCHECK(systems_[SystemT::kTypeId] == nullptr)
<< "System of type: " << SystemT::kTypeId << "was already registered.";
SystemT* system =
new SystemT(SystemContext(app_context_, quit_callback_.share()),
std::forward<Args>(args)...);
systems_[SystemT::kTypeId] = std::unique_ptr<System>(system);
// Listen for System to be initialized if it isn't already.
if (!system->initialized()) {
uninitialized_systems_.insert(system);
system->set_on_initialized_callback(
[this](System* system) { Scenic::OnSystemInitialized(system); });
}
return system;
}
} // namespace scenic_impl
#endif // GARNET_LIB_UI_SCENIC_SCENIC_H_