[macOS] Group per-view information in FlutterCompositor into a class (flutter/engine#51738)

This PR groups per-view information in `FlutterCompositor` into a private class, `ViewPresenter`. This makes it easier to manage per-view data and write view operations.

Part of https://github.com/flutter/flutter/issues/145874.

Currently, view presenters are never removed once created, since the macOS runner doesn't support removing views. This will be added in the future.

[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
This commit is contained in:
Tong Mu 2024-03-28 16:57:21 -07:00 committed by GitHub
parent f4b9b15cf7
commit 115ff71db2
2 changed files with 54 additions and 26 deletions

View File

@ -7,6 +7,7 @@
#include <functional>
#include <list>
#include <unordered_map>
#include "flutter/fml/macros.h"
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterPlatformViewController.h"
@ -34,9 +35,9 @@ class FlutterCompositor {
// The view_provider is used to query FlutterViews from view IDs,
// which are used for presenting and creating backing stores.
// It must not be null, and is typically FlutterViewEngineProvider.
explicit FlutterCompositor(id<FlutterViewProvider> view_provider,
FlutterTimeConverter* time_converter,
FlutterPlatformViewController* platform_views_controller);
FlutterCompositor(id<FlutterViewProvider> view_provider,
FlutterTimeConverter* time_converter,
FlutterPlatformViewController* platform_views_controller);
~FlutterCompositor() = default;
@ -56,19 +57,34 @@ class FlutterCompositor {
FlutterBackingStore* backing_store_out);
// Presents the FlutterLayers by updating the FlutterView specified by
// `view_id` using the layer content. Sets frame_started_ to false.
// `view_id` using the layer content.
bool Present(FlutterViewId view_id, const FlutterLayer** layers, size_t layers_count);
private:
void PresentPlatformViews(FlutterView* default_base_view,
const std::vector<PlatformViewLayerWithIndex>& platform_views_layers);
// A class that contains the information for a view to be presented.
class ViewPresenter {
public:
ViewPresenter();
// Presents the platform view layer represented by `layer`. `layer_index` is
// used to position the layer in the z-axis. If the layer does not have a
// superview, it will become subview of `default_base_view`.
FlutterMutatorView* PresentPlatformView(FlutterView* default_base_view,
const PlatformViewLayer& layer,
size_t index);
void PresentPlatformViews(FlutterView* default_base_view,
const std::vector<PlatformViewLayerWithIndex>& platform_views,
const FlutterPlatformViewController* platform_views_controller);
private:
// Platform view to FlutterMutatorView that contains it.
NSMapTable<NSView*, FlutterMutatorView*>* mutator_views_;
// Presents the platform view layer represented by `layer`. `layer_index` is
// used to position the layer in the z-axis. If the layer does not have a
// superview, it will become subview of `default_base_view`.
FlutterMutatorView* PresentPlatformView(
FlutterView* default_base_view,
const PlatformViewLayer& layer,
size_t layer_position,
const FlutterPlatformViewController* platform_views_controller);
FML_DISALLOW_COPY_AND_ASSIGN(ViewPresenter);
};
// Where the compositor can query FlutterViews. Must not be null.
id<FlutterViewProvider> const view_provider_;
@ -79,8 +95,7 @@ class FlutterCompositor {
// The controller used to manage creation and deletion of platform views.
const FlutterPlatformViewController* platform_view_controller_;
// Platform view to FlutterMutatorView that contains it.
NSMapTable<NSView*, FlutterMutatorView*>* mutator_views_;
std::unordered_map<int64_t, ViewPresenter> presenters_;
FML_DISALLOW_COPY_AND_ASSIGN(FlutterCompositor);
};

View File

@ -27,8 +27,7 @@ FlutterCompositor::FlutterCompositor(id<FlutterViewProvider> view_provider,
FlutterPlatformViewController* platform_view_controller)
: view_provider_(view_provider),
time_converter_(time_converter),
platform_view_controller_(platform_view_controller),
mutator_views_([NSMapTable strongToStrongObjectsMapTable]) {
platform_view_controller_(platform_view_controller) {
FML_CHECK(view_provider != nullptr) << "view_provider cannot be nullptr";
}
@ -55,6 +54,10 @@ bool FlutterCompositor::CreateBackingStore(const FlutterBackingStoreConfig* conf
bool FlutterCompositor::Present(FlutterViewId view_id,
const FlutterLayer** layers,
size_t layers_count) {
// TODO(dkwingsmt): The macOS embedder only supports rendering to the implicit
// view for now. As it supports adding more views, this assertion should be
// lifted. https://github.com/flutter/flutter/issues/142845
FML_DCHECK(view_id == kFlutterImplicitViewId);
FlutterView* view = [view_provider_ viewForId:view_id];
if (!view) {
return false;
@ -98,15 +101,22 @@ bool FlutterCompositor::Present(FlutterViewId view_id,
[view.surfaceManager presentSurfaces:surfaces
atTime:presentation_time
notify:^{
PresentPlatformViews(view, *platform_views_layers);
// Gets a presenter or create a new one for the view.
ViewPresenter& presenter = presenters_[view_id];
presenter.PresentPlatformViews(view, *platform_views_layers,
platform_view_controller_);
}];
return true;
}
void FlutterCompositor::PresentPlatformViews(
FlutterCompositor::ViewPresenter::ViewPresenter()
: mutator_views_([NSMapTable strongToStrongObjectsMapTable]) {}
void FlutterCompositor::ViewPresenter::PresentPlatformViews(
FlutterView* default_base_view,
const std::vector<PlatformViewLayerWithIndex>& platform_views) {
const std::vector<PlatformViewLayerWithIndex>& platform_views,
const FlutterPlatformViewController* platform_view_controller) {
FML_DCHECK([[NSThread currentThread] isMainThread])
<< "Must be on the main thread to present platform views";
@ -114,8 +124,9 @@ void FlutterCompositor::PresentPlatformViews(
NSMutableArray<FlutterMutatorView*>* present_mutators = [NSMutableArray array];
for (const auto& platform_view : platform_views) {
[present_mutators addObject:PresentPlatformView(default_base_view, platform_view.first,
platform_view.second)];
FlutterMutatorView* container = PresentPlatformView(
default_base_view, platform_view.first, platform_view.second, platform_view_controller);
[present_mutators addObject:container];
}
NSMutableArray<FlutterMutatorView*>* obsolete_mutators =
@ -127,17 +138,19 @@ void FlutterCompositor::PresentPlatformViews(
[mutator removeFromSuperview];
}
[platform_view_controller_ disposePlatformViews];
[platform_view_controller disposePlatformViews];
}
FlutterMutatorView* FlutterCompositor::PresentPlatformView(FlutterView* default_base_view,
const PlatformViewLayer& layer,
size_t index) {
FlutterMutatorView* FlutterCompositor::ViewPresenter::PresentPlatformView(
FlutterView* default_base_view,
const PlatformViewLayer& layer,
size_t index,
const FlutterPlatformViewController* platform_view_controller) {
FML_DCHECK([[NSThread currentThread] isMainThread])
<< "Must be on the main thread to present platform views";
int64_t platform_view_id = layer.identifier();
NSView* platform_view = [platform_view_controller_ platformViewWithID:platform_view_id];
NSView* platform_view = [platform_view_controller platformViewWithID:platform_view_id];
FML_DCHECK(platform_view) << "Platform view not found for id: " << platform_view_id;