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 tranform 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  ~FlutterPlatformViewLayerPool() = default;
92 
93  // Gets a layer from the pool if available, or allocates a new one.
94  // Finally, it marks the layer as used. That is, it increments `available_layer_index_`.
95  std::shared_ptr<FlutterPlatformViewLayer> GetLayer(GrDirectContext* gr_context,
96  std::shared_ptr<IOSContext> ios_context);
97 
98  // Gets the layers in the pool that aren't currently used.
99  // This method doesn't mark the layers as unused.
100  std::vector<std::shared_ptr<FlutterPlatformViewLayer>> GetUnusedLayers();
101 
102  // Marks the layers in the pool as available for reuse.
103  void RecycleLayers();
104 
105  private:
106  // The index of the entry in the layers_ vector that determines the beginning of the unused
107  // layers. For example, consider the following vector:
108  // _____
109  // | 0 |
110  /// |---|
111  /// | 1 | <-- available_layer_index_
112  /// |---|
113  /// | 2 |
114  /// |---|
115  ///
116  /// This indicates that entries starting from 1 can be reused meanwhile the entry at position 0
117  /// cannot be reused.
118  size_t available_layer_index_ = 0;
119  std::vector<std::shared_ptr<FlutterPlatformViewLayer>> layers_;
120 
122 };
123 
125  public:
127 
129 
131 
132  void SetFlutterView(UIView* flutter_view);
133 
134  void SetFlutterViewController(UIViewController* flutter_view_controller);
135 
136  UIViewController* getFlutterViewController();
137 
138  void RegisterViewFactory(
139  NSObject<FlutterPlatformViewFactory>* factory,
140  NSString* factoryId,
141  FlutterPlatformViewGestureRecognizersBlockingPolicy gestureRecognizerBlockingPolicy);
142 
143  void SetFrameSize(SkISize frame_size);
144 
145  // Indicates that we don't compisite any platform views or overlays during this frame.
146  // Also reverts the composition_order_ to its original state at the begining of the frame.
147  void CancelFrame();
148 
149  void PrerollCompositeEmbeddedView(int view_id,
150  std::unique_ptr<flutter::EmbeddedViewParams> params);
151 
152  // Returns the `FlutterPlatformView` object associated with the view_id.
153  //
154  // If the `FlutterPlatformViewsController` does not contain any `FlutterPlatformView` object or
155  // a `FlutterPlatformView` object asscociated with the view_id cannot be found, the method
156  // returns nil.
157  NSObject<FlutterPlatformView>* GetPlatformViewByID(int view_id);
158 
159  PostPrerollResult PostPrerollAction(fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger);
160 
161  std::vector<SkCanvas*> GetCurrentCanvases();
162 
163  SkCanvas* CompositeEmbeddedView(int view_id);
164 
165  // The rect of the platform view at index view_id. This rect has been translated into the
166  // host view coordinate system. Units are device screen pixels.
167  SkRect GetPlatformViewRect(int view_id);
168 
169  // Discards all platform views instances and auxiliary resources.
170  void Reset();
171 
172  bool SubmitFrame(GrDirectContext* gr_context,
173  std::shared_ptr<IOSContext> ios_context,
174  std::unique_ptr<SurfaceFrame> frame);
175 
176  // Invoked at the very end of a frame.
177  // After invoking this method, nothing should happen on the current TaskRunner during the same
178  // frame.
179  void EndFrame(bool should_resubmit_frame,
180  fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger);
181 
182  void OnMethodCall(FlutterMethodCall* call, FlutterResult& result);
183 
184  private:
185  static const size_t kMaxLayerAllocations = 2;
186 
187  using LayersMap = std::map<int64_t, std::vector<std::shared_ptr<FlutterPlatformViewLayer>>>;
188 
189  // The pool of reusable view layers. The pool allows to recycle layer in each frame.
190  std::unique_ptr<FlutterPlatformViewLayerPool> layer_pool_;
191 
192  // The platform view's R-tree keyed off the view id, which contains any subsequent
193  // draw operation until the next platform view or the last leaf node in the layer tree.
194  //
195  // The R-trees are deleted by the FlutterPlatformViewsController.reset().
196  std::map<int64_t, sk_sp<RTree>> platform_view_rtrees_;
197 
198  // The platform view's picture recorder keyed off the view id, which contains any subsequent
199  // operation until the next platform view or the end of the last leaf node in the layer tree.
200  std::map<int64_t, std::unique_ptr<SkPictureRecorder>> picture_recorders_;
201 
203  fml::scoped_nsobject<UIView> flutter_view_;
204  fml::scoped_nsobject<UIViewController> flutter_view_controller_;
205  std::map<std::string, fml::scoped_nsobject<NSObject<FlutterPlatformViewFactory>>> factories_;
206  std::map<int64_t, fml::scoped_nsobject<NSObject<FlutterPlatformView>>> views_;
207  std::map<int64_t, fml::scoped_nsobject<FlutterTouchInterceptingView>> touch_interceptors_;
208  // Mapping a platform view ID to the top most parent view (root_view) who is a direct child to
209  // the `flutter_view_`.
210  //
211  // The platform view with the view ID is a child of the root view; If the platform view is not
212  // clipped, and no clipping view is added, the root view will be the intercepting view.
213  std::map<int64_t, fml::scoped_nsobject<UIView>> root_views_;
214  // Mapping a platform view ID to its latest composition params.
215  std::map<int64_t, EmbeddedViewParams> current_composition_params_;
216  // Mapping a platform view ID to the count of the clipping operations that were applied to the
217  // platform view last time it was composited.
218  std::map<int64_t, int64_t> clip_count_;
219  SkISize frame_size_;
220 
221  // The number of frames the rasterizer task runner will continue
222  // to run on the platform thread after no platform view is rendered.
223  //
224  // Note: this is an arbitrary number that attempts to account for cases
225  // where the platform view might be momentarily off the screen.
226  static const int kDefaultMergedLeaseDuration = 10;
227 
228  // Method channel `OnDispose` calls adds the views to be disposed to this set to be disposed on
229  // the next frame.
230  std::unordered_set<int64_t> views_to_dispose_;
231 
232  // A vector of embedded view IDs according to their composition order.
233  // The last ID in this vector belond to the that is composited on top of all others.
234  std::vector<int64_t> composition_order_;
235 
236  // The latest composition order that was presented in Present().
237  std::vector<int64_t> active_composition_order_;
238 
239  // Only compoiste platform views in this set.
240  std::unordered_set<int64_t> views_to_recomposite_;
241 
242  // The FlutterPlatformViewGestureRecognizersBlockingPolicy for each type of platform view.
243  std::map<std::string, FlutterPlatformViewGestureRecognizersBlockingPolicy>
244  gesture_recognizers_blocking_policies;
245 
246  std::unique_ptr<fml::WeakPtrFactory<FlutterPlatformViewsController>> weak_factory_;
247 
248  bool catransaction_added_ = false;
249 
250  void OnCreate(FlutterMethodCall* call, FlutterResult& result);
251  void OnDispose(FlutterMethodCall* call, FlutterResult& result);
252  void OnAcceptGesture(FlutterMethodCall* call, FlutterResult& result);
253  void OnRejectGesture(FlutterMethodCall* call, FlutterResult& result);
254  // Dispose the views in `views_to_dispose_`.
255  void DisposeViews();
256 
257  // Returns true if there are embedded views in the scene at current frame
258  // Or there will be embedded views in the next frame.
259  // TODO(cyanglaz): https://github.com/flutter/flutter/issues/56474
260  // Make this method check if there are pending view operations instead.
261  // Also rename it to `HasPendingViewOperations`.
262  bool HasPlatformViewThisOrNextFrame();
263 
264  // Traverse the `mutators_stack` and return the number of clip operations.
265  int CountClips(const MutatorsStack& mutators_stack);
266 
267  // Applies the mutators in the mutators_stack to the UIView chain that was constructed by
268  // `ReconstructClipViewsChain`
269  //
270  // Clips are applied to the super view with a CALayer mask. Transforms are applied to the
271  // current view that's at the head of the chain. For example the following mutators stack [T_1,
272  // C_2, T_3, T_4, C_5, T_6] where T denotes a transform and C denotes a clip, will result in the
273  // following UIView tree:
274  //
275  // C_2 -> C_5 -> PLATFORM_VIEW
276  // (PLATFORM_VIEW is a subview of C_5 which is a subview of C_2)
277  //
278  // 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.
279  //
280  // After each clip operation, we update the head to the super view of the current head.
281  void ApplyMutators(const MutatorsStack& mutators_stack, UIView* embedded_view);
282  void CompositeWithParams(int view_id, const EmbeddedViewParams& params);
283 
284  // Allocates a new FlutterPlatformViewLayer if needed, draws the pixels within the rect from
285  // the picture on the layer's canvas.
286  std::shared_ptr<FlutterPlatformViewLayer> GetLayer(GrDirectContext* gr_context,
287  std::shared_ptr<IOSContext> ios_context,
288  sk_sp<SkPicture> picture,
289  SkRect rect,
290  int64_t view_id,
291  int64_t overlay_id);
292  // Removes overlay views and platform views that aren't needed in the current frame.
293  // Must run on the platform thread.
294  void RemoveUnusedLayers();
295  // Appends the overlay views and platform view and sets their z index based on the composition
296  // order.
297  void BringLayersIntoView(LayersMap layer_map);
298 
299  // Begin a CATransaction.
300  // This transaction needs to be balanced with |CommitCATransactionIfNeeded|.
301  void BeginCATransaction();
302 
303  // Commit a CATransaction if |BeginCATransaction| has been called during the frame.
304  void CommitCATransactionIfNeeded();
305 
307 };
308 
309 } // namespace flutter
310 
311 // A UIView that is used as the parent for embedded UIViews.
312 //
313 // This view has 2 roles:
314 // 1. Delay or prevent touch events from arriving the embedded view.
315 // 2. Dispatching all events that are hittested to the embedded view to the FlutterView.
316 @interface FlutterTouchInterceptingView : UIView
317 - (instancetype)initWithEmbeddedView:(UIView*)embeddedView
318  platformViewsController:
319  (fml::WeakPtr<flutter::FlutterPlatformViewsController>)platformViewsController
320  gestureRecognizersBlockingPolicy:
321  (FlutterPlatformViewGestureRecognizersBlockingPolicy)blockingPolicy;
322 
323 // Stop delaying any active touch sequence (and let it arrive the embedded view).
324 - (void)releaseGesture;
325 
326 // Prevent the touch sequence from ever arriving to the embedded view.
327 - (void)blockGesture;
328 @end
329 
330 #endif // FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERPLATFORMVIEWS_INTERNAL_H_
fml::scoped_nsobject< UIView > overlay_view_wrapper
void ResetAnchor(CALayer *layer)
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