blob: bc79d0c86707f6c733a8f2dfb4c8c4212dc21c45 [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/global.h>
#include <lib/syslog/logger.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_LOGF(ERROR, "kLogTag",
"Unable to connect to fuchsia_element::Presenter protocol: %s",
graphical_client_end.status_string());
}
presenter_.Bind(std::move(*graphical_client_end), dispatcher_);
FX_LOG(INFO, kLogTag, "Presenter Binded");
auto flatland_client_end =
component::Connect<fuchsia_ui_composition::Flatland>();
if (flatland_client_end.is_error()) {
FX_LOGF(
ERROR, kLogTag,
"Unable to connect to fuchsia_ui_composition::Flatland protocol: %s",
flatland_client_end.status_string());
}
flatland_.Bind(std::move(*flatland_client_end), dispatcher_);
FX_LOG(INFO, kLogTag, "Connected to Flatland");
}
void GraphicalWindow::CreateView() {
FX_LOG(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_LOG(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_LOGF(ERROR, kLogTag, "Unable to run Create View: %s",
create.error_value().status_string());
}
FX_LOG(INFO, kLogTag, "View Created");
auto present_flatland =
flatland_->Present(fuchsia_ui_composition::PresentArgs{});
if (present_flatland.is_error()) {
FX_LOGF(ERROR, kLogTag, "Unable to present Flatland: %s",
present_flatland.error_value().status_string());
}
// Attach View to Parent
presenter_->PresentView({{.view_spec = std::move(view_spec)}})
.Then([](auto result) {
if (result.is_error()) {
FX_LOGF(ERROR, kLogTag, "PresentView failed:");
}
});
FX_LOG(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_LOGF(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_LOGF(INFO, kLogTag, "Width: %d", windowWidth);
FX_LOGF(INFO, kLogTag, "Height: %d", 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_LOGF(ERROR, kLogTag, "Unable to run Create Transform: %s",
create_transform.error_value().status_string());
};
auto root_transform = flatland_->SetRootTransform(
fuchsia_ui_composition::TransformId({.value = kRootTransformId}));
if (root_transform.is_error()) {
FX_LOGF(ERROR, kLogTag, "Unable to run Root Transform: %s",
root_transform.error_value().status_string());
};
FX_LOG(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_LOGF(ERROR, kLogTag, "Unable to Set Region");
};
FX_LOG(INFO, kLogTag, "Square Translation Set");
// Create Square
auto create_rect = flatland_->CreateFilledRect(kFilledRectId);
if (create_rect.is_error()) {
FX_LOGF(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_LOGF(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_LOGF(ERROR, kLogTag, "Unable to Set Content");
};
FX_LOG(INFO, kLogTag, "Content Created");
auto present_flatland =
flatland_->Present(fuchsia_ui_composition::PresentArgs{});
if (present_flatland.is_error()) {
FX_LOGF(ERROR, kLogTag, "Unable to present Flatland: %s",
present_flatland.error_value().status_string());
}
FX_LOG(INFO, kLogTag, "View Presented!");
}