blob: 97d00df12e081b81410a2ed2add1fa95f8fe0d91 [file] [log] [blame]
// Copyright 2024 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 <fidl/fuchsia.ui.composition/cpp/fidl.h>
#include <fidl/fuchsia.ui.views/cpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/component/incoming/cpp/protocol.h>
#include <lib/fidl/cpp/interface_ptr.h>
#include <lib/fidl/cpp/wire/internal/thenable.h>
#include <lib/sys/cpp/component_context.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/ui/scenic/cpp/view_creation_tokens.h>
#include <lib/ui/scenic/cpp/view_identity.h>
#include <zircon/rights.h>
#include <zircon/status.h>
#include <cstdint>
#include <iostream>
#include "graphical_window.h"
namespace {
// Tag for logging errors
constexpr char kLogTag[] = "reference_session";
// ID for transform
static constexpr uint64_t kRootTransformId = 1;
} // namespace
GraphicalWindow::GraphicalWindow(async_dispatcher_t *dispatcher)
: dispatcher_(dispatcher) {
auto graphical_client_end =
component::Connect<fuchsia_element::GraphicalPresenter>();
if (graphical_client_end.is_error()) {
FX_LOGST(ERROR, kLogTag)
<< "Unable to connect to fuchsia_element::Presenter protocol: "
<< graphical_client_end.status_string();
}
presenter_.Bind(std::move(*graphical_client_end), dispatcher_);
FX_LOGST(INFO, kLogTag) << "Presenter Binded";
auto flatland_client_end =
component::Connect<fuchsia_ui_composition::Flatland>();
if (flatland_client_end.is_error()) {
FX_LOGST(ERROR, kLogTag)
<< "Unable to connect to fuchsia_ui_composition::Flatland protocol: "
<< flatland_client_end.status_string();
}
flatland_.Bind(std::move(*flatland_client_end), dispatcher_);
FX_LOGST(INFO, kLogTag) << "Connected to Flatland";
}
void GraphicalWindow::CreateView() {
FX_LOGST(INFO, kLogTag) << "Creating View...";
// Creating Flatland View
auto [view_token, parent_viewport_token] =
scenic::ViewCreationTokenPair::New();
fuchsia_element::ViewSpec view_spec;
view_spec.viewport_creation_token(fuchsia_ui_views::ViewportCreationToken(
std::move(parent_viewport_token.value)));
FX_LOGST(INFO, kLogTag) << "View Creation Token Created";
auto parent_viewport_watcher_endpoints =
fidl::CreateEndpoints<fuchsia_ui_composition::ParentViewportWatcher>();
auto [parent_viewport_watcher_client_end,
parent_viewport_watcher_server_end] =
std::move(parent_viewport_watcher_endpoints.value());
parent_viewport_watcher_.Bind(std::move(parent_viewport_watcher_client_end),
dispatcher_);
auto create =
flatland_->CreateView({{.token = std::move(view_token.value),
.parent_viewport_watcher = std::move(
parent_viewport_watcher_server_end)}});
if (create.is_error()) {
FX_LOGST(ERROR, kLogTag)
<< "Unable to run Create View: " << create.error_value();
}
FX_LOGST(INFO, kLogTag) << "View Created";
auto present_flatland =
flatland_->Present(fuchsia_ui_composition::PresentArgs{});
if (present_flatland.is_error()) {
FX_LOGST(ERROR, kLogTag)
<< "Unable to present Flatland: " << present_flatland.error_value();
}
// Attach View to Parent
presenter_->PresentView({{.view_spec = std::move(view_spec)}})
.Then([](auto result) {
if (result.is_error()) {
FX_LOGST(ERROR, kLogTag)
<< "PresentView failed: " << result.error_value();
}
});
FX_LOGST(INFO, kLogTag) << "View Presented!";
// Gets size of emulator window and draws square
GetLayout();
}
void GraphicalWindow::GetLayout() {
parent_viewport_watcher_->GetLayout().ThenExactlyOnce(
[&](fidl::Result<fuchsia_ui_composition::ParentViewportWatcher::GetLayout>
&result) { OnGetLayout(result); });
}
void GraphicalWindow::OnGetLayout(
fidl::Result<fuchsia_ui_composition::ParentViewportWatcher::GetLayout>
&result) {
// Get terminal window size
if (result.is_ok()) {
FX_LOGST(INFO, kLogTag) << "Layout Received: ";
int32_t windowWidth =
static_cast<int32_t>(result->info().logical_size()->width());
int32_t windowHeight =
static_cast<int32_t>(result->info().logical_size()->height());
FX_LOGST(INFO, kLogTag) << "Width: " << windowWidth;
FX_LOGST(INFO, kLogTag) << "Height: " << windowHeight;
DrawSquare(windowWidth, windowHeight,
static_cast<uint32_t>(windowWidth / 5));
}
}
void GraphicalWindow::DrawSquare(int32_t window_width, int32_t window_height,
uint32_t square_size) {
// Create ID for square
const fuchsia_ui_composition::ContentId kFilledRectId = {1};
// Create Transform and set to root transform
auto create_transform = flatland_->CreateTransform(
fuchsia_ui_composition::TransformId({.value = kRootTransformId}));
if (create_transform.is_error()) {
FX_LOGST(ERROR, kLogTag)
<< "Unable to run Create Transform: " << create_transform.error_value();
};
auto root_transform = flatland_->SetRootTransform(
fuchsia_ui_composition::TransformId({.value = kRootTransformId}));
if (root_transform.is_error()) {
FX_LOGST(ERROR, kLogTag)
<< "Unable to run Root Transform: " << root_transform.error_value();
};
FX_LOGST(INFO, kLogTag) << "Transform Created";
// Move square towards middle of terminal window
auto set_region = flatland_->SetTranslation(
{fuchsia_ui_composition::TransformId({.value = kRootTransformId}),
{static_cast<int32_t>((window_width / 2) - (square_size / 2)),
static_cast<int32_t>((window_height / 2) - (square_size / 2))}});
if (set_region.is_error()) {
FX_LOGST(ERROR, kLogTag) << "Unable to Set Region";
};
FX_LOGST(INFO, kLogTag) << "Square Translation Set";
// Create Square
auto create_rect = flatland_->CreateFilledRect(kFilledRectId);
if (create_rect.is_error()) {
FX_LOGST(ERROR, kLogTag) << "Unable to Create Rectangle";
};
// Here, you can change the color of the rectangle! Change the color of the
// rectangle and run the session again to see the change of your color.
// R G B Alpha
// {x, y, z, a}
// {0.28, 0.46, 1, 1} will give you blue!
auto set_fill =
flatland_->SetSolidFill({{kFilledRectId,
{1, 0, 1, 1} /* The color fuchsia*/,
{square_size, square_size} /* size */}});
if (set_fill.is_error()) {
FX_LOGST(ERROR, kLogTag) << "Unable to Set Solid Fill";
};
// Set Content and Present
auto set_content = flatland_->SetContent(
{{fuchsia_ui_composition::TransformId({.value = kRootTransformId}),
kFilledRectId}});
if (set_content.is_error()) {
FX_LOGST(ERROR, kLogTag) << "Unable to Set Content";
};
FX_LOGST(INFO, kLogTag) << "Content Created";
auto present_flatland =
flatland_->Present(fuchsia_ui_composition::PresentArgs{});
if (present_flatland.is_error()) {
FX_LOGST(ERROR, kLogTag)
<< "Unable to present Flatland: " << present_flatland.error_value();
}
FX_LOGST(INFO, kLogTag) << "View Presented!";
}