blob: 0d0c438beb599f4a15557d9f7bbd5045b06335fc [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 <fuchsia/modular/cpp/fidl.h>
#include <fuchsia/ui/gfx/cpp/fidl.h>
#include <fuchsia/ui/views/cpp/fidl.h>
#include <fuchsia/ui/viewsv1token/cpp/fidl.h>
#include <lib/app_driver/cpp/app_driver.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async/cpp/task.h>
#include <lib/async/default.h>
#include <lib/component/cpp/startup_context.h>
#include <lib/ui/base_view/cpp/base_view.h>
#include <lib/ui/scenic/cpp/view_token_pair.h>
#include <lib/zx/eventpair.h>
#include <src/lib/fxl/logging.h>
#include <trace-provider/provider.h>
#include <array>
#include <memory>
#include "peridot/lib/fidl/single_service_app.h"
namespace {
constexpr int kSwapSeconds = 5;
constexpr std::array<const char*, 2> kModuleQueries{
{"swap_module1", "swap_module2"}};
class RecipeView : public scenic::BaseView {
public:
explicit RecipeView(scenic::ViewContext view_context)
: BaseView(std::move(view_context), "RecipeView") {}
~RecipeView() override = default;
void SetChild(fuchsia::ui::views::ViewHolderToken view_holder_token) {
if (host_node_) {
host_node_->Detach();
host_node_.reset();
host_view_holder_.reset();
}
if (view_holder_token.value) {
host_node_ = std::make_unique<scenic::EntityNode>(session());
host_view_holder_ = std::make_unique<scenic::ViewHolder>(
session(), std::move(view_holder_token), "Swap");
host_node_->SetTranslation(0.f, 0.f, -0.1f);
host_node_->Attach(*host_view_holder_);
root_node().AddChild(*host_node_);
}
}
private:
// |scenic::SessionListener|
void OnScenicError(std::string error) override {
FXL_LOG(ERROR) << "Scenic Error " << error;
}
// |scenic::BaseView|
void OnPropertiesChanged(fuchsia::ui::gfx::ViewProperties) override {
if (host_node_) {
auto child_properties = fuchsia::ui::gfx::ViewProperties::New();
fidl::Clone(view_properties(), child_properties.get());
host_view_holder_->SetViewProperties(*child_properties);
}
}
std::unique_ptr<scenic::EntityNode> host_node_;
std::unique_ptr<scenic::ViewHolder> host_view_holder_;
};
class RecipeApp : public modular::ViewApp {
public:
RecipeApp(component::StartupContext* const startup_context)
: ViewApp(startup_context) {
startup_context->ConnectToEnvironmentService(module_context_.NewRequest());
SwapModule();
}
~RecipeApp() override = default;
private:
// |ViewApp|
void CreateView(
zx::eventpair view_token,
fidl::InterfaceRequest<fuchsia::sys::ServiceProvider> incoming_services,
fidl::InterfaceHandle<fuchsia::sys::ServiceProvider> outgoing_services)
override {
auto scenic =
startup_context()
->ConnectToEnvironmentService<fuchsia::ui::scenic::Scenic>();
scenic::ViewContext view_context = {
.session_and_listener_request =
scenic::CreateScenicSessionPtrAndListenerRequest(scenic.get()),
.view_token = std::move(view_token),
.incoming_services = std::move(incoming_services),
.outgoing_services = std::move(outgoing_services),
.startup_context = startup_context(),
};
view_ = std::make_unique<RecipeView>(std::move(view_context));
SetChild();
}
void SwapModule() {
StartModule(kModuleQueries[query_index_]);
query_index_ = (query_index_ + 1) % kModuleQueries.size();
async::PostDelayedTask(
async_get_default_dispatcher(), [this] { SwapModule(); },
zx::sec(kSwapSeconds));
}
void StartModule(const std::string& module_query) {
if (module_) {
module_->Stop([this, module_query] {
module_.Unbind();
module_view_ =
fidl::InterfaceHandle<fuchsia::ui::viewsv1token::ViewOwner>();
StartModule(module_query);
});
return;
}
// This module is named after its URL.
fuchsia::modular::Intent intent;
intent.handler = module_query;
module_context_->EmbedModule(
module_query, std::move(intent), module_.NewRequest(),
module_view_.NewRequest(),
[](const fuchsia::modular::StartModuleStatus&) {});
SetChild();
}
void SetChild() {
if (view_ && module_view_) {
view_->SetChild(scenic::ToViewHolderToken(
zx::eventpair(module_view_.TakeChannel().release())));
}
}
fuchsia::modular::ModuleContextPtr module_context_;
fuchsia::modular::ModuleControllerPtr module_;
fidl::InterfaceHandle<fuchsia::ui::viewsv1token::ViewOwner> module_view_;
std::unique_ptr<RecipeView> view_;
int query_index_ = 0;
};
} // namespace
int main(int /*argc*/, const char** /*argv*/) {
async::Loop loop(&kAsyncLoopConfigAttachToThread);
trace::TraceProvider trace_provider(loop.dispatcher());
auto context = component::StartupContext::CreateFromStartupInfo();
modular::AppDriver<RecipeApp> driver(
context->outgoing().deprecated_services(),
std::make_unique<RecipeApp>(context.get()), [&loop] { loop.Quit(); });
loop.Run();
return 0;
}