Skip to content

Commit 92944f7

Browse files
authored
Move FlutterPlatformViewsController into FlutterEngine. (flutter#6709)
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.
1 parent d34cb17 commit 92944f7

13 files changed

Lines changed: 68 additions & 77 deletions

shell/platform/darwin/ios/framework/Source/FlutterEngine.mm

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,15 @@ @implementation FlutterEngine {
4444
fml::WeakPtr<FlutterViewController> _viewController;
4545
fml::scoped_nsobject<FlutterObservatoryPublisher> _publisher;
4646

47+
std::unique_ptr<shell::FlutterPlatformViewsController> _platformViewsController;
48+
4749
// Channels
4850
fml::scoped_nsobject<FlutterPlatformPlugin> _platformPlugin;
4951
fml::scoped_nsobject<FlutterTextInputPlugin> _textInputPlugin;
5052
fml::scoped_nsobject<FlutterMethodChannel> _localizationChannel;
5153
fml::scoped_nsobject<FlutterMethodChannel> _navigationChannel;
5254
fml::scoped_nsobject<FlutterMethodChannel> _platformChannel;
55+
fml::scoped_nsobject<FlutterMethodChannel> _platformViewsChannel;
5356
fml::scoped_nsobject<FlutterMethodChannel> _textInputChannel;
5457
fml::scoped_nsobject<FlutterBasicMessageChannel> _lifecycleChannel;
5558
fml::scoped_nsobject<FlutterBasicMessageChannel> _systemChannel;
@@ -73,6 +76,7 @@ - (instancetype)initWithName:(NSString*)labelPrefix project:(FlutterDartProject*
7376

7477
_pluginPublications = [NSMutableDictionary new];
7578
_publisher.reset([[FlutterObservatoryPublisher alloc] init]);
79+
_platformViewsController.reset(new shell::FlutterPlatformViewsController());
7680

7781
[self setupChannels];
7882

@@ -143,6 +147,9 @@ - (FlutterViewController*)viewController {
143147
- (FlutterPlatformPlugin*)platformPlugin {
144148
return _platformPlugin.get();
145149
}
150+
- (shell::FlutterPlatformViewsController*)platformViewsController {
151+
return _platformViewsController.get();
152+
}
146153
- (FlutterTextInputPlugin*)textInputPlugin {
147154
return _textInputPlugin.get();
148155
}
@@ -184,6 +191,11 @@ - (void)setupChannels {
184191
binaryMessenger:self
185192
codec:[FlutterJSONMethodCodec sharedInstance]]);
186193

194+
_platformViewsChannel.reset([[FlutterMethodChannel alloc]
195+
initWithName:@"flutter/platform_views"
196+
binaryMessenger:self
197+
codec:[FlutterStandardMethodCodec sharedInstance]]);
198+
187199
_textInputChannel.reset([[FlutterMethodChannel alloc]
188200
initWithName:@"flutter/textinput"
189201
binaryMessenger:self
@@ -218,6 +230,11 @@ - (void)maybeSetupPlatformViewChannels {
218230
[_platformPlugin.get() handleMethodCall:call result:result];
219231
}];
220232

233+
[_platformViewsChannel.get()
234+
setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
235+
_platformViewsController->OnMethodCall(call, result);
236+
}];
237+
221238
[_textInputChannel.get() setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
222239
[_textInputPlugin.get() handleMethodCall:call result:result];
223240
}];
@@ -379,6 +396,10 @@ - (void)performAction:(FlutterTextInputAction)action withClient:(int)client {
379396
return _shell->Screenshot(type, base64Encode);
380397
}
381398

399+
- (flow::ExternalViewEmbedder*)externalViewEmbedder {
400+
return _platformViewsController.get();
401+
}
402+
382403
#pragma mark - FlutterBinaryMessenger
383404

384405
- (void)sendOnChannel:(NSString*)channel message:(NSData*)message {
@@ -514,18 +535,7 @@ - (NSString*)lookupKeyForAsset:(NSString*)asset fromPackage:(NSString*)package {
514535

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

531541
@end

shell/platform/darwin/ios/framework/Source/FlutterEngine_Internal.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

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

10+
#import "FlutterPlatformViews_Internal.h"
11+
1012
#include "flutter/fml/memory/weak_ptr.h"
1113
#include "flutter/fml/task_runner.h"
1214
#include "flutter/lib/ui/window/pointer_data_packet.h"
@@ -22,7 +24,7 @@
2224

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

25-
@interface FlutterEngine () <FlutterScreenshotDelegate>
27+
@interface FlutterEngine () <FlutterViewEngineDelegate>
2628

2729
- (shell::Shell&)shell;
2830

@@ -37,6 +39,7 @@
3739
base64Encode:(bool)base64Encode;
3840

3941
- (FlutterPlatformPlugin*)platformPlugin;
42+
- (shell::FlutterPlatformViewsController*)platformViewsController;
4043
- (FlutterTextInputPlugin*)textInputPlugin;
4144
- (void)launchEngine:(NSString*)entrypoint libraryURI:(NSString*)libraryOrNil;
4245

shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,8 @@
1414

1515
namespace shell {
1616

17-
FlutterPlatformViewsController::FlutterPlatformViewsController(
18-
NSObject<FlutterBinaryMessenger>* messenger,
19-
FlutterView* flutter_view)
20-
: flutter_view_([flutter_view retain]) {
21-
channel_.reset([[FlutterMethodChannel alloc]
22-
initWithName:@"flutter/platform_views"
23-
binaryMessenger:messenger
24-
codec:[FlutterStandardMethodCodec sharedInstance]]);
25-
[channel_.get() setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
26-
OnMethodCall(call, result);
27-
}];
17+
void FlutterPlatformViewsController::SetFlutterView(UIView* flutter_view) {
18+
flutter_view_.reset(flutter_view);
2819
}
2920

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

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

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

69-
FlutterView* flutter_view = flutter_view_.get();
69+
UIView* flutter_view = flutter_view_.get();
7070
[flutter_view addSubview:views_[viewId].get()];
7171
result(nil);
7272
}

shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
#ifndef FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERPLATFORMVIEWS_INTERNAL_H_
66
#define FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERPLATFORMVIEWS_INTERNAL_H_
77

8-
#include "FlutterView.h"
98
#include "flutter/flow/embedded_views.h"
109
#include "flutter/fml/platform/darwin/scoped_nsobject.h"
1110
#include "flutter/shell/common/shell.h"
@@ -29,20 +28,22 @@ namespace shell {
2928

3029
class FlutterPlatformViewsController : public flow::ExternalViewEmbedder {
3130
public:
32-
FlutterPlatformViewsController(NSObject<FlutterBinaryMessenger>* messenger,
33-
FlutterView* flutter_view);
31+
FlutterPlatformViewsController() = default;
32+
33+
void SetFlutterView(UIView* flutter_view);
3434

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

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

39+
void OnMethodCall(FlutterMethodCall* call, FlutterResult& result);
40+
3941
private:
4042
fml::scoped_nsobject<FlutterMethodChannel> channel_;
41-
fml::scoped_nsobject<FlutterView> flutter_view_;
43+
fml::scoped_nsobject<UIView> flutter_view_;
4244
std::map<std::string, fml::scoped_nsobject<NSObject<FlutterPlatformViewFactory>>> factories_;
4345
std::map<int64_t, fml::scoped_nsobject<FlutterTouchInterceptingView>> views_;
4446

45-
void OnMethodCall(FlutterMethodCall* call, FlutterResult& result);
4647
void OnCreate(FlutterMethodCall* call, FlutterResult& result);
4748
void OnDispose(FlutterMethodCall* call, FlutterResult& result);
4849
void OnAcceptGesture(FlutterMethodCall* call, FlutterResult& result);

shell/platform/darwin/ios/framework/Source/FlutterView.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,20 @@
99

1010
#include <memory>
1111

12+
#import "FlutterPlatformViews_Internal.h"
13+
1214
#include "flutter/flow/embedded_views.h"
1315
#include "flutter/fml/memory/weak_ptr.h"
1416
#include "flutter/shell/common/shell.h"
1517
#include "flutter/shell/platform/darwin/ios/ios_surface.h"
1618

17-
@protocol FlutterScreenshotDelegate <NSObject>
19+
@protocol FlutterViewEngineDelegate <NSObject>
1820

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

24+
- (flow::ExternalViewEmbedder*)externalViewEmbedder;
25+
2226
@end
2327

2428
@interface FlutterView : UIView
@@ -27,7 +31,7 @@
2731
- (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE;
2832
- (instancetype)initWithCoder:(NSCoder*)aDecoder NS_UNAVAILABLE;
2933

30-
- (instancetype)initWithDelegate:(id<FlutterScreenshotDelegate>)delegate
34+
- (instancetype)initWithDelegate:(id<FlutterViewEngineDelegate>)delegate
3135
opaque:(BOOL)opaque NS_DESIGNATED_INITIALIZER;
3236
- (std::unique_ptr<shell::IOSSurface>)createSurface;
3337

shell/platform/darwin/ios/framework/Source/FlutterView.mm

Lines changed: 6 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ @interface FlutterView () <UIInputViewAudioFeedback>
2323

2424
@implementation FlutterView
2525

26-
id<FlutterScreenshotDelegate> _delegate;
26+
id<FlutterViewEngineDelegate> _delegate;
2727

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

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

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

58-
- (FlutterViewController*)flutterViewController {
59-
// Find the first view controller in the responder chain and see if it is a FlutterViewController.
60-
for (UIResponder* responder = self.nextResponder; responder != nil;
61-
responder = responder.nextResponder) {
62-
if ([responder isKindOfClass:[UIViewController class]]) {
63-
if ([responder isKindOfClass:[FlutterViewController class]]) {
64-
return reinterpret_cast<FlutterViewController*>(responder);
65-
} else {
66-
// Should only happen if a non-FlutterViewController tries to somehow (via dynamic class
67-
// resolution or reparenting) set a FlutterView as its view.
68-
return nil;
69-
}
70-
}
71-
}
72-
return nil;
73-
}
74-
7558
- (void)layoutSubviews {
7659
if ([self.layer isKindOfClass:[CAEAGLLayer class]]) {
7760
CAEAGLLayer* layer = reinterpret_cast<CAEAGLLayer*>(self.layer);
@@ -93,16 +76,15 @@ + (Class)layerClass {
9376
}
9477

9578
- (std::unique_ptr<shell::IOSSurface>)createSurface {
96-
::shell::GetExternalViewEmbedder get_view_embedder = [[^() {
97-
return [[self flutterViewController] viewEmbedder];
98-
} copy] autorelease];
9979
if ([self.layer isKindOfClass:[CAEAGLLayer class]]) {
10080
fml::scoped_nsobject<CAEAGLLayer> eagl_layer(
10181
reinterpret_cast<CAEAGLLayer*>([self.layer retain]));
102-
return std::make_unique<shell::IOSSurfaceGL>(std::move(eagl_layer), get_view_embedder);
82+
return std::make_unique<shell::IOSSurfaceGL>(std::move(eagl_layer),
83+
*[_delegate externalViewEmbedder]);
10384
} else {
10485
fml::scoped_nsobject<CALayer> layer(reinterpret_cast<CALayer*>([self.layer retain]));
105-
return std::make_unique<shell::IOSSurfaceSoftware>(std::move(layer), get_view_embedder);
86+
return std::make_unique<shell::IOSSurfaceSoftware>(std::move(layer),
87+
*[_delegate externalViewEmbedder]);
10688
}
10789
}
10890

shell/platform/darwin/ios/framework/Source/FlutterViewController.mm

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,6 @@ - (void)performCommonViewControllerInitialization {
113113
_statusBarStyle = UIStatusBarStyleDefault;
114114

115115
[self setupNotificationCenterObservers];
116-
_platformViewsController.reset(
117-
new shell::FlutterPlatformViewsController(_engine.get(), _flutterView.get()));
118116
}
119117

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

128-
- (flow::ExternalViewEmbedder*)viewEmbedder {
129-
return _platformViewsController.get();
130-
}
131-
132126
- (void)setupNotificationCenterObservers {
133127
NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
134128
[center addObserver:self
@@ -364,10 +358,11 @@ - (void)surfaceUpdated:(BOOL)appeared {
364358
// NotifyCreated/NotifyDestroyed are synchronous and require hops between the UI and GPU thread.
365359
if (appeared) {
366360
[self installSplashScreenViewCallback];
361+
[_engine.get() platformViewsController] -> SetFlutterView(_flutterView.get());
367362
[_engine.get() platformView] -> NotifyCreated();
368-
369363
} else {
370364
[_engine.get() platformView] -> NotifyDestroyed();
365+
[_engine.get() platformViewsController] -> SetFlutterView(nullptr);
371366
}
372367
}
373368

shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@
1919

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

22-
- (flow::ExternalViewEmbedder*)viewEmbedder;
23-
2422
@end
2523

2624
#endif // FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERVIEWCONTROLLER_INTERNAL_H_

shell/platform/darwin/ios/ios_surface.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@
1313

1414
namespace shell {
1515

16-
typedef flow::ExternalViewEmbedder* (^GetExternalViewEmbedder)(void);
17-
1816
class IOSSurface {
1917
public:
2018
IOSSurface();

shell/platform/darwin/ios/ios_surface_gl.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ namespace shell {
1818
class IOSSurfaceGL : public IOSSurface, public GPUSurfaceGLDelegate {
1919
public:
2020
IOSSurfaceGL(fml::scoped_nsobject<CAEAGLLayer> layer,
21-
::shell::GetExternalViewEmbedder get_view_embedder);
21+
flow::ExternalViewEmbedder& external_view_embedder);
2222

2323
~IOSSurfaceGL() override;
2424

@@ -46,7 +46,7 @@ class IOSSurfaceGL : public IOSSurface, public GPUSurfaceGLDelegate {
4646
private:
4747
IOSGLContext context_;
4848

49-
fml::scoped_nsprotocol<::shell::GetExternalViewEmbedder> get_view_embedder_;
49+
flow::ExternalViewEmbedder& external_view_embedder_;
5050

5151
FML_DISALLOW_COPY_AND_ASSIGN(IOSSurfaceGL);
5252
};

0 commit comments

Comments
 (0)