blob: d5dd0f6d001aab151c52c96a06278b1c6bbe0bae [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.
#include "garnet/lib/ui/scenic/scenic.h"
#include <lib/async/default.h>
#include "lib/component/cpp/startup_context.h"
#include "lib/fxl/logging.h"
namespace scenic_impl {
Scenic::Scenic(component::StartupContext* app_context,
fit::closure quit_callback)
: app_context_(app_context), quit_callback_(std::move(quit_callback)) {
FXL_DCHECK(app_context_);
app_context->outgoing().AddPublicService(scenic_bindings_.GetHandler(this));
// Scenic relies on having a valid default dispatcher. A hard check here means
// we don't have to be defensive everywhere else.
FXL_CHECK(async_get_default_dispatcher());
}
Scenic::~Scenic() = default;
void Scenic::OnSystemInitialized(System* system) {
size_t num_erased = uninitialized_systems_.erase(system);
FXL_CHECK(num_erased == 1);
if (uninitialized_systems_.empty()) {
for (auto& closure : run_after_all_systems_initialized_) {
closure();
}
run_after_all_systems_initialized_.clear();
}
}
void Scenic::CloseSession(Session* session) {
// TODO(SCN-1065): Make it so that close session removes the binding from
// session_bindings_, then remove num_sessions_ and return
// session_bindings_.size() in num_sessions() instead
for (auto& binding : session_bindings_.bindings()) {
// It's possible that this is called by BindingSet::CloseAndCheckForEmpty.
// In that case, binding could be empty, so check for that.
if (binding && binding->impl().get() == session) {
binding->Unbind();
--num_sessions_;
return;
}
}
}
void Scenic::CreateSession(
::fidl::InterfaceRequest<fuchsia::ui::scenic::Session> session_request,
::fidl::InterfaceHandle<fuchsia::ui::scenic::SessionListener> listener) {
if (uninitialized_systems_.empty()) {
CreateSessionImmediately(std::move(session_request), std::move(listener));
} else {
run_after_all_systems_initialized_.push_back(
[this, session_request = std::move(session_request),
listener = std::move(listener)]() mutable {
CreateSessionImmediately(std::move(session_request),
std::move(listener));
});
}
}
void Scenic::CreateSessionImmediately(
::fidl::InterfaceRequest<fuchsia::ui::scenic::Session> session_request,
::fidl::InterfaceHandle<fuchsia::ui::scenic::SessionListener> listener) {
auto session =
std::make_unique<Session>(next_session_id_++, std::move(listener));
// Give each installed System an opportunity to install a CommandDispatcher in
// the newly-created Session.
std::array<std::unique_ptr<CommandDispatcher>, System::TypeId::kMaxSystems>
dispatchers;
for (size_t i = 0; i < System::TypeId::kMaxSystems; ++i) {
if (auto& system = systems_[i]) {
dispatchers[i] = system->CreateCommandDispatcher(
CommandDispatcherContext(this, session.get()));
}
}
session->SetCommandDispatchers(std::move(dispatchers));
session_bindings_.AddBinding(std::move(session), std::move(session_request));
++num_sessions_;
}
void Scenic::GetDisplayInfo(
fuchsia::ui::scenic::Scenic::GetDisplayInfoCallback callback) {
FXL_DCHECK(systems_[System::kGfx]);
TempSystemDelegate* delegate =
reinterpret_cast<TempSystemDelegate*>(systems_[System::kGfx].get());
delegate->GetDisplayInfo(std::move(callback));
}
void Scenic::TakeScreenshot(
fuchsia::ui::scenic::Scenic::TakeScreenshotCallback callback) {
FXL_DCHECK(systems_[System::kGfx]);
TempSystemDelegate* delegate =
reinterpret_cast<TempSystemDelegate*>(systems_[System::kGfx].get());
delegate->TakeScreenshot(std::move(callback));
}
void Scenic::GetDisplayOwnershipEvent(
fuchsia::ui::scenic::Scenic::GetDisplayOwnershipEventCallback callback) {
FXL_DCHECK(systems_[System::kGfx]);
TempSystemDelegate* delegate =
reinterpret_cast<TempSystemDelegate*>(systems_[System::kGfx].get());
delegate->GetDisplayOwnershipEvent(std::move(callback));
}
} // namespace scenic_impl