Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion flow/embedded_views.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ class Mutator {
//
// For example consider the following stack: [T1, T2, T3], where T1 is the top
// of the stack and T3 is the bottom of the stack. Applying this mutators stack
// to a platform view P1 will result in T1(T2(T2(P1))).
// to a platform view P1 will result in T1(T2(T3(P1))).
class MutatorsStack {
public:
MutatorsStack() = default;
Expand Down
18 changes: 12 additions & 6 deletions shell/platform/darwin/ios/framework/Source/FlutterPlatformViews.mm
Original file line number Diff line number Diff line change
Expand Up @@ -157,13 +157,13 @@
NSObject<FlutterPlatformView>* embedded_view = [factory createWithFrame:CGRectZero
viewIdentifier:viewId
arguments:params];
UIView* platform_view = [embedded_view view];
// Set a unique view identifier, so the platform view can be identified in unit tests.
[embedded_view view].accessibilityIdentifier =
[NSString stringWithFormat:@"platform_view[%ld]", viewId];
platform_view.accessibilityIdentifier = [NSString stringWithFormat:@"platform_view[%ld]", viewId];
views_[viewId] = fml::scoped_nsobject<NSObject<FlutterPlatformView>>([embedded_view retain]);

FlutterTouchInterceptingView* touch_interceptor = [[[FlutterTouchInterceptingView alloc]
initWithEmbeddedView:embedded_view.view
initWithEmbeddedView:platform_view
platformViewsController:GetWeakPtr()
gestureRecognizersBlockingPolicy:gesture_recognizers_blocking_policies[viewType]]
autorelease];
Expand Down Expand Up @@ -311,11 +311,11 @@
views_to_recomposite_.insert(view_id);
}

NSObject<FlutterPlatformView>* FlutterPlatformViewsController::GetPlatformViewByID(int view_id) {
UIView* FlutterPlatformViewsController::GetPlatformViewByID(int view_id) {
if (views_.empty()) {
return nil;
}
return views_[view_id].get();
return [touch_interceptors_[view_id].get() embeddedView];
}

std::vector<SkCanvas*> FlutterPlatformViewsController::GetCurrentCanvases() {
Expand Down Expand Up @@ -451,7 +451,7 @@
}

SkRect FlutterPlatformViewsController::GetPlatformViewRect(int view_id) {
UIView* platform_view = [views_[view_id].get() view];
UIView* platform_view = GetPlatformViewByID(view_id);
UIScreen* screen = [UIScreen mainScreen];
CGRect platform_view_cgrect = [platform_view convertRect:platform_view.bounds
toView:flutter_view_];
Expand Down Expand Up @@ -734,6 +734,7 @@ - (instancetype)initWithTarget:(id)target
@implementation FlutterTouchInterceptingView {
fml::scoped_nsobject<DelayingGestureRecognizer> _delayingRecognizer;
FlutterPlatformViewGestureRecognizersBlockingPolicy _blockingPolicy;
UIView* _embeddedView;
}
- (instancetype)initWithEmbeddedView:(UIView*)embeddedView
platformViewsController:
Expand All @@ -743,6 +744,7 @@ - (instancetype)initWithEmbeddedView:(UIView*)embeddedView
self = [super initWithFrame:embeddedView.frame];
if (self) {
self.multipleTouchEnabled = YES;
_embeddedView = embeddedView;
embeddedView.autoresizingMask =
(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);

Expand All @@ -764,6 +766,10 @@ - (instancetype)initWithEmbeddedView:(UIView*)embeddedView
return self;
}

- (UIView*)embeddedView {
return [[_embeddedView retain] autorelease];
}

- (void)releaseGesture {
_delayingRecognizer.get().state = UIGestureRecognizerStateFailed;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,31 @@ - (void)dealloc {

@interface FlutterPlatformViewsTestMockFlutterPlatformView : NSObject <FlutterPlatformView>
@property(nonatomic, strong) UIView* view;
@property(nonatomic, assign) BOOL viewCreated;
@end

@implementation FlutterPlatformViewsTestMockFlutterPlatformView

- (instancetype)init {
if (self = [super init]) {
_view = [[FlutterPlatformViewsTestMockPlatformView alloc] init];
_viewCreated = NO;
}
return self;
}

- (UIView*)view {
[self checkViewCreatedOnce];
return _view;
}

- (void)checkViewCreatedOnce {
if (self.viewCreated) {
abort();
}
self.viewCreated = YES;
}

- (void)dealloc {
[_view release];
_view = nil;
Expand Down Expand Up @@ -107,6 +121,60 @@ @interface FlutterPlatformViewsTest : XCTestCase

@implementation FlutterPlatformViewsTest

- (void)testFlutterViewOnlyCreateOnceInOneFrame {
flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
auto thread_task_runner = CreateNewThread("FlutterPlatformViewsTest");
flutter::TaskRunners runners(/*label=*/self.name.UTF8String,
/*platform=*/thread_task_runner,
/*raster=*/thread_task_runner,
/*ui=*/thread_task_runner,
/*io=*/thread_task_runner);
auto flutterPlatformViewsController = std::make_shared<flutter::FlutterPlatformViewsController>();
auto platform_view = std::make_unique<flutter::PlatformViewIOS>(
/*delegate=*/mock_delegate,
/*rendering_api=*/flutter::IOSRenderingAPI::kSoftware,
/*platform_views_controller=*/flutterPlatformViewsController,
/*task_runners=*/runners);

FlutterPlatformViewsTestMockFlutterPlatformFactory* factory =
[[FlutterPlatformViewsTestMockFlutterPlatformFactory new] autorelease];
flutterPlatformViewsController->RegisterViewFactory(
factory, @"MockFlutterPlatformView",
FlutterPlatformViewGestureRecognizersBlockingPolicyEager);
FlutterResult result = ^(id result) {
};
flutterPlatformViewsController->OnMethodCall(
[FlutterMethodCall
methodCallWithMethodName:@"create"
arguments:@{@"id" : @2, @"viewType" : @"MockFlutterPlatformView"}],
result);
UIView* mockFlutterView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 500)] autorelease];
flutterPlatformViewsController->SetFlutterView(mockFlutterView);
// Create embedded view params
flutter::MutatorsStack stack;
// Layer tree always pushes a screen scale factor to the stack
SkMatrix screenScaleMatrix =
SkMatrix::MakeScale([UIScreen mainScreen].scale, [UIScreen mainScreen].scale);
stack.PushTransform(screenScaleMatrix);
// Push a translate matrix
SkMatrix translateMatrix = SkMatrix::MakeTrans(100, 100);
stack.PushTransform(translateMatrix);
SkMatrix finalMatrix;
finalMatrix.setConcat(screenScaleMatrix, translateMatrix);

auto embeddedViewParams =
std::make_unique<flutter::EmbeddedViewParams>(finalMatrix, SkSize::Make(300, 300), stack);

flutterPlatformViewsController->PrerollCompositeEmbeddedView(2, std::move(embeddedViewParams));
flutterPlatformViewsController->CompositeEmbeddedView(2);

flutterPlatformViewsController->GetPlatformViewRect(2);

XCTAssertNotNil(gMockPlatformView);

flutterPlatformViewsController->Reset();
}

- (void)testCanCreatePlatformViewWithoutFlutterView {
flutter::FlutterPlatformViewsTestMockPlatformViewDelegate mock_delegate;
auto thread_task_runner = CreateNewThread("FlutterPlatformViewsTest");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,12 +150,12 @@ class FlutterPlatformViewsController {
void PrerollCompositeEmbeddedView(int view_id,
std::unique_ptr<flutter::EmbeddedViewParams> params);

// Returns the `FlutterPlatformView` object associated with the view_id.
// Returns the `FlutterPlatformView`'s `view` object associated with the view_id.
//
// If the `FlutterPlatformViewsController` does not contain any `FlutterPlatformView` object or
// a `FlutterPlatformView` object asscociated with the view_id cannot be found, the method
// returns nil.
NSObject<FlutterPlatformView>* GetPlatformViewByID(int view_id);
UIView* GetPlatformViewByID(int view_id);

PostPrerollResult PostPrerollAction(fml::RefPtr<fml::RasterThreadMerger> raster_thread_merger);

Expand Down Expand Up @@ -326,6 +326,9 @@ class FlutterPlatformViewsController {

// Prevent the touch sequence from ever arriving to the embedded view.
- (void)blockGesture;

// Get embedded view
- (UIView*)embeddedView;
@end

#endif // FLUTTER_SHELL_PLATFORM_DARWIN_IOS_FRAMEWORK_SOURCE_FLUTTERPLATFORMVIEWS_INTERNAL_H_
Original file line number Diff line number Diff line change
Expand Up @@ -559,7 +559,7 @@ - (instancetype)initWithSemanticsObject:(SemanticsObject*)object {
_semanticsObject = object;
auto controller = object.bridge->GetPlatformViewsController();
if (controller) {
_platformView = [[controller->GetPlatformViewByID(object.node.platformViewId) view] retain];
_platformView = [controller->GetPlatformViewByID(object.node.platformViewId) retain];
}
}
return self;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ @interface TextPlatformView () <TestGestureRecognizerDelegate>
@implementation TextPlatformView {
UITextView* _textView;
FlutterMethodChannel* _channel;
BOOL _viewCreated;
}

- (instancetype)initWithFrame:(CGRect)frame
Expand All @@ -87,11 +88,18 @@ - (instancetype)initWithFrame:(CGRect)frame
[_textView addGestureRecognizer:gestureRecognizer];
gestureRecognizer.testTapGestureRecognizerDelegate = self;
_textView.accessibilityLabel = @"";

_viewCreated = NO;
}
return self;
}

- (UIView*)view {
// Makes sure the engine only calls this method once.
if (_viewCreated) {
abort();
}
_viewCreated = YES;
return _textView;
}

Expand Down