Changeset 207153 in webkit
- Timestamp:
- Oct 11, 2016 11:38:49 AM (8 years ago)
- Location:
- trunk
- Files:
-
- 3 added
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Tools/ChangeLog
r207152 r207153 1 2016-10-11 Megan Gardner <megan_gardner@apple.com> 2 3 Extend event stream to include interpolated events and add a force press test that uses that interpolation 4 https://bugs.webkit.org/show_bug.cgi?id=163161 5 6 Reviewed by Simon Fraser. 7 8 Added functionality to the event stream to allow for interpolated events. 9 Can now do long press, as well as a better way to do drag and other time-based 10 events that require a large stream of descrete HID events. 11 Added a basic force touch test to demostrate this interpolation. 12 Also updated the script to allow for iPhone 7 specific tests, as force touch 13 needs to be on a device that had force touch. 14 15 * Scripts/webkitpy/port/ios.py: 16 (IOSSimulatorPort): 17 * TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl: 18 * WebKitTestRunner/ios/HIDEventGenerator.mm: 19 (linearInterpolation): 20 (simpleCurveInterpolation): 21 (calculateNextCurveLocation): 22 (phaseFromString): 23 (interpolationFromString): 24 (-[HIDEventGenerator eventMaskFromEventInfo:]): 25 (-[HIDEventGenerator _createIOHIDEventWithInfo:]): 26 (-[HIDEventGenerator moveToPoints:touchCount:duration:]): 27 (-[HIDEventGenerator interpolatedEvents:]): 28 (-[HIDEventGenerator processEventsArray:withStartTime:]): 29 (-[HIDEventGenerator eventDispatchThreadEntry:]): 30 (simpleDragCurve): Deleted. 31 (calculateNextLocation): Deleted. 32 1 33 2016-10-11 Alex Christensen <achristensen@webkit.org> 2 34 -
trunk/Tools/Scripts/webkitpy/port/ios.py
r206940 r207153 75 75 76 76 DEFAULT_DEVICE_CLASS = 'iphone' 77 CUSTOM_DEVICE_CLASSES = ['ipad' ]77 CUSTOM_DEVICE_CLASSES = ['ipad', 'iphone7'] 78 78 SDK = 'iphonesimulator' 79 79 … … 87 87 'x86_64': { 88 88 'iphone': 'iPhone 5s', 89 'iphone7': 'iPhone 7', 89 90 'ipad': 'iPad Air' 90 91 }, -
trunk/Tools/TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl
r206798 r207153 68 68 // }, 69 69 // { 70 // "interpolate" : "linear", 71 // "timestep" : 0.025, 72 // "startEvent" : { 73 // "inputType" : "hand", 74 // "timeOffset" : 0.025, 75 // "touches" : [ 76 // { 77 // "inputType" : "finger", 78 // "phase" : "began", 79 // "id" : 1, 80 // "x" : 100, 81 // "y" : 120, 82 // "pressure" : 0 83 // } 84 // ] 85 // }, 86 // "endEvent" : { 87 // "inputType" : "hand", 88 // "timeOffset" : 3.0, 89 // "touches" : [ 90 // { 91 // "inputType" : "finger", 92 // "phase" : "stationary", 93 // "id" : 1, 94 // "x" : 20, 95 // "y" : 40, 96 // "pressure" : 500 97 // } 98 // ] 99 // } 100 // }, 101 // { 70 102 // "inputType" : "hand", 71 103 // "timeOffset" : 0.002, // seconds relative to the first event -
trunk/Tools/WebKitTestRunner/ios/HIDEventGenerator.mm
r206798 r207153 43 43 NSString* const HIDEventTouchesKey = @"touches"; 44 44 NSString* const HIDEventPhaseKey = @"phase"; 45 NSString* const HIDEventInterpolateKey = @"interpolate"; 46 NSString* const HIDEventTimestepKey = @"timestep"; 47 NSString* const HIDEventStartEventKey = @"startEvent"; 48 NSString* const HIDEventEndEventKey = @"endEvent"; 45 49 NSString* const HIDEventTouchIDKey = @"id"; 46 50 NSString* const HIDEventPressureKey = @"pressure"; … … 55 59 NSString* const HIDEventInputTypeStylus = @"stylus"; 56 60 61 NSString* const HIDEventInterpolationTypeLinear = @"linear"; 62 NSString* const HIDEventInterpolationTypeSimpleCurve = @"simpleCurve"; 63 57 64 NSString* const HIDEventPhaseBegan = @"began"; 65 NSString* const HIDEventPhaseStationary = @"stationary"; 58 66 NSString* const HIDEventPhaseMoved = @"moved"; 59 67 NSString* const HIDEventPhaseEnded = @"ended"; … … 70 78 71 79 static int fingerIdentifiers[maxTouchCount] = { 2, 3, 4, 5, 1 }; 80 81 typedef enum { 82 InterpolationTypeLinear, 83 InterpolationTypeSimpleCurve, 84 } InterpolationType; 72 85 73 86 typedef enum { … … 99 112 } 100 113 101 static double simpleDragCurve(double a, double b, double t) 114 static double linearInterpolation(double a, double b, double t) 115 { 116 return (a + (b - a) * t ); 117 } 118 119 static double simpleCurveInterpolation(double a, double b, double t) 102 120 { 103 121 return (a + (b - a) * sin(sin(t * M_PI / 2) * t * M_PI / 2)); 104 122 } 105 123 106 static CGPoint calculateNextLocation(CGPoint a, CGPoint b, CFTimeInterval t) 107 { 108 return CGPointMake(simpleDragCurve(a.x, b.x, t), simpleDragCurve(a.y, b.y, t)); 109 } 124 125 static CGPoint calculateNextCurveLocation(CGPoint a, CGPoint b, CFTimeInterval t) 126 { 127 return CGPointMake(simpleCurveInterpolation(a.x, b.x, t), simpleCurveInterpolation(a.y, b.y, t)); 128 } 129 130 typedef double(*pressureInterpolationFunction)(double, double, CFTimeInterval); 131 static pressureInterpolationFunction interpolations[] = { 132 linearInterpolation, 133 simpleCurveInterpolation, 134 }; 110 135 111 136 static void delayBetweenMove(int eventIndex, double elapsed) … … 188 213 if ([string isEqualToString:HIDEventPhaseBegan]) 189 214 return UITouchPhaseBegan; 215 216 if ([string isEqualToString:HIDEventPhaseStationary]) 217 return UITouchPhaseStationary; 190 218 191 219 if ([string isEqualToString:HIDEventPhaseMoved]) … … 201 229 } 202 230 231 static InterpolationType interpolationFromString(NSString *string) 232 { 233 if ([string isEqualToString:HIDEventInterpolationTypeLinear]) 234 return InterpolationTypeLinear; 235 236 if ([string isEqualToString:HIDEventInterpolationTypeSimpleCurve]) 237 return InterpolationTypeSimpleCurve; 238 239 return InterpolationTypeLinear; 240 } 241 203 242 - (IOHIDDigitizerEventMask)eventMaskFromEventInfo:(NSDictionary *)info 204 243 { 244 IOHIDDigitizerEventMask eventMask = 0; 205 245 NSArray *childEvents = info[HIDEventTouchesKey]; 206 246 for (NSDictionary *touchInfo in childEvents) { … … 208 248 // If there are any new or ended events, mask includes touch. 209 249 if (phase == UITouchPhaseBegan || phase == UITouchPhaseEnded || phase == UITouchPhaseCancelled) 210 return kIOHIDDigitizerEventTouch; 211 } 212 213 return 0; 214 } 215 216 // Returns 1 for all events where the fingers are on the glass (everything but enced and canceled). 250 eventMask |= kIOHIDDigitizerEventTouch; 251 // If there are any pressure readings, set mask must include attribute 252 if ([touchInfo[HIDEventPressureKey] floatValue]) 253 eventMask |= kIOHIDDigitizerEventAttribute; 254 } 255 256 return eventMask; 257 } 258 259 // Returns 1 for all events where the fingers are on the glass (everything but ended and canceled). 217 260 - (CFIndex)touchFromEventInfo:(NSDictionary *)info 218 261 { … … 261 304 262 305 UITouchPhase phase = phaseFromString(touchInfo[HIDEventPhaseKey]); 263 if (phase != UITouchPhaseCancelled && phase != UITouchPhaseBegan && phase != UITouchPhaseEnded )306 if (phase != UITouchPhaseCancelled && phase != UITouchPhaseBegan && phase != UITouchPhaseEnded && phase != UITouchPhaseStationary) 264 307 childEventMask |= kIOHIDDigitizerEventPosition; 265 308 … … 269 312 if (phase == UITouchPhaseCancelled) 270 313 childEventMask |= kIOHIDDigitizerEventCancel; 314 315 if ([touchInfo[HIDEventPressureKey] floatValue]) 316 childEventMask |= kIOHIDDigitizerEventAttribute; 271 317 272 318 IOHIDEventRef subEvent = IOHIDEventCreateDigitizerFingerEvent(kCFAllocatorDefault, machTime, … … 552 598 startLocations[i] = _activePoints[i].point; 553 599 554 nextLocations[i] = calculateNext Location(startLocations[i], newLocations[i], interval);600 nextLocations[i] = calculateNextCurveLocation(startLocations[i], newLocations[i], interval); 555 601 } 556 602 [self _updateTouchPoints:nextLocations count:touchCount]; … … 921 967 } 922 968 969 - (NSArray *)interpolatedEvents:(NSDictionary *)interpolationsDictionary 970 { 971 NSDictionary *startEvent = interpolationsDictionary[HIDEventStartEventKey]; 972 NSDictionary *endEvent = interpolationsDictionary[HIDEventEndEventKey]; 973 NSTimeInterval timeStep = [interpolationsDictionary[HIDEventTimestepKey] doubleValue]; 974 InterpolationType interpolationType = interpolationFromString(interpolationsDictionary[HIDEventInterpolateKey]); 975 976 NSMutableArray *interpolatedEvents = [NSMutableArray arrayWithObject:startEvent]; 977 978 NSTimeInterval startTime = [startEvent[HIDEventTimeOffsetKey] doubleValue]; 979 NSTimeInterval endTime = [endEvent[HIDEventTimeOffsetKey] doubleValue]; 980 NSTimeInterval time = startTime + timeStep; 981 982 NSArray *startTouches = startEvent[HIDEventTouchesKey]; 983 NSArray *endTouches = endEvent[HIDEventTouchesKey]; 984 985 while (time < endTime) { 986 NSMutableDictionary *newEvent = [endEvent mutableCopy]; 987 double timeRatio = (time - startTime) / (endTime - startTime); 988 newEvent[HIDEventTimeOffsetKey] = [NSNumber numberWithDouble:(time)]; 989 990 NSEnumerator *startEnumerator = [startTouches objectEnumerator]; 991 NSDictionary *startTouch; 992 NSMutableArray *newTouches = [NSMutableArray arrayWithCapacity:[endTouches count]]; 993 while (startTouch = [startEnumerator nextObject]) { 994 NSEnumerator *endEnumerator = [endTouches objectEnumerator]; 995 NSDictionary *endTouch = [endEnumerator nextObject]; 996 NSInteger startTouchID = [startTouch[HIDEventTouchIDKey] integerValue]; 997 998 while (endTouch && ([endTouch[HIDEventTouchIDKey] integerValue] != startTouchID)) 999 endTouch = [endEnumerator nextObject]; 1000 1001 if (endTouch) { 1002 NSMutableDictionary *newTouch = [endTouch mutableCopy]; 1003 1004 if (newTouch[HIDEventXKey] != startTouch[HIDEventXKey]) 1005 newTouch[HIDEventXKey] = @(interpolations[interpolationType]([startTouch[HIDEventXKey] doubleValue], [endTouch[HIDEventXKey] doubleValue], timeRatio)); 1006 1007 if (newTouch[HIDEventYKey] != startTouch[HIDEventYKey]) 1008 newTouch[HIDEventYKey] = @(interpolations[interpolationType]([startTouch[HIDEventYKey] doubleValue], [endTouch[HIDEventYKey] doubleValue], timeRatio)); 1009 1010 if (newTouch[HIDEventPressureKey] != startTouch[HIDEventPressureKey]) 1011 newTouch[HIDEventPressureKey] = @(interpolations[interpolationType]([startTouch[HIDEventPressureKey] doubleValue], [endTouch[HIDEventPressureKey] doubleValue], timeRatio)); 1012 1013 [newTouches addObject:newTouch]; 1014 [newTouch release]; 1015 } else 1016 NSLog(@"Missing End Touch with ID: %ld", (long)startTouchID); 1017 } 1018 1019 newEvent[HIDEventTouchesKey] = newTouches; 1020 1021 [interpolatedEvents addObject:newEvent]; 1022 [newEvent release]; 1023 time += timeStep; 1024 } 1025 1026 return interpolatedEvents; 1027 } 1028 1029 - (NSArray *)expandEvents:(NSArray *)events withStartTime:(CFAbsoluteTime)startTime 1030 { 1031 NSMutableArray *expandedEvents = [NSMutableArray array]; 1032 for (NSDictionary *event in events) { 1033 NSString *interpolate = event[HIDEventInterpolateKey]; 1034 // we have key events that we need to generate 1035 if (interpolate) { 1036 NSArray *newEvents = [self interpolatedEvents:event]; 1037 [expandedEvents addObjectsFromArray:[self expandEvents:newEvents withStartTime:startTime]]; 1038 } else 1039 [expandedEvents addObject:event]; 1040 } 1041 return expandedEvents; 1042 } 1043 923 1044 - (void)eventDispatchThreadEntry:(NSDictionary *)threadData 924 1045 { 925 1046 NSDictionary *eventStream = threadData[@"eventInfo"]; 926 1047 void (^completionBlock)() = threadData[@"completionBlock"]; 927 1048 928 1049 NSArray *events = eventStream[TopLevelEventInfoKey]; 929 1050 if (!events.count) { … … 931 1052 return; 932 1053 } 933 1054 934 1055 CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent(); 935 1056 936 for (NSDictionary *eventInfo in events) { 1057 NSArray *expandedEvents = [self expandEvents:events withStartTime:startTime]; 1058 1059 for (NSDictionary *eventInfo in expandedEvents) { 937 1060 NSTimeInterval eventRelativeTime = [eventInfo[HIDEventTimeOffsetKey] doubleValue]; 938 1061 CFAbsoluteTime targetTime = startTime + eventRelativeTime; … … 941 1064 if (waitTime > 0) 942 1065 [NSThread sleepForTimeInterval:waitTime]; 943 1066 944 1067 dispatch_async(dispatch_get_main_queue(), ^ { 945 1068 [self dispatchEventWithInfo:eventInfo]; 946 1069 }); 947 1070 } 948 1071 949 1072 dispatch_async(dispatch_get_main_queue(), ^ { 950 1073 [self _sendMarkerHIDEventWithCompletionBlock:completionBlock];
Note: See TracChangeset
for help on using the changeset viewer.