| // Copyright 2022 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 "flatland_view.h" |
| |
| #include <lib/syslog/cpp/macros.h> |
| #include <lib/syslog/global.h> |
| #include <lib/ui/scenic/cpp/view_creation_tokens.h> |
| #include <lib/ui/scenic/cpp/view_identity.h> |
| |
| #include <cstdio> |
| |
| const char* const kTag = "FlatlandView"; |
| |
| const fuchsia::ui::composition::TransformId kRootTransform = {1}; |
| const fuchsia::ui::composition::ContentId kViewport = {1}; |
| |
| // static |
| std::unique_ptr<FlatlandView> FlatlandView::Create(sys::ComponentContext* context, |
| fuchsia::ui::views::ViewCreationToken view_creation_token, |
| ResizeCallback resize_callback) { |
| auto view = std::make_unique<FlatlandView>(std::move(resize_callback)); |
| if (!view) return nullptr; |
| if (!view->Init(context, std::move(view_creation_token))) return nullptr; |
| return view; |
| } |
| |
| FlatlandView::FlatlandView(ResizeCallback resize_callback) : resize_callback_(std::move(resize_callback)) {} |
| |
| bool FlatlandView::Init(sys::ComponentContext* context, fuchsia::ui::views::ViewCreationToken view_creation_token) { |
| context->svc()->Connect<>(flatland_.NewRequest()); |
| flatland_->SetDebugName(kTag); |
| flatland_.events().OnError = fit::bind_member(this, &FlatlandView::OnFlatlandError); |
| flatland_.events().OnNextFrameBegin = fit::bind_member(this, &FlatlandView::OnNextFrameBegin); |
| |
| flatland_->CreateTransform(kRootTransform); |
| flatland_->SetRootTransform(kRootTransform); |
| flatland_->CreateView2(std::move(view_creation_token), scenic::NewViewIdentityOnCreation(), {}, |
| parent_viewport_watcher_.NewRequest()); |
| parent_viewport_watcher_->GetLayout(fit::bind_member(this, &FlatlandView::OnGetLayout)); |
| |
| zx::channel::create(0, &viewport_creation_token_, &child_view_creation_token_); |
| |
| return true; |
| } |
| |
| void FlatlandView::OnGetLayout(fuchsia::ui::composition::LayoutInfo info) { |
| resize_callback_(info.logical_size().width, info.logical_size().height); |
| |
| fuchsia::ui::composition::ViewportProperties properties; |
| properties.set_logical_size(info.logical_size()); |
| if (viewport_creation_token_.is_valid()) { |
| // The first time that we receive layout information, create a viewport using the token that was stashed during Init(). |
| // External code will attach a view to this viewport via the token obtained from TakeChildViewCreationToken(). |
| fuchsia::ui::views::ViewportCreationToken viewport_creation_token; |
| viewport_creation_token.value = std::move(viewport_creation_token_); |
| fidl::InterfacePtr<fuchsia::ui::composition::ChildViewWatcher> child_view_watcher; |
| flatland_->CreateViewport(kViewport, std::move(viewport_creation_token), std::move(properties), |
| child_view_watcher.NewRequest()); |
| flatland_->SetContent(kRootTransform, kViewport); |
| } else { |
| flatland_->SetViewportProperties(kViewport, std::move(properties)); |
| } |
| |
| Present(); |
| parent_viewport_watcher_->GetLayout(fit::bind_member(this, &FlatlandView::OnGetLayout)); |
| } |
| |
| void FlatlandView::OnFlatlandError(fuchsia::ui::composition::FlatlandError error) { |
| FX_LOGF(ERROR, kTag, "OnFlatlandError: %d", error); |
| } |
| |
| void FlatlandView::Present() { |
| if (present_credits_ == 0) { |
| pending_present_ = true; |
| return; |
| } |
| --present_credits_; |
| fuchsia::ui::composition::PresentArgs present_args; |
| present_args.set_requested_presentation_time(0); |
| present_args.set_acquire_fences({}); |
| present_args.set_release_fences({}); |
| present_args.set_unsquashable(false); |
| flatland_->Present(std::move(present_args)); |
| } |
| |
| void FlatlandView::OnNextFrameBegin(fuchsia::ui::composition::OnNextFrameBeginValues values) { |
| present_credits_ += values.additional_present_credits(); |
| if (present_credits_ > 0 && pending_present_) { |
| Present(); |
| pending_present_ = false; |
| } |
| } |
| |
| FlatlandViewProviderService::FlatlandViewProviderService(sys::ComponentContext* context, CreateView2Callback create_view_callback) |
| : create_view_callback_(std::move(create_view_callback)) { |
| context->outgoing()->AddPublicService<fuchsia::ui::app::ViewProvider>( |
| [this](fidl::InterfaceRequest<fuchsia::ui::app::ViewProvider> request) { |
| this->HandleViewProviderRequest(std::move(request)); |
| }); |
| } |
| |
| void FlatlandViewProviderService::CreateViewWithViewRef(zx::eventpair view_token, |
| fuchsia::ui::views::ViewRefControl view_ref_control, |
| fuchsia::ui::views::ViewRef view_ref) { |
| FX_NOTIMPLEMENTED() << "Only Flatland is supported. This is a Gfx ViewProvider method."; |
| } |
| |
| void FlatlandViewProviderService::CreateView2(fuchsia::ui::app::CreateView2Args args) { create_view_callback_(std::move(args)); } |
| |
| void FlatlandViewProviderService::HandleViewProviderRequest(fidl::InterfaceRequest<fuchsia::ui::app::ViewProvider> request) { |
| bindings_.AddBinding(this, std::move(request)); |
| } |