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