From 1b1b2d7c78b30237646bfb37633363bc277bf343 Mon Sep 17 00:00:00 2001 From: luckysmg <2539699336@qq.com> Date: Fri, 19 Aug 2022 23:10:47 +0800 Subject: [PATCH 01/10] Add code in FlutterViewController and VSyncClient --- .../framework/Source/FlutterViewController.mm | 57 +++++++++++++++++++ .../ios/framework/Source/vsync_waiter_ios.h | 2 + .../ios/framework/Source/vsync_waiter_ios.mm | 4 ++ 3 files changed, 63 insertions(+) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm index cc7947421f8f3..e621b4d7bb6cc 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm @@ -65,6 +65,9 @@ @interface FlutterViewController () (touches.count + touches_to_remove_count); @@ -1111,6 +1121,53 @@ - (void)forceTouchesCancelled:(NSSet*)touches { [self dispatchTouches:touches pointerDataChangeOverride:&cancel event:nullptr]; } +#pragma mark - Touch events rate correction + +- (void)setupTouchRateCorrectionVSyncClient { + NSAssert(_touchRateCorrectionVSyncClient == nil, + @"_touchRateCorrectionVSyncClient should be nil when setup"); + double displayRefreshRate = [DisplayLinkManager displayRefreshRate]; + if (displayRefreshRate <= 60) { + // If current device's max frame rate is not larger than 60HZ, the delivery rate of touch events + // is the same with render vsync rate. So we don't need to create + // _touchRateCorrectionVSyncClient to correct touch callback's rate. + return; + } + + flutter::Shell& shell = [_engine.get() shell]; + auto callback = [](std::unique_ptr recorder) { + // Do nothing in this block. Just trigger system to callback touch events with correct rate. + }; + _touchRateCorrectionVSyncClient = + [[VSyncClient alloc] initWithTaskRunner:shell.GetTaskRunners().GetPlatformTaskRunner() + callback:callback]; + _touchRateCorrectionVSyncClient.allowPauseAfterVsync = NO; +} + +- (void)triggerTouchRateCorrectionIfNeeded:(NSSet*)touches { + // As long as there is a touch's phase is UITouchPhaseBegan or UITouchPhaseMoved, + // we should activate the correction. Otherwise we will pause the correction. + BOOL isUserInteracting = NO; + for (UITouch* touch in touches) { + if (touch.phase == UITouchPhaseBegan || touch.phase == UITouchPhaseMoved) { + isUserInteracting = YES; + break; + } + } + + if (isUserInteracting && [_engine.get() viewController] == self) { + [_touchRateCorrectionVSyncClient await]; + } else { + [_touchRateCorrectionVSyncClient pause]; + } +} + +- (void)invalidateTouchRateCorrectionVSyncClient { + [_touchRateCorrectionVSyncClient invalidate]; + [_touchRateCorrectionVSyncClient release]; + _touchRateCorrectionVSyncClient = nil; +} + #pragma mark - Handle view resizing - (void)updateViewportMetrics { diff --git a/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.h b/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.h index 9185fb00978d9..8178f845b8001 100644 --- a/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.h +++ b/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.h @@ -45,6 +45,8 @@ - (void)await; +- (void)pause; + - (void)invalidate; - (double)getRefreshRate; diff --git a/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.mm b/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.mm index 439ba868ff8b5..63954c9c59b09 100644 --- a/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.mm +++ b/shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.mm @@ -97,6 +97,10 @@ - (void)await { display_link_.get().paused = NO; } +- (void)pause { + display_link_.get().paused = YES; +} + - (void)onDisplayLink:(CADisplayLink*)link { TRACE_EVENT0("flutter", "VSYNC"); From b6554066a40258044172eefc51bdb20003e6a90c Mon Sep 17 00:00:00 2001 From: luckysmg <2539699336@qq.com> Date: Sat, 20 Aug 2022 11:54:52 +0800 Subject: [PATCH 02/10] Add tests --- .../Source/FlutterViewControllerTest.mm | 13 +++ .../Source/FlutterViewControllerTest_mrc.mm | 96 +++++++++++++++++++ 2 files changed, 109 insertions(+) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm index d3f4de66f8710..6595916530c83 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm @@ -114,6 +114,7 @@ @interface FlutterViewController (Tests) @property(nonatomic, assign) double targetViewInsetBottom; +- (void)setupTouchRateCorrectionVSyncClient; - (void)surfaceUpdated:(BOOL)appeared; - (void)performOrientationUpdate:(UIInterfaceOrientationMask)new_preferences; - (void)handlePressEvent:(FlutterUIPressProxy*)press @@ -160,6 +161,18 @@ - (void)tearDown { self.messageSent = nil; } +- (void)testViewDidLoadWillInvokeSetupTouchRateCorrectionVSyncClient { + FlutterEngine* engine = [[FlutterEngine alloc] init]; + [engine runWithEntrypoint:nil]; + FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engine + nibName:nil + bundle:nil]; + FlutterViewController* viewControllerMock = OCMPartialMock(viewController); + [viewControllerMock loadView]; + [viewControllerMock viewDidLoad]; + OCMVerify([viewControllerMock setupTouchRateCorrectionVSyncClient]); +} + - (void)testStartKeyboardAnimationWillInvokeSetupKeyboardAnimationVsyncClient { FlutterEngine* engine = [[FlutterEngine alloc] init]; [engine runWithEntrypoint:nil]; diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest_mrc.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest_mrc.mm index f4cc21706ef47..50677e9b7c828 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest_mrc.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest_mrc.mm @@ -11,6 +11,12 @@ FLUTTER_ASSERT_NOT_ARC +@interface UITouch () + +@property(nonatomic, readwrite) UITouchPhase phase; + +@end + @interface VSyncClient (Testing) - (CADisplayLink*)getDisplayLink; @@ -22,7 +28,11 @@ @interface FlutterViewController (Testing) @property(nonatomic, assign) double targetViewInsetBottom; @property(nonatomic, retain) VSyncClient* keyboardAnimationVSyncClient; +@property(nonatomic, retain) VSyncClient* touchRateCorrectionVSyncClient; + +- (void)setupTouchRateCorrectionVSyncClient; - (void)setupKeyboardAnimationVsyncClient; +- (void)triggerTouchRateCorrectionIfNeeded:(NSSet*)touches; @end @@ -56,4 +66,90 @@ - (void)testSetupKeyboardAnimationVsyncClientWillCreateNewVsyncClientForFlutterV } } +- (void) + testSetupTouchRateCorrectionVSyncClientWillCreateVsyncClientWhenRefreshRateIsLargerThan60HZ { + id mockDisplayLinkManager = [OCMockObject mockForClass:[DisplayLinkManager class]]; + double maxFrameRate = 120; + [[[mockDisplayLinkManager stub] andReturnValue:@(maxFrameRate)] displayRefreshRate]; + FlutterEngine* engine = [[FlutterEngine alloc] init]; + [engine runWithEntrypoint:nil]; + FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engine + nibName:nil + bundle:nil]; + [viewController setupTouchRateCorrectionVSyncClient]; + XCTAssertNotNil(viewController.touchRateCorrectionVSyncClient); +} + +- (void)testSetupTouchRateCorrectionVSyncClientWillCreateVsyncClientWhenRefreshRateIs60HZ { + id mockDisplayLinkManager = [OCMockObject mockForClass:[DisplayLinkManager class]]; + double maxFrameRate = 60; + [[[mockDisplayLinkManager stub] andReturnValue:@(maxFrameRate)] displayRefreshRate]; + FlutterEngine* engine = [[FlutterEngine alloc] init]; + [engine runWithEntrypoint:nil]; + FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engine + nibName:nil + bundle:nil]; + [viewController setupTouchRateCorrectionVSyncClient]; + XCTAssertNil(viewController.touchRateCorrectionVSyncClient); +} + +- (void)testTriggerTouchRateCorrectionVSyncClientCorrectly { + id mockDisplayLinkManager = [OCMockObject mockForClass:[DisplayLinkManager class]]; + double maxFrameRate = 120; + [[[mockDisplayLinkManager stub] andReturnValue:@(maxFrameRate)] displayRefreshRate]; + FlutterEngine* engine = [[FlutterEngine alloc] init]; + [engine runWithEntrypoint:nil]; + FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engine + nibName:nil + bundle:nil]; + [viewController loadView]; + [viewController viewDidLoad]; + + VSyncClient* client = viewController.touchRateCorrectionVSyncClient; + CADisplayLink* link = [client getDisplayLink]; + + UITouch* fakeTouchBegan = [[UITouch alloc] init]; + fakeTouchBegan.phase = UITouchPhaseBegan; + + UITouch* fakeTouchMove = [[UITouch alloc] init]; + fakeTouchMove.phase = UITouchPhaseMoved; + + UITouch* fakeTouchEnd = [[UITouch alloc] init]; + fakeTouchEnd.phase = UITouchPhaseEnded; + + UITouch* fakeTouchCancelled = [[UITouch alloc] init]; + fakeTouchCancelled.phase = UITouchPhaseCancelled; + + [viewController + triggerTouchRateCorrectionIfNeeded:[[NSSet alloc] initWithObjects:fakeTouchBegan, nil]]; + XCTAssertFalse(link.isPaused); + + [viewController + triggerTouchRateCorrectionIfNeeded:[[NSSet alloc] initWithObjects:fakeTouchEnd, nil]]; + XCTAssertTrue(link.isPaused); + + [viewController + triggerTouchRateCorrectionIfNeeded:[[NSSet alloc] initWithObjects:fakeTouchMove, nil]]; + XCTAssertFalse(link.isPaused); + + [viewController + triggerTouchRateCorrectionIfNeeded:[[NSSet alloc] initWithObjects:fakeTouchCancelled, nil]]; + XCTAssertTrue(link.isPaused); + + [viewController + triggerTouchRateCorrectionIfNeeded:[[NSSet alloc] + initWithObjects:fakeTouchBegan, fakeTouchEnd, nil]]; + XCTAssertFalse(link.isPaused); + + [viewController + triggerTouchRateCorrectionIfNeeded:[[NSSet alloc] initWithObjects:fakeTouchEnd, + fakeTouchCancelled, nil]]; + XCTAssertTrue(link.isPaused); + + [viewController + triggerTouchRateCorrectionIfNeeded:[[NSSet alloc] + initWithObjects:fakeTouchMove, fakeTouchEnd, nil]]; + XCTAssertFalse(link.isPaused); +} + @end From 8e93daed0f33fa8b2d40861ee293931d2a7f547c Mon Sep 17 00:00:00 2001 From: luckysmg <2539699336@qq.com> Date: Sat, 20 Aug 2022 14:35:56 +0800 Subject: [PATCH 03/10] Add tests --- .../framework/Source/VsyncWaiterIosTest.mm | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/shell/platform/darwin/ios/framework/Source/VsyncWaiterIosTest.mm b/shell/platform/darwin/ios/framework/Source/VsyncWaiterIosTest.mm index 4ac0529808ed7..15d3f6df652ba 100644 --- a/shell/platform/darwin/ios/framework/Source/VsyncWaiterIosTest.mm +++ b/shell/platform/darwin/ios/framework/Source/VsyncWaiterIosTest.mm @@ -116,4 +116,23 @@ - (void)testDoNotSetVariableRefreshRatesIfCADisableMinimumFrameDurationOnPhoneIs [vsyncClient release]; } +- (void)testAwaitAndPauseWillWorkCorrectly { + auto thread_task_runner = CreateNewThread("VsyncWaiterIosTest"); + VSyncClient* vsyncClient = [[[VSyncClient alloc] + initWithTaskRunner:thread_task_runner + callback:[](std::unique_ptr recorder) {}] + autorelease]; + + CADisplayLink* link = [vsyncClient getDisplayLink]; + XCTAssertTrue(link.isPaused); + + [vsyncClient await]; + XCTAssertFalse(link.isPaused); + + [vsyncClient pause]; + XCTAssertTrue(link.isPaused); + + [vsyncClient release]; +} + @end From 85bc1b55049fa1d26fbb39e25fa92c760992d2dc Mon Sep 17 00:00:00 2001 From: luckysmg <2539699336@qq.com> Date: Sat, 20 Aug 2022 20:03:59 +0800 Subject: [PATCH 04/10] Optimize code --- .../ios/framework/Source/FlutterViewController.mm | 14 ++++++++++---- .../framework/Source/FlutterViewControllerTest.mm | 6 +++--- .../Source/FlutterViewControllerTest_mrc.mm | 10 +++++----- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm index e621b4d7bb6cc..8db6608788137 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm @@ -674,8 +674,8 @@ - (void)viewDidLoad { // Register internal plugins. [self addInternalPlugins]; - // Setup vsync client to correct touch rate. - [self setupTouchRateCorrectionVSyncClient]; + // Create a vsync client to correct touch rate if needed. + [self createTouchRateCorrectionVSyncClientIfNeeded]; if (@available(iOS 13.4, *)) { _hoverGestureRecognizer = @@ -1123,9 +1123,9 @@ - (void)forceTouchesCancelled:(NSSet*)touches { #pragma mark - Touch events rate correction -- (void)setupTouchRateCorrectionVSyncClient { +- (void)createTouchRateCorrectionVSyncClientIfNeeded { NSAssert(_touchRateCorrectionVSyncClient == nil, - @"_touchRateCorrectionVSyncClient should be nil when setup"); + @"_touchRateCorrectionVSyncClient should be nil when setup it"); double displayRefreshRate = [DisplayLinkManager displayRefreshRate]; if (displayRefreshRate <= 60) { // If current device's max frame rate is not larger than 60HZ, the delivery rate of touch events @@ -1145,6 +1145,12 @@ - (void)setupTouchRateCorrectionVSyncClient { } - (void)triggerTouchRateCorrectionIfNeeded:(NSSet*)touches { + if (_touchRateCorrectionVSyncClient == nil) { + // If the _touchRateCorrectionVSyncClient is not created, means current devices doesn't + // need to correct the touch rate. So just return. + return; + } + // As long as there is a touch's phase is UITouchPhaseBegan or UITouchPhaseMoved, // we should activate the correction. Otherwise we will pause the correction. BOOL isUserInteracting = NO; diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm index 6595916530c83..cbdcf3cf6974e 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm @@ -114,7 +114,7 @@ @interface FlutterViewController (Tests) @property(nonatomic, assign) double targetViewInsetBottom; -- (void)setupTouchRateCorrectionVSyncClient; +- (void)createTouchRateCorrectionVSyncClientIfNeeded; - (void)surfaceUpdated:(BOOL)appeared; - (void)performOrientationUpdate:(UIInterfaceOrientationMask)new_preferences; - (void)handlePressEvent:(FlutterUIPressProxy*)press @@ -161,7 +161,7 @@ - (void)tearDown { self.messageSent = nil; } -- (void)testViewDidLoadWillInvokeSetupTouchRateCorrectionVSyncClient { +- (void)testViewDidLoadWillInvokeCreateTouchRateCorrectionVSyncClient { FlutterEngine* engine = [[FlutterEngine alloc] init]; [engine runWithEntrypoint:nil]; FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engine @@ -170,7 +170,7 @@ - (void)testViewDidLoadWillInvokeSetupTouchRateCorrectionVSyncClient { FlutterViewController* viewControllerMock = OCMPartialMock(viewController); [viewControllerMock loadView]; [viewControllerMock viewDidLoad]; - OCMVerify([viewControllerMock setupTouchRateCorrectionVSyncClient]); + OCMVerify([viewControllerMock createTouchRateCorrectionVSyncClientIfNeeded]); } - (void)testStartKeyboardAnimationWillInvokeSetupKeyboardAnimationVsyncClient { diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest_mrc.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest_mrc.mm index 50677e9b7c828..fdc243c784d58 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest_mrc.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest_mrc.mm @@ -30,7 +30,7 @@ @interface FlutterViewController (Testing) @property(nonatomic, retain) VSyncClient* touchRateCorrectionVSyncClient; -- (void)setupTouchRateCorrectionVSyncClient; +- (void)createTouchRateCorrectionVSyncClientIfNeeded; - (void)setupKeyboardAnimationVsyncClient; - (void)triggerTouchRateCorrectionIfNeeded:(NSSet*)touches; @@ -67,7 +67,7 @@ - (void)testSetupKeyboardAnimationVsyncClientWillCreateNewVsyncClientForFlutterV } - (void) - testSetupTouchRateCorrectionVSyncClientWillCreateVsyncClientWhenRefreshRateIsLargerThan60HZ { + testCreateTouchRateCorrectionVSyncClientWillCreateVsyncClientWhenRefreshRateIsLargerThan60HZ { id mockDisplayLinkManager = [OCMockObject mockForClass:[DisplayLinkManager class]]; double maxFrameRate = 120; [[[mockDisplayLinkManager stub] andReturnValue:@(maxFrameRate)] displayRefreshRate]; @@ -76,11 +76,11 @@ - (void)testSetupKeyboardAnimationVsyncClientWillCreateNewVsyncClientForFlutterV FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engine nibName:nil bundle:nil]; - [viewController setupTouchRateCorrectionVSyncClient]; + [viewController createTouchRateCorrectionVSyncClientIfNeeded]; XCTAssertNotNil(viewController.touchRateCorrectionVSyncClient); } -- (void)testSetupTouchRateCorrectionVSyncClientWillCreateVsyncClientWhenRefreshRateIs60HZ { +- (void)testCreateTouchRateCorrectionVSyncClientWillCreateVsyncClientWhenRefreshRateIs60HZ { id mockDisplayLinkManager = [OCMockObject mockForClass:[DisplayLinkManager class]]; double maxFrameRate = 60; [[[mockDisplayLinkManager stub] andReturnValue:@(maxFrameRate)] displayRefreshRate]; @@ -89,7 +89,7 @@ - (void)testSetupTouchRateCorrectionVSyncClientWillCreateVsyncClientWhenRefreshR FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engine nibName:nil bundle:nil]; - [viewController setupTouchRateCorrectionVSyncClient]; + [viewController createTouchRateCorrectionVSyncClientIfNeeded]; XCTAssertNil(viewController.touchRateCorrectionVSyncClient); } From ba09d7c29f1bef887466e2fb3eb3c7420087304f Mon Sep 17 00:00:00 2001 From: luckysmg <2539699336@qq.com> Date: Sat, 20 Aug 2022 20:41:20 +0800 Subject: [PATCH 05/10] Modify test --- .../ios/framework/Source/FlutterViewControllerTest_mrc.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest_mrc.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest_mrc.mm index fdc243c784d58..0798677abdc72 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest_mrc.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest_mrc.mm @@ -80,7 +80,7 @@ - (void)testSetupKeyboardAnimationVsyncClientWillCreateNewVsyncClientForFlutterV XCTAssertNotNil(viewController.touchRateCorrectionVSyncClient); } -- (void)testCreateTouchRateCorrectionVSyncClientWillCreateVsyncClientWhenRefreshRateIs60HZ { +- (void)testCreateTouchRateCorrectionVSyncClientWillNotCreateVsyncClientWhenRefreshRateIs60HZ { id mockDisplayLinkManager = [OCMockObject mockForClass:[DisplayLinkManager class]]; double maxFrameRate = 60; [[[mockDisplayLinkManager stub] andReturnValue:@(maxFrameRate)] displayRefreshRate]; From 47abf4ee637bf654c7f16de629cc99c6af477324 Mon Sep 17 00:00:00 2001 From: luckysmg <2539699336@qq.com> Date: Tue, 23 Aug 2022 11:21:32 +0800 Subject: [PATCH 06/10] nits --- .../darwin/ios/framework/Source/FlutterViewController.mm | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm index 8db6608788137..3eea6cc9f879d 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm @@ -1127,7 +1127,10 @@ - (void)createTouchRateCorrectionVSyncClientIfNeeded { NSAssert(_touchRateCorrectionVSyncClient == nil, @"_touchRateCorrectionVSyncClient should be nil when setup it"); double displayRefreshRate = [DisplayLinkManager displayRefreshRate]; - if (displayRefreshRate <= 60) { + const double normalRefreshRate = 60.0; + const double epsilon = 0.1; + if (displayRefreshRate < normalRefreshRate || + fabs(displayRefreshRate - normalRefreshRate) < epsilon) { // If current device's max frame rate is not larger than 60HZ, the delivery rate of touch events // is the same with render vsync rate. So we don't need to create // _touchRateCorrectionVSyncClient to correct touch callback's rate. From c6b77a9564d97e90a763b393e3a5384aeb398d24 Mon Sep 17 00:00:00 2001 From: luckysmg <2539699336@qq.com> Date: Fri, 26 Aug 2022 10:43:46 +0800 Subject: [PATCH 07/10] nits --- .../framework/Source/FlutterViewController.mm | 11 +++++----- .../Source/FlutterViewControllerTest_mrc.mm | 21 +++++++++++++++++++ 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm index 3eea6cc9f879d..86e4b0c3b2b6d 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm @@ -1124,13 +1124,14 @@ - (void)forceTouchesCancelled:(NSSet*)touches { #pragma mark - Touch events rate correction - (void)createTouchRateCorrectionVSyncClientIfNeeded { - NSAssert(_touchRateCorrectionVSyncClient == nil, - @"_touchRateCorrectionVSyncClient should be nil when setup it"); + if (_touchRateCorrectionVSyncClient != nil) { + return; + } + double displayRefreshRate = [DisplayLinkManager displayRefreshRate]; - const double normalRefreshRate = 60.0; const double epsilon = 0.1; - if (displayRefreshRate < normalRefreshRate || - fabs(displayRefreshRate - normalRefreshRate) < epsilon) { + if (displayRefreshRate < 60.0 + epsilon) { // displayRefreshRate <= 60.0 + // If current device's max frame rate is not larger than 60HZ, the delivery rate of touch events // is the same with render vsync rate. So we don't need to create // _touchRateCorrectionVSyncClient to correct touch callback's rate. diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest_mrc.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest_mrc.mm index 0798677abdc72..e18b0b55c9335 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest_mrc.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest_mrc.mm @@ -80,6 +80,27 @@ - (void)testSetupKeyboardAnimationVsyncClientWillCreateNewVsyncClientForFlutterV XCTAssertNotNil(viewController.touchRateCorrectionVSyncClient); } +- (void)testCreateTouchRateCorrectionVSyncClientWillNotCreateNewVSyncClientWhenClientAlreadyExists { + id mockDisplayLinkManager = [OCMockObject mockForClass:[DisplayLinkManager class]]; + double maxFrameRate = 120; + [[[mockDisplayLinkManager stub] andReturnValue:@(maxFrameRate)] displayRefreshRate]; + + FlutterEngine* engine = [[FlutterEngine alloc] init]; + [engine runWithEntrypoint:nil]; + FlutterViewController* viewController = [[FlutterViewController alloc] initWithEngine:engine + nibName:nil + bundle:nil]; + [viewController createTouchRateCorrectionVSyncClientIfNeeded]; + VSyncClient* clientBefore = viewController.touchRateCorrectionVSyncClient; + XCTAssertNotNil(clientBefore); + + [viewController createTouchRateCorrectionVSyncClientIfNeeded]; + VSyncClient* clientAfter = viewController.touchRateCorrectionVSyncClient; + XCTAssertNotNil(clientAfter); + + XCTAssertTrue(clientBefore == clientAfter); +} + - (void)testCreateTouchRateCorrectionVSyncClientWillNotCreateVsyncClientWhenRefreshRateIs60HZ { id mockDisplayLinkManager = [OCMockObject mockForClass:[DisplayLinkManager class]]; double maxFrameRate = 60; From 4bf7f3f3876694f9873556f024bee8f202b48681 Mon Sep 17 00:00:00 2001 From: luckysmg <2539699336@qq.com> Date: Sat, 27 Aug 2022 10:37:47 +0800 Subject: [PATCH 08/10] nits --- .../ios/framework/Source/FlutterViewController.mm | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm index 86e4b0c3b2b6d..d40569d53555e 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm @@ -65,7 +65,12 @@ @interface FlutterViewController () Date: Wed, 31 Aug 2022 09:41:14 +0800 Subject: [PATCH 09/10] nits --- .../darwin/ios/framework/Source/FlutterViewController.mm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm index d40569d53555e..80894a02affb7 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm @@ -69,7 +69,7 @@ @interface FlutterViewController () Date: Thu, 8 Sep 2022 00:15:30 +0800 Subject: [PATCH 10/10] nits --- .../darwin/ios/framework/Source/FlutterViewController.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm index 80894a02affb7..3e1a4359d98c5 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm @@ -68,7 +68,7 @@ @interface FlutterViewController ()