diff --git a/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm b/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm index 79c4d0b40845a..edc7df58cb950 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterEngine.mm @@ -396,10 +396,6 @@ - (void)performAction:(FlutterTextInputAction)action withClient:(int)client { return _shell->Screenshot(type, base64Encode); } -- (flow::ExternalViewEmbedder*)externalViewEmbedder { - return _platformViewsController.get(); -} - #pragma mark - FlutterBinaryMessenger - (void)sendOnChannel:(NSString*)channel message:(NSData*)message { diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm index cbca478380bd9..0f26dd93e7e28 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm @@ -66,8 +66,6 @@ flutterView:flutter_view_] autorelease]; views_[viewId] = fml::scoped_nsobject([view retain]); - UIView* flutter_view = flutter_view_.get(); - [flutter_view addSubview:views_[viewId].get()]; result(nil); } @@ -127,6 +125,33 @@ UIView* view = views_[view_id]; [view setFrame:rect]; + composition_order_.push_back(view_id); +} + +void FlutterPlatformViewsController::Present() { + if (composition_order_ == active_composition_order_) { + composition_order_.clear(); + return; + } + UIView* flutter_view = flutter_view_.get(); + + // This can be more efficient, instead of removing all views and then re-attaching them, + // we should only remove the views that has been completly removed from the layer tree, and + // reorder the views using UIView's bringSubviewToFront. + // TODO(amirh): make this more efficient. + // https://github.com/flutter/flutter/issues/23793 + for (UIView* sub_view in [flutter_view subviews]) { + [sub_view removeFromSuperview]; + } + + active_composition_order_.clear(); + for (size_t i = 0; i < composition_order_.size(); i++) { + int view_id = composition_order_[i]; + [flutter_view addSubview:views_[view_id].get()]; + active_composition_order_.push_back(view_id); + } + + composition_order_.clear(); } } // namespace shell diff --git a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h index d52d59bf12d1f..3a749a11d0d3f 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h @@ -26,7 +26,7 @@ namespace shell { -class FlutterPlatformViewsController : public flow::ExternalViewEmbedder { +class FlutterPlatformViewsController { public: FlutterPlatformViewsController() = default; @@ -36,6 +36,8 @@ class FlutterPlatformViewsController : public flow::ExternalViewEmbedder { void CompositeEmbeddedView(int view_id, const flow::EmbeddedViewParams& params); + void Present(); + void OnMethodCall(FlutterMethodCall* call, FlutterResult& result); private: @@ -44,6 +46,13 @@ class FlutterPlatformViewsController : public flow::ExternalViewEmbedder { std::map>> factories_; std::map> views_; + // A vector of embedded view IDs according to their composition order. + // The last ID in this vector belond to the that is composited on top of all others. + std::vector composition_order_; + + // The latest composition order that was presented in Present(). + std::vector active_composition_order_; + void OnCreate(FlutterMethodCall* call, FlutterResult& result); void OnDispose(FlutterMethodCall* call, FlutterResult& result); void OnAcceptGesture(FlutterMethodCall* call, FlutterResult& result); diff --git a/shell/platform/darwin/ios/framework/Source/FlutterView.h b/shell/platform/darwin/ios/framework/Source/FlutterView.h index 87402b6a2e64d..b070e25eace0e 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterView.h +++ b/shell/platform/darwin/ios/framework/Source/FlutterView.h @@ -11,7 +11,6 @@ #import "FlutterPlatformViews_Internal.h" -#include "flutter/flow/embedded_views.h" #include "flutter/fml/memory/weak_ptr.h" #include "flutter/shell/common/shell.h" #include "flutter/shell/platform/darwin/ios/ios_surface.h" @@ -21,7 +20,7 @@ - (shell::Rasterizer::Screenshot)takeScreenshot:(shell::Rasterizer::ScreenshotType)type asBase64Encoded:(BOOL)base64Encode; -- (flow::ExternalViewEmbedder*)externalViewEmbedder; +- (shell::FlutterPlatformViewsController*)platformViewsController; @end diff --git a/shell/platform/darwin/ios/framework/Source/FlutterView.mm b/shell/platform/darwin/ios/framework/Source/FlutterView.mm index a6fb0449baa90..3909f6367ee2e 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterView.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterView.mm @@ -80,11 +80,11 @@ + (Class)layerClass { fml::scoped_nsobject eagl_layer( reinterpret_cast([self.layer retain])); return std::make_unique(std::move(eagl_layer), - *[_delegate externalViewEmbedder]); + *[_delegate platformViewsController]); } else { fml::scoped_nsobject layer(reinterpret_cast([self.layer retain])); return std::make_unique(std::move(layer), - *[_delegate externalViewEmbedder]); + *[_delegate platformViewsController]); } } diff --git a/shell/platform/darwin/ios/ios_surface.h b/shell/platform/darwin/ios/ios_surface.h index 8011905db4d68..f0f835e684342 100644 --- a/shell/platform/darwin/ios/ios_surface.h +++ b/shell/platform/darwin/ios/ios_surface.h @@ -5,6 +5,8 @@ #ifndef FLUTTER_SHELL_PLATFORM_DARWIN_IOS_IOS_SURFACE_H_ #define FLUTTER_SHELL_PLATFORM_DARWIN_IOS_IOS_SURFACE_H_ +#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h" + #include #include "flutter/fml/macros.h" @@ -15,7 +17,7 @@ namespace shell { class IOSSurface { public: - IOSSurface(); + IOSSurface(FlutterPlatformViewsController& platform_views_controller); virtual ~IOSSurface(); @@ -27,6 +29,12 @@ class IOSSurface { virtual std::unique_ptr CreateGPUSurface() = 0; + protected: + FlutterPlatformViewsController& GetPlatformViewsController(); + + private: + FlutterPlatformViewsController& platform_views_controller_; + public: FML_DISALLOW_COPY_AND_ASSIGN(IOSSurface); }; diff --git a/shell/platform/darwin/ios/ios_surface.mm b/shell/platform/darwin/ios/ios_surface.mm index b3fe77bb38462..1a62e70e59b15 100644 --- a/shell/platform/darwin/ios/ios_surface.mm +++ b/shell/platform/darwin/ios/ios_surface.mm @@ -11,8 +11,12 @@ namespace shell { -IOSSurface::IOSSurface() = default; +IOSSurface::IOSSurface(FlutterPlatformViewsController& platform_views_controller) + : platform_views_controller_(platform_views_controller) {} IOSSurface::~IOSSurface() = default; +FlutterPlatformViewsController& IOSSurface::GetPlatformViewsController() { + return platform_views_controller_; +} } // namespace shell diff --git a/shell/platform/darwin/ios/ios_surface_gl.h b/shell/platform/darwin/ios/ios_surface_gl.h index 2c4146a9094b4..a2765890eb3bd 100644 --- a/shell/platform/darwin/ios/ios_surface_gl.h +++ b/shell/platform/darwin/ios/ios_surface_gl.h @@ -15,10 +15,12 @@ namespace shell { -class IOSSurfaceGL : public IOSSurface, public GPUSurfaceGLDelegate { +class IOSSurfaceGL : public IOSSurface, + public GPUSurfaceGLDelegate, + public flow::ExternalViewEmbedder { public: IOSSurfaceGL(fml::scoped_nsobject layer, - flow::ExternalViewEmbedder& external_view_embedder); + FlutterPlatformViewsController& platform_views_controller); ~IOSSurfaceGL() override; @@ -43,11 +45,12 @@ class IOSSurfaceGL : public IOSSurface, public GPUSurfaceGLDelegate { // |shell::GPUSurfaceGLDelegate| flow::ExternalViewEmbedder* GetExternalViewEmbedder() override; + // |flow::ExternalViewEmbedder| + void CompositeEmbeddedView(int view_id, const flow::EmbeddedViewParams& params) override; + private: IOSGLContext context_; - flow::ExternalViewEmbedder& external_view_embedder_; - FML_DISALLOW_COPY_AND_ASSIGN(IOSSurfaceGL); }; diff --git a/shell/platform/darwin/ios/ios_surface_gl.mm b/shell/platform/darwin/ios/ios_surface_gl.mm index 954e50239fa16..b65015e4d56d1 100644 --- a/shell/platform/darwin/ios/ios_surface_gl.mm +++ b/shell/platform/darwin/ios/ios_surface_gl.mm @@ -10,8 +10,8 @@ namespace shell { IOSSurfaceGL::IOSSurfaceGL(fml::scoped_nsobject layer, - flow::ExternalViewEmbedder& view_embedder) - : context_(std::move(layer)), external_view_embedder_(view_embedder) {} + FlutterPlatformViewsController& platform_views_controller) + : IOSSurface(platform_views_controller), context_(std::move(layer)) {} IOSSurfaceGL::~IOSSurfaceGL() = default; @@ -55,11 +55,20 @@ bool IOSSurfaceGL::GLContextPresent() { TRACE_EVENT0("flutter", "IOSSurfaceGL::GLContextPresent"); - return IsValid() ? context_.PresentRenderBuffer() : false; + if (!IsValid() || !context_.PresentRenderBuffer()) { + return false; + } + + GetPlatformViewsController().Present(); + return true; } flow::ExternalViewEmbedder* IOSSurfaceGL::GetExternalViewEmbedder() { - return &external_view_embedder_; + return this; +} + +void IOSSurfaceGL::CompositeEmbeddedView(int view_id, const flow::EmbeddedViewParams& params) { + GetPlatformViewsController().CompositeEmbeddedView(view_id, params); } } // namespace shell diff --git a/shell/platform/darwin/ios/ios_surface_software.h b/shell/platform/darwin/ios/ios_surface_software.h index 86eaa16ee210b..6abfeecf0b17c 100644 --- a/shell/platform/darwin/ios/ios_surface_software.h +++ b/shell/platform/darwin/ios/ios_surface_software.h @@ -5,6 +5,7 @@ #ifndef FLUTTER_SHELL_PLATFORM_DARWIN_IOS_IOS_SURFACE_SOFTWARE_H_ #define FLUTTER_SHELL_PLATFORM_DARWIN_IOS_IOS_SURFACE_SOFTWARE_H_ +#include "flutter/flow/embedded_views.h" #include "flutter/fml/macros.h" #include "flutter/fml/platform/darwin/scoped_nsobject.h" #include "flutter/shell/gpu/gpu_surface_software.h" @@ -14,10 +15,12 @@ namespace shell { -class IOSSurfaceSoftware final : public IOSSurface, public GPUSurfaceSoftwareDelegate { +class IOSSurfaceSoftware final : public IOSSurface, + public GPUSurfaceSoftwareDelegate, + public flow::ExternalViewEmbedder { public: IOSSurfaceSoftware(fml::scoped_nsobject layer, - flow::ExternalViewEmbedder& view_embedder); + FlutterPlatformViewsController& platform_views_controller); ~IOSSurfaceSoftware() override; @@ -42,9 +45,11 @@ class IOSSurfaceSoftware final : public IOSSurface, public GPUSurfaceSoftwareDel // |shell::GPUSurfaceSoftwareDelegate| flow::ExternalViewEmbedder* GetExternalViewEmbedder() override; + // |flow::ExternalViewEmbedder| + void CompositeEmbeddedView(int view_id, const flow::EmbeddedViewParams& params) override; + private: fml::scoped_nsobject layer_; - flow::ExternalViewEmbedder& external_view_embedder_; sk_sp sk_surface_; FML_DISALLOW_COPY_AND_ASSIGN(IOSSurfaceSoftware); diff --git a/shell/platform/darwin/ios/ios_surface_software.mm b/shell/platform/darwin/ios/ios_surface_software.mm index cb4768a168a2e..2c561b78c397b 100644 --- a/shell/platform/darwin/ios/ios_surface_software.mm +++ b/shell/platform/darwin/ios/ios_surface_software.mm @@ -16,8 +16,8 @@ namespace shell { IOSSurfaceSoftware::IOSSurfaceSoftware(fml::scoped_nsobject layer, - flow::ExternalViewEmbedder& view_embedder) - : layer_(std::move(layer)), external_view_embedder_(view_embedder) { + FlutterPlatformViewsController& platform_views_controller) + : IOSSurface(platform_views_controller), layer_(std::move(layer)) { UpdateStorageSizeIfNecessary(); } @@ -123,11 +123,17 @@ layer_.get().contents = reinterpret_cast(static_cast(pixmap_image)); + GetPlatformViewsController().Present(); + return true; } flow::ExternalViewEmbedder* IOSSurfaceSoftware::GetExternalViewEmbedder() { - return &external_view_embedder_; + return this; +} +void IOSSurfaceSoftware::CompositeEmbeddedView(int view_id, + const flow::EmbeddedViewParams& params) { + GetPlatformViewsController().CompositeEmbeddedView(view_id, params); } } // namespace shell