Flutter Engine
FlutterPlatformViews_Internal.h
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERPLATFORMVIEWS_INTERNAL_H_
6 #define FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERPLATFORMVIEWS_INTERNAL_H_
7 
8 #include "flutter/flow/embedded_views.h"
9 #include "flutter/flow/rtree.h"
10 #include "flutter/fml/platform/darwin/scoped_nsobject.h"
11 #include "flutter/shell/common/shell.h"
12 #import "flutter/shell/platform/darwin/common/framework/Headers/FlutterBinaryMessenger.h"
13 #import "flutter/shell/platform/darwin/common/framework/Headers/FlutterChannels.h"
14 #import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterPlatformViews.h"
15 #import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterPlugin.h"
16 #import "flutter/shell/platform/darwin/ios/ios_context.h"
17 #include "third_party/skia/include/core/SkPictureRecorder.h"
18 
20 
21 // A UIView that acts as a clipping mask for the |ChildClippingView|.
22 //
23 // On the [UIView drawRect:] method, this view performs a series of clipping operations and sets the
24 // alpha channel to the final resulting area to be 1; it also sets the "clipped out" area's alpha
25 // channel to be 0.
26 //
27 // When a UIView sets a |FlutterClippingMaskView| as its `maskView`, the alpha channel of the UIView
28 // is replaced with the alpha channel of the |FlutterClippingMaskView|.
29 @interface FlutterClippingMaskView : UIView
30 
31 // Adds a clip rect operation to the queue.
32 //
33 // The `clipSkRect` is transformed with the `matrix` before adding to the queue.
34 - (void)clipRect:(const SkRect&)clipSkRect matrix:(const CATransform3D&)matrix;
35 
36 // Adds a clip rrect operation to the queue.
37 //
38 // The `clipSkRRect` is transformed with the `matrix` before adding to the queue.
39 - (void)clipRRect:(const SkRRect&)clipSkRRect matrix:(const CATransform3D&)matrix;
40 
41 // Adds a clip path operation to the queue.
42 //
43 // The `path` is transformed with the `matrix` before adding to the queue.
44 - (void)clipPath:(const SkPath&)path matrix:(const CATransform3D&)matrix;
45 
46 @end
47 
48 // The parent view handles clipping to its subviews.
49 @interface ChildClippingView : UIView
50 
51 @end
52 
53 namespace flutter {
54 // Converts a SkMatrix to CATransform3D.
55 // Certain fields are ignored in CATransform3D since SkMatrix is 3x3 and CATransform3D is 4x4.
56 CATransform3D GetCATransform3DFromSkMatrix(const SkMatrix& matrix);
57 
58 // Reset the anchor of `layer` to match the transform operation from flow.
59 // The position of the `layer` should be unchanged after resetting the anchor.
60 void ResetAnchor(CALayer* layer);
61 
62 class IOSContextGL;
63 class IOSSurface;
64 
67  fml::scoped_nsobject<UIView> overlay_view_wrapper,
68  std::unique_ptr<IOSSurface> ios_surface,
69  std::unique_ptr<Surface> surface);
70 
72 
75  std::unique_ptr<IOSSurface> ios_surface;
76  std::unique_ptr<Surface> surface;
77 
78  // Whether a frame for this layer was submitted.
80 
81  // The GrContext that is currently used by the overlay surfaces.
82  // We track this to know when the GrContext for the Flutter app has changed
83  // so we can update the overlay with the new context.
84  GrDirectContext* gr_context;
85 };
86 
87 // This class isn't thread safe.
89  public:
90  FlutterPlatformViewLayerPool() = default;
91 
92  ~FlutterPlatformViewLayerPool() = default;
93 
94  // Gets a layer from the pool if available, or allocates a new one.
95  // Finally, it marks the layer as used. That is, it increments `available_layer_index_`.
96  std::shared_ptr<FlutterPlatformViewLayer> GetLayer(GrDirectContext* gr_context,
97  std::shared_ptr<IOSContext> ios_context);
98 
99  // Gets the layers in the pool that aren't currently used.
100  // This method doesn't mark the layers as unused.
101  std::vector<std::shared_ptr<FlutterPlatformViewLayer>> GetUnusedLayers();
102 
103  // Marks the layers in the pool as available for reuse.
104  void RecycleLayers();
105 
106  private:
107  // The index of the entry in the layers_ vector that determines the beginning of the unused
108  // layers. For example, consider the following vector:
109  // _____
110  // | 0 |
111  /// |---|
112  /// | 1 | <-- available_layer_index_
113  /// |---|
114  /// | 2 |
115  /// |---|
116  ///
117  /// This indicates that entries starting from 1 can be reused meanwhile the entry at position 0
118  /// cannot be reused.
119  size_t available_layer_index_ = 0;
120  std::vector<std::shared_ptr<FlutterPlatformViewLayer>> layers_;
121 
123 };
124 
126  public:
128 
130 
132 
133  void SetFlutterView(UIView* flutter_view);
134 
135  void SetFlutterViewController(UIViewController* flutter_view_controller);
136 
137  UIViewController* getFlutterViewController();
138 
139  void RegisterViewFactory(
140  NSObject<FlutterPlatformViewFactory>* factory,
141  NSString* factoryId,
142  FlutterPlatformViewGestureRecognizersBlockingPolicy gestureRecognizerBlockingPolicy);
143 
144  // Called at the beginning of each frame.
145  void BeginFrame(SkISize frame_size);
146 
147  // Indicates that we don't compisite any platform views or overlays during this frame.
148  // Also reverts the composition_order_ to its original state at the beginning of the frame.
149  void CancelFrame();
150 
151  void PrerollCompositeEmbeddedView(int view_id,
152  std::unique_ptr<flutter::EmbeddedViewParams> params);
153 
154  // Returns the `FlutterPlatformView`'s `view` object associated with the view_id.
155  //
156  // If the `FlutterPlatformViewsController` does not contain any `FlutterPlatformView` object or
157  // a `FlutterPlatformView` object asscociated with the view_id cannot be found, the method
158  // returns nil.
159  UIView* GetPlatformViewByID(int view_id);
160 
161  PostPrerollResult PostPrerollAction(fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger);
162 
163  std::vector<SkCanvas*> GetCurrentCanvases();
164 
165  SkCanvas* CompositeEmbeddedView(int view_id);
166 
167  // The rect of the platform view at index view_id. This rect has been translated into the
168  // host view coordinate system. Units are device screen pixels.
169  SkRect GetPlatformViewRect(int view_id);
170 
171  // Discards all platform views instances and auxiliary resources.
172  void Reset();
173 
174  bool SubmitFrame(GrDirectContext* gr_context,
175  std::shared_ptr<IOSContext> ios_context,
176  std::unique_ptr<SurfaceFrame> frame);
177 
178  void OnMethodCall(FlutterMethodCall* call, FlutterResult& result);
179 
180  private:
181  static const size_t kMaxLayerAllocations = 2;
182 
183  using LayersMap = std::map<int64_t, std::vector<std::shared_ptr<FlutterPlatformViewLayer>>>;
184 
185  // The pool of reusable view layers. The pool allows to recycle layer in each frame.
186  std::unique_ptr<FlutterPlatformViewLayerPool> layer_pool_;
187 
188  // The platform view's R-tree keyed off the view id, which contains any subsequent
189  // draw operation until the next platform view or the last leaf node in the layer tree.
190  //
191  // The R-trees are deleted by the FlutterPlatformViewsController.reset().
192  std::map<int64_t, sk_sp<RTree>> platform_view_rtrees_;
193 
194  // The platform view's picture recorder keyed off the view id, which contains any subsequent
195  // operation until the next platform view or the end of the last leaf node in the layer tree.
196  std::map<int64_t, std::unique_ptr<SkPictureRecorder>> picture_recorders_;
197 
199  fml::scoped_nsobject<UIView> flutter_view_;
200  fml::scoped_nsobject<UIViewController> flutter_view_controller_;
201  std::map<std::string, fml::scoped_nsobject<NSObject<FlutterPlatformViewFactory>>> factories_;
202  std::map<int64_t, fml::scoped_nsobject<NSObject<FlutterPlatformView>>> views_;
203  std::map<int64_t, fml::scoped_nsobject<FlutterTouchInterceptingView>> touch_interceptors_;
204  // Mapping a platform view ID to the top most parent view (root_view) of a platform view. In
205  // |SubmitFrame|, root_views_ are added to flutter_view_ as child views.
206  //
207  // The platform view with the view ID is a child of the root view; If the platform view is not
208  // clipped, and no clipping view is added, the root view will be the intercepting view.
209  std::map<int64_t, fml::scoped_nsobject<UIView>> root_views_;
210  // Mapping a platform view ID to its latest composition params.
211  std::map<int64_t, EmbeddedViewParams> current_composition_params_;
212  // Mapping a platform view ID to the count of the clipping operations that were applied to the
213  // platform view last time it was composited.
214  std::map<int64_t, int64_t> clip_count_;
215  SkISize frame_size_;
216 
217  // The number of frames the rasterizer task runner will continue
218  // to run on the platform thread after no platform view is rendered.
219  //
220  // Note: this is an arbitrary number that attempts to account for cases
221  // where the platform view might be momentarily off the screen.
222  static const int kDefaultMergedLeaseDuration = 10;
223 
224  // Method channel `OnDispose` calls adds the views to be disposed to this set to be disposed on
225  // the next frame.
226  std::unordered_set<int64_t> views_to_dispose_;
227 
228  // A vector of embedded view IDs according to their composition order.
229  // The last ID in this vector belond to the that is composited on top of all others.
230  std::vector<int64_t> composition_order_;
231 
232  // The latest composition order that was presented in Present().
233  std::vector<int64_t> active_composition_order_;
234 
235  // Only compoiste platform views in this set.
236  std::unordered_set<int64_t> views_to_recomposite_;
237 
238  // The FlutterPlatformViewGestureRecognizersBlockingPolicy for each type of platform view.
239  std::map<std::string, FlutterPlatformViewGestureRecognizersBlockingPolicy>
240  gesture_recognizers_blocking_policies;
241 
242  std::unique_ptr<fml::WeakPtrFactory<FlutterPlatformViewsController>> weak_factory_;
243 
244  bool catransaction_added_ = false;
245 
246  void OnCreate(FlutterMethodCall* call, FlutterResult& result);
247  void OnDispose(FlutterMethodCall* call, FlutterResult& result);
248  void OnAcceptGesture(FlutterMethodCall* call, FlutterResult& result);
249  void OnRejectGesture(FlutterMethodCall* call, FlutterResult& result);
250  // Dispose the views in `views_to_dispose_`.
251  void DisposeViews();
252 
253  // Returns true if there are embedded views in the scene at current frame
254  // Or there will be embedded views in the next frame.
255  // TODO(cyanglaz): https://github.com/flutter/flutter/issues/56474
256  // Make this method check if there are pending view operations instead.
257  // Also rename it to `HasPendingViewOperations`.
258  bool HasPlatformViewThisOrNextFrame();
259 
260  // Traverse the `mutators_stack` and return the number of clip operations.
261  int CountClips(const MutatorsStack& mutators_stack);
262 
263  // Applies the mutators in the mutators_stack to the UIView chain that was constructed by
264  // `ReconstructClipViewsChain`
265  //
266  // Clips are applied to the super view with a CALayer mask. Transforms are applied to the
267  // current view that's at the head of the chain. For example the following mutators stack [T_1,
268  // C_2, T_3, T_4, C_5, T_6] where T denotes a transform and C denotes a clip, will result in the
269  // following UIView tree:
270  //
271  // C_2 -> C_5 -> PLATFORM_VIEW
272  // (PLATFORM_VIEW is a subview of C_5 which is a subview of C_2)
273  //
274  // T_1 is applied to C_2, T_3 and T_4 are applied to C_5, and T_6 is applied to PLATFORM_VIEW.
275  //
276  // After each clip operation, we update the head to the super view of the current head.
277  void ApplyMutators(const MutatorsStack& mutators_stack, UIView* embedded_view);
278  void CompositeWithParams(int view_id, const EmbeddedViewParams& params);
279 
280  // Allocates a new FlutterPlatformViewLayer if needed, draws the pixels within the rect from
281  // the picture on the layer's canvas.
282  std::shared_ptr<FlutterPlatformViewLayer> GetLayer(GrDirectContext* gr_context,
283  std::shared_ptr<IOSContext> ios_context,
284  sk_sp<SkPicture> picture,
285  SkRect rect,
286  int64_t view_id,
287  int64_t overlay_id);
288  // Removes overlay views and platform views that aren't needed in the current frame.
289  // Must run on the platform thread.
290  void RemoveUnusedLayers();
291  // Appends the overlay views and platform view and sets their z index based on the composition
292  // order.
293  void BringLayersIntoView(LayersMap layer_map);
294 
295  // Begin a CATransaction.
296  // This transaction needs to be balanced with |CommitCATransactionIfNeeded|.
297  void BeginCATransaction();
298 
299  // Commit a CATransaction if |BeginCATransaction| has been called during the frame.
300  void CommitCATransactionIfNeeded();
301 
302  // Resets the state of the frame.
303  void ResetFrameState();
304 
306 };
307 
308 } // namespace flutter
309 
310 // A UIView that is used as the parent for embedded UIViews.
311 //
312 // This view has 2 roles:
313 // 1. Delay or prevent touch events from arriving the embedded view.
314 // 2. Dispatching all events that are hittested to the embedded view to the FlutterView.
315 @interface FlutterTouchInterceptingView : UIView
316 - (instancetype)initWithEmbeddedView:(UIView*)embeddedView
317  platformViewsController:
318  (fml::WeakPtr<flutter::FlutterPlatformViewsController>)platformViewsController
319  gestureRecognizersBlockingPolicy:
320  (FlutterPlatformViewGestureRecognizersBlockingPolicy)blockingPolicy;
321 
322 // Stop delaying any active touch sequence (and let it arrive the embedded view).
323 - (void)releaseGesture;
324 
325 // Prevent the touch sequence from ever arriving to the embedded view.
326 - (void)blockGesture;
327 
328 // Get embedded view
329 - (UIView*)embeddedView;
330 @end
331 
332 #endif // FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERPLATFORMVIEWS_INTERNAL_H_
fml::scoped_nsobject< UIView > overlay_view_wrapper
void ResetAnchor(CALayer *layer)
GAsyncResult * result
void(^ FlutterResult)(id _Nullable result)
CATransform3D GetCATransform3DFromSkMatrix(const SkMatrix &matrix)
fml::scoped_nsobject< UIView > overlay_view
FlutterPlatformViewGestureRecognizersBlockingPolicy
#define FML_DISALLOW_COPY_AND_ASSIGN(TypeName)
Definition: macros.h:27