Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 56187fa

Browse files
authored
Fix timestamp of touch events should use system startup time (#30422)
1 parent bbebccd commit 56187fa

File tree

2 files changed

+28
-10
lines changed

2 files changed

+28
-10
lines changed

shell/platform/darwin/ios/framework/Source/FlutterViewController.mm

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -421,16 +421,24 @@ - (void)loadView {
421421
_scrollView.reset(scrollView);
422422
}
423423

424+
- (flutter::PointerData)generatePointerDataForFake {
425+
flutter::PointerData pointer_data;
426+
pointer_data.Clear();
427+
pointer_data.kind = flutter::PointerData::DeviceKind::kTouch;
428+
// `UITouch.timestamp` is defined as seconds since system startup. Synthesized events can get this
429+
// time with `NSProcessInfo.systemUptime`. See
430+
// https://developer.apple.com/documentation/uikit/uitouch/1618144-timestamp?language=objc
431+
pointer_data.time_stamp = [[NSProcessInfo processInfo] systemUptime] * kMicrosecondsPerSecond;
432+
return pointer_data;
433+
}
434+
424435
static void SendFakeTouchEvent(FlutterEngine* engine,
425436
CGPoint location,
426437
flutter::PointerData::Change change) {
427438
const CGFloat scale = [UIScreen mainScreen].scale;
428-
flutter::PointerData pointer_data;
429-
pointer_data.Clear();
439+
flutter::PointerData pointer_data = [[engine viewController] generatePointerDataForFake];
430440
pointer_data.physical_x = location.x * scale;
431441
pointer_data.physical_y = location.y * scale;
432-
pointer_data.kind = flutter::PointerData::DeviceKind::kTouch;
433-
pointer_data.time_stamp = [[NSDate date] timeIntervalSince1970] * kMicrosecondsPerSecond;
434442
auto packet = std::make_unique<flutter::PointerDataPacket>(/*count=*/1);
435443
pointer_data.change = change;
436444
packet->SetPointerData(0, pointer_data);
@@ -759,14 +767,9 @@ - (void)flushOngoingTouches {
759767
// touches to the framework so nothing gets orphaned.
760768
for (NSNumber* device in _ongoingTouches.get()) {
761769
// Create fake PointerData to balance out each previously started one for the framework.
762-
flutter::PointerData pointer_data;
763-
pointer_data.Clear();
764-
765-
// Use current time.
766-
pointer_data.time_stamp = [[NSDate date] timeIntervalSince1970] * kMicrosecondsPerSecond;
770+
flutter::PointerData pointer_data = [self generatePointerDataForFake];
767771

768772
pointer_data.change = flutter::PointerData::Change::kCancel;
769-
pointer_data.kind = flutter::PointerData::DeviceKind::kTouch;
770773
pointer_data.device = device.longLongValue;
771774
pointer_data.pointer_identifier = 0;
772775

shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include "flutter/fml/platform/darwin/message_loop_darwin.h"
99
#import "flutter/lib/ui/window/platform_configuration.h"
10+
#include "flutter/lib/ui/window/pointer_data.h"
1011
#import "flutter/lib/ui/window/viewport_metrics.h"
1112
#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterBinaryMessenger.h"
1213
#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterMacros.h"
@@ -138,6 +139,7 @@ - (void)startKeyBoardAnimation:(NSTimeInterval)duration;
138139
- (void)ensureViewportMetricsIsCorrect;
139140
- (void)invalidateDisplayLink;
140141
- (void)addInternalPlugins;
142+
- (flutter::PointerData)generatePointerDataForFake;
141143
@end
142144

143145
@interface FlutterViewControllerTest : XCTestCase
@@ -1092,4 +1094,17 @@ - (void)testMouseSupport API_AVAILABLE(ios(13.4)) {
10921094
dispatchPointerDataPacket:std::make_unique<flutter::PointerDataPacket>(0)];
10931095
}
10941096

1097+
- (void)testFakeEventTimeStamp {
1098+
FlutterViewController* vc = [[FlutterViewController alloc] initWithEngine:self.mockEngine
1099+
nibName:nil
1100+
bundle:nil];
1101+
XCTAssertNotNil(vc);
1102+
1103+
flutter::PointerData pointer_data = [vc generatePointerDataForFake];
1104+
int64_t current_micros = [[NSProcessInfo processInfo] systemUptime] * 1000 * 1000;
1105+
int64_t interval_micros = current_micros - pointer_data.time_stamp;
1106+
const int64_t tolerance_millis = 2;
1107+
XCTAssertTrue(interval_micros / 1000 < tolerance_millis,
1108+
@"PointerData.time_stamp should be equal to NSProcessInfo.systemUptime");
1109+
}
10951110
@end

0 commit comments

Comments
 (0)