Skip to content

Commit

Permalink
Move FlutterPlatformViewsController into FlutterEngine. (flutter#6709)
Browse files Browse the repository at this point in the history
This PR breaks PlatformViewsController's construction dependency on FlutterView,
which allows making FlutterEngine its owner instead of
FlutterViewController.

Also renamed the FlutterScreenshotDelegate to FlutterViewEngineDelegate
which is FlutterView's delegate to the engine, and expanded it to
provide a view embedder.
  • Loading branch information
amirh authored Oct 31, 2018
1 parent d34cb17 commit 92944f7
Show file tree
Hide file tree
Showing 13 changed files with 68 additions and 77 deletions.
34 changes: 22 additions & 12 deletions shell/platform/darwin/ios/framework/Source/FlutterEngine.mm
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,15 @@ @implementation FlutterEngine {
fml::WeakPtr<FlutterViewController> _viewController;
fml::scoped_nsobject<FlutterObservatoryPublisher> _publisher;

std::unique_ptr<shell::FlutterPlatformViewsController> _platformViewsController;

// Channels
fml::scoped_nsobject<FlutterPlatformPlugin> _platformPlugin;
fml::scoped_nsobject<FlutterTextInputPlugin> _textInputPlugin;
fml::scoped_nsobject<FlutterMethodChannel> _localizationChannel;
fml::scoped_nsobject<FlutterMethodChannel> _navigationChannel;
fml::scoped_nsobject<FlutterMethodChannel> _platformChannel;
fml::scoped_nsobject<FlutterMethodChannel> _platformViewsChannel;
fml::scoped_nsobject<FlutterMethodChannel> _textInputChannel;
fml::scoped_nsobject<FlutterBasicMessageChannel> _lifecycleChannel;
fml::scoped_nsobject<FlutterBasicMessageChannel> _systemChannel;
Expand All @@ -73,6 +76,7 @@ - (instancetype)initWithName:(NSString*)labelPrefix project:(FlutterDartProject*

_pluginPublications = [NSMutableDictionary new];
_publisher.reset([[FlutterObservatoryPublisher alloc] init]);
_platformViewsController.reset(new shell::FlutterPlatformViewsController());

[self setupChannels];

Expand Down Expand Up @@ -143,6 +147,9 @@ - (FlutterViewController*)viewController {
- (FlutterPlatformPlugin*)platformPlugin {
return _platformPlugin.get();
}
- (shell::FlutterPlatformViewsController*)platformViewsController {
return _platformViewsController.get();
}
- (FlutterTextInputPlugin*)textInputPlugin {
return _textInputPlugin.get();
}
Expand Down Expand Up @@ -184,6 +191,11 @@ - (void)setupChannels {
binaryMessenger:self
codec:[FlutterJSONMethodCodec sharedInstance]]);

_platformViewsChannel.reset([[FlutterMethodChannel alloc]
initWithName:@"flutter/platform_views"
binaryMessenger:self
codec:[FlutterStandardMethodCodec sharedInstance]]);

_textInputChannel.reset([[FlutterMethodChannel alloc]
initWithName:@"flutter/textinput"
binaryMessenger:self
Expand Down Expand Up @@ -218,6 +230,11 @@ - (void)maybeSetupPlatformViewChannels {
[_platformPlugin.get() handleMethodCall:call result:result];
}];

[_platformViewsChannel.get()
setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
_platformViewsController->OnMethodCall(call, result);
}];

[_textInputChannel.get() setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
[_textInputPlugin.get() handleMethodCall:call result:result];
}];
Expand Down Expand Up @@ -379,6 +396,10 @@ - (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 Expand Up @@ -514,18 +535,7 @@ - (NSString*)lookupKeyForAsset:(NSString*)asset fromPackage:(NSString*)package {

- (void)registerViewFactory:(NSObject<FlutterPlatformViewFactory>*)factory
withId:(NSString*)factoryId {
// TODO(amirh/dnfield): this shouldn't need to fail - PlatformViewsController should be
// independent. Dev builds of engine should just fail here. We don't want to fail in release mode
// because this shouldn't ordinarily happen.
FML_DCHECK([_flutterEngine viewController])
<< "Cannot register a view factory on a headless engine.";
if ([_flutterEngine viewController]) {
[[_flutterEngine viewController] platformViewsController]->RegisterViewFactory(factory,
factoryId);
} else {
// Shouldn't ordinarily happen, but at least give warning if it does.
FML_LOG(ERROR) << "Cannot register a view factory on a headless engine.";
}
[_flutterEngine platformViewsController] -> RegisterViewFactory(factory, factoryId);
}

@end
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

#import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterEngine.h"

#import "FlutterPlatformViews_Internal.h"

#include "flutter/fml/memory/weak_ptr.h"
#include "flutter/fml/task_runner.h"
#include "flutter/lib/ui/window/pointer_data_packet.h"
Expand All @@ -22,7 +24,7 @@

#include "flutter/shell/platform/darwin/ios/framework/Headers/FlutterEngine.h"

@interface FlutterEngine () <FlutterScreenshotDelegate>
@interface FlutterEngine () <FlutterViewEngineDelegate>

- (shell::Shell&)shell;

Expand All @@ -37,6 +39,7 @@
base64Encode:(bool)base64Encode;

- (FlutterPlatformPlugin*)platformPlugin;
- (shell::FlutterPlatformViewsController*)platformViewsController;
- (FlutterTextInputPlugin*)textInputPlugin;
- (void)launchEngine:(NSString*)entrypoint libraryURI:(NSString*)libraryOrNil;

Expand Down
24 changes: 12 additions & 12 deletions shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,8 @@

namespace shell {

FlutterPlatformViewsController::FlutterPlatformViewsController(
NSObject<FlutterBinaryMessenger>* messenger,
FlutterView* flutter_view)
: flutter_view_([flutter_view retain]) {
channel_.reset([[FlutterMethodChannel alloc]
initWithName:@"flutter/platform_views"
binaryMessenger:messenger
codec:[FlutterStandardMethodCodec sharedInstance]]);
[channel_.get() setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
OnMethodCall(call, result);
}];
void FlutterPlatformViewsController::SetFlutterView(UIView* flutter_view) {
flutter_view_.reset(flutter_view);
}

void FlutterPlatformViewsController::OnMethodCall(FlutterMethodCall* call, FlutterResult& result) {
Expand All @@ -40,6 +31,15 @@
}

void FlutterPlatformViewsController::OnCreate(FlutterMethodCall* call, FlutterResult& result) {
if (!flutter_view_.get()) {
// Right now we assume we have a reference to FlutterView when creating a new view.
// TODO(amirh): support this by setting the refernce to FlutterView when it becomes available.
// https://github.com/flutter/flutter/issues/23787
result([FlutterError errorWithCode:@"create_failed"
message:@"can't create a view on a headless engine"
details:nil]);
return;
}
NSDictionary<NSString*, id>* args = [call arguments];

long viewId = [args[@"id"] longValue];
Expand All @@ -66,7 +66,7 @@
flutterView:flutter_view_] autorelease];
views_[viewId] = fml::scoped_nsobject<FlutterTouchInterceptingView>([view retain]);

FlutterView* flutter_view = flutter_view_.get();
UIView* flutter_view = flutter_view_.get();
[flutter_view addSubview:views_[viewId].get()];
result(nil);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#ifndef FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERPLATFORMVIEWS_INTERNAL_H_
#define FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERPLATFORMVIEWS_INTERNAL_H_

#include "FlutterView.h"
#include "flutter/flow/embedded_views.h"
#include "flutter/fml/platform/darwin/scoped_nsobject.h"
#include "flutter/shell/common/shell.h"
Expand All @@ -29,20 +28,22 @@ namespace shell {

class FlutterPlatformViewsController : public flow::ExternalViewEmbedder {
public:
FlutterPlatformViewsController(NSObject<FlutterBinaryMessenger>* messenger,
FlutterView* flutter_view);
FlutterPlatformViewsController() = default;

void SetFlutterView(UIView* flutter_view);

void RegisterViewFactory(NSObject<FlutterPlatformViewFactory>* factory, NSString* factoryId);

void CompositeEmbeddedView(int view_id, const flow::EmbeddedViewParams& params);

void OnMethodCall(FlutterMethodCall* call, FlutterResult& result);

private:
fml::scoped_nsobject<FlutterMethodChannel> channel_;
fml::scoped_nsobject<FlutterView> flutter_view_;
fml::scoped_nsobject<UIView> flutter_view_;
std::map<std::string, fml::scoped_nsobject<NSObject<FlutterPlatformViewFactory>>> factories_;
std::map<int64_t, fml::scoped_nsobject<FlutterTouchInterceptingView>> views_;

void OnMethodCall(FlutterMethodCall* call, FlutterResult& result);
void OnCreate(FlutterMethodCall* call, FlutterResult& result);
void OnDispose(FlutterMethodCall* call, FlutterResult& result);
void OnAcceptGesture(FlutterMethodCall* call, FlutterResult& result);
Expand Down
8 changes: 6 additions & 2 deletions shell/platform/darwin/ios/framework/Source/FlutterView.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,20 @@

#include <memory>

#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"

@protocol FlutterScreenshotDelegate <NSObject>
@protocol FlutterViewEngineDelegate <NSObject>

- (shell::Rasterizer::Screenshot)takeScreenshot:(shell::Rasterizer::ScreenshotType)type
asBase64Encoded:(BOOL)base64Encode;

- (flow::ExternalViewEmbedder*)externalViewEmbedder;

@end

@interface FlutterView : UIView
Expand All @@ -27,7 +31,7 @@
- (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE;
- (instancetype)initWithCoder:(NSCoder*)aDecoder NS_UNAVAILABLE;

- (instancetype)initWithDelegate:(id<FlutterScreenshotDelegate>)delegate
- (instancetype)initWithDelegate:(id<FlutterViewEngineDelegate>)delegate
opaque:(BOOL)opaque NS_DESIGNATED_INITIALIZER;
- (std::unique_ptr<shell::IOSSurface>)createSurface;

Expand Down
30 changes: 6 additions & 24 deletions shell/platform/darwin/ios/framework/Source/FlutterView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ @interface FlutterView () <UIInputViewAudioFeedback>

@implementation FlutterView

id<FlutterScreenshotDelegate> _delegate;
id<FlutterViewEngineDelegate> _delegate;

- (instancetype)init {
@throw([NSException exceptionWithName:@"FlutterView must initWithDelegate"
Expand All @@ -43,7 +43,7 @@ - (instancetype)initWithCoder:(NSCoder*)aDecoder {
userInfo:nil]);
}

- (instancetype)initWithDelegate:(id<FlutterScreenshotDelegate>)delegate opaque:(BOOL)opaque {
- (instancetype)initWithDelegate:(id<FlutterViewEngineDelegate>)delegate opaque:(BOOL)opaque {
FML_DCHECK(delegate) << "Delegate must not be nil.";
self = [super initWithFrame:CGRectNull];

Expand All @@ -55,23 +55,6 @@ - (instancetype)initWithDelegate:(id<FlutterScreenshotDelegate>)delegate opaque:
return self;
}

- (FlutterViewController*)flutterViewController {
// Find the first view controller in the responder chain and see if it is a FlutterViewController.
for (UIResponder* responder = self.nextResponder; responder != nil;
responder = responder.nextResponder) {
if ([responder isKindOfClass:[UIViewController class]]) {
if ([responder isKindOfClass:[FlutterViewController class]]) {
return reinterpret_cast<FlutterViewController*>(responder);
} else {
// Should only happen if a non-FlutterViewController tries to somehow (via dynamic class
// resolution or reparenting) set a FlutterView as its view.
return nil;
}
}
}
return nil;
}

- (void)layoutSubviews {
if ([self.layer isKindOfClass:[CAEAGLLayer class]]) {
CAEAGLLayer* layer = reinterpret_cast<CAEAGLLayer*>(self.layer);
Expand All @@ -93,16 +76,15 @@ + (Class)layerClass {
}

- (std::unique_ptr<shell::IOSSurface>)createSurface {
::shell::GetExternalViewEmbedder get_view_embedder = [[^() {
return [[self flutterViewController] viewEmbedder];
} copy] autorelease];
if ([self.layer isKindOfClass:[CAEAGLLayer class]]) {
fml::scoped_nsobject<CAEAGLLayer> eagl_layer(
reinterpret_cast<CAEAGLLayer*>([self.layer retain]));
return std::make_unique<shell::IOSSurfaceGL>(std::move(eagl_layer), get_view_embedder);
return std::make_unique<shell::IOSSurfaceGL>(std::move(eagl_layer),
*[_delegate externalViewEmbedder]);
} else {
fml::scoped_nsobject<CALayer> layer(reinterpret_cast<CALayer*>([self.layer retain]));
return std::make_unique<shell::IOSSurfaceSoftware>(std::move(layer), get_view_embedder);
return std::make_unique<shell::IOSSurfaceSoftware>(std::move(layer),
*[_delegate externalViewEmbedder]);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,6 @@ - (void)performCommonViewControllerInitialization {
_statusBarStyle = UIStatusBarStyleDefault;

[self setupNotificationCenterObservers];
_platformViewsController.reset(
new shell::FlutterPlatformViewsController(_engine.get(), _flutterView.get()));
}

- (fml::scoped_nsobject<FlutterEngine>)engine {
Expand All @@ -125,10 +123,6 @@ - (void)performCommonViewControllerInitialization {
return _weakFactory->GetWeakPtr();
}

- (flow::ExternalViewEmbedder*)viewEmbedder {
return _platformViewsController.get();
}

- (void)setupNotificationCenterObservers {
NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
[center addObserver:self
Expand Down Expand Up @@ -364,10 +358,11 @@ - (void)surfaceUpdated:(BOOL)appeared {
// NotifyCreated/NotifyDestroyed are synchronous and require hops between the UI and GPU thread.
if (appeared) {
[self installSplashScreenViewCallback];
[_engine.get() platformViewsController] -> SetFlutterView(_flutterView.get());
[_engine.get() platformView] -> NotifyCreated();

} else {
[_engine.get() platformView] -> NotifyDestroyed();
[_engine.get() platformViewsController] -> SetFlutterView(nullptr);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@

@property(readonly) fml::scoped_nsobject<FlutterEngine> engine;

- (flow::ExternalViewEmbedder*)viewEmbedder;

@end

#endif // FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERVIEWCONTROLLER_INTERNAL_H_
2 changes: 0 additions & 2 deletions shell/platform/darwin/ios/ios_surface.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@

namespace shell {

typedef flow::ExternalViewEmbedder* (^GetExternalViewEmbedder)(void);

class IOSSurface {
public:
IOSSurface();
Expand Down
4 changes: 2 additions & 2 deletions shell/platform/darwin/ios/ios_surface_gl.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ namespace shell {
class IOSSurfaceGL : public IOSSurface, public GPUSurfaceGLDelegate {
public:
IOSSurfaceGL(fml::scoped_nsobject<CAEAGLLayer> layer,
::shell::GetExternalViewEmbedder get_view_embedder);
flow::ExternalViewEmbedder& external_view_embedder);

~IOSSurfaceGL() override;

Expand Down Expand Up @@ -46,7 +46,7 @@ class IOSSurfaceGL : public IOSSurface, public GPUSurfaceGLDelegate {
private:
IOSGLContext context_;

fml::scoped_nsprotocol<::shell::GetExternalViewEmbedder> get_view_embedder_;
flow::ExternalViewEmbedder& external_view_embedder_;

FML_DISALLOW_COPY_AND_ASSIGN(IOSSurfaceGL);
};
Expand Down
6 changes: 3 additions & 3 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,
::shell::GetExternalViewEmbedder get_view_embedder)
: context_(std::move(layer)), get_view_embedder_([get_view_embedder retain]) {}
flow::ExternalViewEmbedder& view_embedder)
: context_(std::move(layer)), external_view_embedder_(view_embedder) {}

IOSSurfaceGL::~IOSSurfaceGL() = default;

Expand Down Expand Up @@ -59,7 +59,7 @@
}

flow::ExternalViewEmbedder* IOSSurfaceGL::GetExternalViewEmbedder() {
return get_view_embedder_.get()();
return &external_view_embedder_;
}

} // namespace shell
4 changes: 2 additions & 2 deletions shell/platform/darwin/ios/ios_surface_software.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ namespace shell {
class IOSSurfaceSoftware final : public IOSSurface, public GPUSurfaceSoftwareDelegate {
public:
IOSSurfaceSoftware(fml::scoped_nsobject<CALayer> layer,
::shell::GetExternalViewEmbedder get_view_embedder);
flow::ExternalViewEmbedder& view_embedder);

~IOSSurfaceSoftware() override;

Expand All @@ -44,7 +44,7 @@ class IOSSurfaceSoftware final : public IOSSurface, public GPUSurfaceSoftwareDel

private:
fml::scoped_nsobject<CALayer> layer_;
fml::scoped_nsprotocol<::shell::GetExternalViewEmbedder> get_view_embedder_;
flow::ExternalViewEmbedder& external_view_embedder_;
sk_sp<SkSurface> sk_surface_;

FML_DISALLOW_COPY_AND_ASSIGN(IOSSurfaceSoftware);
Expand Down
Loading

0 comments on commit 92944f7

Please sign in to comment.