| Flutter iOS Embedder |

platform_views_controller.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_PLATFORM_VIEWS_CONTROLLER_H_
6 #define FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_PLATFORM_VIEWS_CONTROLLER_H_
7
8 #include <Metal/Metal.h>
9
10 #include "flutter/flow/surface.h"
11 #include "flutter/fml/memory/weak_ptr.h"
12 #include "flutter/fml/platform/darwin/scoped_nsobject.h"
13 #include "flutter/fml/task_runner.h"
14 #include "flutter/fml/trace_event.h"
15 #include "impeller/base/thread_safety.h"
16 #include "third_party/skia/include/core/SkRect.h"
17
18 #import "flutter/shell/platform/darwin/common/framework/Headers/FlutterChannels.h"
19 #import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterPlatformViews.h"
20 #import "flutter/shell/platform/darwin/ios/framework/Headers/FlutterPlugin.h"
21 #import "flutter/shell/platform/darwin/ios/framework/Source/FlutterViewResponder.h"
22 #import "flutter/shell/platform/darwin/ios/framework/Source/overlay_layer_pool.h"
23 #import "flutter/shell/platform/darwin/ios/ios_context.h"
24
25 @class FlutterTouchInterceptingView;
26 @class FlutterClippingMaskViewPool;
27
28 namespace flutter {
29
30 /// @brief Composites Flutter UI and overlay layers alongside embedded UIViews.
31 class PlatformViewsController {
32 public:
33 PlatformViewsController();
34
35 ~PlatformViewsController() = default;
36
37 /// @brief Retrieve a weak pointer to this controller.
38 fml::WeakPtr<flutter::PlatformViewsController> GetWeakPtr();
39
40 /// @brief Set the platform task runner used to post rendering tasks.
41 void SetTaskRunner(const fml::RefPtr<fml::TaskRunner>& platform_task_runner);
42
43 /// @brief Set the flutter view.
44 void SetFlutterView(UIView* flutter_view) __attribute__((cf_audited_transfer));
45
46 /// @brief Set the flutter view controller.
47 void SetFlutterViewController(UIViewController<FlutterViewResponder>* flutter_view_controller)
48 __attribute__((cf_audited_transfer));
49
50 /// @brief Retrieve the view controller.
51 UIViewController<FlutterViewResponder>* GetFlutterViewController()
52 __attribute__((cf_audited_transfer));
53
54 /// @brief set the factory used to construct embedded UI Views.
55 void RegisterViewFactory(
56 NSObject<FlutterPlatformViewFactory>* factory,
57 NSString* factoryId,
58 FlutterPlatformViewGestureRecognizersBlockingPolicy gestureRecognizerBlockingPolicy)
59 __attribute__((cf_audited_transfer));
60
61 /// @brief Mark the beginning of a frame and record the size of the onscreen.
62 void BeginFrame(SkISize frame_size);
63
64 /// @brief Cancel the current frame, indicating that no platform views are composited.
65 ///
66 /// Additionally, reverts the composition order to its original state at the beginning of the
67 /// frame.
68 void CancelFrame();
69
70 /// @brief Record a platform view in the layer tree to be rendered, along with the positioning and
71 /// mutator parameters.
72 ///
73 /// Called from the raster thread.
74 void PrerollCompositeEmbeddedView(int64_t view_id,
75 std::unique_ptr<flutter::EmbeddedViewParams> params);
76
77 /// @brief Returns the`FlutterTouchInterceptingView` with the provided view_id.
78 ///
79 /// Returns nil if there is no platform view with the provided id. Called
80 /// from the platform thread.
81 FlutterTouchInterceptingView* GetFlutterTouchInterceptingViewByID(int64_t view_id);
82
83 /// @brief Determine if thread merging is required after prerolling platform views.
84 ///
85 /// Called from the raster thread.
86 PostPrerollResult PostPrerollAction(
87 const fml::RefPtr<fml::RasterThreadMerger>& raster_thread_merger,
88 bool impeller_enabled);
89
90 /// @brief Mark the end of a compositor frame.
91 ///
92 /// May determine changes are required to the thread merging state.
93 /// Called from the raster thread.
94 void EndFrame(bool should_resubmit_frame,
95 const fml::RefPtr<fml::RasterThreadMerger>& raster_thread_merger,
96 bool impeller_enabled);
97
98 /// @brief Returns the Canvas for the overlay slice for the given platform view.
99 ///
100 /// Called from the raster thread.
101 DlCanvas* CompositeEmbeddedView(int64_t view_id);
102
103 /// @brief Discards all platform views instances and auxiliary resources.
104 ///
105 /// Called from the raster thread.
106 void Reset();
107
108 /// @brief Encode rendering for the Flutter overlay views and queue up perform platform view
109 /// mutations.
110 ///
111 /// Called from the raster thread.
112 bool SubmitFrame(GrDirectContext* gr_context,
113 const std::shared_ptr<IOSContext>& ios_context,
114 std::unique_ptr<SurfaceFrame> frame);
115
116 /// @brief Handler for platform view message channels.
117 void OnMethodCall(FlutterMethodCall* call, FlutterResult result)
118 __attribute__((cf_audited_transfer));
119
120 /// @brief Returns the platform view id if the platform view (or any of its descendant view) is
121 /// the first responder.
122 ///
123 /// Returns -1 if no such platform view is found.
124 long FindFirstResponderPlatformViewId();
125
126 /// @brief Pushes backdrop filter mutation to the mutator stack of each visited platform view.
127 void PushFilterToVisitedPlatformViews(const std::shared_ptr<const DlImageFilter>& filter,
128 const SkRect& filter_rect);
129
130 /// @brief Pushes the view id of a visted platform view to the list of visied platform views.
131 void PushVisitedPlatformView(int64_t view_id) { visited_platform_views_.push_back(view_id); }
132
133 // visible for testing.
134 size_t EmbeddedViewCount() const;
135
136 // visible for testing.
137 size_t LayerPoolSize() const;
138
139 // visible for testing.
140 // Returns the `FlutterPlatformView`'s `view` object associated with the view_id.
141 //
142 // If the `PlatformViewsController` does not contain any `FlutterPlatformView` object or
143 // a `FlutterPlatformView` object associated with the view_id cannot be found, the method
144 // returns nil.
145 UIView* GetPlatformViewByID(int64_t view_id);
146
147 // Visible for testing.
148 void CompositeWithParams(int64_t view_id, const EmbeddedViewParams& params);
149
150 // Visible for testing.
151 const EmbeddedViewParams& GetCompositionParams(int64_t view_id) const {
152 return current_composition_params_.find(view_id)->second;
153 }
154
155 private:
156 PlatformViewsController(const PlatformViewsController&) = delete;
157 PlatformViewsController& operator=(const PlatformViewsController&) = delete;
158
159 struct LayerData {
160 SkRect rect;
161 int64_t view_id;
162 int64_t overlay_id;
163 std::shared_ptr<OverlayLayer> layer;
164 };
165
166 using LayersMap = std::unordered_map<int64_t, LayerData>;
167
168 // Update the buffers and mutate the platform views in CATransaction.
169 //
170 // Runs on the platform thread.
171 void PerformSubmit(const LayersMap& platform_view_layers,
172 std::unordered_map<int64_t, EmbeddedViewParams>& current_composition_params,
173 const std::unordered_set<int64_t>& views_to_recomposite,
174 const std::vector<int64_t>& composition_order,
175 const std::vector<std::shared_ptr<OverlayLayer>>& unused_layers,
176 const std::vector<std::unique_ptr<SurfaceFrame>>& surface_frames);
177
178 /// @brief Populate any missing overlay layers.
179 ///
180 /// This requires posting a task to the platform thread and blocking on its completion.
181 void CreateMissingOverlays(GrDirectContext* gr_context,
182 const std::shared_ptr<IOSContext>& ios_context,
183 size_t required_overlay_layers);
184
185 void OnCreate(FlutterMethodCall* call, FlutterResult result) __attribute__((cf_audited_transfer));
186
187 void OnDispose(FlutterMethodCall* call, FlutterResult result)
188 __attribute__((cf_audited_transfer));
189
190 void OnAcceptGesture(FlutterMethodCall* call, FlutterResult result)
191 __attribute__((cf_audited_transfer));
192
193 void OnRejectGesture(FlutterMethodCall* call, FlutterResult result)
194 __attribute__((cf_audited_transfer));
195
196 /// @brief Return all views to be disposed on the platform thread.
197 std::vector<UIView*> GetViewsToDispose();
198
199 void ClipViewSetMaskView(UIView* clipView) __attribute__((cf_audited_transfer));
200
201 // Applies the mutators in the mutators_stack to the UIView chain that was constructed by
202 // `ReconstructClipViewsChain`
203 //
204 // Clips are applied to the `embedded_view`'s super view(|ChildClippingView|) using a
205 // |FlutterClippingMaskView|. Transforms are applied to `embedded_view`
206 //
207 // The `bounding_rect` is the final bounding rect of the PlatformView
208 // (EmbeddedViewParams::finalBoundingRect). If a clip mutator's rect contains the final bounding
209 // rect of the PlatformView, the clip mutator is not applied for performance optimization.
210 void ApplyMutators(const MutatorsStack& mutators_stack,
211 UIView* embedded_view,
212 const SkRect& bounding_rect) __attribute__((cf_audited_transfer));
213
214 std::shared_ptr<OverlayLayer> GetExistingLayer();
215
216 // Runs on the platform thread.
217 void CreateLayer(GrDirectContext* gr_context,
218 const std::shared_ptr<IOSContext>& ios_context,
219 MTLPixelFormat pixel_format);
220
221 // Removes overlay views and platform views that aren't needed in the current frame.
222 // Must run on the platform thread.
223 void RemoveUnusedLayers(const std::vector<std::shared_ptr<OverlayLayer>>& unused_layers,
224 const std::vector<int64_t>& composition_order);
225
226 // Appends the overlay views and platform view and sets their z index based on the composition
227 // order.
228 void BringLayersIntoView(const LayersMap& layer_map,
229 const std::vector<int64_t>& composition_order);
230
231 // Resets the state of the frame.
232 void ResetFrameState();
233
234 // The pool of reusable view layers. The pool allows to recycle layer in each frame.
235 std::unique_ptr<OverlayLayerPool> layer_pool_;
236
237 // The platform view's |EmbedderViewSlice| keyed off the view id, which contains any subsequent
238 // operation until the next platform view or the end of the last leaf node in the layer tree.
239 //
240 // The Slices are deleted by the PlatformViewsController.reset().
241 std::unordered_map<int64_t, std::unique_ptr<EmbedderViewSlice>> slices_;
242
243 fml::scoped_nsobject<FlutterMethodChannel> channel_;
244 fml::scoped_nsobject<UIView> flutter_view_;
245 fml::scoped_nsobject<UIViewController<FlutterViewResponder>> flutter_view_controller_;
246 fml::scoped_nsobject<FlutterClippingMaskViewPool> mask_view_pool_;
247 std::unordered_map<std::string, fml::scoped_nsobject<NSObject<FlutterPlatformViewFactory>>>
248 factories_;
249
250 // The FlutterPlatformViewGestureRecognizersBlockingPolicy for each type of platform view.
251 std::unordered_map<std::string, FlutterPlatformViewGestureRecognizersBlockingPolicy>
252 gesture_recognizers_blocking_policies_;
253
254 /// The size of the current onscreen surface in physical pixels.
255 SkISize frame_size_;
256
257 /// The task runner for posting tasks to the platform thread.
258 fml::RefPtr<fml::TaskRunner> platform_task_runner_;
259
260 /// Each of the following structs stores part of the platform view hierarchy according to its
261 /// ID.
262 ///
263 /// This data must only be accessed on the platform thread.
264 struct PlatformViewData {
265 fml::scoped_nsobject<NSObject<FlutterPlatformView>> view;
266 fml::scoped_nsobject<FlutterTouchInterceptingView> touch_interceptor;
267 fml::scoped_nsobject<UIView> root_view;
268 };
269
270 /// This data must only be accessed on the platform thread.
271 std::unordered_map<int64_t, PlatformViewData> platform_views_;
272
273 /// The composition parameters for each platform view.
274 ///
275 /// This state is only modified on the raster thread.
276 std::unordered_map<int64_t, EmbeddedViewParams> current_composition_params_;
277
278 /// Method channel `OnDispose` calls adds the views to be disposed to this set to be disposed on
279 /// the next frame.
280 ///
281 /// This state is modified on both the platform and raster thread.
282 std::unordered_set<int64_t> views_to_dispose_;
283
284 /// view IDs in composition order.
285 ///
286 /// This state is only modified on the raster thread.
287 std::vector<int64_t> composition_order_;
288
289 /// platform view IDs visited during layer tree composition.
290 ///
291 /// This state is only modified on the raster thread.
292 std::vector<int64_t> visited_platform_views_;
293
294 /// Only composite platform views in this set.
295 ///
296 /// This state is only modified on the raster thread.
297 std::unordered_set<int64_t> views_to_recomposite_;
298
299 #if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
300 /// A set to keep track of embedded views that do not have (0, 0) origin.
301 /// An insertion triggers a warning message about non-zero origin logged on the debug console.
302 /// See https://github.com/flutter/flutter/issues/109700 for details.
303 std::unordered_set<int64_t> non_zero_origin_views_;
304 #endif
305
306 /// @brief The composition order from the previous thread.
307 ///
308 /// Only accessed from the platform thread.
309 std::vector<int64_t> previous_composition_order_;
310
311 /// Whether the previous frame had any platform views in active composition order.
312 ///
313 /// This state is tracked so that the first frame after removing the last platform view
314 /// runs through the platform view rendering code path, giving us a chance to remove the
315 /// platform view from the UIView hierarchy.
316 ///
317 /// Only accessed from the raster thread.
318 bool had_platform_views_ = false;
319
320 // WeakPtrFactory must be the last member.
321 std::unique_ptr<fml::WeakPtrFactory<PlatformViewsController>> weak_factory_;
322 };
323
324 } // namespace flutter
325
326 #endif // FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_PLATFORM_VIEWS_CONTROLLER_H_
flutter::PlatformViewsController::FindFirstResponderPlatformViewId
long FindFirstResponderPlatformViewId()
Returns the platform view id if the platform view (or any of its descendant view) is the first respon...
Definition: platform_views_controller.mm:389
flutter::PlatformViewsController::PostPrerollAction
PostPrerollResult PostPrerollAction(const fml::RefPtr< fml::RasterThreadMerger > &raster_thread_merger, bool impeller_enabled)
Determine if thread merging is required after prerolling platform views.
Definition: platform_views_controller.mm:291
flutter::PlatformViewsController::SetTaskRunner
void SetTaskRunner(const fml::RefPtr< fml::TaskRunner > &platform_task_runner)
Set the platform task runner used to post rendering tasks.
Definition: platform_views_controller.mm:120
flutter::PlatformViewsController::EndFrame
void EndFrame(bool should_resubmit_frame, const fml::RefPtr< fml::RasterThreadMerger > &raster_thread_merger, bool impeller_enabled)
Mark the end of a compositor frame.
Definition: platform_views_controller.mm:326
FlutterPlatformViews.h
flutter::PlatformViewsController::PlatformViewsController
PlatformViewsController()
Definition: platform_views_controller.mm:113
flutter::PlatformViewsController::SetFlutterView
void SetFlutterView(UIView *flutter_view) __attribute__((cf_audited_transfer))
Set the flutter view.
Definition: platform_views_controller.mm:129
flutter::PlatformViewsController::LayerPoolSize
size_t LayerPoolSize() const
Definition: platform_views_controller.mm:373
flutter::PlatformViewsController::~PlatformViewsController
~PlatformViewsController()=default
FlutterChannels.h
flutter::PlatformViewsController::CompositeEmbeddedView
DlCanvas * CompositeEmbeddedView(int64_t view_id)
Returns the Canvas for the overlay slice for the given platform view.
Definition: platform_views_controller.mm:579
flutter::PlatformViewsController::EmbeddedViewCount
size_t EmbeddedViewCount() const
Definition: platform_views_controller.mm:369
flutter::PlatformViewsController::PrerollCompositeEmbeddedView
void PrerollCompositeEmbeddedView(int64_t view_id, std::unique_ptr< flutter::EmbeddedViewParams > params)
Record a platform view in the layer tree to be rendered, along with the positioning and mutator param...
Definition: platform_views_controller.mm:350
FlutterPlugin.h
FlutterViewResponder.h
FlutterMethodCall
Definition: FlutterCodecs.h:220
flutter::PlatformViewsController::GetFlutterViewController
UIViewController< FlutterViewResponder > * GetFlutterViewController() __attribute__((cf_audited_transfer))
Retrieve the view controller.
Definition: platform_views_controller.mm:138
flutter::PlatformViewsController::SubmitFrame
bool SubmitFrame(GrDirectContext *gr_context, const std::shared_ptr< IOSContext > &ios_context, std::unique_ptr< SurfaceFrame > frame)
Encode rendering for the Flutter overlay views and queue up perform platform view mutations.
Definition: platform_views_controller.mm:603
flutter
Definition: accessibility_bridge.h:28
flutter::PlatformViewsController::Reset
void Reset()
Discards all platform views instances and auxiliary resources.
Definition: platform_views_controller.mm:583
flutter::PlatformViewsController::BeginFrame
void BeginFrame(SkISize frame_size)
Mark the beginning of a frame and record the size of the onscreen.
Definition: platform_views_controller.mm:282
FlutterResult
void(^ FlutterResult)(id _Nullable result)
Definition: FlutterChannels.h:194
FlutterPlatformViewGestureRecognizersBlockingPolicy
FlutterPlatformViewGestureRecognizersBlockingPolicy
Definition: FlutterPlugin.h:252
flutter::PlatformViewsController::GetCompositionParams
const EmbeddedViewParams & GetCompositionParams(int64_t view_id) const
Definition: platform_views_controller.h:151
FlutterClippingMaskViewPool
Definition: FlutterPlatformViews_Internal.h:66
flutter::PlatformViewsController::RegisterViewFactory
void RegisterViewFactory(NSObject< FlutterPlatformViewFactory > *factory, NSString *factoryId, FlutterPlatformViewGestureRecognizersBlockingPolicy gestureRecognizerBlockingPolicy) __attribute__((cf_audited_transfer))
set the factory used to construct embedded UI Views.
Definition: platform_views_controller.mm:272
flutter::PlatformViewsController::SetFlutterViewController
void SetFlutterViewController(UIViewController< FlutterViewResponder > *flutter_view_controller) __attribute__((cf_audited_transfer))
Set the flutter view controller.
Definition: platform_views_controller.mm:133
overlay_layer_pool.h
flutter::PlatformViewsController::PushFilterToVisitedPlatformViews
void PushFilterToVisitedPlatformViews(const std::shared_ptr< const DlImageFilter > &filter, const SkRect &filter_rect)
Pushes backdrop filter mutation to the mutator stack of each visited platform view.
Definition: platform_views_controller.mm:340
flutter::PlatformViewsController::GetPlatformViewByID
UIView * GetPlatformViewByID(int64_t view_id)
Definition: platform_views_controller.mm:377
flutter::PlatformViewsController::OnMethodCall
void OnMethodCall(FlutterMethodCall *call, FlutterResult result) __attribute__((cf_audited_transfer))
Handler for platform view message channels.
Definition: platform_views_controller.mm:142
flutter::PlatformViewsController::PushVisitedPlatformView
void PushVisitedPlatformView(int64_t view_id)
Pushes the view id of a visted platform view to the list of visied platform views.
Definition: platform_views_controller.h:131
flutter::PlatformViewsController
Composites Flutter UI and overlay layers alongside embedded UIViews.
Definition: platform_views_controller.h:31
flutter::PlatformViewsController::CompositeWithParams
void CompositeWithParams(int64_t view_id, const EmbeddedViewParams &params)
Definition: platform_views_controller.mm:540
flutter::PlatformViewsController::GetFlutterTouchInterceptingViewByID
FlutterTouchInterceptingView * GetFlutterTouchInterceptingViewByID(int64_t view_id)
Returns theFlutterTouchInterceptingView with the provided view_id.
Definition: platform_views_controller.mm:381
ios_context.h
flutter::PlatformViewsController::GetWeakPtr
fml::WeakPtr< flutter::PlatformViewsController > GetWeakPtr()
Retrieve a weak pointer to this controller.
Definition: platform_views_controller.mm:125
FlutterTouchInterceptingView
Definition: FlutterPlatformViews_Internal.h:138
flutter::PlatformViewsController::CancelFrame
void CancelFrame()
Cancel the current frame, indicating that no platform views are composited.
Definition: platform_views_controller.mm:287