From a442c637da6a7fc4ae4d49e56156ecf7454311ae Mon Sep 17 00:00:00 2001 From: KyleWong Date: Mon, 3 Sep 2018 17:42:49 +0800 Subject: [PATCH 1/2] Fix a gesture failure problem cause by that "touchesBegan&touchesEnded/Cancelled can't always be called in paris". --- .../framework/Source/FlutterViewController.mm | 79 ++++++++++++++++--- .../framework/Source/flutter_touch_mapper.mm | 9 +++ 2 files changed, 77 insertions(+), 11 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm index 2fb9f90c6f281..8a69b839ab5c7 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm @@ -21,8 +21,13 @@ #include "flutter/shell/platform/darwin/ios/framework/Source/platform_message_response_darwin.h" #include "flutter/shell/platform/darwin/ios/platform_view_ios.h" +static double kTouchTrackerCheckInterval = 1.f; + @interface FlutterViewController () @property(nonatomic, readonly) NSMutableDictionary* pluginPublications; +@property(nonatomic,retain) NSMutableSet *touchTrackerSet; +@property(nonatomic,retain) NSMutableDictionary *touchTrackerDict; + @end @interface FlutterViewControllerRegistrar : NSObject @@ -69,6 +74,9 @@ - (instancetype)initWithProject:(FlutterDartProject*)projectOrNil _dartProject.reset([[FlutterDartProject alloc] init]); else _dartProject.reset([projectOrNil retain]); + + _touchTrackerSet = [[NSMutableSet set] retain]; + _touchTrackerDict = [[NSMutableDictionary dictionary] retain]; [self performCommonViewControllerInitialization]; } @@ -476,6 +484,9 @@ - (void)viewDidDisappear:(BOOL)animated { - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; [_pluginPublications release]; + [_touchTrackerSet release]; + [_touchTrackerDict release]; + [super dealloc]; } @@ -547,12 +558,13 @@ static inline PointerChangeMapperPhase PointerChangePhaseFromUITouchPhase(UITouc return blink::PointerData::DeviceKind::kTouch; } -- (void)dispatchTouches:(NSSet*)touches phase:(UITouchPhase)phase { +- (void)dispatchTouches:(NSSet*)touches phase:(UITouchPhase)phase trackTouches:(BOOL)bTrack{ // Note: we cannot rely on touch.phase, since in some cases, e.g., // handleStatusBarTouches, we synthesize touches from existing events. // // TODO(cbracken) consider creating out own class with the touch fields we // need. + NSTimeInterval tsNow = [[NSDate date] timeIntervalSinceReferenceDate]; auto eventTypePhase = PointerChangePhaseFromUITouchPhase(phase); const CGFloat scale = [UIScreen mainScreen].scale; auto packet = std::make_unique(touches.count); @@ -560,17 +572,37 @@ - (void)dispatchTouches:(NSSet*)touches phase:(UITouchPhase)phase { int i = 0; for (UITouch* touch in touches) { int device_id = 0; - + NSValue *key = [NSValue valueWithPointer:(void*)touch]; + switch (eventTypePhase.second) { - case Accessed: + case Accessed:{ device_id = _touchMapper.identifierOf(touch); + if(bTrack){ + [self.touchTrackerSet addObject:touch]; + self.touchTrackerDict[key]=@(tsNow+kTouchTrackerCheckInterval); + } break; - case Added: + } + case Added:{ device_id = _touchMapper.registerTouch(touch); + if(bTrack){ + [self.touchTrackerSet addObject:touch]; + self.touchTrackerDict[key]=@(tsNow+kTouchTrackerCheckInterval); + } break; - case Removed: + } + case Removed:{ device_id = _touchMapper.unregisterTouch(touch); + if(bTrack){ + [self.touchTrackerDict removeObjectForKey:key]; + [self.touchTrackerSet removeObject:touch]; + } break; + } + } + + if(device_id == 0){ + continue; } FML_DCHECK(device_id != 0); @@ -656,19 +688,44 @@ - (void)dispatchTouches:(NSSet*)touches phase:(UITouchPhase)phase { } - (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event { - [self dispatchTouches:touches phase:UITouchPhaseBegan]; + [self dispatchTouches:touches phase:UITouchPhaseBegan trackTouches:TRUE]; + [self checkIfCompleteTouches]; } - (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event { - [self dispatchTouches:touches phase:UITouchPhaseMoved]; + [self dispatchTouches:touches phase:UITouchPhaseMoved trackTouches:TRUE]; } - (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event { - [self dispatchTouches:touches phase:UITouchPhaseEnded]; + [self dispatchTouches:touches phase:UITouchPhaseEnded trackTouches:TRUE]; } - (void)touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event { - [self dispatchTouches:touches phase:UITouchPhaseCancelled]; + [self dispatchTouches:touches phase:UITouchPhaseCancelled trackTouches:TRUE]; +} + +- (BOOL)checkIfCompleteTouches{ + NSInteger cnt = self.touchTrackerSet.count; + if(cnt<=0) + return FALSE; + NSTimeInterval tsNow = [[NSDate date] timeIntervalSinceReferenceDate]; + NSSet *tmpTrackingTouches = [self.touchTrackerSet copy]; + NSMutableSet *set = [NSMutableSet set]; + for(UITouch *touch in tmpTrackingTouches){ + NSValue *key = [NSValue valueWithPointer:(void*)touch]; + NSNumber *expiredTime = [self.touchTrackerDict objectForKey:key]; + if(expiredTime.doubleValue<=tsNow){ + [set addObject:touch]; + [self.touchTrackerDict removeObjectForKey:key]; + [self.touchTrackerSet removeObject:touch]; + } + } + if(set.count>0){ + [self dispatchTouches:set phase:UITouchPhaseBegan trackTouches:FALSE]; + [self dispatchTouches:set phase:UITouchPhaseCancelled trackTouches:FALSE]; + return TRUE; + } + return FALSE; } #pragma mark - Handle view resizing @@ -973,8 +1030,8 @@ - (void)handleStatusBarTouches:(UIEvent*)event { CGPoint screenLoc = [touch.window convertPoint:windowLoc toWindow:nil]; if (CGRectContainsPoint(statusBarFrame, screenLoc)) { NSSet* statusbarTouches = [NSSet setWithObject:touch]; - [self dispatchTouches:statusbarTouches phase:UITouchPhaseBegan]; - [self dispatchTouches:statusbarTouches phase:UITouchPhaseEnded]; + [self dispatchTouches:statusbarTouches phase:UITouchPhaseBegan trackTouches:TRUE]; + [self dispatchTouches:statusbarTouches phase:UITouchPhaseEnded trackTouches:TRUE]; return; } } diff --git a/shell/platform/darwin/ios/framework/Source/flutter_touch_mapper.mm b/shell/platform/darwin/ios/framework/Source/flutter_touch_mapper.mm index b0a69b03acd47..989410bf16a5d 100644 --- a/shell/platform/darwin/ios/framework/Source/flutter_touch_mapper.mm +++ b/shell/platform/darwin/ios/framework/Source/flutter_touch_mapper.mm @@ -11,6 +11,9 @@ TouchMapper::~TouchMapper() = default; int TouchMapper::registerTouch(UITouch* touch) { + if(touch_map_.find(touch) != touch_map_.end()){ + return 0; + } int freeSpot = ffsll(free_spots_); touch_map_[touch] = freeSpot; free_spots_ &= ~(1 << (freeSpot - 1)); @@ -18,6 +21,9 @@ } int TouchMapper::unregisterTouch(UITouch* touch) { + if(touch_map_.find(touch) == touch_map_.end()){ + return 0; + } auto index = touch_map_[touch]; free_spots_ |= 1 << (index - 1); touch_map_.erase(touch); @@ -25,6 +31,9 @@ } int TouchMapper::identifierOf(UITouch* touch) const { + if(touch_map_.find(touch) == touch_map_.end()){ + return 0; + } return touch_map_.at(touch); } From ef52de11d85b37b9706eed6116c49f6479e91e84 Mon Sep 17 00:00:00 2001 From: KyleWong Date: Mon, 3 Sep 2018 22:45:06 +0800 Subject: [PATCH 2/2] Format files modified previously using flutter/ci/format.sh. --- .../framework/Source/FlutterViewController.mm | 84 +++++++++---------- .../framework/Source/flutter_touch_mapper.mm | 12 +-- 2 files changed, 48 insertions(+), 48 deletions(-) diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm index 8a69b839ab5c7..b64d2f7089928 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm @@ -25,8 +25,8 @@ @interface FlutterViewController () @property(nonatomic, readonly) NSMutableDictionary* pluginPublications; -@property(nonatomic,retain) NSMutableSet *touchTrackerSet; -@property(nonatomic,retain) NSMutableDictionary *touchTrackerDict; +@property(nonatomic, retain) NSMutableSet* touchTrackerSet; +@property(nonatomic, retain) NSMutableDictionary* touchTrackerDict; @end @@ -74,7 +74,7 @@ - (instancetype)initWithProject:(FlutterDartProject*)projectOrNil _dartProject.reset([[FlutterDartProject alloc] init]); else _dartProject.reset([projectOrNil retain]); - + _touchTrackerSet = [[NSMutableSet set] retain]; _touchTrackerDict = [[NSMutableDictionary dictionary] retain]; @@ -558,7 +558,7 @@ static inline PointerChangeMapperPhase PointerChangePhaseFromUITouchPhase(UITouc return blink::PointerData::DeviceKind::kTouch; } -- (void)dispatchTouches:(NSSet*)touches phase:(UITouchPhase)phase trackTouches:(BOOL)bTrack{ +- (void)dispatchTouches:(NSSet*)touches phase:(UITouchPhase)phase trackTouches:(BOOL)bTrack { // Note: we cannot rely on touch.phase, since in some cases, e.g., // handleStatusBarTouches, we synthesize touches from existing events. // @@ -572,37 +572,37 @@ - (void)dispatchTouches:(NSSet*)touches phase:(UITouchPhase)phase trackTouches:( int i = 0; for (UITouch* touch in touches) { int device_id = 0; - NSValue *key = [NSValue valueWithPointer:(void*)touch]; - + NSValue* key = [NSValue valueWithPointer:(void*)touch]; + switch (eventTypePhase.second) { - case Accessed:{ + case Accessed: { device_id = _touchMapper.identifierOf(touch); - if(bTrack){ - [self.touchTrackerSet addObject:touch]; - self.touchTrackerDict[key]=@(tsNow+kTouchTrackerCheckInterval); + if (bTrack) { + [self.touchTrackerSet addObject:touch]; + self.touchTrackerDict[key] = @(tsNow + kTouchTrackerCheckInterval); } break; } - case Added:{ + case Added: { device_id = _touchMapper.registerTouch(touch); - if(bTrack){ - [self.touchTrackerSet addObject:touch]; - self.touchTrackerDict[key]=@(tsNow+kTouchTrackerCheckInterval); + if (bTrack) { + [self.touchTrackerSet addObject:touch]; + self.touchTrackerDict[key] = @(tsNow + kTouchTrackerCheckInterval); } break; } - case Removed:{ + case Removed: { device_id = _touchMapper.unregisterTouch(touch); - if(bTrack){ - [self.touchTrackerDict removeObjectForKey:key]; - [self.touchTrackerSet removeObject:touch]; + if (bTrack) { + [self.touchTrackerDict removeObjectForKey:key]; + [self.touchTrackerSet removeObject:touch]; } break; } } - - if(device_id == 0){ - continue; + + if (device_id == 0) { + continue; } FML_DCHECK(device_id != 0); @@ -704,28 +704,28 @@ - (void)touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event { [self dispatchTouches:touches phase:UITouchPhaseCancelled trackTouches:TRUE]; } -- (BOOL)checkIfCompleteTouches{ - NSInteger cnt = self.touchTrackerSet.count; - if(cnt<=0) - return FALSE; - NSTimeInterval tsNow = [[NSDate date] timeIntervalSinceReferenceDate]; - NSSet *tmpTrackingTouches = [self.touchTrackerSet copy]; - NSMutableSet *set = [NSMutableSet set]; - for(UITouch *touch in tmpTrackingTouches){ - NSValue *key = [NSValue valueWithPointer:(void*)touch]; - NSNumber *expiredTime = [self.touchTrackerDict objectForKey:key]; - if(expiredTime.doubleValue<=tsNow){ - [set addObject:touch]; - [self.touchTrackerDict removeObjectForKey:key]; - [self.touchTrackerSet removeObject:touch]; - } - } - if(set.count>0){ - [self dispatchTouches:set phase:UITouchPhaseBegan trackTouches:FALSE]; - [self dispatchTouches:set phase:UITouchPhaseCancelled trackTouches:FALSE]; - return TRUE; - } +- (BOOL)checkIfCompleteTouches { + NSInteger cnt = self.touchTrackerSet.count; + if (cnt <= 0) return FALSE; + NSTimeInterval tsNow = [[NSDate date] timeIntervalSinceReferenceDate]; + NSSet* tmpTrackingTouches = [self.touchTrackerSet copy]; + NSMutableSet* set = [NSMutableSet set]; + for (UITouch* touch in tmpTrackingTouches) { + NSValue* key = [NSValue valueWithPointer:(void*)touch]; + NSNumber* expiredTime = [self.touchTrackerDict objectForKey:key]; + if (expiredTime.doubleValue <= tsNow) { + [set addObject:touch]; + [self.touchTrackerDict removeObjectForKey:key]; + [self.touchTrackerSet removeObject:touch]; + } + } + if (set.count > 0) { + [self dispatchTouches:set phase:UITouchPhaseBegan trackTouches:FALSE]; + [self dispatchTouches:set phase:UITouchPhaseCancelled trackTouches:FALSE]; + return TRUE; + } + return FALSE; } #pragma mark - Handle view resizing diff --git a/shell/platform/darwin/ios/framework/Source/flutter_touch_mapper.mm b/shell/platform/darwin/ios/framework/Source/flutter_touch_mapper.mm index 989410bf16a5d..cb76466ca0969 100644 --- a/shell/platform/darwin/ios/framework/Source/flutter_touch_mapper.mm +++ b/shell/platform/darwin/ios/framework/Source/flutter_touch_mapper.mm @@ -11,8 +11,8 @@ TouchMapper::~TouchMapper() = default; int TouchMapper::registerTouch(UITouch* touch) { - if(touch_map_.find(touch) != touch_map_.end()){ - return 0; + if (touch_map_.find(touch) != touch_map_.end()) { + return 0; } int freeSpot = ffsll(free_spots_); touch_map_[touch] = freeSpot; @@ -21,8 +21,8 @@ } int TouchMapper::unregisterTouch(UITouch* touch) { - if(touch_map_.find(touch) == touch_map_.end()){ - return 0; + if (touch_map_.find(touch) == touch_map_.end()) { + return 0; } auto index = touch_map_[touch]; free_spots_ |= 1 << (index - 1); @@ -31,8 +31,8 @@ } int TouchMapper::identifierOf(UITouch* touch) const { - if(touch_map_.find(touch) == touch_map_.end()){ - return 0; + if (touch_map_.find(touch) == touch_map_.end()) { + return 0; } return touch_map_.at(touch); }