diff --git a/engine/src/flutter/shell/platform/fuchsia/flutter/engine.cc b/engine/src/flutter/shell/platform/fuchsia/flutter/engine.cc index caf4785407d..2e62e8df9b3 100644 --- a/engine/src/flutter/shell/platform/fuchsia/flutter/engine.cc +++ b/engine/src/flutter/shell/platform/fuchsia/flutter/engine.cc @@ -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 Engine::CreateSurface() { return std::make_unique(thread_label_, GetExternalViewEmbedder(), surface_producer_->gr_context()); diff --git a/engine/src/flutter/shell/platform/fuchsia/flutter/engine.h b/engine/src/flutter/shell/platform/fuchsia/flutter/engine.h index 2197baa3c4a..c4cc33ae620 100644 --- a/engine/src/flutter/shell/platform/fuchsia/flutter/engine.h +++ b/engine/src/flutter/shell/platform/fuchsia/flutter/engine.h @@ -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, diff --git a/engine/src/flutter/shell/platform/fuchsia/flutter/flatland_external_view_embedder.cc b/engine/src/flutter/shell/platform/fuchsia/flutter/flatland_external_view_embedder.cc index 413ab7ad53c..67a8ece842a 100644 --- a/engine/src/flutter/shell/platform/fuchsia/flutter/flatland_external_view_embedder.cc +++ b/engine/src/flutter/shell/platform/fuchsia/flutter/flatland_external_view_embedder.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "flatland_external_view_embedder.h" +#include #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))); } diff --git a/engine/src/flutter/shell/platform/fuchsia/flutter/flatland_external_view_embedder.h b/engine/src/flutter/shell/platform/fuchsia/flutter/flatland_external_view_embedder.h index 72e794022ec..8ca3682724f 100644 --- a/engine/src/flutter/shell/platform/fuchsia/flutter/flatland_external_view_embedder.h +++ b/engine/src/flutter/shell/platform/fuchsia/flutter/flatland_external_view_embedder.h @@ -30,7 +30,10 @@ namespace flutter_runner { -using FlatlandViewCallback = std::function; +using ViewCallback = std::function; +using FlatlandViewCreatedCallback = std::function; using FlatlandViewIdCallback = std::function; @@ -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(); }; diff --git a/engine/src/flutter/shell/platform/fuchsia/flutter/flatland_platform_view.cc b/engine/src/flutter/shell/platform/fuchsia/flutter/flatland_platform_view.cc index d62eaf98179..d3fffc305e1 100644 --- a/engine/src/flutter/shell/platform/fuchsia/flutter/flatland_platform_view.cc +++ b/engine/src/flutter/shell/platform/fuchsia/flutter/flatland_platform_view.cc @@ -23,9 +23,9 @@ FlatlandPlatformView::FlatlandPlatformView( fidl::InterfaceRequest 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 message = + std::make_unique( + "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 diff --git a/engine/src/flutter/shell/platform/fuchsia/flutter/flatland_platform_view.h b/engine/src/flutter/shell/platform/fuchsia/flutter/flatland_platform_view.h index b2fa8357b18..ec53e882f3f 100644 --- a/engine/src/flutter/shell/platform/fuchsia/flutter/flatland_platform_view.h +++ b/engine/src/flutter/shell/platform/fuchsia/flutter/flatland_platform_view.h @@ -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 + +#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; + +// 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 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 + 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 + weak_factory_; // Must be the last member. + FML_DISALLOW_COPY_AND_ASSIGN(FlatlandPlatformView); }; diff --git a/engine/src/flutter/shell/platform/fuchsia/flutter/fuchsia_external_view_embedder.cc b/engine/src/flutter/shell/platform/fuchsia/flutter/fuchsia_external_view_embedder.cc index eb6783113f7..f9ba84978b4 100644 --- a/engine/src/flutter/shell/platform/fuchsia/flutter/fuchsia_external_view_embedder.cc +++ b/engine/src/flutter/shell/platform/fuchsia/flutter/fuchsia_external_view_embedder.cc @@ -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(); diff --git a/engine/src/flutter/shell/platform/fuchsia/flutter/fuchsia_external_view_embedder.h b/engine/src/flutter/shell/platform/fuchsia/flutter/fuchsia_external_view_embedder.h index 7021a3df333..a066e57a2bb 100644 --- a/engine/src/flutter/shell/platform/fuchsia/flutter/fuchsia_external_view_embedder.h +++ b/engine/src/flutter/shell/platform/fuchsia/flutter/fuchsia_external_view_embedder.h @@ -33,7 +33,7 @@ namespace flutter_runner { using ViewCallback = std::function; -using ViewIdCallback = std::function; +using GfxViewIdCallback = std::function; // 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, diff --git a/engine/src/flutter/shell/platform/fuchsia/flutter/gfx_platform_view.cc b/engine/src/flutter/shell/platform/fuchsia/flutter/gfx_platform_view.cc index c4eaa77744d..af1be401779 100644 --- a/engine/src/flutter/shell/platform/fuchsia/flutter/gfx_platform_view.cc +++ b/engine/src/flutter/shell/platform/fuchsia/flutter/gfx_platform_view.cc @@ -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 message = + std::make_unique( + "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 message = + std::make_unique( + "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 message = + std::make_unique( + "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 diff --git a/engine/src/flutter/shell/platform/fuchsia/flutter/gfx_platform_view.h b/engine/src/flutter/shell/platform/fuchsia/flutter/gfx_platform_view.h index 45e36d6c7cc..faa89fee3bd 100644 --- a/engine/src/flutter/shell/platform/fuchsia/flutter/gfx_platform_view.h +++ b/engine/src/flutter/shell/platform/fuchsia/flutter/gfx_platform_view.h @@ -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 #include +#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; +using OnDestroyGfxView = fit::function; + // 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 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 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 child_view_ids_; + + OnCreateGfxView on_create_view_callback_; + OnDestroyGfxView on_destroy_view_callback_; + fml::WeakPtrFactory weak_factory_; // Must be the last member. diff --git a/engine/src/flutter/shell/platform/fuchsia/flutter/platform_view.cc b/engine/src/flutter/shell/platform/fuchsia/flutter/platform_view.cc index 2e1ab444c7e..4acc60df2bc 100644 --- a/engine/src/flutter/shell/platform/fuchsia/flutter/platform_view.cc +++ b/engine/src/flutter/shell/platform/fuchsia/flutter/platform_view.cc @@ -64,9 +64,7 @@ PlatformView::PlatformView( fidl::InterfaceRequest 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(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 message = - std::make_unique( - "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 message = - std::make_unique( - "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 message = - std::make_unique( - "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({'[', '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( std::vector({'[', '0', ']'}))); diff --git a/engine/src/flutter/shell/platform/fuchsia/flutter/platform_view.h b/engine/src/flutter/shell/platform/fuchsia/flutter/platform_view.h index 7ff209bdca0..ce5b4f34c2c 100644 --- a/engine/src/flutter/shell/platform/fuchsia/flutter/platform_view.h +++ b/engine/src/flutter/shell/platform/fuchsia/flutter/platform_view.h @@ -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; -using OnCreateView = - fit::function; +using ViewCallback = std::function; using OnUpdateView = fit::function; -using OnDestroyView = fit::function; using OnCreateSurface = fit::function()>; using OnSemanticsNodeUpdate = fit::function; @@ -80,9 +77,7 @@ class PlatformView : public flutter::PlatformView, fidl::InterfaceRequest 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 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 ClampToViewSpace(const float x, const float y) const; @@ -200,9 +193,7 @@ class PlatformView : public flutter::PlatformView, std::optional 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 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. diff --git a/engine/src/flutter/shell/platform/fuchsia/flutter/platform_view_unittest.cc b/engine/src/flutter/shell/platform/fuchsia/flutter/platform_view_unittest.cc index 8cbebd85752..6647f1d906e 100644 --- a/engine/src/flutter/shell/platform/fuchsia/flutter/platform_view_unittest.cc +++ b/engine/src/flutter/shell/platform/fuchsia/flutter/platform_view_unittest.cc @@ -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),