Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Next Next commit
Add code in FlutterViewController and VSyncClient
  • Loading branch information
luckysmg committed Aug 19, 2022
commit 1b1b2d7c78b30237646bfb37633363bc277bf343
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ @interface FlutterViewController () <FlutterBinaryMessenger, UIScrollViewDelegat
@property(nonatomic, assign) double targetViewInsetBottom;
@property(nonatomic, retain) VSyncClient* keyboardAnimationVSyncClient;

/// VSyncClient for touch callback's rate correction.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nits:

Suggested change
/// VSyncClient for touch callback's rate correction.
/// VSyncClient for touch callback's frame rate correction.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe also add a short explanation about why this is needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@property(nonatomic, retain) VSyncClient* touchRateCorrectionVSyncClient;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is VSyncClient necessary here? Since this is just for increasing resolution of touch events and doesn't directly affect rendering, should we just use CADisplayLink directly?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using VSyncClient ensures the preferred frame rate that used is the same as the one used on UIThread.


/*
* Mouse and trackpad gesture recognizers
*/
Expand Down Expand Up @@ -671,6 +674,9 @@ - (void)viewDidLoad {
// Register internal plugins.
[self addInternalPlugins];

// Setup vsync client to correct touch rate.
[self setupTouchRateCorrectionVSyncClient];

if (@available(iOS 13.4, *)) {
_hoverGestureRecognizer =
[[UIHoverGestureRecognizer alloc] initWithTarget:self action:@selector(hoverEvent:)];
Expand Down Expand Up @@ -833,6 +839,7 @@ - (void)dealloc {
[self deregisterNotifications];

[self invalidateKeyboardAnimationVSyncClient];
[self invalidateTouchRateCorrectionVSyncClient];
_scrollView.get().delegate = nil;
_hoverGestureRecognizer.delegate = nil;
[_hoverGestureRecognizer release];
Expand Down Expand Up @@ -966,6 +973,9 @@ - (void)dispatchTouches:(NSSet*)touches
}
}

// Activate or pause touch rate correction according to the touches when user is interacting.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"touch rate" is a little ambiguous. maybe "frame rate during touch events"?

Copy link
Contributor Author

@luckysmg luckysmg Aug 27, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have changed it to delivery frame rate of touch events, which seems to be more accurate.😄

[self triggerTouchRateCorrectionIfNeeded:touches];

const CGFloat scale = [UIScreen mainScreen].scale;
auto packet =
std::make_unique<flutter::PointerDataPacket>(touches.count + touches_to_remove_count);
Expand Down Expand Up @@ -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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not use we in comments.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done^_^

// _touchRateCorrectionVSyncClient to correct touch callback's rate.
return;
}

flutter::Shell& shell = [_engine.get() shell];
auto callback = [](std::unique_ptr<flutter::FrameTimingsRecorder> 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.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We in comments.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done^_^

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 {
Expand Down
2 changes: 2 additions & 0 deletions shell/platform/darwin/ios/framework/Source/vsync_waiter_ios.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@

- (void)await;

- (void)pause;

- (void)invalidate;

- (double)getRefreshRate;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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");

Expand Down