Changeset 196679 in webkit


Ignore:
Timestamp:
Feb 16, 2016 7:27:05 PM (8 years ago)
Author:
dino@apple.com
Message:

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:]):

Location:
trunk/Source/WebKit2
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit2/ChangeLog

    r196674 r196679  
     12016-02-16  Dean Jackson  <dino@apple.com>
     2
     3        Allow double tap to zoom in fast-click pages
     4        https://bugs.webkit.org/show_bug.cgi?id=154318
     5        <rdar://problem/24223767>
     6
     7        Reviewed by Simon Fraser and Benjamin Poulain.
     8       
     9        Most of the patch comes from Jon Lee.
     10
     11        Our fast-click algorithm exposed a number of cases where
     12        people missed the double-tap-to-zoom behaviour. In particular,
     13        when you double tap on a large body of text, typical in
     14        blogs and articles.
     15
     16        This patch enhances the algorithm to have a parallel
     17        double-tap gesture recognizer in the situations where
     18        fast-click is enabled. This new gesture recongizer does
     19        not cause the single tap to block for 350ms, so clicks
     20        are still dispatched fast. If it fires, we already have
     21        some information about whether we have a pending double
     22        tap, based on the first tap.
     23
     24        * UIProcess/ios/PageClientImplIOS.mm:
     25        (WebKit::PageClientImpl::disableDoubleTapGesturesDuringTapIfNecessary): Remove the optimization
     26        that only told the content view to disable on pages that allowed double taps. We now allow
     27        them even on fast click pages.
     28
     29        * UIProcess/ios/WKContentViewInteraction.h: Add the new UITapGestureRecognizer for double taps
     30        in fast click pages. This is called nonBlockingDoubleTapGestureRecognizer because, unlike
     31        the existing DoubleTapGestureRecognizer, this one does not force the singleTapRecognizer
     32        to wait.
     33        * UIProcess/ios/WKContentViewInteraction.mm:
     34        (-[WKContentView setupInteraction]): Set up the new UITapGestureRecognizer.
     35        (-[WKContentView cleanupInteraction]): And remove it when we're done.
     36        (-[WKContentView _removeDefaultGestureRecognizers]): Ditto.
     37        (-[WKContentView _addDefaultGestureRecognizers]):
     38        (-[WKContentView _inspectorNodeSearchRecognized:]): Something happened, we are no longer in
     39        a potential double tap situation.
     40        (-[WKContentView _disableDoubleTapGesturesDuringTapIfNecessary:]): Remove the check
     41        for potential tap in progress.
     42        (-[WKContentView gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer:]):
     43        (-[WKContentView gestureRecognizerShouldBegin:]):
     44        (-[WKContentView _highlightLongPressRecognized:]): Again, something happened, so we are
     45        no longer in a double tap situation.
     46        (-[WKContentView _longPressRecognized:]): Ditto.
     47        (-[WKContentView _singleTapRecognized:]): Ditto.
     48        (-[WKContentView _doubleTapRecognized:]): Ditto.
     49        (-[WKContentView _resetIsDoubleTapPending]):
     50        (-[WKContentView _fastDoubleTapRecognized:]): We're now pending a double tap.
     51        (-[WKContentView _twoFingerDoubleTapRecognized:]):
     52        (-[WKContentView _didNotHandleTapAsClick:]): If we get here and we have a pending
     53        double tap, then trigger a zoom operation.
     54        (-[WKContentView _setDoubleTapGesturesEnabled:]):
     55
    1562016-02-16  Alex Christensen  <achristensen@webkit.org>
    257
  • trunk/Source/WebKit2/UIProcess/ios/PageClientImplIOS.mm

    r195769 r196679  
    262262void PageClientImpl::disableDoubleTapGesturesDuringTapIfNecessary(uint64_t requestID)
    263263{
    264     if (!m_webView._allowsDoubleTapGestures)
    265         return;
    266 
    267264    [m_contentView _disableDoubleTapGesturesDuringTapIfNecessary:requestID];
    268265}
  • trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.h

    r196037 r196679  
    103103    RetainPtr<UILongPressGestureRecognizer> _longPressGestureRecognizer;
    104104    RetainPtr<UITapGestureRecognizer> _doubleTapGestureRecognizer;
     105    RetainPtr<UITapGestureRecognizer> _nonBlockingDoubleTapGestureRecognizer;
    105106    RetainPtr<UITapGestureRecognizer> _twoFingerDoubleTapGestureRecognizer;
    106107    RetainPtr<WKInspectorNodeSearchGestureRecognizer> _inspectorNodeSearchGestureRecognizer;
     
    155156    BOOL _isTapHighlightIDValid;
    156157    BOOL _potentialTapInProgress;
     158    BOOL _isDoubleTapPending;
    157159    BOOL _highlightLongPressCanClick;
    158160    BOOL _hasTapHighlightForPotentialTap;
  • trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.mm

    r196645 r196679  
    462462    [self addGestureRecognizer:_singleTapGestureRecognizer.get()];
    463463
     464    _nonBlockingDoubleTapGestureRecognizer = adoptNS([[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(_nonBlockingDoubleTapRecognized:)]);
     465    [_nonBlockingDoubleTapGestureRecognizer setNumberOfTapsRequired:2];
     466    [_nonBlockingDoubleTapGestureRecognizer setDelegate:self];
     467    [_nonBlockingDoubleTapGestureRecognizer setEnabled:NO];
     468    [self addGestureRecognizer:_nonBlockingDoubleTapGestureRecognizer.get()];
     469
    464470    [self _createAndConfigureDoubleTapGestureRecognizer];
    465471
     
    495501    _smartMagnificationController = std::make_unique<SmartMagnificationController>(self);
    496502    _isExpectingFastSingleTapCommit = NO;
     503    _potentialTapInProgress = NO;
     504    _isDoubleTapPending = NO;
    497505    _showDebugTapHighlightsForFastClicking = [[NSUserDefaults standardUserDefaults] boolForKey:@"WebKitShowFastClickDebugTapHighlights"];
    498506}
     
    533541    [self removeGestureRecognizer:_doubleTapGestureRecognizer.get()];
    534542
     543    [_nonBlockingDoubleTapGestureRecognizer setDelegate:nil];
     544    [self removeGestureRecognizer:_nonBlockingDoubleTapGestureRecognizer.get()];
     545
    535546    [_twoFingerDoubleTapGestureRecognizer setDelegate:nil];
    536547    [self removeGestureRecognizer:_twoFingerDoubleTapGestureRecognizer.get()];
     
    560571    [self removeGestureRecognizer:_highlightLongPressGestureRecognizer.get()];
    561572    [self removeGestureRecognizer:_doubleTapGestureRecognizer.get()];
     573    [self removeGestureRecognizer:_nonBlockingDoubleTapGestureRecognizer.get()];
    562574    [self removeGestureRecognizer:_twoFingerDoubleTapGestureRecognizer.get()];
    563575}
     
    569581    [self addGestureRecognizer:_highlightLongPressGestureRecognizer.get()];
    570582    [self addGestureRecognizer:_doubleTapGestureRecognizer.get()];
     583    [self addGestureRecognizer:_nonBlockingDoubleTapGestureRecognizer.get()];
    571584    [self addGestureRecognizer:_twoFingerDoubleTapGestureRecognizer.get()];
    572585}
     
    733746{
    734747    ASSERT(_inspectorNodeSearchEnabled);
     748    [self _resetIsDoubleTapPending];
    735749
    736750    CGPoint point = [gestureRecognizer locationInView:self];
     
    921935- (void)_disableDoubleTapGesturesDuringTapIfNecessary:(uint64_t)requestID
    922936{
    923     if (!_potentialTapInProgress || _latestTapID != requestID)
     937    if (_latestTapID != requestID)
    924938        return;
    925939
     
    10501064        return YES;
    10511065
     1066    if (isSamePair(gestureRecognizer, otherGestureRecognizer, _singleTapGestureRecognizer.get(), _nonBlockingDoubleTapGestureRecognizer.get()))
     1067        return YES;
     1068
     1069    if (isSamePair(gestureRecognizer, otherGestureRecognizer, _highlightLongPressGestureRecognizer.get(), _nonBlockingDoubleTapGestureRecognizer.get()))
     1070        return YES;
     1071
    10521072    if (isSamePair(gestureRecognizer, otherGestureRecognizer, _highlightLongPressGestureRecognizer.get(), _previewSecondaryGestureRecognizer.get()))
    10531073        return YES;
     
    11131133    if (gestureRecognizer == _highlightLongPressGestureRecognizer
    11141134        || gestureRecognizer == _doubleTapGestureRecognizer
     1135        || gestureRecognizer == _nonBlockingDoubleTapGestureRecognizer
    11151136        || gestureRecognizer == _twoFingerDoubleTapGestureRecognizer
    11161137        || gestureRecognizer == _singleTapGestureRecognizer) {
     
    12341255{
    12351256    ASSERT(gestureRecognizer == _highlightLongPressGestureRecognizer);
     1257    [self _resetIsDoubleTapPending];
    12361258
    12371259    _lastInteractionLocation = gestureRecognizer.startPoint;
     
    12641286{
    12651287    ASSERT(gestureRecognizer == _longPressGestureRecognizer);
     1288    [self _resetIsDoubleTapPending];
    12661289
    12671290    _lastInteractionLocation = gestureRecognizer.startPoint;
     
    12881311    ASSERT(gestureRecognizer == _singleTapGestureRecognizer);
    12891312    ASSERT(!_potentialTapInProgress);
     1313    [self _resetIsDoubleTapPending];
    12901314
    12911315    _page->potentialTapAtPosition(gestureRecognizer.location, ++_latestTapID);
     
    13131337{
    13141338    [self _cancelInteraction];
     1339}
     1340
     1341- (void)_didNotHandleTapAsClick:(const WebCore::IntPoint&)point
     1342{
     1343    // FIXME: we should also take into account whether or not the UI delegate
     1344    // has handled this notification.
     1345    if (_hasValidPositionInformation && point == _positionInformation.point && _positionInformation.isDataDetectorLink) {
     1346        [self _showDataDetectorsSheet];
     1347        return;
     1348    }
     1349
     1350    if (!_isDoubleTapPending)
     1351        return;
     1352
     1353    _smartMagnificationController->handleSmartMagnificationGesture(_lastInteractionLocation);
     1354    _isDoubleTapPending = NO;
    13151355}
    13161356
     
    13521392- (void)_doubleTapRecognized:(UITapGestureRecognizer *)gestureRecognizer
    13531393{
     1394    [self _resetIsDoubleTapPending];
    13541395    _lastInteractionLocation = gestureRecognizer.location;
    13551396
     
    13571398}
    13581399
     1400- (void)_resetIsDoubleTapPending
     1401{
     1402    _isDoubleTapPending = NO;
     1403}
     1404
     1405- (void)_nonBlockingDoubleTapRecognized:(UITapGestureRecognizer *)gestureRecognizer
     1406{
     1407    _lastInteractionLocation = gestureRecognizer.location;
     1408    _isDoubleTapPending = YES;
     1409}
     1410
    13591411- (void)_twoFingerDoubleTapRecognized:(UITapGestureRecognizer *)gestureRecognizer
    13601412{
     1413    [self _resetIsDoubleTapPending];
    13611414    _lastInteractionLocation = gestureRecognizer.location;
    13621415
     
    14001453{
    14011454    _page->clearSelection();
    1402 }
    1403 
    1404 - (void)_didNotHandleTapAsClick:(const WebCore::IntPoint&)point
    1405 {
    1406     // FIXME: we should also take into account whether or not the UI delegate
    1407     // has handled this notification.
    1408     if (_hasValidPositionInformation && point == _positionInformation.point && _positionInformation.isDataDetectorLink)
    1409         [self _showDataDetectorsSheet];
    14101455}
    14111456
     
    24612506
    24622507    [_doubleTapGestureRecognizer setEnabled:enabled];
     2508    [_nonBlockingDoubleTapGestureRecognizer setEnabled:!enabled];
     2509    [self _resetIsDoubleTapPending];
    24632510}
    24642511
Note: See TracChangeset for help on using the changeset viewer.