| // 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 |