• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/fml/platform/darwin/scoped_nsobject.h"
10 #include "flutter/shell/common/shell.h"
11 #include "flutter/shell/platform/darwin/common/framework/Headers/FlutterBinaryMessenger.h"
12 #include "flutter/shell/platform/darwin/common/framework/Headers/FlutterChannels.h"
13 #include "flutter/shell/platform/darwin/ios/framework/Headers/FlutterPlatformViews.h"
14 
15 // A UIView that is used as the parent for embedded UIViews.
16 //
17 // This view has 2 roles:
18 // 1. Delay or prevent touch events from arriving the embedded view.
19 // 2. Dispatching all events that are hittested to the embedded view to the FlutterView.
20 @interface FlutterTouchInterceptingView : UIView
21 - (instancetype)initWithEmbeddedView:(UIView*)embeddedView
22                flutterViewController:(UIViewController*)flutterViewController;
23 
24 // Stop delaying any active touch sequence (and let it arrive the embedded view).
25 - (void)releaseGesture;
26 
27 // Prevent the touch sequence from ever arriving to the embedded view.
28 - (void)blockGesture;
29 @end
30 
31 // The parent view handles clipping to its subviews.
32 @interface ChildClippingView : UIView
33 
34 // Performs the clipping based on the type.
35 //
36 // The `type` must be one of the 3: clip_rect, clip_rrect, clip_path.
37 - (void)setClip:(flutter::MutatorType)type
38            rect:(const SkRect&)rect
39           rrect:(const SkRRect&)rrect
40            path:(const SkPath&)path;
41 
42 @end
43 
44 namespace flutter {
45 // Converts a SkMatrix to CATransform3D.
46 // Certain fields are ignored in CATransform3D since SkMatrix is 3x3 and CATransform3D is 4x4.
47 CATransform3D GetCATransform3DFromSkMatrix(const SkMatrix& matrix);
48 
49 // Reset the anchor of `layer` to match the tranform operation from flow.
50 // The position of the `layer` should be unchanged after resetting the anchor.
51 void ResetAnchor(CALayer* layer);
52 
53 class IOSGLContext;
54 class IOSSurface;
55 
56 struct FlutterPlatformViewLayer {
57   FlutterPlatformViewLayer(fml::scoped_nsobject<UIView> overlay_view,
58                            std::unique_ptr<IOSSurface> ios_surface,
59                            std::unique_ptr<Surface> surface);
60 
61   ~FlutterPlatformViewLayer();
62 
63   fml::scoped_nsobject<UIView> overlay_view;
64   std::unique_ptr<IOSSurface> ios_surface;
65   std::unique_ptr<Surface> surface;
66 };
67 
68 class FlutterPlatformViewsController {
69  public:
70   FlutterPlatformViewsController();
71 
72   ~FlutterPlatformViewsController();
73 
74   void SetFlutterView(UIView* flutter_view);
75 
76   void SetFlutterViewController(UIViewController* flutter_view_controller);
77 
78   void RegisterViewFactory(NSObject<FlutterPlatformViewFactory>* factory, NSString* factoryId);
79 
80   void SetFrameSize(SkISize frame_size);
81 
82   void CancelFrame();
83 
84   void PrerollCompositeEmbeddedView(int view_id,
85                                     std::unique_ptr<flutter::EmbeddedViewParams> params);
86 
87   // Returns the `FlutterPlatformView` object associated with the view_id.
88   //
89   // If the `FlutterPlatformViewsController` does not contain any `FlutterPlatformView` object or
90   // a `FlutterPlatformView` object asscociated with the view_id cannot be found, the method
91   // returns nil.
92   NSObject<FlutterPlatformView>* GetPlatformViewByID(int view_id);
93 
94   PostPrerollResult PostPrerollAction(fml::RefPtr<fml::GpuThreadMerger> gpu_thread_merger);
95 
96   std::vector<SkCanvas*> GetCurrentCanvases();
97 
98   SkCanvas* CompositeEmbeddedView(int view_id);
99 
100   // Discards all platform views instances and auxiliary resources.
101   void Reset();
102 
103   bool SubmitFrame(bool gl_rendering,
104                    GrContext* gr_context,
105                    std::shared_ptr<IOSGLContext> gl_context);
106 
107   void OnMethodCall(FlutterMethodCall* call, FlutterResult& result);
108 
109  private:
110   fml::scoped_nsobject<FlutterMethodChannel> channel_;
111   fml::scoped_nsobject<UIView> flutter_view_;
112   fml::scoped_nsobject<UIViewController> flutter_view_controller_;
113   std::map<std::string, fml::scoped_nsobject<NSObject<FlutterPlatformViewFactory>>> factories_;
114   std::map<int64_t, fml::scoped_nsobject<NSObject<FlutterPlatformView>>> views_;
115   std::map<int64_t, fml::scoped_nsobject<FlutterTouchInterceptingView>> touch_interceptors_;
116   // Mapping a platform view ID to the top most parent view (root_view) who is a direct child to
117   // the `flutter_view_`.
118   //
119   // The platform view with the view ID is a child of the root view; If the platform view is not
120   // clipped, and no clipping view is added, the root view will be the intercepting view.
121   std::map<int64_t, fml::scoped_nsobject<UIView>> root_views_;
122   // Mapping a platform view ID to its latest composition params.
123   std::map<int64_t, EmbeddedViewParams> current_composition_params_;
124   // Mapping a platform view ID to the count of the clipping operations that were applied to the
125   // platform view last time it was composited.
126   std::map<int64_t, int64_t> clip_count_;
127   std::map<int64_t, std::unique_ptr<FlutterPlatformViewLayer>> overlays_;
128   // The GrContext that is currently used by all of the overlay surfaces.
129   // We track this to know when the GrContext for the Flutter app has changed
130   // so we can update the overlays with the new context.
131   GrContext* overlays_gr_context_;
132   SkISize frame_size_;
133 
134   // This is the number of frames the task runners will stay
135   // merged after a frame where we see a mutation to the embedded views.
136   // Note: This number was arbitrarily picked. The rationale being
137   // merge-unmerge are not zero cost operations. To account for cases
138   // like animating platform views, we picked it to be > 2, as we would
139   // want to avoid merge-unmerge during each frame with a mutation.
140   static const int kDefaultMergedLeaseDuration = 10;
141 
142   // Method channel `OnDispose` calls adds the views to be disposed to this set to be disposed on
143   // the next frame.
144   std::unordered_set<int64_t> views_to_dispose_;
145 
146   // A vector of embedded view IDs according to their composition order.
147   // The last ID in this vector belond to the that is composited on top of all others.
148   std::vector<int64_t> composition_order_;
149 
150   // The latest composition order that was presented in Present().
151   std::vector<int64_t> active_composition_order_;
152 
153   // Only compoiste platform views in this set.
154   std::unordered_set<int64_t> views_to_recomposite_;
155 
156   std::map<int64_t, std::unique_ptr<SkPictureRecorder>> picture_recorders_;
157 
158   void OnCreate(FlutterMethodCall* call, FlutterResult& result);
159   void OnDispose(FlutterMethodCall* call, FlutterResult& result);
160   void OnAcceptGesture(FlutterMethodCall* call, FlutterResult& result);
161   void OnRejectGesture(FlutterMethodCall* call, FlutterResult& result);
162 
163   void DetachUnusedLayers();
164   // Dispose the views in `views_to_dispose_`.
165   void DisposeViews();
166   void EnsureOverlayInitialized(int64_t overlay_id);
167   void EnsureGLOverlayInitialized(int64_t overlay_id,
168                                   std::shared_ptr<IOSGLContext> gl_context,
169                                   GrContext* gr_context);
170 
171   // This will return true after pre-roll if any of the embedded views
172   // have mutated for last layer tree.
173   bool HasPendingViewOperations();
174 
175   // Traverse the `mutators_stack` and return the number of clip operations.
176   int CountClips(const MutatorsStack& mutators_stack);
177 
178   // Make sure that platform_view has exactly clip_count ChildClippingView ancestors.
179   //
180   // Existing ChildClippingViews are re-used. If there are currently more ChildClippingView
181   // ancestors than needed, the extra views are detached. If there are less ChildClippingView
182   // ancestors than needed, new ChildClippingViews will be added.
183   //
184   // If head_clip_view was attached as a subview to FlutterView, the head of the newly constructed
185   // ChildClippingViews chain is attached to FlutterView in the same position.
186   //
187   // Returns the new head of the clip views chain.
188   UIView* ReconstructClipViewsChain(int number_of_clips,
189                                     UIView* platform_view,
190                                     UIView* head_clip_view);
191 
192   // Applies the mutators in the mutators_stack to the UIView chain that was constructed by
193   // `ReconstructClipViewsChain`
194   //
195   // Clips are applied to the super view with a CALayer mask. Transforms are applied to the
196   // current view that's at the head of the chain. For example the following mutators stack [T_1,
197   // C_2, T_3, T_4, C_5, T_6] where T denotes a transform and C denotes a clip, will result in the
198   // following UIView tree:
199   //
200   // C_2 -> C_5 -> PLATFORM_VIEW
201   // (PLATFORM_VIEW is a subview of C_5 which is a subview of C_2)
202   //
203   // 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.
204   //
205   // After each clip operation, we update the head to the super view of the current head.
206   void ApplyMutators(const MutatorsStack& mutators_stack, UIView* embedded_view);
207   void CompositeWithParams(int view_id, const EmbeddedViewParams& params);
208 
209   FML_DISALLOW_COPY_AND_ASSIGN(FlutterPlatformViewsController);
210 };
211 
212 }  // namespace flutter
213 
214 #endif  // FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERPLATFORMVIEWS_INTERNAL_H_
215