Modified: trunk/Source/WebKit2/ChangeLog (196678 => 196679)
--- trunk/Source/WebKit2/ChangeLog 2016-02-17 02:34:36 UTC (rev 196678)
+++ trunk/Source/WebKit2/ChangeLog 2016-02-17 03:27:05 UTC (rev 196679)
@@ -1,3 +1,58 @@
+2016-02-16 Dean Jackson <[email protected]>
+
+ Allow double tap to zoom in fast-click pages
+ https://bugs.webkit.org/show_bug.cgi?id=154318
+ <rdar://problem/24223767>
+
+ Reviewed by Simon Fraser and Benjamin Poulain.
+
+ Most of the patch comes from Jon Lee.
+
+ Our fast-click algorithm exposed a number of cases where
+ people missed the double-tap-to-zoom behaviour. In particular,
+ when you double tap on a large body of text, typical in
+ blogs and articles.
+
+ This patch enhances the algorithm to have a parallel
+ double-tap gesture recognizer in the situations where
+ fast-click is enabled. This new gesture recongizer does
+ not cause the single tap to block for 350ms, so clicks
+ are still dispatched fast. If it fires, we already have
+ some information about whether we have a pending double
+ tap, based on the first tap.
+
+ * UIProcess/ios/PageClientImplIOS.mm:
+ (WebKit::PageClientImpl::disableDoubleTapGesturesDuringTapIfNecessary): Remove the optimization
+ that only told the content view to disable on pages that allowed double taps. We now allow
+ them even on fast click pages.
+
+ * UIProcess/ios/WKContentViewInteraction.h: Add the new UITapGestureRecognizer for double taps
+ in fast click pages. This is called nonBlockingDoubleTapGestureRecognizer because, unlike
+ the existing DoubleTapGestureRecognizer, this one does not force the singleTapRecognizer
+ to wait.
+ * UIProcess/ios/WKContentViewInteraction.mm:
+ (-[WKContentView setupInteraction]): Set up the new UITapGestureRecognizer.
+ (-[WKContentView cleanupInteraction]): And remove it when we're done.
+ (-[WKContentView _removeDefaultGestureRecognizers]): Ditto.
+ (-[WKContentView _addDefaultGestureRecognizers]):
+ (-[WKContentView _inspectorNodeSearchRecognized:]): Something happened, we are no longer in
+ a potential double tap situation.
+ (-[WKContentView _disableDoubleTapGesturesDuringTapIfNecessary:]): Remove the check
+ for potential tap in progress.
+ (-[WKContentView gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:]):
+ (-[WKContentView gestureRecognizerShouldBegin:]):
+ (-[WKContentView _highlightLongPressRecognized:]): Again, something happened, so we are
+ no longer in a double tap situation.
+ (-[WKContentView _longPressRecognized:]): Ditto.
+ (-[WKContentView _singleTapRecognized:]): Ditto.
+ (-[WKContentView _doubleTapRecognized:]): Ditto.
+ (-[WKContentView _resetIsDoubleTapPending]):
+ (-[WKContentView _fastDoubleTapRecognized:]): We're now pending a double tap.
+ (-[WKContentView _twoFingerDoubleTapRecognized:]):
+ (-[WKContentView _didNotHandleTapAsClick:]): If we get here and we have a pending
+ double tap, then trigger a zoom operation.
+ (-[WKContentView _setDoubleTapGesturesEnabled:]):
+
2016-02-16 Alex Christensen <[email protected]>
CMake build fix.
Modified: trunk/Source/WebKit2/UIProcess/ios/PageClientImplIOS.mm (196678 => 196679)
--- trunk/Source/WebKit2/UIProcess/ios/PageClientImplIOS.mm 2016-02-17 02:34:36 UTC (rev 196678)
+++ trunk/Source/WebKit2/UIProcess/ios/PageClientImplIOS.mm 2016-02-17 03:27:05 UTC (rev 196679)
@@ -261,9 +261,6 @@
void PageClientImpl::disableDoubleTapGesturesDuringTapIfNecessary(uint64_t requestID)
{
- if (!m_webView._allowsDoubleTapGestures)
- return;
-
[m_contentView _disableDoubleTapGesturesDuringTapIfNecessary:requestID];
}
Modified: trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.h (196678 => 196679)
--- trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.h 2016-02-17 02:34:36 UTC (rev 196678)
+++ trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.h 2016-02-17 03:27:05 UTC (rev 196679)
@@ -102,6 +102,7 @@
RetainPtr<_UIWebHighlightLongPressGestureRecognizer> _highlightLongPressGestureRecognizer;
RetainPtr<UILongPressGestureRecognizer> _longPressGestureRecognizer;
RetainPtr<UITapGestureRecognizer> _doubleTapGestureRecognizer;
+ RetainPtr<UITapGestureRecognizer> _nonBlockingDoubleTapGestureRecognizer;
RetainPtr<UITapGestureRecognizer> _twoFingerDoubleTapGestureRecognizer;
RetainPtr<WKInspectorNodeSearchGestureRecognizer> _inspectorNodeSearchGestureRecognizer;
@@ -154,6 +155,7 @@
BOOL _hasValidPositionInformation;
BOOL _isTapHighlightIDValid;
BOOL _potentialTapInProgress;
+ BOOL _isDoubleTapPending;
BOOL _highlightLongPressCanClick;
BOOL _hasTapHighlightForPotentialTap;
BOOL _selectionNeedsUpdate;
Modified: trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.mm (196678 => 196679)
--- trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.mm 2016-02-17 02:34:36 UTC (rev 196678)
+++ trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.mm 2016-02-17 03:27:05 UTC (rev 196679)
@@ -461,6 +461,12 @@
[_singleTapGestureRecognizer setResetTarget:self action:@selector(_singleTapDidReset:)];
[self addGestureRecognizer:_singleTapGestureRecognizer.get()];
+ _nonBlockingDoubleTapGestureRecognizer = adoptNS([[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(_nonBlockingDoubleTapRecognized:)]);
+ [_nonBlockingDoubleTapGestureRecognizer setNumberOfTapsRequired:2];
+ [_nonBlockingDoubleTapGestureRecognizer setDelegate:self];
+ [_nonBlockingDoubleTapGestureRecognizer setEnabled:NO];
+ [self addGestureRecognizer:_nonBlockingDoubleTapGestureRecognizer.get()];
+
[self _createAndConfigureDoubleTapGestureRecognizer];
_twoFingerDoubleTapGestureRecognizer = adoptNS([[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(_twoFingerDoubleTapRecognized:)]);
@@ -494,6 +500,8 @@
[_actionSheetAssistant setDelegate:self];
_smartMagnificationController = std::make_unique<SmartMagnificationController>(self);
_isExpectingFastSingleTapCommit = NO;
+ _potentialTapInProgress = NO;
+ _isDoubleTapPending = NO;
_showDebugTapHighlightsForFastClicking = [[NSUserDefaults standardUserDefaults] boolForKey:@"WebKitShowFastClickDebugTapHighlights"];
}
@@ -532,6 +540,9 @@
[_doubleTapGestureRecognizer setDelegate:nil];
[self removeGestureRecognizer:_doubleTapGestureRecognizer.get()];
+ [_nonBlockingDoubleTapGestureRecognizer setDelegate:nil];
+ [self removeGestureRecognizer:_nonBlockingDoubleTapGestureRecognizer.get()];
+
[_twoFingerDoubleTapGestureRecognizer setDelegate:nil];
[self removeGestureRecognizer:_twoFingerDoubleTapGestureRecognizer.get()];
@@ -559,6 +570,7 @@
[self removeGestureRecognizer:_singleTapGestureRecognizer.get()];
[self removeGestureRecognizer:_highlightLongPressGestureRecognizer.get()];
[self removeGestureRecognizer:_doubleTapGestureRecognizer.get()];
+ [self removeGestureRecognizer:_nonBlockingDoubleTapGestureRecognizer.get()];
[self removeGestureRecognizer:_twoFingerDoubleTapGestureRecognizer.get()];
}
@@ -568,6 +580,7 @@
[self addGestureRecognizer:_singleTapGestureRecognizer.get()];
[self addGestureRecognizer:_highlightLongPressGestureRecognizer.get()];
[self addGestureRecognizer:_doubleTapGestureRecognizer.get()];
+ [self addGestureRecognizer:_nonBlockingDoubleTapGestureRecognizer.get()];
[self addGestureRecognizer:_twoFingerDoubleTapGestureRecognizer.get()];
}
@@ -732,6 +745,7 @@
- (void)_inspectorNodeSearchRecognized:(UIGestureRecognizer *)gestureRecognizer
{
ASSERT(_inspectorNodeSearchEnabled);
+ [self _resetIsDoubleTapPending];
CGPoint point = [gestureRecognizer locationInView:self];
@@ -920,7 +934,7 @@
- (void)_disableDoubleTapGesturesDuringTapIfNecessary:(uint64_t)requestID
{
- if (!_potentialTapInProgress || _latestTapID != requestID)
+ if (_latestTapID != requestID)
return;
[self _setDoubleTapGesturesEnabled:NO];
@@ -1049,6 +1063,12 @@
if (isSamePair(gestureRecognizer, otherGestureRecognizer, _singleTapGestureRecognizer.get(), _textSelectionAssistant.get().singleTapGesture))
return YES;
+ if (isSamePair(gestureRecognizer, otherGestureRecognizer, _singleTapGestureRecognizer.get(), _nonBlockingDoubleTapGestureRecognizer.get()))
+ return YES;
+
+ if (isSamePair(gestureRecognizer, otherGestureRecognizer, _highlightLongPressGestureRecognizer.get(), _nonBlockingDoubleTapGestureRecognizer.get()))
+ return YES;
+
if (isSamePair(gestureRecognizer, otherGestureRecognizer, _highlightLongPressGestureRecognizer.get(), _previewSecondaryGestureRecognizer.get()))
return YES;
@@ -1112,6 +1132,7 @@
if (gestureRecognizer == _highlightLongPressGestureRecognizer
|| gestureRecognizer == _doubleTapGestureRecognizer
+ || gestureRecognizer == _nonBlockingDoubleTapGestureRecognizer
|| gestureRecognizer == _twoFingerDoubleTapGestureRecognizer
|| gestureRecognizer == _singleTapGestureRecognizer) {
@@ -1233,6 +1254,7 @@
- (void)_highlightLongPressRecognized:(UILongPressGestureRecognizer *)gestureRecognizer
{
ASSERT(gestureRecognizer == _highlightLongPressGestureRecognizer);
+ [self _resetIsDoubleTapPending];
_lastInteractionLocation = gestureRecognizer.startPoint;
@@ -1263,6 +1285,7 @@
- (void)_longPressRecognized:(UILongPressGestureRecognizer *)gestureRecognizer
{
ASSERT(gestureRecognizer == _longPressGestureRecognizer);
+ [self _resetIsDoubleTapPending];
_lastInteractionLocation = gestureRecognizer.startPoint;
@@ -1287,6 +1310,7 @@
{
ASSERT(gestureRecognizer == _singleTapGestureRecognizer);
ASSERT(!_potentialTapInProgress);
+ [self _resetIsDoubleTapPending];
_page->potentialTapAtPosition(gestureRecognizer.location, ++_latestTapID);
_potentialTapInProgress = YES;
@@ -1314,6 +1338,22 @@
[self _cancelInteraction];
}
+- (void)_didNotHandleTapAsClick:(const WebCore::IntPoint&)point
+{
+ // FIXME: we should also take into account whether or not the UI delegate
+ // has handled this notification.
+ if (_hasValidPositionInformation && point == _positionInformation.point && _positionInformation.isDataDetectorLink) {
+ [self _showDataDetectorsSheet];
+ return;
+ }
+
+ if (!_isDoubleTapPending)
+ return;
+
+ _smartMagnificationController->handleSmartMagnificationGesture(_lastInteractionLocation);
+ _isDoubleTapPending = NO;
+}
+
- (void)_singleTapCommited:(UITapGestureRecognizer *)gestureRecognizer
{
ASSERT(gestureRecognizer == _singleTapGestureRecognizer);
@@ -1351,13 +1391,26 @@
- (void)_doubleTapRecognized:(UITapGestureRecognizer *)gestureRecognizer
{
+ [self _resetIsDoubleTapPending];
_lastInteractionLocation = gestureRecognizer.location;
_smartMagnificationController->handleSmartMagnificationGesture(gestureRecognizer.location);
}
+- (void)_resetIsDoubleTapPending
+{
+ _isDoubleTapPending = NO;
+}
+
+- (void)_nonBlockingDoubleTapRecognized:(UITapGestureRecognizer *)gestureRecognizer
+{
+ _lastInteractionLocation = gestureRecognizer.location;
+ _isDoubleTapPending = YES;
+}
+
- (void)_twoFingerDoubleTapRecognized:(UITapGestureRecognizer *)gestureRecognizer
{
+ [self _resetIsDoubleTapPending];
_lastInteractionLocation = gestureRecognizer.location;
_smartMagnificationController->handleResetMagnificationGesture(gestureRecognizer.location);
@@ -1401,14 +1454,6 @@
_page->clearSelection();
}
-- (void)_didNotHandleTapAsClick:(const WebCore::IntPoint&)point
-{
- // FIXME: we should also take into account whether or not the UI delegate
- // has handled this notification.
- if (_hasValidPositionInformation && point == _positionInformation.point && _positionInformation.isDataDetectorLink)
- [self _showDataDetectorsSheet];
-}
-
- (void)_positionInformationDidChange:(const InteractionInformationAtPosition&)info
{
_positionInformation = info;
@@ -2460,6 +2505,8 @@
_tapHighlightInformation.color = [self _tapHighlightColorForFastClick:YES];
[_doubleTapGestureRecognizer setEnabled:enabled];
+ [_nonBlockingDoubleTapGestureRecognizer setEnabled:!enabled];
+ [self _resetIsDoubleTapPending];
}
- (void)accessoryAutoFill