blob: af2367d9c916be405aaf5bbb7bc4077ebb5270a6 [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 "src/ui/scenic/lib/scenic/scenic.h"
#include <lib/async/default.h>
#include <lib/sys/cpp/component_context.h>
#include "src/lib/fxl/logging.h"
namespace scenic_impl {
Scenic::Scenic(sys::ComponentContext* app_context, inspect_deprecated::Node inspect_node,
fit::closure quit_callback)
: app_context_(app_context),
quit_callback_(std::move(quit_callback)),
inspect_node_(std::move(inspect_node)) {
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::SetInitialized() {
initialized_ = true;
for (auto& closure : run_after_initialized_) {
closure();
}
run_after_initialized_.clear();
}
void Scenic::SetFrameScheduler(const std::shared_ptr<scheduling::FrameScheduler>& frame_scheduler) {
FXL_DCHECK(!frame_scheduler_) << "Error: FrameScheduler already set";
FXL_DCHECK(frame_scheduler) << "Error: No FrameScheduler provided";
frame_scheduler_ = frame_scheduler;
}
void Scenic::CloseSession(scheduling::SessionId session_id) { sessions_.erase(session_id); }
void Scenic::RunAfterInitialized(fit::closure closure) {
if (initialized_) {
closure();
} else {
run_after_initialized_.push_back(std::move(closure));
}
}
void Scenic::CreateSession(fidl::InterfaceRequest<fuchsia::ui::scenic::Session> session_request,
fidl::InterfaceHandle<fuchsia::ui::scenic::SessionListener> listener) {
RunAfterInitialized([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<scenic_impl::Session>(
next_session_id_++, std::move(session_request), std::move(listener));
session->SetFrameScheduler(frame_scheduler_);
session->set_binding_error_handler(
[this, session_id = session->id()](zx_status_t status) { CloseSession(session_id); });
// Give each installed System an opportunity to install a CommandDispatcher in
// the newly-created Session.
std::array<CommandDispatcherUniquePtr, 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));
FXL_CHECK(sessions_.find(session->id()) == sessions_.end());
sessions_[session->id()] = std::move(session);
}
void Scenic::GetDisplayInfo(fuchsia::ui::scenic::Scenic::GetDisplayInfoCallback callback) {
RunAfterInitialized([this, callback = std::move(callback)]() mutable {
// TODO(fxb/23686): This code assumes that, once all systems have been initialized, that there
// will be a proper delegate for Scenic API functions. Attached to the bug to remove this
// delegate class completely. If the delegate becomes a permanent fixture of the system,
// switch to SCN-1506, as we need a more formal mechanism for delayed execution and
// initialization order logic.
FXL_DCHECK(display_delegate_);
display_delegate_->GetDisplayInfo(std::move(callback));
});
}
void Scenic::TakeScreenshot(fuchsia::ui::scenic::Scenic::TakeScreenshotCallback callback) {
RunAfterInitialized([this, callback = std::move(callback)]() mutable {
// TODO(fxb/23686): This code assumes that, once all systems have been initialized, that there
// will be a proper delegate for Scenic API functions. Attached to the bug to remove this
// delegate class completely. If the delegate becomes a permanent fixture of the system,
// switch to SCN-1506, as we need a more formal mechanism for delayed execution and
// initialization order logic.
FXL_DCHECK(screenshot_delegate_);
screenshot_delegate_->TakeScreenshot(std::move(callback));
});
}
void Scenic::GetDisplayOwnershipEvent(
fuchsia::ui::scenic::Scenic::GetDisplayOwnershipEventCallback callback) {
RunAfterInitialized([this, callback = std::move(callback)]() mutable {
// TODO(fxb/23686): This code assumes that, once all systems have been initialized, that there
// will be a proper delegate for Scenic API functions. Attached to the bug to remove this
// delegate class completely. If the delegate becomes a permanent fixture of the system,
// switch to SCN-1506, as we need a more formal mechanism for delayed execution and
// initialization order logic.
FXL_DCHECK(display_delegate_);
display_delegate_->GetDisplayOwnershipEvent(std::move(callback));
});
}
void Scenic::InitializeSnapshotService(
std::unique_ptr<fuchsia::ui::scenic::internal::Snapshot> snapshot) {
snapshot_ = std::move(snapshot);
app_context_->outgoing()->AddPublicService(snapshot_bindings_.GetHandler(snapshot_.get()));
}
size_t Scenic::num_sessions() {
int num_sessions = 0;
for (auto&& elem : sessions_) {
if (elem.second->is_bound())
++num_sessions;
}
return num_sessions;
}
} // namespace scenic_impl