blob: 2647ae4e8405d4d3455d21b504a63cdb0f862b19 [file] [log] [blame]
// Copyright 2016 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 "garnet/bin/ui/view_manager/view_container_state.h"
#include <ostream>
#include "lib/fxl/logging.h"
#include "garnet/bin/ui/view_manager/view_registry.h"
#include "lib/ui/scenic/cpp/commands.h"
namespace view_manager {
ViewContainerState::ViewContainerState(ViewRegistry* registry,
fuchsia::ui::scenic::Scenic* scenic)
: view_registry_(registry), scenic_(scenic) {}
ViewContainerState::~ViewContainerState() {}
void ViewContainerState::AddChild(uint32_t child_key,
zx::eventpair view_holder_token,
zx::eventpair host_import_token) {
// See if this view was previously transferred
std::unique_ptr<ChildView> child =
view_registry_->FindOrphanedView(view_holder_token.get());
if (child) {
// Re-using previous ViewHolder.
FXL_VLOG(1) << "Re-using previously transferred View.";
child->child_key = child_key;
child->host_node =
std::make_unique<scenic::ImportNode>(child->session.get());
} else {
scenic::Session* session_ptr = new scenic::Session(scenic_);
child = std::unique_ptr<ChildView>(
new ChildView{nullptr, ViewConnectionState::UNKNOWN, view_registry_,
child_key, std::unique_ptr<scenic::Session>(session_ptr),
std::make_unique<scenic::ImportNode>(session_ptr),
scenic::ViewHolder(
session_ptr, std::move(view_holder_token),
"ViewContainer child=" + std::to_string(child_key))});
}
child->session->set_error_handler(
[view_registry = view_registry_,
child_ptr = child.get()](zx_status_t status) {
view_registry->RemoveOrphanedView(child_ptr);
});
child->session->set_event_handler(
[this, child_ptr =
child.get()](std::vector<fuchsia::ui::scenic::Event> events) {
ChildView::OnScenicEvent(child_ptr, std::move(events));
});
child->host_node->Bind(std::move(host_import_token));
child->host_node->Attach(child->view_holder);
child->session->Present(0, [](fuchsia::images::PresentationInfo info) {});
if (child->view_connected == ViewConnectionState::CONNECTED) {
view_registry_->SendChildAttached(this, child->child_key,
fuchsia::ui::viewsv1::ViewInfo());
} else if (child->view_connected == ViewConnectionState::DISCONNECTED) {
view_registry_->SendChildUnavailable(this, child->child_key);
}
child->container = this;
children_.insert({child_key, std::move(child)});
}
void ViewContainerState::RemoveChild(uint32_t child_key,
zx::eventpair transferred_view_token) {
auto child_it = children_.find(child_key);
FXL_CHECK(child_it != children_.end());
std::unique_ptr<ChildView> child = std::move(child_it->second);
child->container = nullptr;
children_.erase(child_it);
if (transferred_view_token) {
child->host_node->DetachChildren();
child->session->Present(0, [](fuchsia::images::PresentationInfo info) {});
view_registry_->AddOrphanedView(std::move(transferred_view_token),
std::move(child));
}
}
void ViewContainerState::RemoveAllChildren() { children_.clear(); }
void ViewContainerState::SetChildProperties(
uint32_t child_key,
::fuchsia::ui::viewsv1::ViewPropertiesPtr child_properties) {
auto child_it = children_.find(child_key);
FXL_CHECK(child_it != children_.end());
auto& child = child_it->second;
auto view_holder_id = child->view_holder.id();
bool send_update = false;
if (child_properties && child_properties->view_layout) {
auto size = child_properties->view_layout->size;
auto inset = child_properties->view_layout->inset;
child->min_dimensions = {0.f, 0.f, 0.f};
child->max_dimensions = {size.width, size.height, 1000.f};
child->inset_min = {inset.left, inset.top, 0.f};
child->inset_max = {-inset.right, -inset.bottom, 0.f};
send_update = true;
}
auto view_properties = scenic::NewSetViewPropertiesCmd(
view_holder_id, child->min_dimensions.data(),
child->max_dimensions.data(), child->inset_min.data(),
child->inset_max.data());
if (child_properties && child_properties->custom_focus_behavior) {
view_properties.set_view_properties().properties.focus_change =
child_properties->custom_focus_behavior->allow_focus;
send_update = true;
}
if (send_update) {
child->session->Enqueue(std::move(view_properties));
child->session->Present(0, [](fuchsia::images::PresentationInfo info) {});
}
}
void ViewContainerState::ChildView::OnScenicEvent(
ChildView* child, std::vector<fuchsia::ui::scenic::Event> events) {
for (const auto& event : events) {
switch (event.Which()) {
case fuchsia::ui::scenic::Event::Tag::kGfx:
switch (event.gfx().Which()) {
case fuchsia::ui::gfx::Event::Tag::kViewConnected: {
auto view_holder_id = event.gfx().view_connected().view_holder_id;
FXL_CHECK(child->view_holder.id() == view_holder_id);
child->view_connected = ViewConnectionState::CONNECTED;
if (child->container) {
child->view_registry->SendChildAttached(
child->container, child->child_key,
fuchsia::ui::viewsv1::ViewInfo());
}
break;
}
case fuchsia::ui::gfx::Event::Tag::kViewDisconnected: {
auto view_holder_id =
event.gfx().view_disconnected().view_holder_id;
FXL_CHECK(child->view_holder.id() == view_holder_id);
child->view_connected = ViewConnectionState::DISCONNECTED;
if (child->container) {
child->view_registry->SendChildUnavailable(child->container,
child->child_key);
}
break;
}
default:
break;
}
break;
default:
break;
}
}
}
ViewState* ViewContainerState::AsViewState() { return nullptr; }
ViewTreeState* ViewContainerState::AsViewTreeState() { return nullptr; }
std::ostream& operator<<(std::ostream& os, ViewContainerState* state) {
if (!state)
return os << "null";
return os << state->FormattedLabel();
}
} // namespace view_manager