blob: 98b33e1a9367fd38958ba038b06b9e73e984defb [file] [log] [blame]
// 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));
}