Skip to content

Commit

Permalink
Apply changes to the embedded UIView tree when presenting a frame (#6712
Browse files Browse the repository at this point in the history
)

Also tracks the order of embedded views from frame to frame, and only
removes and reattaches subviews if there is a structural change to the
UIView hierarchy.
  • Loading branch information
amirh authored Oct 31, 2018
1 parent 92944f7 commit 0ec3b7d
Show file tree
Hide file tree
Showing 11 changed files with 91 additions and 27 deletions.
4 changes: 0 additions & 4 deletions shell/platform/darwin/ios/framework/Source/FlutterEngine.mm
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
29 changes: 27 additions & 2 deletions shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,6 @@
flutterView:flutter_view_] autorelease];
views_[viewId] = fml::scoped_nsobject<FlutterTouchInterceptingView>([view retain]);

UIView* flutter_view = flutter_view_.get();
[flutter_view addSubview:views_[viewId].get()];
result(nil);
}

Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@

namespace shell {

class FlutterPlatformViewsController : public flow::ExternalViewEmbedder {
class FlutterPlatformViewsController {
public:
FlutterPlatformViewsController() = default;

Expand All @@ -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:
Expand All @@ -44,6 +46,13 @@ class FlutterPlatformViewsController : public flow::ExternalViewEmbedder {
std::map<std::string, fml::scoped_nsobject<NSObject<FlutterPlatformViewFactory>>> factories_;
std::map<int64_t, fml::scoped_nsobject<FlutterTouchInterceptingView>> 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<int64_t> composition_order_;

// The latest composition order that was presented in Present().
std::vector<int64_t> active_composition_order_;

void OnCreate(FlutterMethodCall* call, FlutterResult& result);
void OnDispose(FlutterMethodCall* call, FlutterResult& result);
void OnAcceptGesture(FlutterMethodCall* call, FlutterResult& result);
Expand Down
3 changes: 1 addition & 2 deletions shell/platform/darwin/ios/framework/Source/FlutterView.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -21,7 +20,7 @@
- (shell::Rasterizer::Screenshot)takeScreenshot:(shell::Rasterizer::ScreenshotType)type
asBase64Encoded:(BOOL)base64Encode;

- (flow::ExternalViewEmbedder*)externalViewEmbedder;
- (shell::FlutterPlatformViewsController*)platformViewsController;

@end

Expand Down
4 changes: 2 additions & 2 deletions shell/platform/darwin/ios/framework/Source/FlutterView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,11 @@ + (Class)layerClass {
fml::scoped_nsobject<CAEAGLLayer> eagl_layer(
reinterpret_cast<CAEAGLLayer*>([self.layer retain]));
return std::make_unique<shell::IOSSurfaceGL>(std::move(eagl_layer),
*[_delegate externalViewEmbedder]);
*[_delegate platformViewsController]);
} else {
fml::scoped_nsobject<CALayer> layer(reinterpret_cast<CALayer*>([self.layer retain]));
return std::make_unique<shell::IOSSurfaceSoftware>(std::move(layer),
*[_delegate externalViewEmbedder]);
*[_delegate platformViewsController]);
}
}

Expand Down
10 changes: 9 additions & 1 deletion shell/platform/darwin/ios/ios_surface.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 <memory>

#include "flutter/fml/macros.h"
Expand All @@ -15,7 +17,7 @@ namespace shell {

class IOSSurface {
public:
IOSSurface();
IOSSurface(FlutterPlatformViewsController& platform_views_controller);

virtual ~IOSSurface();

Expand All @@ -27,6 +29,12 @@ class IOSSurface {

virtual std::unique_ptr<Surface> CreateGPUSurface() = 0;

protected:
FlutterPlatformViewsController& GetPlatformViewsController();

private:
FlutterPlatformViewsController& platform_views_controller_;

public:
FML_DISALLOW_COPY_AND_ASSIGN(IOSSurface);
};
Expand Down
6 changes: 5 additions & 1 deletion shell/platform/darwin/ios/ios_surface.mm
Original file line number Diff line number Diff line change
Expand Up @@ -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
11 changes: 7 additions & 4 deletions shell/platform/darwin/ios/ios_surface_gl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<CAEAGLLayer> layer,
flow::ExternalViewEmbedder& external_view_embedder);
FlutterPlatformViewsController& platform_views_controller);

~IOSSurfaceGL() override;

Expand All @@ -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);
};

Expand Down
17 changes: 13 additions & 4 deletions shell/platform/darwin/ios/ios_surface_gl.mm
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
namespace shell {

IOSSurfaceGL::IOSSurfaceGL(fml::scoped_nsobject<CAEAGLLayer> 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;

Expand Down Expand Up @@ -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
11 changes: 8 additions & 3 deletions shell/platform/darwin/ios/ios_surface_software.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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<CALayer> layer,
flow::ExternalViewEmbedder& view_embedder);
FlutterPlatformViewsController& platform_views_controller);

~IOSSurfaceSoftware() override;

Expand All @@ -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<CALayer> layer_;
flow::ExternalViewEmbedder& external_view_embedder_;
sk_sp<SkSurface> sk_surface_;

FML_DISALLOW_COPY_AND_ASSIGN(IOSSurfaceSoftware);
Expand Down
12 changes: 9 additions & 3 deletions shell/platform/darwin/ios/ios_surface_software.mm
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
namespace shell {

IOSSurfaceSoftware::IOSSurfaceSoftware(fml::scoped_nsobject<CALayer> 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();
}

Expand Down Expand Up @@ -123,11 +123,17 @@

layer_.get().contents = reinterpret_cast<id>(static_cast<CGImageRef>(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

0 comments on commit 0ec3b7d

Please sign in to comment.