Skip to content

Commit

Permalink
Make the FlutterPlatformViewFactory create FlutterPlatformViews. (#6782)
Browse files Browse the repository at this point in the history
Handing a UIView refererence directly to the engine makes it challenging
for plugin authors to retain a controller for that UIView (e.g the
controller that talks over the platform channel) for as long as the
embedded view is needed.

We instead make the factory return a FlutterPlatformView which is a
wrapper around the UIView that the engine retains as long as the
platform view instance is needed. This allows plugin authors to keep
their control logic in the FlutterPlatformView and know that the engine
is responsible for retaining the reference.
  • Loading branch information
amirh authored Nov 8, 2018
1 parent 7ed4909 commit a0efb94
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 20 deletions.
7 changes: 3 additions & 4 deletions shell/common/rasterizer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -164,10 +164,9 @@ bool Rasterizer::DrawToSurface(flow::LayerTree& layer_tree) {

auto external_view_embedder = surface_->GetExternalViewEmbedder();

// TODO(amirh): uncomment this once external_view_embedder is populated.
// if (external_view_embedder != nullptr) {
// external_view_embedder->SetFrameSize(layer_tree.frame_size());
// }
if (external_view_embedder != nullptr) {
external_view_embedder->SetFrameSize(layer_tree.frame_size());
}

auto compositor_frame = compositor_context_->AcquireFrame(
surface_->GetContext(), canvas, external_view_embedder,
Expand Down
16 changes: 13 additions & 3 deletions shell/platform/darwin/ios/framework/Headers/FlutterPlatformViews.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,16 @@

NS_ASSUME_NONNULL_BEGIN

/**
* Wraps a `UIView` for embedding in the Flutter hierarchy
*/
@protocol FlutterPlatformView <NSObject>
/**
* Returns a reference to the `UIView` that is wrapped by this `FlutterPlatformView`.
*/
- (UIView*)view;
@end

FLUTTER_EXPORT
@protocol FlutterPlatformViewFactory <NSObject>
/**
Expand All @@ -28,9 +38,9 @@ FLUTTER_EXPORT
* code, this will be null. Otherwise this will be the value sent from the Dart code as decoded by
* `createArgsCodec`.
*/
- (UIView*)createWithFrame:(CGRect)frame
viewIdentifier:(int64_t)viewId
arguments:(id _Nullable)args;
- (NSObject<FlutterPlatformView>*)createWithFrame:(CGRect)frame
viewIdentifier:(int64_t)viewId
arguments:(id _Nullable)args;

/**
* Returns the `FlutterMessageCodec` for decoding the args parameter of `createWithFrame`.
Expand Down
29 changes: 17 additions & 12 deletions shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,17 @@
}
}

UIView* embedded_view = [factory createWithFrame:CGRectZero
viewIdentifier:viewId
arguments:params];
FlutterTouchInterceptingView* view =
[[[FlutterTouchInterceptingView alloc] initWithEmbeddedView:embedded_view
NSObject<FlutterPlatformView>* embedded_view = [factory createWithFrame:CGRectZero
viewIdentifier:viewId
arguments:params];
views_[viewId] = fml::scoped_nsobject<NSObject<FlutterPlatformView>>([embedded_view retain]);

FlutterTouchInterceptingView* touch_interceptor =
[[[FlutterTouchInterceptingView alloc] initWithEmbeddedView:embedded_view.view
flutterView:flutter_view_] autorelease];
views_[viewId] = fml::scoped_nsobject<FlutterTouchInterceptingView>([view retain]);

touch_interceptors_[viewId] =
fml::scoped_nsobject<FlutterTouchInterceptingView>([touch_interceptor retain]);

result(nil);
}
Expand All @@ -94,9 +98,10 @@
return;
}

UIView* view = views_[viewId].get();
[view removeFromSuperview];
UIView* touch_interceptor = touch_interceptors_[viewId].get();
[touch_interceptor removeFromSuperview];
views_.erase(viewId);
touch_interceptors_.erase(viewId);
overlays_.erase(viewId);
result(nil);
}
Expand All @@ -113,7 +118,7 @@
return;
}

FlutterTouchInterceptingView* view = views_[viewId].get();
FlutterTouchInterceptingView* view = touch_interceptors_[viewId].get();
[view releaseGesture];

result(nil);
Expand Down Expand Up @@ -159,8 +164,8 @@
CGRectMake(params.offsetPixels.x() / screenScale, params.offsetPixels.y() / screenScale,
params.sizePoints.width(), params.sizePoints.height());

UIView* view = views_[view_id].get();
[view setFrame:rect];
UIView* touch_interceptor = touch_interceptors_[view_id].get();
[touch_interceptor setFrame:rect];

SkCanvas* canvas = composition_frames_[view_id]->SkiaCanvas();
canvas->clear(SK_ColorTRANSPARENT);
Expand Down Expand Up @@ -204,7 +209,7 @@
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()];
[flutter_view addSubview:touch_interceptors_[view_id].get()];
[flutter_view addSubview:overlays_[view_id]->overlay_view.get()];
active_composition_order_.push_back(view_id);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ class FlutterPlatformViewsController {
fml::scoped_nsobject<FlutterMethodChannel> channel_;
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_;
std::map<int64_t, fml::scoped_nsobject<NSObject<FlutterPlatformView>>> views_;
std::map<int64_t, fml::scoped_nsobject<FlutterTouchInterceptingView>> touch_interceptors_;
std::map<int64_t, std::unique_ptr<FlutterPlatformViewLayer>> overlays_;
SkISize frame_size_;

Expand Down

0 comments on commit a0efb94

Please sign in to comment.