- Revision
- 271193
- Author
- [email protected]
- Date
- 2021-01-05 21:59:24 -0800 (Tue, 05 Jan 2021)
Log Message
Refactor some logic around touch event deferring gesture recognizers
https://bugs.webkit.org/show_bug.cgi?id=220345
Reviewed by Tim Horton.
Rename `_deferringGestureRecognizerForFoo` to `_touchStartDeferringGestureRecognizerForFoo`, to make it clear
that these deferring gestures are only intended to defer native gestures until the "touchstart" event has been
handled.
This distinction becomes important once I introduce deferring gesture recognizers that defer the "touchend"
event, and prevent gestures that activate upon touch end (i.e. various types of tap gesture recognizers).
See below for more details.
* UIProcess/PageClient.h:
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::handlePreventableTouchEvent):
* UIProcess/ios/PageClientImplIOS.h:
* UIProcess/ios/PageClientImplIOS.mm:
(WebKit::PageClientImpl::doneDeferringTouchStart):
(WebKit::PageClientImpl::doneDeferringNativeGestures): Deleted.
* UIProcess/ios/WKContentViewInteraction.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView setUpInteraction]):
(-[WKContentView cleanUpInteraction]):
(-[WKContentView _removeDefaultGestureRecognizers]):
(-[WKContentView _addDefaultGestureRecognizers]):
(-[WKContentView _webTouchEventsRecognized:]):
(-[WKContentView _touchStartDeferringGestures]):
(-[WKContentView _doneDeferringTouchStart:]):
(-[WKContentView gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:]):
(-[WKContentView deferringGestureRecognizer:shouldDeferOtherGestureRecognizer:]):
(-[WKContentView _deferringGestureRecognizers]): Deleted.
(-[WKContentView _doneDeferringNativeGestures:]): Deleted.
Rename this to `-_doneDeferringTouchStart:`.
(-[WKContentView deferringGestureRecognizer:shouldDeferGesturesAfterEndingTouchesWithEvent:]):
Deleted. This logic has been moved to WKContentView (see below).
* UIProcess/ios/WKDeferringGestureRecognizer.h:
* UIProcess/ios/WKDeferringGestureRecognizer.mm:
(-[WKDeferringGestureRecognizer touchesEnded:withEvent:]): Deleted.
Additionally refactor this code so that this fallback logic for lifting the gesture gate exists inside
`WKContentView` (after ending all touches), rather than inside the deferring gesture recognizer. While this
doesn't affect the extant touch start deferring gestures, it will ensure that touch end deferring gestures won't
get reset prematurely due to the web touch events gesture recognizer ending before the touch end deferring
gesture.
Modified Paths
Diff
Modified: trunk/Source/WebKit/ChangeLog (271192 => 271193)
--- trunk/Source/WebKit/ChangeLog 2021-01-06 05:29:40 UTC (rev 271192)
+++ trunk/Source/WebKit/ChangeLog 2021-01-06 05:59:24 UTC (rev 271193)
@@ -1,3 +1,56 @@
+2021-01-05 Wenson Hsieh <[email protected]>
+
+ Refactor some logic around touch event deferring gesture recognizers
+ https://bugs.webkit.org/show_bug.cgi?id=220345
+
+ Reviewed by Tim Horton.
+
+ Rename `_deferringGestureRecognizerForFoo` to `_touchStartDeferringGestureRecognizerForFoo`, to make it clear
+ that these deferring gestures are only intended to defer native gestures until the "touchstart" event has been
+ handled.
+
+ This distinction becomes important once I introduce deferring gesture recognizers that defer the "touchend"
+ event, and prevent gestures that activate upon touch end (i.e. various types of tap gesture recognizers).
+
+ See below for more details.
+
+ * UIProcess/PageClient.h:
+ * UIProcess/WebPageProxy.cpp:
+ (WebKit::WebPageProxy::handlePreventableTouchEvent):
+ * UIProcess/ios/PageClientImplIOS.h:
+ * UIProcess/ios/PageClientImplIOS.mm:
+ (WebKit::PageClientImpl::doneDeferringTouchStart):
+ (WebKit::PageClientImpl::doneDeferringNativeGestures): Deleted.
+ * UIProcess/ios/WKContentViewInteraction.h:
+ * UIProcess/ios/WKContentViewInteraction.mm:
+ (-[WKContentView setUpInteraction]):
+ (-[WKContentView cleanUpInteraction]):
+ (-[WKContentView _removeDefaultGestureRecognizers]):
+ (-[WKContentView _addDefaultGestureRecognizers]):
+ (-[WKContentView _webTouchEventsRecognized:]):
+ (-[WKContentView _touchStartDeferringGestures]):
+ (-[WKContentView _doneDeferringTouchStart:]):
+ (-[WKContentView gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:]):
+ (-[WKContentView deferringGestureRecognizer:shouldDeferOtherGestureRecognizer:]):
+ (-[WKContentView _deferringGestureRecognizers]): Deleted.
+ (-[WKContentView _doneDeferringNativeGestures:]): Deleted.
+
+ Rename this to `-_doneDeferringTouchStart:`.
+
+ (-[WKContentView deferringGestureRecognizer:shouldDeferGesturesAfterEndingTouchesWithEvent:]):
+
+ Deleted. This logic has been moved to WKContentView (see below).
+
+ * UIProcess/ios/WKDeferringGestureRecognizer.h:
+ * UIProcess/ios/WKDeferringGestureRecognizer.mm:
+ (-[WKDeferringGestureRecognizer touchesEnded:withEvent:]): Deleted.
+
+ Additionally refactor this code so that this fallback logic for lifting the gesture gate exists inside
+ `WKContentView` (after ending all touches), rather than inside the deferring gesture recognizer. While this
+ doesn't affect the extant touch start deferring gestures, it will ensure that touch end deferring gestures won't
+ get reset prematurely due to the web touch events gesture recognizer ending before the touch end deferring
+ gesture.
+
2021-01-05 Kate Cheney <[email protected]>
NSCrossWebsiteTrackingUsageDescription is not working on Mac, ITP is always enabled
Modified: trunk/Source/WebKit/UIProcess/PageClient.h (271192 => 271193)
--- trunk/Source/WebKit/UIProcess/PageClient.h 2021-01-06 05:29:40 UTC (rev 271192)
+++ trunk/Source/WebKit/UIProcess/PageClient.h 2021-01-06 05:59:24 UTC (rev 271193)
@@ -339,7 +339,7 @@
virtual void doneWithTouchEvent(const NativeWebTouchEvent&, bool wasEventHandled) = 0;
#endif
#if ENABLE(IOS_TOUCH_EVENTS)
- virtual void doneDeferringNativeGestures(bool preventNativeGestures) = 0;
+ virtual void doneDeferringTouchStart(bool preventNativeGestures) = 0;
#endif
virtual RefPtr<WebPopupMenuProxy> createPopupMenuProxy(WebPageProxy&) = 0;
Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.cpp (271192 => 271193)
--- trunk/Source/WebKit/UIProcess/WebPageProxy.cpp 2021-01-06 05:29:40 UTC (rev 271192)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.cpp 2021-01-06 05:59:24 UTC (rev 271193)
@@ -2891,7 +2891,7 @@
TrackingType touchEventsTrackingType = touchEventTrackingType(event);
if (touchEventsTrackingType == TrackingType::NotTracking) {
if (!isHandlingPreventableTouchStart())
- pageClient().doneDeferringNativeGestures(false);
+ pageClient().doneDeferringTouchStart(false);
return;
}
@@ -2906,7 +2906,7 @@
handleUnpreventableTouchEvent(event);
didReceiveEvent(event.type(), false);
if (!isHandlingPreventableTouchStart())
- pageClient().doneDeferringNativeGestures(false);
+ pageClient().doneDeferringTouchStart(false);
return;
}
@@ -2913,9 +2913,10 @@
if (event.type() == WebEvent::TouchStart) {
++m_handlingPreventableTouchStartCount;
Function<void(bool, CallbackBase::Error)> completionHandler = [this, protectedThis = makeRef(*this), event](bool handled, CallbackBase::Error error) {
- ASSERT(m_handlingPreventableTouchStartCount);
- if (m_handlingPreventableTouchStartCount)
- --m_handlingPreventableTouchStartCount;
+ bool didFinishDeferringTouchStart = false;
+ ASSERT_IMPLIES(event.type() == WebEvent::TouchStart, m_handlingPreventableTouchStartCount);
+ if (event.type() == WebEvent::TouchStart && m_handlingPreventableTouchStartCount)
+ didFinishDeferringTouchStart = !--m_handlingPreventableTouchStartCount;
bool handledOrFailedWithError = handled || error != CallbackBase::Error::None || m_handledSynchronousTouchEventWhileDispatchingPreventableTouchStart;
if (!isHandlingPreventableTouchStart())
@@ -2926,8 +2927,9 @@
didReceiveEvent(event.type(), handledOrFailedWithError);
pageClient().doneWithTouchEvent(event, handledOrFailedWithError);
- if (!isHandlingPreventableTouchStart())
- pageClient().doneDeferringNativeGestures(handledOrFailedWithError);
+
+ if (didFinishDeferringTouchStart)
+ pageClient().doneDeferringTouchStart(handledOrFailedWithError);
};
auto callbackID = m_callbacks.put(WTFMove(completionHandler), m_process->throttler().backgroundActivity("WebPageProxy::handlePreventableTouchEvent"_s));
@@ -2944,7 +2946,7 @@
didReceiveEvent(event.type(), handled);
pageClient().doneWithTouchEvent(event, handled);
if (!isHandlingPreventableTouchStart())
- pageClient().doneDeferringNativeGestures(handled);
+ pageClient().doneDeferringTouchStart(handled);
else if (handled)
m_handledSynchronousTouchEventWhileDispatchingPreventableTouchStart = true;
m_process->stopResponsivenessTimer();
Modified: trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.h (271192 => 271193)
--- trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.h 2021-01-06 05:29:40 UTC (rev 271192)
+++ trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.h 2021-01-06 05:59:24 UTC (rev 271193)
@@ -112,7 +112,7 @@
void doneWithTouchEvent(const NativeWebTouchEvent&, bool wasEventHandled) override;
#endif
#if ENABLE(IOS_TOUCH_EVENTS)
- void doneDeferringNativeGestures(bool preventNativeGestures) override;
+ void doneDeferringTouchStart(bool preventNativeGestures) override;
#endif
RefPtr<WebPopupMenuProxy> createPopupMenuProxy(WebPageProxy&) override;
Ref<WebCore::ValidationBubble> createValidationBubble(const String& message, const WebCore::ValidationBubble::Settings&) final;
Modified: trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm (271192 => 271193)
--- trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm 2021-01-06 05:29:40 UTC (rev 271192)
+++ trunk/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm 2021-01-06 05:59:24 UTC (rev 271193)
@@ -447,9 +447,9 @@
#if ENABLE(IOS_TOUCH_EVENTS)
-void PageClientImpl::doneDeferringNativeGestures(bool preventNativeGestures)
+void PageClientImpl::doneDeferringTouchStart(bool preventNativeGestures)
{
- [m_contentView _doneDeferringNativeGestures:preventNativeGestures];
+ [m_contentView _doneDeferringTouchStart:preventNativeGestures];
}
#endif // ENABLE(IOS_TOUCH_EVENTS)
Modified: trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h (271192 => 271193)
--- trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h 2021-01-06 05:29:40 UTC (rev 271192)
+++ trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h 2021-01-06 05:59:24 UTC (rev 271193)
@@ -242,9 +242,9 @@
@interface WKContentView () {
#if ENABLE(IOS_TOUCH_EVENTS)
- RetainPtr<WKDeferringGestureRecognizer> _deferringGestureRecognizerForImmediatelyResettableGestures;
- RetainPtr<WKDeferringGestureRecognizer> _deferringGestureRecognizerForDelayedResettableGestures;
- RetainPtr<WKDeferringGestureRecognizer> _deferringGestureRecognizerForSyntheticTapGestures;
+ RetainPtr<WKDeferringGestureRecognizer> _touchStartDeferringGestureRecognizerForImmediatelyResettableGestures;
+ RetainPtr<WKDeferringGestureRecognizer> _touchStartDeferringGestureRecognizerForDelayedResettableGestures;
+ RetainPtr<WKDeferringGestureRecognizer> _touchStartDeferringGestureRecognizerForSyntheticTapGestures;
#endif
RetainPtr<UIWebTouchEventsGestureRecognizer> _touchEventGestureRecognizer;
@@ -539,7 +539,7 @@
- (void)_webTouchEvent:(const WebKit::NativeWebTouchEvent&)touchEvent preventsNativeGestures:(BOOL)preventsDefault;
#endif
#if ENABLE(IOS_TOUCH_EVENTS)
-- (void)_doneDeferringNativeGestures:(BOOL)preventNativeGestures;
+- (void)_doneDeferringTouchStart:(BOOL)preventNativeGestures;
#endif
- (void)_commitPotentialTapFailed;
- (void)_didNotHandleTapAsClick:(const WebCore::IntPoint&)point;
Modified: trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm (271192 => 271193)
--- trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm 2021-01-06 05:29:40 UTC (rev 271192)
+++ trunk/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm 2021-01-06 05:59:24 UTC (rev 271193)
@@ -764,20 +764,20 @@
[self addGestureRecognizer:_touchActionDownSwipeGestureRecognizer.get()];
#if ENABLE(IOS_TOUCH_EVENTS)
- _deferringGestureRecognizerForImmediatelyResettableGestures = adoptNS([[WKDeferringGestureRecognizer alloc] initWithDeferringGestureDelegate:self]);
- [_deferringGestureRecognizerForImmediatelyResettableGestures setName:@"Touch event deferrer (immediate reset)"];
+ _touchStartDeferringGestureRecognizerForImmediatelyResettableGestures = adoptNS([[WKDeferringGestureRecognizer alloc] initWithDeferringGestureDelegate:self]);
+ [_touchStartDeferringGestureRecognizerForImmediatelyResettableGestures setName:@"Touch start deferrer (immediate reset)"];
- _deferringGestureRecognizerForDelayedResettableGestures = adoptNS([[WKDeferringGestureRecognizer alloc] initWithDeferringGestureDelegate:self]);
- [_deferringGestureRecognizerForDelayedResettableGestures setName:@"Touch event deferrer (delayed reset)"];
+ _touchStartDeferringGestureRecognizerForDelayedResettableGestures = adoptNS([[WKDeferringGestureRecognizer alloc] initWithDeferringGestureDelegate:self]);
+ [_touchStartDeferringGestureRecognizerForDelayedResettableGestures setName:@"Touch start deferrer (delayed reset)"];
- _deferringGestureRecognizerForSyntheticTapGestures = adoptNS([[WKDeferringGestureRecognizer alloc] initWithDeferringGestureDelegate:self]);
- [_deferringGestureRecognizerForSyntheticTapGestures setName:@"Touch event deferrer (synthetic tap)"];
+ _touchStartDeferringGestureRecognizerForSyntheticTapGestures = adoptNS([[WKDeferringGestureRecognizer alloc] initWithDeferringGestureDelegate:self]);
+ [_touchStartDeferringGestureRecognizerForSyntheticTapGestures setName:@"Touch start deferrer (synthetic tap)"];
- for (WKDeferringGestureRecognizer *gesture in self._deferringGestureRecognizers) {
+ for (WKDeferringGestureRecognizer *gesture in self._touchStartDeferringGestures) {
gesture.delegate = self;
[self addGestureRecognizer:gesture];
}
-#endif
+#endif // ENABLE(IOS_TOUCH_EVENTS)
_touchEventGestureRecognizer = adoptNS([[UIWebTouchEventsGestureRecognizer alloc] initWithTarget:self action:@selector(_webTouchEventsRecognized:) touchDelegate:self]);
[_touchEventGestureRecognizer setDelegate:self];
@@ -953,7 +953,7 @@
[self removeGestureRecognizer:_touchEventGestureRecognizer.get()];
#if ENABLE(IOS_TOUCH_EVENTS)
- for (WKDeferringGestureRecognizer *gesture in self._deferringGestureRecognizers) {
+ for (WKDeferringGestureRecognizer *gesture in self._touchStartDeferringGestures) {
gesture.delegate = nil;
[self removeGestureRecognizer:gesture];
}
@@ -1084,7 +1084,7 @@
- (void)_removeDefaultGestureRecognizers
{
#if ENABLE(IOS_TOUCH_EVENTS)
- for (WKDeferringGestureRecognizer *gesture in self._deferringGestureRecognizers)
+ for (WKDeferringGestureRecognizer *gesture in self._touchStartDeferringGestures)
[self removeGestureRecognizer:gesture];
#endif
[self removeGestureRecognizer:_touchEventGestureRecognizer.get()];
@@ -1111,7 +1111,7 @@
- (void)_addDefaultGestureRecognizers
{
#if ENABLE(IOS_TOUCH_EVENTS)
- for (WKDeferringGestureRecognizer *gesture in self._deferringGestureRecognizers)
+ for (WKDeferringGestureRecognizer *gesture in self._touchStartDeferringGestures)
[self addGestureRecognizer:gesture];
#endif
[self addGestureRecognizer:_touchEventGestureRecognizer.get()];
@@ -1548,8 +1548,17 @@
if (nativeWebTouchEvent.isPotentialTap() && self.hasHiddenContentEditable && self._hasFocusedElement && !self.window.keyWindow)
[self.window makeKeyWindow];
+
+#if ENABLE(IOS_TOUCH_EVENTS)
+ if (!_page->isHandlingPreventableTouchStart()) {
+ for (WKDeferringGestureRecognizer *gesture in self._touchStartDeferringGestures) {
+ if (gesture.state == UIGestureRecognizerStatePossible)
+ gesture.state = UIGestureRecognizerStateFailed;
+ }
+ }
+#endif // ENABLE(IOS_TOUCH_EVENTS)
}
-#endif
+#endif // ENABLE(TOUCH_EVENTS)
}
#if ENABLE(TOUCH_EVENTS)
@@ -1727,7 +1736,7 @@
#if ENABLE(IOS_TOUCH_EVENTS)
-- (NSArray<WKDeferringGestureRecognizer *> *)_deferringGestureRecognizers
+- (NSArray<WKDeferringGestureRecognizer *> *)_touchStartDeferringGestures
{
WKDeferringGestureRecognizer *recognizers[3];
NSUInteger count = 0;
@@ -1735,15 +1744,15 @@
if (recognizer)
recognizers[count++] = recognizer.get();
};
- add(_deferringGestureRecognizerForImmediatelyResettableGestures);
- add(_deferringGestureRecognizerForDelayedResettableGestures);
- add(_deferringGestureRecognizerForSyntheticTapGestures);
+ add(_touchStartDeferringGestureRecognizerForImmediatelyResettableGestures);
+ add(_touchStartDeferringGestureRecognizerForDelayedResettableGestures);
+ add(_touchStartDeferringGestureRecognizerForSyntheticTapGestures);
return [NSArray arrayWithObjects:recognizers count:count];
}
-- (void)_doneDeferringNativeGestures:(BOOL)preventNativeGestures
+- (void)_doneDeferringTouchStart:(BOOL)preventNativeGestures
{
- for (WKDeferringGestureRecognizer *gesture in self._deferringGestureRecognizers)
+ for (WKDeferringGestureRecognizer *gesture in self._touchStartDeferringGestures)
[gesture setDefaultPrevented:preventNativeGestures];
}
@@ -2128,7 +2137,7 @@
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer*)otherGestureRecognizer
{
#if ENABLE(IOS_TOUCH_EVENTS)
- for (WKDeferringGestureRecognizer *gesture in self._deferringGestureRecognizers) {
+ for (WKDeferringGestureRecognizer *gesture in self._touchStartDeferringGestures) {
if (isSamePair(gestureRecognizer, otherGestureRecognizer, _touchEventGestureRecognizer.get(), gesture))
return YES;
}
@@ -7301,11 +7310,6 @@
return ![self gestureRecognizer:deferringGestureRecognizer isInterruptingMomentumScrollingWithEvent:event];
}
-- (BOOL)deferringGestureRecognizer:(WKDeferringGestureRecognizer *)deferringGestureRecognizer shouldDeferGesturesAfterEndingTouchesWithEvent:(UIEvent *)event
-{
- return _page->isHandlingPreventableTouchStart();
-}
-
- (BOOL)deferringGestureRecognizer:(WKDeferringGestureRecognizer *)deferringGestureRecognizer shouldDeferOtherGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
{
#if ENABLE(IOS_TOUCH_EVENTS)
@@ -7357,13 +7361,13 @@
return NO;
};
- if (gestureRecognizer == _doubleTapGestureRecognizer || gestureRecognizer == _singleTapGestureRecognizer)
- return deferringGestureRecognizer == _deferringGestureRecognizerForSyntheticTapGestures;
+ if ([gestureRecognizer isKindOfClass:WKSyntheticTapGestureRecognizer.class])
+ return deferringGestureRecognizer == _touchStartDeferringGestureRecognizerForSyntheticTapGestures;
if (mayDelayResetOfContainingSubgraph(gestureRecognizer))
- return deferringGestureRecognizer == _deferringGestureRecognizerForDelayedResettableGestures;
+ return deferringGestureRecognizer == _touchStartDeferringGestureRecognizerForDelayedResettableGestures;
- return deferringGestureRecognizer == _deferringGestureRecognizerForImmediatelyResettableGestures;
+ return deferringGestureRecognizer == _touchStartDeferringGestureRecognizerForImmediatelyResettableGestures;
#else
UNUSED_PARAM(deferringGestureRecognizer);
UNUSED_PARAM(gestureRecognizer);
Modified: trunk/Source/WebKit/UIProcess/ios/WKDeferringGestureRecognizer.h (271192 => 271193)
--- trunk/Source/WebKit/UIProcess/ios/WKDeferringGestureRecognizer.h 2021-01-06 05:29:40 UTC (rev 271192)
+++ trunk/Source/WebKit/UIProcess/ios/WKDeferringGestureRecognizer.h 2021-01-06 05:59:24 UTC (rev 271193)
@@ -30,7 +30,6 @@
@class WKDeferringGestureRecognizer;
@protocol WKDeferringGestureRecognizerDelegate
-- (BOOL)deferringGestureRecognizer:(WKDeferringGestureRecognizer *)deferringGestureRecognizer shouldDeferGesturesAfterEndingTouchesWithEvent:(UIEvent *)event;
- (BOOL)deferringGestureRecognizer:(WKDeferringGestureRecognizer *)deferringGestureRecognizer shouldDeferGesturesAfterBeginningTouchesWithEvent:(UIEvent *)event;
- (BOOL)deferringGestureRecognizer:(WKDeferringGestureRecognizer *)deferringGestureRecognizer shouldDeferOtherGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer;
@end
Modified: trunk/Source/WebKit/UIProcess/ios/WKDeferringGestureRecognizer.mm (271192 => 271193)
--- trunk/Source/WebKit/UIProcess/ios/WKDeferringGestureRecognizer.mm 2021-01-06 05:29:40 UTC (rev 271192)
+++ trunk/Source/WebKit/UIProcess/ios/WKDeferringGestureRecognizer.mm 2021-01-06 05:59:24 UTC (rev 271193)
@@ -55,19 +55,6 @@
self.state = UIGestureRecognizerStateFailed;
}
-- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
-{
- [super touchesEnded:touches withEvent:event];
-
- if (self.state != UIGestureRecognizerStatePossible)
- return;
-
- if ([_deferringGestureDelegate deferringGestureRecognizer:self shouldDeferGesturesAfterEndingTouchesWithEvent:event])
- return;
-
- self.state = UIGestureRecognizerStateFailed;
-}
-
- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[super touchesCancelled:touches withEvent:event];