5#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h"
7#include <Metal/Metal.h>
9#include "flutter/fml/platform/darwin/scoped_nsobject.h"
10#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterOverlayView.h"
11#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterView.h"
12#import "flutter/shell/platform/darwin/ios/ios_surface.h"
17- (
BOOL)flt_hasFirstResponderInViewHierarchySubtree {
18 if (
self.isFirstResponder) {
21 for (UIView* subview in
self.subviews) {
22 if (subview.flt_hasFirstResponderInViewHierarchySubtree) {
39 const SkRect& platformview_boundingrect,
41 SkRect transformed_rect = transform_matrix.
mapRect(clip_rect);
42 return transformed_rect.
contains(platformview_boundingrect);
54 const SkRect& platformview_boundingrect,
56 SkVector upper_left = clip_rrect.
radii(SkRRect::Corner::kUpperLeft_Corner);
57 SkVector upper_right = clip_rrect.
radii(SkRRect::Corner::kUpperRight_Corner);
58 SkVector lower_right = clip_rrect.
radii(SkRRect::Corner::kLowerRight_Corner);
59 SkVector lower_left = clip_rrect.
radii(SkRRect::Corner::kLowerLeft_Corner);
70 SkVector corners[] = {{transformed_upper_left_x, transformed_upper_left_y},
71 {transformed_upper_right_x, transformed_upper_right_y},
72 {transformed_lower_right_x, transformed_lower_right_y},
73 {transformed_lower_left_x, transformed_lower_left_y}};
74 transformed_rrect.
setRectRadii(transformed_clip_rect, corners);
75 return transformed_rrect.
contains(platformview_boundingrect);
82std::shared_ptr<FlutterPlatformViewLayer> FlutterPlatformViewLayerPool::GetLayer(
84 const std::shared_ptr<IOSContext>& ios_context,
85 MTLPixelFormat pixel_format) {
86 if (available_layer_index_ >= layers_.size()) {
87 std::shared_ptr<FlutterPlatformViewLayer> layer;
91 bool impeller_enabled = !!ios_context->GetImpellerContext();
92 if (!gr_context && !impeller_enabled) {
98 std::unique_ptr<Surface>
surface = ios_surface->CreateGPUSurface();
100 layer = std::make_shared<FlutterPlatformViewLayer>(
101 std::move(overlay_view), std::move(overlay_view_wrapper), std::move(ios_surface),
104 CGFloat screenScale = [UIScreen mainScreen].scale;
106 pixelFormat:pixel_format]);
108 pixelFormat:pixel_format]);
112 std::unique_ptr<Surface>
surface = ios_surface->CreateGPUSurface(gr_context);
114 layer = std::make_shared<FlutterPlatformViewLayer>(
115 std::move(overlay_view), std::move(overlay_view_wrapper), std::move(ios_surface),
117 layer->gr_context = gr_context;
133 layer->overlay_view_wrapper.get().clipsToBounds = YES;
134 [layer->overlay_view_wrapper.get() addSubview:layer->overlay_view];
135 layers_.push_back(layer);
137 std::shared_ptr<FlutterPlatformViewLayer> layer = layers_[available_layer_index_];
138 if (gr_context != layer->gr_context) {
139 layer->gr_context = gr_context;
142 IOSSurface* ios_surface = layer->ios_surface.get();
144 layer->surface = std::move(
surface);
146 available_layer_index_++;
150void FlutterPlatformViewLayerPool::RecycleLayers() {
151 available_layer_index_ = 0;
154std::vector<std::shared_ptr<FlutterPlatformViewLayer>>
155FlutterPlatformViewLayerPool::GetUnusedLayers() {
156 std::vector<std::shared_ptr<FlutterPlatformViewLayer>> results;
157 for (
size_t i = available_layer_index_;
i < layers_.size();
i++) {
158 results.push_back(layers_[
i]);
163void FlutterPlatformViewsController::SetFlutterView(UIView* flutter_view) {
164 flutter_view_.reset(flutter_view);
167void FlutterPlatformViewsController::SetFlutterViewController(
168 UIViewController<FlutterViewResponder>* flutter_view_controller) {
169 flutter_view_controller_.reset(flutter_view_controller);
172UIViewController<FlutterViewResponder>* FlutterPlatformViewsController::getFlutterViewController() {
173 return flutter_view_controller_.get();
177 if ([[
call method] isEqualToString:
@"create"]) {
179 }
else if ([[
call method] isEqualToString:
@"dispose"]) {
181 }
else if ([[
call method] isEqualToString:
@"acceptGesture"]) {
183 }
else if ([[
call method] isEqualToString:
@"rejectGesture"]) {
193 int64_t viewId = [args[@"id"] longLongValue];
194 NSString* viewTypeString =
args[@"viewType"];
195 std::string viewType(viewTypeString.UTF8String);
197 if (views_.count(viewId) != 0) {
199 message:
@"trying to create an already created view"
200 details:[NSString stringWithFormat:
@"view id: '%lld'", viewId]]);
203 NSObject<FlutterPlatformViewFactory>* factory = factories_[viewType].get();
204 if (factory == nil) {
206 errorWithCode:
@"unregistered_view_type"
207 message:[NSString stringWithFormat:
@"A UIKitView widget is trying to create a "
208 @"PlatformView with an unregistered type: < %@ >",
210 details:
@"If you are the author of the PlatformView, make sure `registerViewFactory` "
213 @"https://docs.flutter.dev/development/platform-integration/"
214 @"platform-views#on-the-platform-side-1 for more details.\n"
215 @"If you are not the author of the PlatformView, make sure to call "
216 @"`GeneratedPluginRegistrant.register`."]);
221 if ([factory respondsToSelector:
@selector(createArgsCodec)]) {
222 NSObject<FlutterMessageCodec>* codec = [factory createArgsCodec];
223 if (codec != nil &&
args[
@"params"] != nil) {
225 params = [codec decode:paramsData.data];
229 NSObject<FlutterPlatformView>* embedded_view = [factory createWithFrame:CGRectZero
230 viewIdentifier:viewId
235 [NSString stringWithFormat:@"platform_view[%lld]", viewId];
239 initWithEmbeddedView:platform_view
240 platformViewsController:GetWeakPtr()
241 gestureRecognizersBlockingPolicy:gesture_recognizers_blocking_policies_[viewType]];
243 touch_interceptors_[viewId] =
247 [clipping_view addSubview:touch_interceptor];
255 int64_t viewId = [arg longLongValue];
257 if (views_.count(viewId) == 0) {
259 message:
@"trying to dispose an unknown"
260 details:[NSString stringWithFormat:
@"view id: '%lld'", viewId]]);
264 views_to_dispose_.insert(viewId);
271 int64_t viewId = [args[@"id"] longLongValue];
273 if (views_.count(viewId) == 0) {
275 message:
@"trying to set gesture state for an unknown view"
276 details:[NSString stringWithFormat:
@"view id: '%lld'", viewId]]);
289 int64_t viewId = [args[@"id"] longLongValue];
291 if (views_.count(viewId) == 0) {
293 message:
@"trying to set gesture state for an unknown view"
294 details:[NSString stringWithFormat:
@"view id: '%lld'", viewId]]);
304void FlutterPlatformViewsController::RegisterViewFactory(
305 NSObject<FlutterPlatformViewFactory>* factory,
308 std::string idString([factoryId UTF8String]);
309 FML_CHECK(factories_.count(idString) == 0);
311 gesture_recognizers_blocking_policies_[idString] = gestureRecognizerBlockingPolicy;
314void FlutterPlatformViewsController::BeginFrame(
SkISize frame_size) {
316 frame_size_ = frame_size;
319void FlutterPlatformViewsController::CancelFrame() {
326bool FlutterPlatformViewsController::HasPlatformViewThisOrNextFrame() {
327 return !composition_order_.empty() || !active_composition_order_.empty();
330const int FlutterPlatformViewsController::kDefaultMergedLeaseDuration;
336 if (!HasPlatformViewThisOrNextFrame()) {
339 if (!raster_thread_merger->
IsMerged()) {
349 return PostPrerollResult::kSkipAndRetryFrame;
355 BeginCATransaction();
356 raster_thread_merger->
ExtendLeaseTo(kDefaultMergedLeaseDuration);
360void FlutterPlatformViewsController::EndFrame(
361 bool should_resubmit_frame,
363 if (should_resubmit_frame) {
364 raster_thread_merger->
MergeWithLease(kDefaultMergedLeaseDuration);
368void FlutterPlatformViewsController::PushFilterToVisitedPlatformViews(
369 const std::shared_ptr<const DlImageFilter>& filter,
370 const SkRect& filter_rect) {
371 for (int64_t
id : visited_platform_views_) {
373 params.PushImageFilter(filter, filter_rect);
374 current_composition_params_[id] =
params;
378void FlutterPlatformViewsController::PrerollCompositeEmbeddedView(
380 std::unique_ptr<EmbeddedViewParams>
params) {
386 std::unique_ptr<EmbedderViewSlice> view;
387 view = std::make_unique<DisplayListEmbedderViewSlice>(view_bounds);
388 slices_.insert_or_assign(view_id, std::move(view));
390 composition_order_.push_back(view_id);
392 if (current_composition_params_.count(view_id) == 1 &&
393 current_composition_params_[view_id] == *
params.get()) {
398 views_to_recomposite_.insert(view_id);
401size_t FlutterPlatformViewsController::EmbeddedViewCount() {
402 return composition_order_.size();
405UIView* FlutterPlatformViewsController::GetPlatformViewByID(int64_t view_id) {
411 if (views_.empty()) {
414 return touch_interceptors_[view_id].get();
417long FlutterPlatformViewsController::FindFirstResponderPlatformViewId() {
418 for (
auto const& [
id, root_view] : root_views_) {
419 if (((UIView*)root_view.get()).flt_hasFirstResponderInViewHierarchySubtree) {
426int FlutterPlatformViewsController::CountClips(
const MutatorsStack& mutators_stack) {
427 std::vector<std::shared_ptr<Mutator>>::const_reverse_iterator iter = mutators_stack.
Bottom();
429 while (iter != mutators_stack.
Top()) {
430 if ((*iter)->IsClipType()) {
438void FlutterPlatformViewsController::ClipViewSetMaskView(UIView* clipView) {
439 if (clipView.maskView) {
442 UIView* flutterView = flutter_view_.get();
444 CGRectMake(-clipView.frame.origin.x, -clipView.frame.origin.y,
445 CGRectGetWidth(flutterView.bounds), CGRectGetHeight(flutterView.bounds));
446 clipView.maskView = [mask_view_pool_.get() getMaskViewWithFrame:frame];
451void FlutterPlatformViewsController::ApplyMutators(
const MutatorsStack& mutators_stack,
452 UIView* embedded_view,
453 const SkRect& bounding_rect) {
454 if (flutter_view_ ==
nullptr) {
457 FML_DCHECK(CATransform3DEqualToTransform(embedded_view.layer.transform, CATransform3DIdentity));
462 NSMutableArray* blurFilters = [[NSMutableArray alloc]
init];
465 if (clipView.maskView) {
466 [mask_view_pool_.get() insertViewToPoolIfNeeded:(FlutterClippingMaskView*)(clipView.maskView)];
467 clipView.maskView = nil;
469 CGFloat screenScale = [UIScreen mainScreen].scale;
470 auto iter = mutators_stack.Begin();
471 while (iter != mutators_stack.End()) {
472 switch ((*iter)->GetType()) {
474 transformMatrix.preConcat((*iter)->GetMatrix());
482 ClipViewSetMaskView(clipView);
484 matrix:transformMatrix];
492 ClipViewSetMaskView(clipView);
494 matrix:transformMatrix];
501 ClipViewSetMaskView(clipView);
503 matrix:transformMatrix];
507 embedded_view.alpha = (*iter)->GetAlphaFloat() * embedded_view.alpha;
517 filterRect = CGRectApplyAffineTransform(
518 filterRect, CGAffineTransformMakeScale(1 / screenScale, 1 / screenScale));
522 if (CGRectIsNull(CGRectIntersection(filterRect, clipView.frame))) {
525 CGRect intersection = CGRectIntersection(filterRect, clipView.frame);
526 CGRect frameInClipView = [flutter_view_.get() convertRect:intersection toView:clipView];
531 CGFloat blurRadius = (*iter)->GetFilterMutation().GetFilter().asBlur()->sigma_x();
532 UIVisualEffectView* visualEffectView = [[UIVisualEffectView alloc]
533 initWithEffect:[UIBlurEffect effectWithStyle:UIBlurEffectStyleLight]];
535 blurRadius:blurRadius
536 visualEffectView:visualEffectView];
540 [blurFilters addObject:filter];
557 transformMatrix.postScale(1 / screenScale, 1 / screenScale);
566 transformMatrix.postTranslate(-clipView.frame.origin.x, -clipView.frame.origin.y);
579void FlutterPlatformViewsController::CompositeWithParams(int64_t view_id,
580 const EmbeddedViewParams&
params) {
581 CGRect
frame = CGRectMake(0, 0,
params.sizePoints().width(),
params.sizePoints().height());
583#if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
584 FML_DCHECK(CGPointEqualToPoint([touchInterceptor embeddedView].
frame.origin, CGPointZero));
585 if (non_zero_origin_views_.find(view_id) == non_zero_origin_views_.end() &&
586 !CGPointEqualToPoint([touchInterceptor embeddedView].
frame.origin, CGPointZero)) {
587 non_zero_origin_views_.insert(view_id);
589 @"A Embedded PlatformView's origin is not CGPointZero.\n"
591 " View info: \n %@ \n"
592 "A non-zero origin might cause undefined behavior.\n"
593 "See https://github.com/flutter/flutter/issues/109700 for more details.\n"
594 "If you are the author of the PlatformView, please update the implementation of the "
595 "PlatformView to have a (0, 0) origin.\n"
596 "If you have a valid case of using a non-zero origin, "
597 "please leave a comment at https://github.com/flutter/flutter/issues/109700 with details.",
598 @(view_id), [touchInterceptor embeddedView]);
601 touchInterceptor.layer.transform = CATransform3DIdentity;
602 touchInterceptor.frame =
frame;
603 touchInterceptor.alpha = 1;
605 const MutatorsStack& mutatorStack =
params.mutatorsStack();
606 UIView* clippingView = root_views_[view_id].get();
612 CGFloat screenScale = [UIScreen mainScreen].scale;
613 clippingView.frame = CGRectMake(
rect.x() / screenScale,
rect.y() / screenScale,
614 rect.width() / screenScale,
rect.height() / screenScale);
615 ApplyMutators(mutatorStack, touchInterceptor,
rect);
618DlCanvas* FlutterPlatformViewsController::CompositeEmbeddedView(int64_t view_id) {
620 FML_DCHECK([[NSThread currentThread] isMainThread]);
622 if (views_to_recomposite_.count(view_id) == 0) {
623 return slices_[view_id]->canvas();
625 CompositeWithParams(view_id, current_composition_params_[view_id]);
626 views_to_recomposite_.erase(view_id);
627 return slices_[view_id]->canvas();
631 for (int64_t view_id : active_composition_order_) {
632 UIView* sub_view = root_views_[view_id].get();
633 [sub_view removeFromSuperview];
636 touch_interceptors_.clear();
638 composition_order_.clear();
639 active_composition_order_.clear();
641 current_composition_params_.clear();
643 views_to_recomposite_.clear();
644 layer_pool_->RecycleLayers();
645 visited_platform_views_.clear();
648SkRect FlutterPlatformViewsController::GetPlatformViewRect(int64_t view_id) {
650 UIScreen* screen = [UIScreen mainScreen];
651 CGRect platform_view_cgrect = [platform_view convertRect:platform_view.bounds
652 toView:flutter_view_];
654 platform_view_cgrect.origin.y * screen.scale,
655 platform_view_cgrect.size.width * screen.scale,
656 platform_view_cgrect.size.height * screen.scale
661 const std::shared_ptr<IOSContext>& ios_context,
662 std::unique_ptr<SurfaceFrame>
frame) {
663 TRACE_EVENT0(
"flutter",
"FlutterPlatformViewsController::SubmitFrame");
666 FML_DCHECK([[NSThread currentThread] isMainThread]);
667 if (flutter_view_ ==
nullptr) {
668 return frame->Submit();
676 background_canvas->
Flush();
683 LayersMap platform_view_layers;
685 auto did_submit =
true;
686 auto num_platform_views = composition_order_.size();
690 for (
size_t i = 0;
i < num_platform_views;
i++) {
691 int64_t platform_view_id = composition_order_[i];
697 for (
size_t j =
i + 1; j > 0; j--) {
698 int64_t current_platform_view_id = composition_order_[j - 1];
699 SkRect platform_view_rect = GetPlatformViewRect(current_platform_view_id);
700 std::vector<SkIRect> intersection_rects = slice->
region(platform_view_rect).
getRects();
701 const SkIRect rounded_in_platform_view_rect = platform_view_rect.
roundIn();
712 for (
auto it = intersection_rects.begin(); it != intersection_rects.end(); ) {
716 it = intersection_rects.erase(it);
722 auto allocation_size = intersection_rects.size();
726 auto overlay_id = platform_view_layers[current_platform_view_id].size();
733 if (allocation_size > kMaxLayerAllocations) {
740 intersection_rects.clear();
741 intersection_rects.push_back(joined_rect);
743 for (
SkIRect& joined_rect : intersection_rects) {
746 joined_rect.intersect(platform_view_rect.
roundOut());
751 std::shared_ptr<FlutterPlatformViewLayer> layer =
756 current_platform_view_id,
760 did_submit &= layer->did_submit_last_frame;
761 platform_view_layers[current_platform_view_id].push_back(layer);
773 RemoveUnusedLayers();
775 BringLayersIntoView(platform_view_layers);
777 layer_pool_->RecycleLayers();
779 did_submit &=
frame->Submit();
784 CommitCATransactionIfNeeded();
788void FlutterPlatformViewsController::BringLayersIntoView(LayersMap layer_map) {
790 UIView* flutter_view = flutter_view_.get();
792 active_composition_order_.clear();
793 NSMutableArray* desired_platform_subviews = [NSMutableArray array];
794 for (
size_t i = 0;
i < composition_order_.size();
i++) {
795 int64_t platform_view_id = composition_order_[i];
796 std::vector<std::shared_ptr<FlutterPlatformViewLayer>> layers = layer_map[platform_view_id];
797 UIView* platform_view_root = root_views_[platform_view_id].get();
798 [desired_platform_subviews addObject:platform_view_root];
799 for (
const std::shared_ptr<FlutterPlatformViewLayer>& layer : layers) {
800 [desired_platform_subviews addObject:layer->overlay_view_wrapper];
802 active_composition_order_.push_back(platform_view_id);
805 NSSet* desired_platform_subviews_set = [NSSet setWithArray:desired_platform_subviews];
806 NSArray* existing_platform_subviews = [flutter_view.subviews
807 filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id object,
808 NSDictionary* bindings) {
809 return [desired_platform_subviews_set containsObject:object];
815 if (![desired_platform_subviews isEqualToArray:existing_platform_subviews]) {
816 for (UIView* subview in desired_platform_subviews) {
818 [flutter_view addSubview:subview];
823std::shared_ptr<FlutterPlatformViewLayer> FlutterPlatformViewsController::GetLayer(
825 const std::shared_ptr<IOSContext>& ios_context,
826 EmbedderViewSlice* slice,
830 MTLPixelFormat pixel_format) {
832 std::shared_ptr<FlutterPlatformViewLayer> layer =
833 layer_pool_->GetLayer(gr_context, ios_context, pixel_format);
835 UIView* overlay_view_wrapper = layer->overlay_view_wrapper.get();
836 auto screenScale = [UIScreen mainScreen].scale;
839 overlay_view_wrapper.frame = CGRectMake(
rect.x() / screenScale,
rect.y() / screenScale,
840 rect.width() / screenScale,
rect.height() / screenScale);
842 overlay_view_wrapper.accessibilityIdentifier =
843 [NSString stringWithFormat:@"platform_view[%lld].overlay[%lld]", view_id, overlay_id];
845 UIView* overlay_view = layer->overlay_view.get();
848 overlay_view.frame = [flutter_view_.get() convertRect:flutter_view_.get().bounds
849 toView:overlay_view_wrapper];
851 overlay_view.accessibilityIdentifier =
852 [NSString stringWithFormat:@"platform_view[%lld].overlay_view[%lld]", view_id, overlay_id];
854 std::unique_ptr<SurfaceFrame>
frame = layer->surface->AcquireFrame(frame_size_);
860 int restore_count = overlay_canvas->GetSaveCount();
861 overlay_canvas->Save();
864 slice->render_into(overlay_canvas);
865 overlay_canvas->RestoreToCount(restore_count);
867 layer->did_submit_last_frame =
frame->Submit();
871void FlutterPlatformViewsController::RemoveUnusedLayers() {
872 std::vector<std::shared_ptr<FlutterPlatformViewLayer>> layers = layer_pool_->GetUnusedLayers();
873 for (
const std::shared_ptr<FlutterPlatformViewLayer>& layer : layers) {
874 [layer->overlay_view_wrapper removeFromSuperview];
877 std::unordered_set<int64_t> composition_order_set;
878 for (int64_t view_id : composition_order_) {
879 composition_order_set.insert(view_id);
882 for (int64_t view_id : active_composition_order_) {
883 if (composition_order_set.find(view_id) == composition_order_set.end()) {
884 UIView* platform_view_root = root_views_[view_id].get();
885 [platform_view_root removeFromSuperview];
890void FlutterPlatformViewsController::DisposeViews() {
891 if (views_to_dispose_.empty()) {
895 FML_DCHECK([[NSThread currentThread] isMainThread]);
897 std::unordered_set<int64_t> views_to_composite(composition_order_.begin(),
898 composition_order_.end());
899 std::unordered_set<int64_t> views_to_delay_dispose;
900 for (int64_t viewId : views_to_dispose_) {
901 if (views_to_composite.count(viewId)) {
902 views_to_delay_dispose.insert(viewId);
905 UIView* root_view = root_views_[viewId].get();
906 [root_view removeFromSuperview];
907 views_.erase(viewId);
908 touch_interceptors_.erase(viewId);
909 root_views_.erase(viewId);
910 current_composition_params_.erase(viewId);
911 clip_count_.erase(viewId);
912 views_to_recomposite_.erase(viewId);
915 views_to_dispose_ = std::move(views_to_delay_dispose);
918void FlutterPlatformViewsController::BeginCATransaction() {
919 FML_DCHECK([[NSThread currentThread] isMainThread]);
921 [CATransaction begin];
922 catransaction_added_ =
true;
925void FlutterPlatformViewsController::CommitCATransactionIfNeeded() {
926 if (catransaction_added_) {
927 FML_DCHECK([[NSThread currentThread] isMainThread]);
928 [CATransaction commit];
929 catransaction_added_ =
false;
933void FlutterPlatformViewsController::ResetFrameState() {
935 composition_order_.clear();
936 visited_platform_views_.clear();
959- (instancetype)initWithTarget:(
id)target
961 forwardingRecognizer:(UIGestureRecognizer*)forwardingRecognizer;
975- (instancetype)initWithTarget:(
id)target
976 platformViewsController:
987- (instancetype)initWithEmbeddedView:(UIView*)embeddedView
988 platformViewsController:
990 gestureRecognizersBlockingPolicy:
992 self = [
super initWithFrame:embeddedView.frame];
994 self.multipleTouchEnabled = YES;
997 (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
999 [
self addSubview:embeddedView];
1003 platformViewsController:platformViewsController];
1007 forwardingRecognizer:forwardingRecognizer];
1010 [
self addGestureRecognizer:_delayingRecognizer];
1011 [
self addGestureRecognizer:forwardingRecognizer];
1017 self.delayingRecognizer.state = UIGestureRecognizerStateFailed;
1021 switch (_blockingPolicy) {
1024 self.delayingRecognizer.state = UIGestureRecognizerStateEnded;
1027 if (
self.delayingRecognizer.touchedEndedWithoutBlocking) {
1031 self.delayingRecognizer.state = UIGestureRecognizerStateEnded;
1036 self.delayingRecognizer.shouldEndInNextTouchesEnded = YES;
1047- (void)touchesBegan:(NSSet<UITouch*>*)touches withEvent:(
UIEvent*)event {
1050- (void)touchesMoved:(NSSet<UITouch*>*)touches withEvent:(
UIEvent*)event {
1053- (void)touchesCancelled:(NSSet<UITouch*>*)touches withEvent:(
UIEvent*)event {
1056- (void)touchesEnded:(NSSet*)touches withEvent:(
UIEvent*)event {
1060 return self.flutterAccessibilityContainer;
1067- (instancetype)initWithTarget:(
id)target
1069 forwardingRecognizer:(UIGestureRecognizer*)forwardingRecognizer {
1070 self = [
super initWithTarget:target action:action];
1072 self.delaysTouchesBegan = YES;
1073 self.delaysTouchesEnded = YES;
1075 _shouldEndInNextTouchesEnded = NO;
1076 _touchedEndedWithoutBlocking = NO;
1082- (
BOOL)gestureRecognizer:(UIGestureRecognizer*)gestureRecognizer
1083 shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer*)otherGestureRecognizer {
1086 return otherGestureRecognizer != _forwardingRecognizer && otherGestureRecognizer !=
self;
1089- (
BOOL)gestureRecognizer:(UIGestureRecognizer*)gestureRecognizer
1090 shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer*)otherGestureRecognizer {
1091 return otherGestureRecognizer ==
self;
1094- (void)touchesBegan:(NSSet<UITouch*>*)touches withEvent:(
UIEvent*)event {
1095 self.touchedEndedWithoutBlocking = NO;
1096 [
super touchesBegan:touches withEvent:event];
1099- (void)touchesEnded:(NSSet<UITouch*>*)touches withEvent:(
UIEvent*)event {
1100 if (
self.shouldEndInNextTouchesEnded) {
1101 self.state = UIGestureRecognizerStateEnded;
1102 self.shouldEndInNextTouchesEnded = NO;
1104 self.touchedEndedWithoutBlocking = YES;
1106 [
super touchesEnded:touches withEvent:event];
1109- (void)touchesCancelled:(NSSet*)touches withEvent:(
UIEvent*)event {
1110 self.state = UIGestureRecognizerStateFailed;
1132- (instancetype)initWithTarget:(
id)target
1133 platformViewsController:
1134 (
fml::
WeakPtr<
flutter::FlutterPlatformViewsController>)platformViewsController {
1135 self = [
super initWithTarget:target action:nil];
1138 FML_DCHECK(platformViewsController.get() !=
nullptr);
1145- (void)touchesBegan:(NSSet*)touches withEvent:(
UIEvent*)event {
1153 [_flutterViewController.get() touchesBegan:touches withEvent:event];
1157- (void)touchesMoved:(NSSet*)touches withEvent:(
UIEvent*)event {
1158 [_flutterViewController.get() touchesMoved:touches withEvent:event];
1161- (void)touchesEnded:(NSSet*)touches withEvent:(
UIEvent*)event {
1162 [_flutterViewController.get() touchesEnded:touches withEvent:event];
1169 self.state = UIGestureRecognizerStateFailed;
1174- (void)touchesCancelled:(NSSet*)touches withEvent:(
UIEvent*)event {
1180 [_flutterViewController.get() forceTouchesCancelled:touches];
1183 self.state = UIGestureRecognizerStateFailed;
1188- (
BOOL)gestureRecognizer:(UIGestureRecognizer*)gestureRecognizer
1189 shouldRecognizeSimultaneouslyWithGestureRecognizer:
1190 (UIGestureRecognizer*)otherGestureRecognizer {
void(^ FlutterResult)(id _Nullable result)
FLUTTER_DARWIN_EXPORT NSObject const * FlutterMethodNotImplemented
FlutterPlatformViewGestureRecognizersBlockingPolicy
@ FlutterPlatformViewGestureRecognizersBlockingPolicyEager
@ FlutterPlatformViewGestureRecognizersBlockingPolicyWaitUntilTouchesEnded
static sk_sp< Effect > Create()
id accessibilityContainer()
DelayingGestureRecognizer * delayingRecognizer
FlutterPlatformViewGestureRecognizersBlockingPolicy blockingPolicy
SkScalar mapRadius(SkScalar radius) const
bool mapRect(SkRect *dst, const SkRect &src, SkApplyPerspectiveClip pc=SkApplyPerspectiveClip::kYes) const
const SkRect & rect() const
SkVector radii(Corner corner) const
void setRectRadii(const SkRect &rect, const SkVector radii[4])
bool contains(const SkRect &rect) const
Developer-facing API for rendering anything within the engine.
virtual void ClipRect(const SkRect &rect, ClipOp clip_op=ClipOp::kIntersect, bool is_aa=false)=0
std::vector< SkIRect > getRects(bool deband=true) const
virtual void render_into(DlCanvas *canvas)=0
virtual void end_recording()=0
DlRegion region(const SkRect &query) const
virtual std::unique_ptr< Surface > CreateGPUSurface(GrDirectContext *gr_context=nullptr)=0
void ExtendLeaseTo(size_t lease_term)
void MergeWithLease(size_t lease_term)
void reset(NST *object=Traits::InvalidValue(), scoped_policy::OwnershipPolicy policy=scoped_policy::OwnershipPolicy::kAssume)
const EmbeddedViewParams * params
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
#define FML_CHECK(condition)
#define FML_DCHECK(condition)
void applyBlurBackdropFilters:(NSArray< PlatformViewFilter * > *filters)
UIGestureRecognizer * forwardingRecognizer
BOOL touchedEndedWithoutBlocking
BOOL shouldEndInNextTouchesEnded
std::shared_ptr< flutter::FlutterPlatformViewsController > _platformViewsController
constexpr SkColor4f kTransparent
sk_sp< SkBlender > blender SkRect rect
auto WeakPtr(std::shared_ptr< T > pointer)
BOOL canApplyBlurBackdrop
void ResetAnchor(CALayer *layer)
CATransform3D GetCATransform3DFromSkMatrix(const SkMatrix &matrix)
CGRect GetCGRectFromSkRect(const SkRect &clipSkRect)
flutter::DlCanvas DlCanvas
static bool Intersects(const SkIRect &a, const SkIRect &b)
void join(const SkIRect &r)
static constexpr SkIRect MakeEmpty()
constexpr float y() const
constexpr float x() const
static SkRect Make(const SkISize &size)
void roundIn(SkIRect *dst) const
static constexpr SkRect MakeXYWH(float x, float y, float w, float h)
bool contains(SkScalar x, SkScalar y) const
void roundOut(SkIRect *dst) const
#define TRACE_EVENT0(category_group, name)