fuchsia: Add child views to flatland engine (flutter/engine#28811)

This commit is contained in:
Emircan Uysaler 2021-09-27 15:13:01 -04:00 committed by GitHub
parent c9f351741d
commit ea8305d95f
13 changed files with 457 additions and 222 deletions

View File

@ -251,16 +251,27 @@ void Engine::Initialize(
OnEnableWireframe on_enable_wireframe_callback = std::bind(
&Engine::DebugWireframeSettingsChanged, this, std::placeholders::_1);
OnCreateView on_create_view_callback = std::bind(
&Engine::CreateView, this, std::placeholders::_1, std::placeholders::_2,
std::placeholders::_3, std::placeholders::_4, std::placeholders::_5);
OnCreateGfxView on_create_gfx_view_callback =
std::bind(&Engine::CreateGfxView, this, std::placeholders::_1,
std::placeholders::_2, std::placeholders::_3,
std::placeholders::_4, std::placeholders::_5);
OnCreateFlatlandView on_create_flatland_view_callback =
std::bind(&Engine::CreateFlatlandView, this, std::placeholders::_1,
std::placeholders::_2, std::placeholders::_3,
std::placeholders::_4, std::placeholders::_5);
OnUpdateView on_update_view_callback = std::bind(
&Engine::UpdateView, this, std::placeholders::_1, std::placeholders::_2,
std::placeholders::_3, std::placeholders::_4);
std::placeholders::_3, std::placeholders::_4, use_flatland);
OnDestroyView on_destroy_view_callback = std::bind(
&Engine::DestroyView, this, std::placeholders::_1, std::placeholders::_2);
OnDestroyGfxView on_destroy_gfx_view_callback =
std::bind(&Engine::DestroyGfxView, this, std::placeholders::_1,
std::placeholders::_2);
OnDestroyFlatlandView on_destroy_flatland_view_callback =
std::bind(&Engine::DestroyFlatlandView, this, std::placeholders::_1,
std::placeholders::_2);
OnCreateSurface on_create_surface_callback =
std::bind(&Engine::CreateSurface, this);
@ -330,9 +341,14 @@ void Engine::Initialize(
std::move(on_session_listener_error_callback),
on_enable_wireframe_callback =
std::move(on_enable_wireframe_callback),
on_create_view_callback = std::move(on_create_view_callback),
on_create_gfx_view_callback = std::move(on_create_gfx_view_callback),
on_create_flatland_view_callback =
std::move(on_create_flatland_view_callback),
on_update_view_callback = std::move(on_update_view_callback),
on_destroy_view_callback = std::move(on_destroy_view_callback),
on_destroy_gfx_view_callback =
std::move(on_destroy_gfx_view_callback),
on_destroy_flatland_view_callback =
std::move(on_destroy_flatland_view_callback),
on_create_surface_callback = std::move(on_create_surface_callback),
on_semantics_node_update_callback =
std::move(on_semantics_node_update_callback),
@ -408,9 +424,9 @@ void Engine::Initialize(
// fuchsia.ui.input3.KeyboardListener connection.
std::move(keyboard_listener_request),
std::move(on_enable_wireframe_callback),
std::move(on_create_view_callback),
std::move(on_create_flatland_view_callback),
std::move(on_update_view_callback),
std::move(on_destroy_view_callback),
std::move(on_destroy_flatland_view_callback),
std::move(on_create_surface_callback),
std::move(on_semantics_node_update_callback),
std::move(on_request_announce_callback),
@ -435,9 +451,9 @@ void Engine::Initialize(
std::move(keyboard_listener_request),
std::move(on_session_listener_error_callback),
std::move(on_enable_wireframe_callback),
std::move(on_create_view_callback),
std::move(on_create_gfx_view_callback),
std::move(on_update_view_callback),
std::move(on_destroy_view_callback),
std::move(on_destroy_gfx_view_callback),
std::move(on_create_surface_callback),
std::move(on_semantics_node_update_callback),
std::move(on_request_announce_callback),
@ -677,15 +693,12 @@ void Engine::DebugWireframeSettingsChanged(bool enabled) {
});
}
void Engine::CreateView(int64_t view_id,
ViewCallback on_view_created,
ViewIdCallback on_view_bound,
bool hit_testable,
bool focusable) {
void Engine::CreateGfxView(int64_t view_id,
ViewCallback on_view_created,
GfxViewIdCallback on_view_bound,
bool hit_testable,
bool focusable) {
FML_CHECK(shell_);
// TODO(fxbug.dev/64201): Add flatland hookup. |view_id| may be interpreted
// based on use_flatland from the initializer.
shell_->GetTaskRunners().GetRasterTaskRunner()->PostTask(
[this, view_id, hit_testable, focusable,
on_view_created = std::move(on_view_created),
@ -698,23 +711,46 @@ void Engine::CreateView(int64_t view_id,
});
}
void Engine::UpdateView(int64_t view_id,
SkRect occlusion_hint,
bool hit_testable,
bool focusable) {
void Engine::CreateFlatlandView(int64_t view_id,
ViewCallback on_view_created,
FlatlandViewCreatedCallback on_view_bound,
bool hit_testable,
bool focusable) {
FML_CHECK(shell_);
// TODO(fxbug.dev/64201): Add flatland hookup. |view_id| may be interpreted
// based on use_flatland from the initializer.
shell_->GetTaskRunners().GetRasterTaskRunner()->PostTask(
[this, view_id, occlusion_hint, hit_testable, focusable]() {
FML_CHECK(external_view_embedder_);
external_view_embedder_->SetViewProperties(view_id, occlusion_hint,
[this, view_id, hit_testable, focusable,
on_view_created = std::move(on_view_created),
on_view_bound = std::move(on_view_bound)]() {
FML_CHECK(flatland_view_embedder_);
flatland_view_embedder_->CreateView(view_id, std::move(on_view_created),
std::move(on_view_bound));
flatland_view_embedder_->SetViewProperties(view_id, SkRect::MakeEmpty(),
hit_testable, focusable);
});
}
void Engine::DestroyView(int64_t view_id, ViewIdCallback on_view_unbound) {
void Engine::UpdateView(int64_t view_id,
SkRect occlusion_hint,
bool hit_testable,
bool focusable,
bool use_flatland) {
FML_CHECK(shell_);
shell_->GetTaskRunners().GetRasterTaskRunner()->PostTask(
[this, use_flatland, view_id, occlusion_hint, hit_testable, focusable]() {
if (use_flatland) {
FML_CHECK(flatland_view_embedder_);
flatland_view_embedder_->SetViewProperties(view_id, occlusion_hint,
hit_testable, focusable);
} else {
FML_CHECK(external_view_embedder_);
external_view_embedder_->SetViewProperties(view_id, occlusion_hint,
hit_testable, focusable);
}
});
}
void Engine::DestroyGfxView(int64_t view_id,
GfxViewIdCallback on_view_unbound) {
FML_CHECK(shell_);
// TODO(fxbug.dev/64201): Add flatland hookup. |view_id| may be interpreted
@ -727,6 +763,20 @@ void Engine::DestroyView(int64_t view_id, ViewIdCallback on_view_unbound) {
});
}
void Engine::DestroyFlatlandView(int64_t view_id,
FlatlandViewIdCallback on_view_unbound) {
FML_CHECK(shell_);
// TODO(fxbug.dev/64201): Add flatland hookup. |view_id| may be interpreted
// based on use_flatland from the initializer.
shell_->GetTaskRunners().GetRasterTaskRunner()->PostTask(
[this, view_id, on_view_unbound = std::move(on_view_unbound)]() {
FML_CHECK(flatland_view_embedder_);
flatland_view_embedder_->DestroyView(view_id,
std::move(on_view_unbound));
});
}
std::unique_ptr<flutter::Surface> Engine::CreateSurface() {
return std::make_unique<Surface>(thread_label_, GetExternalViewEmbedder(),
surface_producer_->gr_context());

View File

@ -147,16 +147,24 @@ class Engine final : public fuchsia::memorypressure::Watcher {
void Terminate();
void DebugWireframeSettingsChanged(bool enabled);
void CreateView(int64_t view_id,
ViewCallback on_view_created,
ViewIdCallback on_view_bound,
bool hit_testable,
bool focusable);
void CreateGfxView(int64_t view_id,
ViewCallback on_view_created,
GfxViewIdCallback on_view_bound,
bool hit_testable,
bool focusable);
void CreateFlatlandView(int64_t view_id,
ViewCallback on_view_created,
FlatlandViewCreatedCallback on_view_bound,
bool hit_testable,
bool focusable);
void UpdateView(int64_t view_id,
SkRect occlusion_hint,
bool hit_testable,
bool focusable);
void DestroyView(int64_t view_id, ViewIdCallback on_view_unbound);
bool focusable,
bool use_flatland);
void DestroyGfxView(int64_t view_id, GfxViewIdCallback on_view_unbound);
void DestroyFlatlandView(int64_t view_id,
FlatlandViewIdCallback on_view_unbound);
// |fuchsia::memorypressure::Watcher|
void OnLevelChanged(fuchsia::memorypressure::Level level,

View File

@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "flatland_external_view_embedder.h"
#include <cstdint>
#include "flutter/fml/trace_event.h"
#include "third_party/skia/include/core/SkPicture.h"
@ -10,6 +11,8 @@
namespace flutter_runner {
constexpr uint32_t kFlatlandDefaultViewportSize = 32;
FlatlandExternalViewEmbedder::FlatlandExternalViewEmbedder(
std::string debug_label,
fuchsia::ui::views::ViewCreationToken view_creation_token,
@ -318,22 +321,26 @@ void FlatlandExternalViewEmbedder::SubmitFrame(
void FlatlandExternalViewEmbedder::CreateView(
int64_t view_id,
FlatlandViewCallback on_view_created,
FlatlandViewIdCallback on_view_bound) {
ViewCallback on_view_created,
FlatlandViewCreatedCallback on_view_bound) {
FML_CHECK(flatland_views_.find(view_id) == flatland_views_.end());
FlatlandView new_view = {.transform_id = flatland_.NextTransformId(),
.viewport_id = flatland_.NextContentId()};
flatland_.flatland()->CreateTransform(new_view.transform_id);
fuchsia::ui::composition::ViewportProperties properties;
// TODO(fxbug.dev/64201): Add initial viewport size.
// TODO(fxbug.dev/64201): Investigate if it is possible to avoid using a
// default size by finding the size before creation.
properties.set_logical_size(
{kFlatlandDefaultViewportSize, kFlatlandDefaultViewportSize});
fuchsia::ui::composition::ChildViewWatcherPtr child_view_watcher;
flatland_.flatland()->CreateViewport(
new_view.viewport_id, {zx::channel((zx_handle_t)view_id)},
std::move(properties), new_view.content_link.NewRequest());
std::move(properties), child_view_watcher.NewRequest());
flatland_.flatland()->SetContent(new_view.transform_id, new_view.viewport_id);
on_view_created();
on_view_bound(new_view.viewport_id);
on_view_bound(new_view.viewport_id, std::move(child_view_watcher));
flatland_views_.emplace(std::make_pair(view_id, std::move(new_view)));
}

View File

@ -30,7 +30,10 @@
namespace flutter_runner {
using FlatlandViewCallback = std::function<void()>;
using ViewCallback = std::function<void()>;
using FlatlandViewCreatedCallback = std::function<void(
fuchsia::ui::composition::ContentId,
fuchsia::ui::composition::ChildViewWatcherPtr child_view_watcher)>;
using FlatlandViewIdCallback =
std::function<void(fuchsia::ui::composition::ContentId)>;
@ -95,8 +98,8 @@ class FlatlandExternalViewEmbedder final
// |SetViewProperties| doesn't manipulate the view directly -- it sets pending
// properties for the next |UpdateView| call.
void CreateView(int64_t view_id,
FlatlandViewCallback on_view_created,
FlatlandViewIdCallback on_view_bound);
ViewCallback on_view_created,
FlatlandViewCreatedCallback on_view_bound);
void DestroyView(int64_t view_id, FlatlandViewIdCallback on_view_unbound);
void SetViewProperties(int64_t view_id,
const SkRect& occlusion_hint,
@ -153,7 +156,6 @@ class FlatlandExternalViewEmbedder final
struct FlatlandView {
fuchsia::ui::composition::TransformId transform_id;
fuchsia::ui::composition::ContentId viewport_id;
fuchsia::ui::composition::ChildViewWatcherPtr content_link;
ViewMutators mutators;
SkSize size = SkSize::MakeEmpty();
};

View File

@ -23,9 +23,9 @@ FlatlandPlatformView::FlatlandPlatformView(
fidl::InterfaceRequest<fuchsia::ui::input3::KeyboardListener>
keyboard_listener,
OnEnableWireframe wireframe_enabled_callback,
OnCreateView on_create_view_callback,
OnCreateFlatlandView on_create_view_callback,
OnUpdateView on_update_view_callback,
OnDestroyView on_destroy_view_callback,
OnDestroyFlatlandView on_destroy_view_callback,
OnCreateSurface on_create_surface_callback,
OnSemanticsNodeUpdate on_semantics_node_update_callback,
OnRequestAnnounce on_request_announce_callback,
@ -45,9 +45,7 @@ FlatlandPlatformView::FlatlandPlatformView(
std::move(touch_source),
std::move(keyboard_listener),
std::move(wireframe_enabled_callback),
std::move(on_create_view_callback),
std::move(on_update_view_callback),
std::move(on_destroy_view_callback),
std::move(on_create_surface_callback),
std::move(on_semantics_node_update_callback),
std::move(on_request_announce_callback),
@ -55,7 +53,10 @@ FlatlandPlatformView::FlatlandPlatformView(
std::move(view_embedder),
std::move(await_vsync_callback),
std::move(await_vsync_for_secondary_callback_callback)),
parent_viewport_watcher_(std::move(parent_viewport_watcher)) {
parent_viewport_watcher_(std::move(parent_viewport_watcher)),
on_create_view_callback_(std::move(on_create_view_callback)),
on_destroy_view_callback_(std::move(on_destroy_view_callback)),
weak_factory_(this) {
parent_viewport_watcher_.set_error_handler([](zx_status_t status) {
FML_LOG(ERROR) << "Interface error on: ParentViewportWatcher status: "
<< status;
@ -63,6 +64,8 @@ FlatlandPlatformView::FlatlandPlatformView(
parent_viewport_watcher_->GetLayout(
fit::bind_member(this, &FlatlandPlatformView::OnGetLayout));
parent_viewport_watcher_->GetStatus(
fit::bind_member(this, &FlatlandPlatformView::OnParentViewportStatus));
}
FlatlandPlatformView::~FlatlandPlatformView() = default;
@ -97,4 +100,106 @@ void FlatlandPlatformView::OnGetLayout(
fit::bind_member(this, &FlatlandPlatformView::OnGetLayout));
}
void FlatlandPlatformView::OnParentViewportStatus(
fuchsia::ui::composition::ParentViewportStatus status) {
// TODO(fxbug.dev/64201): Investigate if it is useful to send hidden/shown
// signals.
parent_viewport_status_ = status;
parent_viewport_watcher_->GetStatus(
fit::bind_member(this, &FlatlandPlatformView::OnParentViewportStatus));
}
void FlatlandPlatformView::OnChildViewStatus(
uint64_t content_id,
fuchsia::ui::composition::ChildViewStatus status) {
FML_DCHECK(child_view_info_.count(content_id) == 1);
std::ostringstream out;
out << "{"
<< "\"method\":\"View.viewStateChanged\","
<< "\"args\":{"
<< " \"viewId\":" << child_view_info_.at(content_id).view_id
<< "," // ViewId
<< " \"is_rendering\":true," // IsViewRendering
<< " \"state\":true" // IsViewRendering
<< " }"
<< "}";
auto call = out.str();
std::unique_ptr<flutter::PlatformMessage> message =
std::make_unique<flutter::PlatformMessage>(
"flutter/platform_views",
fml::MallocMapping::Copy(call.c_str(), call.size()), nullptr);
DispatchPlatformMessage(std::move(message));
child_view_info_.at(content_id)
.child_view_watcher->GetStatus(
[this, content_id](fuchsia::ui::composition::ChildViewStatus status) {
OnChildViewStatus(content_id, status);
});
}
void FlatlandPlatformView::OnCreateView(ViewCallback on_view_created,
int64_t view_id_raw,
bool hit_testable,
bool focusable) {
auto on_view_bound = [weak = weak_factory_.GetWeakPtr(),
platform_task_runner =
task_runners_.GetPlatformTaskRunner(),
view_id = view_id_raw](
fuchsia::ui::composition::ContentId content_id,
fuchsia::ui::composition::ChildViewWatcherPtr
child_view_watcher) {
child_view_watcher.set_error_handler([](zx_status_t status) {
FML_LOG(ERROR) << "Interface error on: ChildViewWatcher status: "
<< status;
});
platform_task_runner->PostTask(
fml::MakeCopyable([weak, view_id, content_id,
watcher = std::move(child_view_watcher)]() mutable {
if (!weak) {
FML_LOG(WARNING)
<< "Flatland View bound to PlatformView after PlatformView was "
"destroyed; ignoring.";
return;
}
FML_DCHECK(weak->child_view_info_.count(content_id.value) == 0);
FML_DCHECK(watcher);
weak->child_view_info_.emplace(
std::piecewise_construct, std::forward_as_tuple(content_id.value),
std::forward_as_tuple(view_id, std::move(watcher)));
weak->child_view_info_.at(content_id.value)
.child_view_watcher->GetStatus(
[weak, id = content_id.value](
fuchsia::ui::composition::ChildViewStatus status) {
weak->OnChildViewStatus(id, status);
});
}));
};
on_create_view_callback_(view_id_raw, std::move(on_view_created),
std::move(on_view_bound), hit_testable, focusable);
}
void FlatlandPlatformView::OnDisposeView(int64_t view_id_raw) {
auto on_view_unbound =
[weak = weak_factory_.GetWeakPtr(),
platform_task_runner = task_runners_.GetPlatformTaskRunner()](
fuchsia::ui::composition::ContentId content_id) {
platform_task_runner->PostTask([weak, content_id]() {
if (!weak) {
FML_LOG(WARNING)
<< "Flatland View unbound from PlatformView after PlatformView"
"was destroyed; ignoring.";
return;
}
FML_DCHECK(weak->child_view_info_.count(content_id.value) == 1);
weak->child_view_info_.erase(content_id.value);
});
};
on_destroy_view_callback_(view_id_raw, std::move(on_view_unbound));
}
} // namespace flutter_runner

View File

@ -5,11 +5,21 @@
#ifndef FLUTTER_SHELL_PLATFORM_FUCHSIA_FLUTTER_FLATLAND_PLATFORM_VIEW_H_
#define FLUTTER_SHELL_PLATFORM_FUCHSIA_FLUTTER_FLATLAND_PLATFORM_VIEW_H_
#include "platform_view.h"
#include "flutter/shell/platform/fuchsia/flutter/platform_view.h"
#include <fuchsia/ui/composition/cpp/fidl.h>
#include "flutter/fml/memory/weak_ptr.h"
#include "flutter/shell/platform/fuchsia/flutter/flatland_external_view_embedder.h"
namespace flutter_runner {
// The FlatlandPlatformView...
using OnCreateFlatlandView = fit::function<
void(int64_t, ViewCallback, FlatlandViewCreatedCallback, bool, bool)>;
using OnDestroyFlatlandView =
fit::function<void(int64_t, FlatlandViewIdCallback)>;
// The FlatlandPlatformView that does Flatland specific...
class FlatlandPlatformView final : public flutter_runner::PlatformView {
public:
FlatlandPlatformView(
@ -28,9 +38,9 @@ class FlatlandPlatformView final : public flutter_runner::PlatformView {
fidl::InterfaceRequest<fuchsia::ui::input3::KeyboardListener>
keyboard_listener,
OnEnableWireframe wireframe_enabled_callback,
OnCreateView on_create_view_callback,
OnCreateFlatlandView on_create_view_callback,
OnUpdateView on_update_view_callback,
OnDestroyView on_destroy_view_callback,
OnDestroyFlatlandView on_destroy_view_callback,
OnCreateSurface on_create_surface_callback,
OnSemanticsNodeUpdate on_semantics_node_update_callback,
OnRequestAnnounce on_request_announce_callback,
@ -42,10 +52,41 @@ class FlatlandPlatformView final : public flutter_runner::PlatformView {
~FlatlandPlatformView();
void OnGetLayout(fuchsia::ui::composition::LayoutInfo info);
void OnParentViewportStatus(
fuchsia::ui::composition::ParentViewportStatus status);
void OnChildViewStatus(uint64_t content_id,
fuchsia::ui::composition::ChildViewStatus status);
private:
void OnCreateView(ViewCallback on_view_created,
int64_t view_id_raw,
bool hit_testable,
bool focusable) override;
void OnDisposeView(int64_t view_id_raw) override;
// child_view_ids_ maintains a persistent mapping from Flatland ContentId's to
// flutter view ids, which are really zx_handle_t of ViewCreationToken.
struct ChildViewInfo {
ChildViewInfo(zx_handle_t token,
fuchsia::ui::composition::ChildViewWatcherPtr watcher)
: view_id(token), child_view_watcher(std::move(watcher)) {}
zx_handle_t view_id;
fuchsia::ui::composition::ChildViewWatcherPtr child_view_watcher;
};
std::unordered_map<uint64_t /*fuchsia::ui::composition::ContentId*/,
ChildViewInfo>
child_view_info_;
fuchsia::ui::composition::ParentViewportWatcherPtr parent_viewport_watcher_;
OnCreateFlatlandView on_create_view_callback_;
OnDestroyFlatlandView on_destroy_view_callback_;
fuchsia::ui::composition::ParentViewportStatus parent_viewport_status_;
fml::WeakPtrFactory<FlatlandPlatformView>
weak_factory_; // Must be the last member.
FML_DISALLOW_COPY_AND_ASSIGN(FlatlandPlatformView);
};

View File

@ -578,7 +578,7 @@ void FuchsiaExternalViewEmbedder::EnableWireframe(bool enable) {
void FuchsiaExternalViewEmbedder::CreateView(int64_t view_id,
ViewCallback on_view_created,
ViewIdCallback on_view_bound) {
GfxViewIdCallback on_view_bound) {
FML_CHECK(scenic_views_.find(view_id) == scenic_views_.end());
ScenicView new_view = {
@ -602,8 +602,9 @@ void FuchsiaExternalViewEmbedder::CreateView(int64_t view_id,
scenic_views_.emplace(std::make_pair(view_id, std::move(new_view)));
}
void FuchsiaExternalViewEmbedder::DestroyView(int64_t view_id,
ViewIdCallback on_view_unbound) {
void FuchsiaExternalViewEmbedder::DestroyView(
int64_t view_id,
GfxViewIdCallback on_view_unbound) {
auto scenic_view = scenic_views_.find(view_id);
FML_CHECK(scenic_view != scenic_views_.end());
scenic::ResourceId resource_id = scenic_view->second.view_holder.id();

View File

@ -33,7 +33,7 @@
namespace flutter_runner {
using ViewCallback = std::function<void()>;
using ViewIdCallback = std::function<void(scenic::ResourceId)>;
using GfxViewIdCallback = std::function<void(scenic::ResourceId)>;
// This struct represents a transformed clip rect.
struct TransformedClip {
@ -126,8 +126,8 @@ class FuchsiaExternalViewEmbedder final : public flutter::ExternalViewEmbedder {
void EnableWireframe(bool enable);
void CreateView(int64_t view_id,
ViewCallback on_view_created,
ViewIdCallback on_view_bound);
void DestroyView(int64_t view_id, ViewIdCallback on_view_unbound);
GfxViewIdCallback on_view_bound);
void DestroyView(int64_t view_id, GfxViewIdCallback on_view_unbound);
void SetViewProperties(int64_t view_id,
const SkRect& occlusion_hint,
bool hit_testable,

View File

@ -25,9 +25,9 @@ GfxPlatformView::GfxPlatformView(
keyboard_listener,
fit::closure on_session_listener_error_callback,
OnEnableWireframe wireframe_enabled_callback,
OnCreateView on_create_view_callback,
OnCreateGfxView on_create_view_callback,
OnUpdateView on_update_view_callback,
OnDestroyView on_destroy_view_callback,
OnDestroyGfxView on_destroy_view_callback,
OnCreateSurface on_create_surface_callback,
OnSemanticsNodeUpdate on_semantics_node_update_callback,
OnRequestAnnounce on_request_announce_callback,
@ -47,9 +47,7 @@ GfxPlatformView::GfxPlatformView(
std::move(touch_source),
std::move(keyboard_listener),
std::move(wireframe_enabled_callback),
std::move(on_create_view_callback),
std::move(on_update_view_callback),
std::move(on_destroy_view_callback),
std::move(on_create_surface_callback),
std::move(on_semantics_node_update_callback),
std::move(on_request_announce_callback),
@ -60,6 +58,8 @@ GfxPlatformView::GfxPlatformView(
session_listener_binding_(this, std::move(session_listener_request)),
session_listener_error_callback_(
std::move(on_session_listener_error_callback)),
on_create_view_callback_(std::move(on_create_view_callback)),
on_destroy_view_callback_(std::move(on_destroy_view_callback)),
weak_factory_(this) {
session_listener_binding_.set_error_handler([](zx_status_t status) {
FML_LOG(ERROR) << "Interface error on: SessionListener, status: " << status;
@ -261,4 +261,125 @@ void GfxPlatformView::OnScenicEvent(
}
}
bool GfxPlatformView::OnChildViewConnected(scenic::ResourceId view_holder_id) {
auto view_id_mapping = child_view_ids_.find(view_holder_id);
if (view_id_mapping == child_view_ids_.end()) {
return false;
}
std::ostringstream out;
out << "{"
<< "\"method\":\"View.viewConnected\","
<< "\"args\":{"
<< " \"viewId\":" << view_id_mapping->second // ViewHolderToken handle
<< " }"
<< "}";
auto call = out.str();
std::unique_ptr<flutter::PlatformMessage> message =
std::make_unique<flutter::PlatformMessage>(
"flutter/platform_views",
fml::MallocMapping::Copy(call.c_str(), call.size()), nullptr);
DispatchPlatformMessage(std::move(message));
return true;
}
bool GfxPlatformView::OnChildViewDisconnected(
scenic::ResourceId view_holder_id) {
auto view_id_mapping = child_view_ids_.find(view_holder_id);
if (view_id_mapping == child_view_ids_.end()) {
return false;
}
std::ostringstream out;
out << "{"
<< "\"method\":\"View.viewDisconnected\","
<< "\"args\":{"
<< " \"viewId\":" << view_id_mapping->second // ViewHolderToken handle
<< " }"
<< "}";
auto call = out.str();
std::unique_ptr<flutter::PlatformMessage> message =
std::make_unique<flutter::PlatformMessage>(
"flutter/platform_views",
fml::MallocMapping::Copy(call.c_str(), call.size()), nullptr);
DispatchPlatformMessage(std::move(message));
return true;
}
bool GfxPlatformView::OnChildViewStateChanged(scenic::ResourceId view_holder_id,
bool is_rendering) {
auto view_id_mapping = child_view_ids_.find(view_holder_id);
if (view_id_mapping == child_view_ids_.end()) {
return false;
}
const std::string is_rendering_str = is_rendering ? "true" : "false";
std::ostringstream out;
out << "{"
<< "\"method\":\"View.viewStateChanged\","
<< "\"args\":{"
<< " \"viewId\":" << view_id_mapping->second << "," // ViewHolderToken
<< " \"is_rendering\":" << is_rendering_str << "," // IsViewRendering
<< " \"state\":" << is_rendering_str // IsViewRendering
<< " }"
<< "}";
auto call = out.str();
std::unique_ptr<flutter::PlatformMessage> message =
std::make_unique<flutter::PlatformMessage>(
"flutter/platform_views",
fml::MallocMapping::Copy(call.c_str(), call.size()), nullptr);
DispatchPlatformMessage(std::move(message));
return true;
}
void GfxPlatformView::OnCreateView(ViewCallback on_view_created,
int64_t view_id_raw,
bool hit_testable,
bool focusable) {
auto on_view_bound =
[weak = weak_factory_.GetWeakPtr(),
platform_task_runner = task_runners_.GetPlatformTaskRunner(),
view_id = view_id_raw](scenic::ResourceId resource_id) {
platform_task_runner->PostTask([weak, view_id, resource_id]() {
if (!weak) {
FML_LOG(WARNING)
<< "ViewHolder bound to PlatformView after PlatformView was "
"destroyed; ignoring.";
return;
}
FML_DCHECK(weak->child_view_ids_.count(resource_id) == 0);
weak->child_view_ids_[resource_id] = view_id;
});
};
on_create_view_callback_(view_id_raw, std::move(on_view_created),
std::move(on_view_bound), hit_testable, focusable);
}
void GfxPlatformView::OnDisposeView(int64_t view_id_raw) {
auto on_view_unbound =
[weak = weak_factory_.GetWeakPtr(),
platform_task_runner = task_runners_.GetPlatformTaskRunner()](
scenic::ResourceId resource_id) {
platform_task_runner->PostTask([weak, resource_id]() {
if (!weak) {
FML_LOG(WARNING)
<< "ViewHolder unbound from PlatformView after PlatformView"
"was destroyed; ignoring.";
return;
}
FML_DCHECK(weak->child_view_ids_.count(resource_id) == 1);
weak->child_view_ids_.erase(resource_id);
});
};
on_destroy_view_callback_(view_id_raw, std::move(on_view_unbound));
}
} // namespace flutter_runner

View File

@ -5,13 +5,20 @@
#ifndef FLUTTER_SHELL_PLATFORM_FUCHSIA_FLUTTER_GFX_PLATFORM_VIEW_H_
#define FLUTTER_SHELL_PLATFORM_FUCHSIA_FLUTTER_GFX_PLATFORM_VIEW_H_
#include "platform_view.h"
#include "flutter/shell/platform/fuchsia/flutter/platform_view.h"
#include <fuchsia/ui/gfx/cpp/fidl.h>
#include <fuchsia/ui/pointer/cpp/fidl.h>
#include "flutter/fml/memory/weak_ptr.h"
#include "flutter/shell/platform/fuchsia/flutter/fuchsia_external_view_embedder.h"
namespace flutter_runner {
using OnCreateGfxView =
fit::function<void(int64_t, ViewCallback, GfxViewIdCallback, bool, bool)>;
using OnDestroyGfxView = fit::function<void(int64_t, GfxViewIdCallback)>;
// The GfxPlatformView implements SessionListener and gets Session events but it
// does *not* actually own the Session itself; that is owned by the
// FuchsiaExternalViewEmbedder on the raster thread.
@ -35,9 +42,9 @@ class GfxPlatformView final : public flutter_runner::PlatformView,
keyboard_listener,
fit::closure on_session_listener_error_callback,
OnEnableWireframe wireframe_enabled_callback,
OnCreateView on_create_view_callback,
OnCreateGfxView on_create_view_callback,
OnUpdateView on_update_view_callback,
OnDestroyView on_destroy_view_callback,
OnDestroyGfxView on_destroy_view_callback,
OnCreateSurface on_create_surface_callback,
OnSemanticsNodeUpdate on_semantics_node_update_callback,
OnRequestAnnounce on_request_announce_callback,
@ -53,9 +60,30 @@ class GfxPlatformView final : public flutter_runner::PlatformView,
void OnScenicError(std::string error) override;
void OnScenicEvent(std::vector<fuchsia::ui::scenic::Event> events) override;
// ViewHolder event handlers. These return false if the ViewHolder
// corresponding to `view_holder_id` could not be found and the evnt was
// unhandled.
bool OnChildViewConnected(scenic::ResourceId view_holder_id);
bool OnChildViewDisconnected(scenic::ResourceId view_holder_id);
bool OnChildViewStateChanged(scenic::ResourceId view_holder_id,
bool is_rendering);
void OnCreateView(ViewCallback on_view_created,
int64_t view_id_raw,
bool hit_testable,
bool focusable) override;
void OnDisposeView(int64_t view_id_raw) override;
fidl::Binding<fuchsia::ui::scenic::SessionListener> session_listener_binding_;
fit::closure session_listener_error_callback_;
// child_view_ids_ maintains a persistent mapping from Scenic ResourceId's to
// flutter view ids, which are really zx_handle_t of ViewHolderToken.
std::unordered_map<scenic::ResourceId, zx_handle_t> child_view_ids_;
OnCreateGfxView on_create_view_callback_;
OnDestroyGfxView on_destroy_view_callback_;
fml::WeakPtrFactory<GfxPlatformView>
weak_factory_; // Must be the last member.

View File

@ -64,9 +64,7 @@ PlatformView::PlatformView(
fidl::InterfaceRequest<fuchsia::ui::input3::KeyboardListener>
keyboard_listener_request,
OnEnableWireframe wireframe_enabled_callback,
OnCreateView on_create_view_callback,
OnUpdateView on_update_view_callback,
OnDestroyView on_destroy_view_callback,
OnCreateSurface on_create_surface_callback,
OnSemanticsNodeUpdate on_semantics_node_update_callback,
OnRequestAnnounce on_request_announce_callback,
@ -83,9 +81,7 @@ PlatformView::PlatformView(
pointer_delegate_(
std::make_shared<PointerDelegate>(std::move(touch_source))),
wireframe_enabled_callback_(std::move(wireframe_enabled_callback)),
on_create_view_callback_(std::move(on_create_view_callback)),
on_update_view_callback_(std::move(on_update_view_callback)),
on_destroy_view_callback_(std::move(on_destroy_view_callback)),
on_create_surface_callback_(std::move(on_create_surface_callback)),
on_semantics_node_update_callback_(
std::move(on_semantics_node_update_callback)),
@ -255,82 +251,6 @@ void PlatformView::OnAction(fuchsia::ui::input::InputMethodAction action) {
);
}
bool PlatformView::OnChildViewConnected(scenic::ResourceId view_holder_id) {
auto view_id_mapping = child_view_ids_.find(view_holder_id);
if (view_id_mapping == child_view_ids_.end()) {
return false;
}
std::ostringstream out;
out << "{"
<< "\"method\":\"View.viewConnected\","
<< "\"args\":{"
<< " \"viewId\":" << view_id_mapping->second // ViewHolderToken handle
<< " }"
<< "}";
auto call = out.str();
std::unique_ptr<flutter::PlatformMessage> message =
std::make_unique<flutter::PlatformMessage>(
"flutter/platform_views",
fml::MallocMapping::Copy(call.c_str(), call.size()), nullptr);
DispatchPlatformMessage(std::move(message));
return true;
}
bool PlatformView::OnChildViewDisconnected(scenic::ResourceId view_holder_id) {
auto view_id_mapping = child_view_ids_.find(view_holder_id);
if (view_id_mapping == child_view_ids_.end()) {
return false;
}
std::ostringstream out;
out << "{"
<< "\"method\":\"View.viewDisconnected\","
<< "\"args\":{"
<< " \"viewId\":" << view_id_mapping->second // ViewHolderToken handle
<< " }"
<< "}";
auto call = out.str();
std::unique_ptr<flutter::PlatformMessage> message =
std::make_unique<flutter::PlatformMessage>(
"flutter/platform_views",
fml::MallocMapping::Copy(call.c_str(), call.size()), nullptr);
DispatchPlatformMessage(std::move(message));
return true;
}
bool PlatformView::OnChildViewStateChanged(scenic::ResourceId view_holder_id,
bool is_rendering) {
auto view_id_mapping = child_view_ids_.find(view_holder_id);
if (view_id_mapping == child_view_ids_.end()) {
return false;
}
const std::string is_rendering_str = is_rendering ? "true" : "false";
std::ostringstream out;
out << "{"
<< "\"method\":\"View.viewStateChanged\","
<< "\"args\":{"
<< " \"viewId\":" << view_id_mapping->second << "," // ViewHolderToken
<< " \"is_rendering\":" << is_rendering_str << "," // IsViewRendering
<< " \"state\":" << is_rendering_str // IsViewRendering
<< " }"
<< "}";
auto call = out.str();
std::unique_ptr<flutter::PlatformMessage> message =
std::make_unique<flutter::PlatformMessage>(
"flutter/platform_views",
fml::MallocMapping::Copy(call.c_str(), call.size()), nullptr);
DispatchPlatformMessage(std::move(message));
return true;
}
static flutter::PointerData::Change GetChangeFromPointerEventPhase(
fuchsia::ui::input::PointerEventPhase phase) {
switch (phase) {
@ -800,7 +720,6 @@ bool PlatformView::HandleFlutterPlatformViewsChannelPlatformMessage(
return false;
}
const int64_t view_id_raw = view_id->value.GetUint64();
auto on_view_created = fml::MakeCopyable(
[platform_task_runner = task_runners_.GetPlatformTaskRunner(),
message = std::move(message)]() {
@ -811,25 +730,8 @@ bool PlatformView::HandleFlutterPlatformViewsChannelPlatformMessage(
std::vector<uint8_t>({'[', '0', ']'})));
}
});
auto on_view_bound =
[weak = weak_factory_.GetWeakPtr(),
platform_task_runner = task_runners_.GetPlatformTaskRunner(),
view_id = view_id_raw](scenic::ResourceId resource_id) {
platform_task_runner->PostTask([weak, view_id, resource_id]() {
if (!weak) {
FML_LOG(WARNING)
<< "ViewHolder bound to PlatformView after PlatformView was "
"destroyed; ignoring.";
return;
}
FML_DCHECK(weak->child_view_ids_.count(resource_id) == 0);
weak->child_view_ids_[resource_id] = view_id;
});
};
on_create_view_callback_(
view_id_raw, std::move(on_view_created), std::move(on_view_bound),
hit_testable->value.GetBool(), focusable->value.GetBool());
OnCreateView(std::move(on_view_created), view_id->value.GetUint64(),
hit_testable->value.GetBool(), focusable->value.GetBool());
return true;
} else if (method == "View.update") {
auto args_it = root.FindMember("args");
@ -917,24 +819,7 @@ bool PlatformView::HandleFlutterPlatformViewsChannelPlatformMessage(
return false;
}
const int64_t view_id_raw = view_id->value.GetUint64();
auto on_view_unbound =
[weak = weak_factory_.GetWeakPtr(),
platform_task_runner = task_runners_.GetPlatformTaskRunner()](
scenic::ResourceId resource_id) {
platform_task_runner->PostTask([weak, resource_id]() {
if (!weak) {
FML_LOG(WARNING)
<< "ViewHolder unbound from PlatformView after PlatformView"
"was destroyed; ignoring.";
return;
}
FML_DCHECK(weak->child_view_ids_.count(resource_id) == 1);
weak->child_view_ids_.erase(resource_id);
});
};
on_destroy_view_callback_(view_id_raw, std::move(on_view_unbound));
OnDisposeView(view_id->value.GetUint64());
if (message->response()) {
message->response()->Complete(std::make_unique<fml::DataMapping>(
std::vector<uint8_t>({'[', '0', ']'})));

View File

@ -29,7 +29,6 @@
#include "flutter/fml/memory/weak_ptr.h"
#include "flutter/fml/time/time_delta.h"
#include "flutter/shell/common/platform_view.h"
#include "flutter/shell/platform/fuchsia/flutter/fuchsia_external_view_embedder.h"
#include "flutter/shell/platform/fuchsia/flutter/keyboard.h"
#include "flutter/shell/platform/fuchsia/flutter/vsync_waiter.h"
#include "focus_delegate.h"
@ -38,10 +37,8 @@
namespace flutter_runner {
using OnEnableWireframe = fit::function<void(bool)>;
using OnCreateView =
fit::function<void(int64_t, ViewCallback, ViewIdCallback, bool, bool)>;
using ViewCallback = std::function<void()>;
using OnUpdateView = fit::function<void(int64_t, SkRect, bool, bool)>;
using OnDestroyView = fit::function<void(int64_t, ViewIdCallback)>;
using OnCreateSurface = fit::function<std::unique_ptr<flutter::Surface>()>;
using OnSemanticsNodeUpdate =
fit::function<void(flutter::SemanticsNodeUpdates, float)>;
@ -80,9 +77,7 @@ class PlatformView : public flutter::PlatformView,
fidl::InterfaceRequest<fuchsia::ui::input3::KeyboardListener>
keyboard_listener,
OnEnableWireframe wireframe_enabled_callback,
OnCreateView on_create_view_callback,
OnUpdateView on_update_view_callback,
OnDestroyView on_destroy_view_callback,
OnCreateSurface on_create_surface_callback,
OnSemanticsNodeUpdate on_semantics_node_update_callback,
OnRequestAnnounce on_request_announce_callback,
@ -118,14 +113,6 @@ class PlatformView : public flutter::PlatformView,
// |fuchsia::ui::input::InputMethodEditorClient|
void OnAction(fuchsia::ui::input::InputMethodAction action) override;
// ViewHolder event handlers. These return false if the ViewHolder
// corresponding to `view_holder_id` could not be found and the evnt was
// unhandled.
bool OnChildViewConnected(scenic::ResourceId view_holder_id);
bool OnChildViewDisconnected(scenic::ResourceId view_holder_id);
bool OnChildViewStateChanged(scenic::ResourceId view_holder_id,
bool is_rendering);
bool OnHandlePointerEvent(const fuchsia::ui::input::PointerEvent& pointer);
bool OnHandleFocusEvent(const fuchsia::ui::input::FocusEvent& focus);
@ -178,6 +165,12 @@ class PlatformView : public flutter::PlatformView,
OnShaderWarmup on_shader_warmup,
std::unique_ptr<flutter::PlatformMessage> message);
virtual void OnCreateView(ViewCallback on_view_created,
int64_t view_id_raw,
bool hit_testable,
bool focusable) = 0;
virtual void OnDisposeView(int64_t view_id_raw) = 0;
// Utility function for coordinate massaging.
std::array<float, 2> ClampToViewSpace(const float x, const float y) const;
@ -200,9 +193,7 @@ class PlatformView : public flutter::PlatformView,
std::optional<float> view_pixel_ratio_;
OnEnableWireframe wireframe_enabled_callback_;
OnCreateView on_create_view_callback_;
OnUpdateView on_update_view_callback_;
OnDestroyView on_destroy_view_callback_;
OnCreateSurface on_create_surface_callback_;
// Accessibility handlers:
@ -219,10 +210,6 @@ class PlatformView : public flutter::PlatformView,
fuchsia::sys::ServiceProviderPtr parent_environment_service_provider_;
// child_view_ids_ maintains a persistent mapping from Scenic ResourceId's to
// flutter view ids, which are really zx_handle_t of ViewHolderToken.
std::unordered_map<scenic::ResourceId, zx_handle_t> child_view_ids_;
// last_text_state_ is the last state of the text input as reported by the IME
// or initialized by Flutter. We set it to null if Flutter doesn't want any
// input, since then there is no text input state at all.

View File

@ -215,7 +215,7 @@ class PlatformViewBuilder {
return *this;
}
PlatformViewBuilder& SetDestroyViewCallback(OnDestroyView callback) {
PlatformViewBuilder& SetDestroyViewCallback(OnDestroyGfxView callback) {
on_destroy_view_callback_ = std::move(callback);
return *this;
}
@ -230,7 +230,7 @@ class PlatformViewBuilder {
return *this;
}
PlatformViewBuilder& SetCreateViewCallback(OnCreateView callback) {
PlatformViewBuilder& SetCreateViewCallback(OnCreateGfxView callback) {
on_create_view_callback_ = std::move(callback);
return *this;
}
@ -310,9 +310,9 @@ class PlatformViewBuilder {
keyboard_listener_{nullptr};
fit::closure on_session_listener_error_callback_{nullptr};
OnEnableWireframe wireframe_enabled_callback_{nullptr};
OnCreateView on_create_view_callback_{nullptr};
OnCreateGfxView on_create_view_callback_{nullptr};
OnUpdateView on_update_view_callback_{nullptr};
OnDestroyView on_destroy_view_callback_{nullptr};
OnDestroyGfxView on_destroy_view_callback_{nullptr};
OnCreateSurface on_create_surface_callback_{nullptr};
OnSemanticsNodeUpdate on_semantics_node_update_callback_{nullptr};
OnRequestAnnounce on_request_announce_callback_{nullptr};
@ -706,7 +706,7 @@ TEST_F(PlatformViewTests, CreateViewTest) {
auto CreateViewCallback = [&create_view_called](
int64_t view_id,
flutter_runner::ViewCallback on_view_created,
flutter_runner::ViewIdCallback on_view_bound,
flutter_runner::GfxViewIdCallback on_view_bound,
bool hit_testable, bool focusable) {
create_view_called = true;
on_view_created();
@ -883,8 +883,8 @@ TEST_F(PlatformViewTests, DestroyViewTest) {
// setting |wireframe_enabled| to true.
bool destroy_view_called = false;
auto DestroyViewCallback =
[&destroy_view_called](int64_t view_id,
flutter_runner::ViewIdCallback on_view_unbound) {
[&destroy_view_called](
int64_t view_id, flutter_runner::GfxViewIdCallback on_view_unbound) {
destroy_view_called = true;
on_view_unbound(0);
};
@ -942,14 +942,14 @@ TEST_F(PlatformViewTests, ViewEventsTest) {
nullptr // io
);
auto on_create_view = [kViewId](int64_t view_id,
flutter_runner::ViewCallback on_view_created,
flutter_runner::ViewIdCallback on_view_bound,
bool hit_testable, bool focusable) {
ASSERT_EQ(view_id, kViewId);
on_view_created();
on_view_bound(kViewHolderId);
};
auto on_create_view =
[kViewId](int64_t view_id, flutter_runner::ViewCallback on_view_created,
flutter_runner::GfxViewIdCallback on_view_bound,
bool hit_testable, bool focusable) {
ASSERT_EQ(view_id, kViewId);
on_view_created();
on_view_bound(kViewHolderId);
};
flutter_runner::GfxPlatformView platform_view =
PlatformViewBuilder(delegate, std::move(task_runners),