Changeset 261480 in webkit
- Timestamp:
- May 11, 2020 9:22:56 AM (4 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r261477 r261480 1 2020-05-11 Wenson Hsieh <wenson_hsieh@apple.com> 2 3 REGRESSION (r253267): issues on touchstart/touchend/touchmove (pointerdown/pointerup/pointermove) events 4 https://bugs.webkit.org/show_bug.cgi?id=211521 5 <rdar://problem/62942374> 6 7 Reviewed by Darin Adler. 8 9 Add a layout test that synthesizes a tap-and-half gesture over an element with active touch event listeners, and 10 verifies that the second half of the gesture (i.e. the pan gesture) dispatches touchstart, touchmove, and 11 touchend events. 12 13 * fast/events/touch/ios/tap-and-half-when-viewport-is-not-responsive-expected.txt: Added. 14 * fast/events/touch/ios/tap-and-half-when-viewport-is-not-responsive.html: Added. 15 1 16 2020-05-11 Jason Lawrence <lawrence.j@apple.com> 2 17 -
trunk/Source/WebKit/ChangeLog
r261479 r261480 1 2020-05-11 Wenson Hsieh <wenson_hsieh@apple.com> 2 3 REGRESSION (r253267): issues on touchstart/touchend/touchmove (pointerdown/pointerup/pointermove) events 4 https://bugs.webkit.org/show_bug.cgi?id=211521 5 <rdar://problem/62942374> 6 7 Reviewed by Darin Adler. 8 9 As a brief refresher, deferring gesture recognizers allow us to handle otherwise blocking touch events 10 asynchronously by having all preventable native gesture recognizers require the deferring gesture recognizer to 11 fail; we only fail the deferring gesture recognizer once the web process has handled the touch event, and did 12 not call `preventDefault()`. 13 14 These additional failure requirements can cause preventable gestures to be linked together in the same gesture 15 dependency subgraph; since each subgraph is reset only once all gestures in the subgraph have failed or ended, 16 this might cause some gestures to be reset after a delay (rather than being reset immediately). To mitigate 17 this, we divide the set of preventable gestures into multiple (currently, 2) subgraphs: one for gestures that 18 are reset after a delay, and another for gestures that are immediately resettable. This way, immediately 19 resettable gestures are able to reset and recognize again, without having to wait for other slower preventable 20 gesture recognizers to reset. 21 22 When fast-clicking is disabled (e.g. when loading a desktop web page on a mobile form factor, or when the 23 viewport has been zoomed in), the blocking synthetic double tap gesture recognizer (that is, `WKContentView`'s 24 `_doubleTapGestureRecognizer`) is enabled, and adds itself as a dynamic failure requirement to the content 25 view's synthetic single tap gesture recognizer (`_singleTapGestureRecognizer`). In terms of the gesture 26 dependency graph, this causes the single tap gesture to form an edge with the double tap gesture, which ends up 27 uniting both deferring gesture recognizers under the same subgraph. This means UIWebTouchEventsGestureRecognizer, 28 which should be one of the gestures in the immediately resettable subgraph, is now connected to the rest of the 29 delayed resettable gestures, meaning that it cannot recognize until "slowly resettable" gestures such as the 30 tap-and-half text selection gesture have also been reset. This delay causes touch events to be dropped, as is 31 the case in this bug. 32 33 To fix this, simply quarantine the single tap and double tap gestures inside their own subgraph by introducing a 34 separate deferring gesture recognizer for them. When fast-clicking is enabled, this does not hinder the ability 35 for the single tap gesture to fire in rapid succession, since the double tap gesture is disabled (and thus, not 36 a part of the graph at all). when fast-clicking is disabled, then the double tap gesture will prevent the single 37 tap gesture from being immediately reset anyways, due to the direct failure requirement between the double and 38 single tap gesture. 39 40 Doing this ensures that no other immediately resettable gesture (`UIWebTouchEventsGestureRecognizer` included) 41 is accidentally blocked from immediately resetting due to being linked to the delayed resettable gestures by way 42 of the synthetic single and double tap gestures. 43 44 Test: fast/events/touch/ios/tap-and-half-when-viewport-is-not-responsive.html 45 46 * UIProcess/ios/WKContentViewInteraction.h: 47 48 Add a dedicated deferring gesture recognizer for the synthetic single tap and double tap gesture recognizers. 49 50 * UIProcess/ios/WKContentViewInteraction.mm: 51 (-[WKContentView setUpInteraction]): 52 (-[WKContentView cleanUpInteraction]): 53 54 Use -_deferringGestureRecognizers instead of hard-coding logic for each deferring gesture. 55 56 (-[WKContentView _removeDefaultGestureRecognizers]): Ditto. 57 (-[WKContentView _addDefaultGestureRecognizers]): Ditto. 58 (-[WKContentView _deferringGestureRecognizers]): 59 60 We now have 3 distinct deferring gestures; instead of handling the three deferring gestures individually in 61 various places in this file, group them all behind a getter that returns an array of deferring gestures, and use 62 this instead. 63 64 (-[WKContentView _doneDeferringNativeGestures:]): Ditto. 65 (-[WKContentView gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:]): Ditto. 66 (-[WKContentView deferringGestureRecognizer:shouldDeferOtherGestureRecognizer:]): 67 68 Partition the synthetic single tap and double tap gestures into their own subgraph. 69 1 70 2020-05-11 Per Arne Vollan <pvollan@apple.com> 2 71 -
trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h
r261457 r261480 212 212 RetainPtr<WKDeferringGestureRecognizer> _deferringGestureRecognizerForImmediatelyResettableGestures; 213 213 RetainPtr<WKDeferringGestureRecognizer> _deferringGestureRecognizerForDelayedResettableGestures; 214 RetainPtr<WKDeferringGestureRecognizer> _deferringGestureRecognizerForSyntheticTapGestures; 214 215 #endif 215 216 RetainPtr<UIWebTouchEventsGestureRecognizer> _touchEventGestureRecognizer; -
trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm
r261457 r261480 762 762 _deferringGestureRecognizerForImmediatelyResettableGestures = adoptNS([[WKDeferringGestureRecognizer alloc] initWithDeferringGestureDelegate:self]); 763 763 [_deferringGestureRecognizerForImmediatelyResettableGestures setName:@"Touch event deferrer (immediate reset)"]; 764 [_deferringGestureRecognizerForImmediatelyResettableGestures setDelegate:self];765 [self addGestureRecognizer:_deferringGestureRecognizerForImmediatelyResettableGestures.get()];766 764 767 765 _deferringGestureRecognizerForDelayedResettableGestures = adoptNS([[WKDeferringGestureRecognizer alloc] initWithDeferringGestureDelegate:self]); 768 766 [_deferringGestureRecognizerForDelayedResettableGestures setName:@"Touch event deferrer (delayed reset)"]; 769 [_deferringGestureRecognizerForDelayedResettableGestures setDelegate:self]; 770 [self addGestureRecognizer:_deferringGestureRecognizerForDelayedResettableGestures.get()]; 767 768 _deferringGestureRecognizerForSyntheticTapGestures = adoptNS([[WKDeferringGestureRecognizer alloc] initWithDeferringGestureDelegate:self]); 769 [_deferringGestureRecognizerForSyntheticTapGestures setName:@"Touch event deferrer (synthetic tap)"]; 770 771 for (WKDeferringGestureRecognizer *gesture in self._deferringGestureRecognizers) { 772 gesture.delegate = self; 773 [self addGestureRecognizer:gesture]; 774 } 771 775 #endif 772 776 … … 935 939 936 940 #if ENABLE(IOS_TOUCH_EVENTS) 937 [_deferringGestureRecognizerForImmediatelyResettableGestures setDelegate:nil]; 938 [self removeGestureRecognizer:_deferringGestureRecognizerForImmediatelyResettableGestures.get()]; 939 940 [_deferringGestureRecognizerForDelayedResettableGestures setDelegate:nil]; 941 [self removeGestureRecognizer:_deferringGestureRecognizerForDelayedResettableGestures.get()]; 941 for (WKDeferringGestureRecognizer *gesture in self._deferringGestureRecognizers) { 942 gesture.delegate = nil; 943 [self removeGestureRecognizer:gesture]; 944 } 942 945 #endif 943 946 … … 1054 1057 { 1055 1058 #if ENABLE(IOS_TOUCH_EVENTS) 1056 [self removeGestureRecognizer:_deferringGestureRecognizerForImmediatelyResettableGestures.get()];1057 [self removeGestureRecognizer:_deferringGestureRecognizerForDelayedResettableGestures.get()];1059 for (WKDeferringGestureRecognizer *gesture in self._deferringGestureRecognizers) 1060 [self removeGestureRecognizer:gesture]; 1058 1061 #endif 1059 1062 [self removeGestureRecognizer:_touchEventGestureRecognizer.get()]; … … 1082 1085 { 1083 1086 #if ENABLE(IOS_TOUCH_EVENTS) 1084 [self addGestureRecognizer:_deferringGestureRecognizerForImmediatelyResettableGestures.get()];1085 [self addGestureRecognizer:_deferringGestureRecognizerForDelayedResettableGestures.get()];1087 for (WKDeferringGestureRecognizer *gesture in self._deferringGestureRecognizers) 1088 [self addGestureRecognizer:gesture]; 1086 1089 #endif 1087 1090 [self addGestureRecognizer:_touchEventGestureRecognizer.get()]; … … 1657 1660 #if ENABLE(IOS_TOUCH_EVENTS) 1658 1661 1662 - (NSArray<WKDeferringGestureRecognizer *> *)_deferringGestureRecognizers 1663 { 1664 WKDeferringGestureRecognizer *recognizers[3]; 1665 NSUInteger count = 0; 1666 auto add = [&] (const RetainPtr<WKDeferringGestureRecognizer>& recognizer) { 1667 if (recognizer) 1668 recognizers[count++] = recognizer.get(); 1669 }; 1670 add(_deferringGestureRecognizerForImmediatelyResettableGestures); 1671 add(_deferringGestureRecognizerForDelayedResettableGestures); 1672 add(_deferringGestureRecognizerForSyntheticTapGestures); 1673 return [NSArray arrayWithObjects:recognizers count:count]; 1674 } 1675 1659 1676 - (void)_doneDeferringNativeGestures:(BOOL)preventNativeGestures 1660 1677 { 1661 [_deferringGestureRecognizerForImmediatelyResettableGestures setDefaultPrevented:preventNativeGestures];1662 [_deferringGestureRecognizerForDelayedResettableGesturessetDefaultPrevented:preventNativeGestures];1663 } 1664 1665 #endif 1678 for (WKDeferringGestureRecognizer *gesture in self._deferringGestureRecognizers) 1679 [gesture setDefaultPrevented:preventNativeGestures]; 1680 } 1681 1682 #endif // ENABLE(IOS_TOUCH_EVENTS) 1666 1683 1667 1684 static NSValue *nsSizeForTapHighlightBorderRadius(WebCore::IntSize borderRadius, CGFloat borderRadiusScale) … … 2042 2059 { 2043 2060 #if ENABLE(IOS_TOUCH_EVENTS) 2044 if (isSamePair(gestureRecognizer, otherGestureRecognizer, _touchEventGestureRecognizer.get(), _deferringGestureRecognizerForImmediatelyResettableGestures.get())) 2045 return YES; 2046 2047 if (isSamePair(gestureRecognizer, otherGestureRecognizer, _touchEventGestureRecognizer.get(), _deferringGestureRecognizerForDelayedResettableGestures.get())) 2048 return YES; 2061 for (WKDeferringGestureRecognizer *gesture in self._deferringGestureRecognizers) { 2062 if (isSamePair(gestureRecognizer, otherGestureRecognizer, _touchEventGestureRecognizer.get(), gesture)) 2063 return YES; 2064 } 2049 2065 #endif 2050 2066 … … 7101 7117 }; 7102 7118 7119 if (gestureRecognizer == _doubleTapGestureRecognizer || gestureRecognizer == _singleTapGestureRecognizer) 7120 return deferringGestureRecognizer == _deferringGestureRecognizerForSyntheticTapGestures; 7121 7103 7122 if (mayDelayResetOfContainingSubgraph(gestureRecognizer)) 7104 7123 return deferringGestureRecognizer == _deferringGestureRecognizerForDelayedResettableGestures;
Note: See TracChangeset
for help on using the changeset viewer.