Flutter iOS Embedder
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 
9 
10 #include <Metal/Metal.h>
11 
12 #include "flutter/flow/surface.h"
13 #include "flutter/fml/memory/weak_ptr.h"
14 #include "flutter/fml/task_runner.h"
15 #include "flutter/fml/trace_event.h"
16 #include "flutter/impeller/base/thread_safety.h"
22 
23 // A UIView that acts as a clipping mask for the |ChildClippingView|.
24 //
25 // On the [UIView drawRect:] method, this view performs a series of clipping operations and sets the
26 // alpha channel to the final resulting area to be 1; it also sets the "clipped out" area's alpha
27 // channel to be 0.
28 //
29 // When a UIView sets a |FlutterClippingMaskView| as its `maskView`, the alpha channel of the UIView
30 // is replaced with the alpha channel of the |FlutterClippingMaskView|.
31 @interface FlutterClippingMaskView : UIView
32 
33 - (instancetype)initWithFrame:(CGRect)frame screenScale:(CGFloat)screenScale;
34 
35 - (void)reset;
36 
37 // Adds a clip rect operation to the queue.
38 //
39 // The `clipSkRect` is transformed with the `matrix` before adding to the queue.
40 - (void)clipRect:(const flutter::DlRect&)clipDlRect matrix:(const flutter::DlMatrix&)matrix;
41 
42 // Adds a clip rrect operation to the queue.
43 //
44 // The `clipSkRRect` is transformed with the `matrix` before adding to the queue.
45 - (void)clipRRect:(const flutter::DlRoundRect&)clipDlRRect matrix:(const flutter::DlMatrix&)matrix;
46 
47 // Adds a clip path operation to the queue.
48 //
49 // The `path` is transformed with the `matrix` before adding to the queue.
50 - (void)clipPath:(const flutter::DlPath&)path matrix:(const flutter::DlMatrix&)matrix;
51 
52 @end
53 
54 // A pool that provides |FlutterClippingMaskView|s.
55 //
56 // The pool has a capacity that can be set in the initializer.
57 // When requesting a FlutterClippingMaskView, the pool will first try to reuse an available maskView
58 // in the pool. If there are none available, a new FlutterClippingMaskView is constructed. If the
59 // capacity is reached, the newly constructed FlutterClippingMaskView is not added to the pool.
60 //
61 // Call |insertViewToPoolIfNeeded:| to return a maskView to the pool.
62 @interface FlutterClippingMaskViewPool : NSObject
63 
64 // Initialize the pool with `capacity`. When the `capacity` is reached, a FlutterClippingMaskView is
65 // constructed when requested, and it is not added to the pool.
66 - (instancetype)initWithCapacity:(NSInteger)capacity;
67 
68 // Reuse a maskView from the pool, or allocate a new one.
69 - (FlutterClippingMaskView*)getMaskViewWithFrame:(CGRect)frame;
70 
71 // Insert the `maskView` into the pool.
72 - (void)insertViewToPoolIfNeeded:(FlutterClippingMaskView*)maskView;
73 
74 @end
75 
76 // An object represents a blur filter.
77 //
78 // This object produces a `backdropFilterView`.
79 // To blur a View, add `backdropFilterView` as a subView of the View.
80 @interface PlatformViewFilter : NSObject
81 
82 // Determines the rect of the blur effect in the coordinate system of `backdropFilterView`'s
83 // parentView.
84 @property(nonatomic, readonly) CGRect frame;
85 
86 // Determines the blur intensity.
87 //
88 // It is set as the value of `inputRadius` of the `gaussianFilter` that is internally used.
89 @property(nonatomic, readonly) CGFloat blurRadius;
90 
91 // This is the view to use to blur the PlatformView.
92 //
93 // It is a modified version of UIKit's `UIVisualEffectView`.
94 // The inputRadius can be customized and it doesn't add any color saturation to the blurred view.
95 @property(nonatomic, readonly) UIVisualEffectView* backdropFilterView;
96 
97 // Determines the corner radius of the backdrop filter view.
98 @property(nonatomic, readonly) CGFloat cornerRadius;
99 
100 // For testing only.
101 + (void)resetPreparation;
102 
103 - (instancetype)init NS_UNAVAILABLE;
104 
105 // Initialize the filter object.
106 //
107 // The `frame` determines the rect of the blur effect in the coordinate system of
108 // `backdropFilterView`'s parentView. The `blurRadius` determines the blur intensity. It is set as
109 // the value of `inputRadius` of the `gaussianFilter` that is internally used. The
110 // `UIVisualEffectView` is the view that is used to add the blur effects. It is modified to become
111 // `backdropFilterView`, which better supports the need of Flutter.
112 //
113 // Note: if the implementation of UIVisualEffectView changes in a way that affects the
114 // implementation in `PlatformViewFilter`, this method will return nil.
115 - (instancetype)initWithFrame:(CGRect)frame
116  blurRadius:(CGFloat)blurRadius
117  cornerRadius:(CGFloat)cornerRadius
118  visualEffectView:(UIVisualEffectView*)visualEffectView NS_DESIGNATED_INITIALIZER;
119 
120 @end
121 
122 // The parent view handles clipping to its subViews.
123 @interface ChildClippingView : UIView
124 
125 // Applies blur backdrop filters to the ChildClippingView with blur values from
126 // filters.
127 - (void)applyBlurBackdropFilters:(NSArray<PlatformViewFilter*>*)filters;
128 
129 // For testing only.
130 - (NSMutableArray*)backdropFilterSubviews;
131 @end
132 
133 // A UIView that is used as the parent for embedded UIViews.
134 //
135 // This view has 2 roles:
136 // 1. Delay or prevent touch events from arriving the embedded view.
137 // 2. Dispatching all events that are hittested to the embedded view to the FlutterView.
138 @interface FlutterTouchInterceptingView : UIView
139 - (instancetype)initWithEmbeddedView:(UIView*)embeddedView
140  platformViewsController:(FlutterPlatformViewsController*)platformViewsController
141  gestureRecognizersBlockingPolicy:
143 
144 // Stop delaying any active touch sequence (and let it arrive the embedded view).
145 - (void)releaseGesture;
146 
147 // Prevent the touch sequence from ever arriving to the embedded view.
148 - (void)blockGesture;
149 
150 // Get embedded view
151 - (UIView*)embeddedView;
152 
153 // Sets flutterAccessibilityContainer as this view's accessibilityContainer.
154 @property(nonatomic, retain) id flutterAccessibilityContainer;
155 @end
156 
157 @interface UIView (FirstResponder)
158 // Returns YES if a view or any of its descendant view is the first responder. Returns NO otherwise.
159 @property(nonatomic, readonly) BOOL flt_hasFirstResponderInViewHierarchySubtree;
160 @end
161 
162 // This recognizer delays touch events from being dispatched to the responder chain until it failed
163 // recognizing a gesture.
164 //
165 // We only fail this recognizer when asked to do so by the Flutter framework (which does so by
166 // invoking an acceptGesture method on the platform_views channel). And this is how we allow the
167 // Flutter framework to delay or prevent the embedded view from getting a touch sequence.
168 @interface FlutterDelayingGestureRecognizer : UIGestureRecognizer <UIGestureRecognizerDelegate>
169 
170 // Indicates that if the `FlutterDelayingGestureRecognizer`'s state should be set to
171 // `UIGestureRecognizerStateEnded` during next `touchesEnded` call.
172 @property(nonatomic) BOOL shouldEndInNextTouchesEnded;
173 
174 // Indicates that the `FlutterDelayingGestureRecognizer`'s `touchesEnded` has been invoked without
175 // setting the state to `UIGestureRecognizerStateEnded`.
176 @property(nonatomic) BOOL touchedEndedWithoutBlocking;
177 
178 @property(nonatomic) UIGestureRecognizer* forwardingRecognizer;
179 
180 - (instancetype)initWithTarget:(id)target
181  action:(SEL)action
182  forwardingRecognizer:(UIGestureRecognizer*)forwardingRecognizer;
183 @end
184 
185 // While the FlutterDelayingGestureRecognizer is preventing touches from hitting the responder chain
186 // the touch events are not arriving to the FlutterView (and thus not arriving to the Flutter
187 // framework). We use this gesture recognizer to dispatch the events directly to the FlutterView
188 // while during this phase.
189 //
190 // If the Flutter framework decides to dispatch events to the embedded view, we fail the
191 // FlutterDelayingGestureRecognizer which sends the events up the responder chain. But since the
192 // events are handled by the embedded view they are not delivered to the Flutter framework in this
193 // phase as well. So during this phase as well the ForwardingGestureRecognizer dispatched the events
194 // directly to the FlutterView.
195 @interface ForwardingGestureRecognizer : UIGestureRecognizer <UIGestureRecognizerDelegate>
196 - (instancetype)initWithTarget:(id)target
197  platformViewsController:(FlutterPlatformViewsController*)platformViewsController;
198 - (ForwardingGestureRecognizer*)recreateRecognizerWithTarget:(id)target;
199 @end
200 
201 @interface PendingRRectClip : NSObject
202 @property(nonatomic) flutter::DlRect rect;
203 @property(nonatomic) CGFloat topLeftRadius;
204 @property(nonatomic) CGFloat topRightRadius;
205 @property(nonatomic) CGFloat bottomRightRadius;
206 @property(nonatomic) CGFloat bottomLeftRadius;
207 @end
208 
209 #endif // FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERPLATFORMVIEWS_INTERNAL_H_
FlutterPlatformViewGestureRecognizersBlockingPolicy
instancetype initWithFrame
NSMutableArray * backdropFilterSubviews()
instancetype NS_UNAVAILABLE()
UIVisualEffectView * backdropFilterView