Title: [191309] trunk/Source/WebKit2
Revision
191309
Author
wenson_hs...@apple.com
Date
2015-10-19 12:53:45 -0700 (Mon, 19 Oct 2015)

Log Message

Extend fast-clicking behavior to trigger on elements that have negligible zoom
https://bugs.webkit.org/show_bug.cgi?id=150248
<rdar://problem/23140069>

Reviewed by Simon Fraser.

Currently, fast-clicking only triggers on pages that have unscalable viewports. To allow more websites to benefit from fast-clicking
behavior, we generalize fast-clicking to also occur when tapping on elements for which double-tap-to-zoom would zoom the element in
or out by an insignificant amount. We define an insignificant amount of zoom to mean that zooming would increase the viewport scale
by less than a configurable threshold, or decrease the viewport scale by more than a configurable threshold. We accomplish this by
temporarily disabling the double tap gesture recognizer for the duration of the tap. This patch refactors some logic used to compute
zoomed viewports to make it possible to predict the change in viewport scale when double tapping to zoom. See the changes in
SmartMagnificationController and ViewGestureGeometryCollector for more details.

There are no new tests, since this patch does not change existing behavior. Instead, this patch adds the machinery needed for zoom-
dependent fast-clicking: by setting the preferences WebKitFastClickingEnabled and WebKitFastClickZoomThreshold, we will be able to tweak
the behavior dynamically.

* UIProcess/API/Cocoa/WKWebView.mm:
(-[WKWebView _didCommitLayerTree:]):
(-[WKWebView _contentZoomScale]):
(-[WKWebView _targetContentZoomScaleForRect:currentScale:fitEntireRect:minimumScale:maximumScale:]):
(-[WKWebView _zoomToRect:withOrigin:fitEntireRect:minimumScale:maximumScale:minimumScrollDistance:]):
(-[WKWebView _viewportIsUserScalable]):
* UIProcess/API/Cocoa/WKWebViewInternal.h:
* UIProcess/API/Cocoa/WKWebViewPrivate.h:
* UIProcess/PageClient.h:
* UIProcess/WebPageProxy.h:
* UIProcess/WebPageProxy.messages.in:
* UIProcess/ios/PageClientImplIOS.h:
* UIProcess/ios/PageClientImplIOS.mm:
(WebKit::PageClientImpl::disableDoubleTapGesturesUntilTapIsFinishedIfNecessary):
* UIProcess/ios/SmartMagnificationController.h:
* UIProcess/ios/SmartMagnificationController.mm:
(WebKit::SmartMagnificationController::adjustSmartMagnificationTargetRectAndZoomScales):
(WebKit::SmartMagnificationController::didCollectGeometryForSmartMagnificationGesture):
(WebKit::SmartMagnificationController::magnify):
* UIProcess/ios/WKContentViewInteraction.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView _didGetTapHighlightForRequest:color:quads:topLeftRadius:topRightRadius:bottomLeftRadius:bottomRightRadius:]):
(-[WKContentView _fastClickZoomThreshold]):
(-[WKContentView _allowDoubleTapToZoomForCurrentZoomScale:andTargetZoomScale:]):
(-[WKContentView _disableDoubleTapGesturesUntilTapIsFinishedIfNecessary:allowsDoubleTapZoom:targetRect:isReplaced:minimumScale:maximumScale:]):
(-[WKContentView _highlightLongPressRecognized:]):
(-[WKContentView _endPotentialTapAndEnableDoubleTapGesturesIfNecessary]):
(-[WKContentView _singleTapRecognized:]):
(cancelPotentialTapIfNecessary):
(-[WKContentView _singleTapCommited:]):
(-[WKContentView webSelectionRects]): Deleted.
* UIProcess/ios/WebPageProxyIOS.mm:
(WebKit::WebPageProxy::disableDoubleTapGesturesUntilTapIsFinishedIfNecessary):
* WebProcess/WebPage/ViewGestureGeometryCollector.cpp:
(WebKit::ViewGestureGeometryCollector::collectGeometryForSmartMagnificationGesture):
(WebKit::ViewGestureGeometryCollector::computeZoomInformationForNode):
* WebProcess/WebPage/ViewGestureGeometryCollector.h:
* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::potentialTapAtPosition):

Modified Paths

Diff

Modified: trunk/Source/WebKit2/ChangeLog (191308 => 191309)


--- trunk/Source/WebKit2/ChangeLog	2015-10-19 19:37:48 UTC (rev 191308)
+++ trunk/Source/WebKit2/ChangeLog	2015-10-19 19:53:45 UTC (rev 191309)
@@ -1,3 +1,63 @@
+2015-10-17  Wenson Hsieh  <wenson_hs...@apple.com>
+
+        Extend fast-clicking behavior to trigger on elements that have negligible zoom
+        https://bugs.webkit.org/show_bug.cgi?id=150248
+        <rdar://problem/23140069>
+
+        Reviewed by Simon Fraser.
+
+        Currently, fast-clicking only triggers on pages that have unscalable viewports. To allow more websites to benefit from fast-clicking
+        behavior, we generalize fast-clicking to also occur when tapping on elements for which double-tap-to-zoom would zoom the element in
+        or out by an insignificant amount. We define an insignificant amount of zoom to mean that zooming would increase the viewport scale
+        by less than a configurable threshold, or decrease the viewport scale by more than a configurable threshold. We accomplish this by
+        temporarily disabling the double tap gesture recognizer for the duration of the tap. This patch refactors some logic used to compute
+        zoomed viewports to make it possible to predict the change in viewport scale when double tapping to zoom. See the changes in
+        SmartMagnificationController and ViewGestureGeometryCollector for more details.
+
+        There are no new tests, since this patch does not change existing behavior. Instead, this patch adds the machinery needed for zoom-
+        dependent fast-clicking: by setting the preferences WebKitFastClickingEnabled and WebKitFastClickZoomThreshold, we will be able to tweak
+        the behavior dynamically.
+
+        * UIProcess/API/Cocoa/WKWebView.mm:
+        (-[WKWebView _didCommitLayerTree:]):
+        (-[WKWebView _contentZoomScale]):
+        (-[WKWebView _targetContentZoomScaleForRect:currentScale:fitEntireRect:minimumScale:maximumScale:]):
+        (-[WKWebView _zoomToRect:withOrigin:fitEntireRect:minimumScale:maximumScale:minimumScrollDistance:]):
+        (-[WKWebView _viewportIsUserScalable]):
+        * UIProcess/API/Cocoa/WKWebViewInternal.h:
+        * UIProcess/API/Cocoa/WKWebViewPrivate.h:
+        * UIProcess/PageClient.h:
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/WebPageProxy.messages.in:
+        * UIProcess/ios/PageClientImplIOS.h:
+        * UIProcess/ios/PageClientImplIOS.mm:
+        (WebKit::PageClientImpl::disableDoubleTapGesturesUntilTapIsFinishedIfNecessary):
+        * UIProcess/ios/SmartMagnificationController.h:
+        * UIProcess/ios/SmartMagnificationController.mm:
+        (WebKit::SmartMagnificationController::adjustSmartMagnificationTargetRectAndZoomScales):
+        (WebKit::SmartMagnificationController::didCollectGeometryForSmartMagnificationGesture):
+        (WebKit::SmartMagnificationController::magnify):
+        * UIProcess/ios/WKContentViewInteraction.h:
+        * UIProcess/ios/WKContentViewInteraction.mm:
+        (-[WKContentView _didGetTapHighlightForRequest:color:quads:topLeftRadius:topRightRadius:bottomLeftRadius:bottomRightRadius:]):
+        (-[WKContentView _fastClickZoomThreshold]):
+        (-[WKContentView _allowDoubleTapToZoomForCurrentZoomScale:andTargetZoomScale:]):
+        (-[WKContentView _disableDoubleTapGesturesUntilTapIsFinishedIfNecessary:allowsDoubleTapZoom:targetRect:isReplaced:minimumScale:maximumScale:]):
+        (-[WKContentView _highlightLongPressRecognized:]):
+        (-[WKContentView _endPotentialTapAndEnableDoubleTapGesturesIfNecessary]):
+        (-[WKContentView _singleTapRecognized:]):
+        (cancelPotentialTapIfNecessary):
+        (-[WKContentView _singleTapCommited:]):
+        (-[WKContentView webSelectionRects]): Deleted.
+        * UIProcess/ios/WebPageProxyIOS.mm:
+        (WebKit::WebPageProxy::disableDoubleTapGesturesUntilTapIsFinishedIfNecessary):
+        * WebProcess/WebPage/ViewGestureGeometryCollector.cpp:
+        (WebKit::ViewGestureGeometryCollector::collectGeometryForSmartMagnificationGesture):
+        (WebKit::ViewGestureGeometryCollector::computeZoomInformationForNode):
+        * WebProcess/WebPage/ViewGestureGeometryCollector.h:
+        * WebProcess/WebPage/ios/WebPageIOS.mm:
+        (WebKit::WebPage::potentialTapAtPosition):
+
 2015-10-19  Tim Horton  <timothy_hor...@apple.com>
 
         WKView being inside WKWebView leads to weird API issues

Modified: trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm (191308 => 191309)


--- trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm	2015-10-19 19:37:48 UTC (rev 191308)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebView.mm	2015-10-19 19:53:45 UTC (rev 191309)
@@ -997,7 +997,7 @@
     if (!layerTreeTransaction.scaleWasSetByUIProcess() && ![_scrollView isZooming] && ![_scrollView isZoomBouncing] && ![_scrollView _isAnimatingZoom])
         [_scrollView setZoomScale:layerTreeTransaction.pageScaleFactor()];
 
-    [_contentView _setDoubleTapGesturesEnabled:[_scrollView isZoomEnabled] && [_scrollView minimumZoomScale] < [_scrollView maximumZoomScale]];
+    [_contentView _setDoubleTapGesturesEnabled:self._viewportIsUserScalable];
 
     [self _updateScrollViewBackground];
 
@@ -1395,12 +1395,13 @@
                         force:YES];
 }
 
-- (BOOL)_zoomToRect:(WebCore::FloatRect)targetRect withOrigin:(WebCore::FloatPoint)origin fitEntireRect:(BOOL)fitEntireRect minimumScale:(double)minimumScale maximumScale:(double)maximumScale minimumScrollDistance:(float)minimumScrollDistance
+- (CGFloat)_contentZoomScale
 {
-    const float maximumScaleFactorDeltaForPanScroll = 0.02;
+    return contentZoomScale(self);
+}
 
-    double currentScale = contentZoomScale(self);
-
+- (CGFloat)_targetContentZoomScaleForRect:(const WebCore::FloatRect&)targetRect currentScale:(double)currentScale fitEntireRect:(BOOL)fitEntireRect minimumScale:(double)minimumScale maximumScale:(double)maximumScale
+{
     WebCore::FloatSize unobscuredContentSize([self _contentRectForUserInteraction].size);
     double horizontalScale = unobscuredContentSize.width() * currentScale / targetRect.width();
     double verticalScale = unobscuredContentSize.height() * currentScale / targetRect.height();
@@ -1408,7 +1409,16 @@
     horizontalScale = std::min(std::max(horizontalScale, minimumScale), maximumScale);
     verticalScale = std::min(std::max(verticalScale, minimumScale), maximumScale);
 
-    double targetScale = fitEntireRect ? std::min(horizontalScale, verticalScale) : horizontalScale;
+    return fitEntireRect ? std::min(horizontalScale, verticalScale) : horizontalScale;
+}
+
+- (BOOL)_zoomToRect:(WebCore::FloatRect)targetRect withOrigin:(WebCore::FloatPoint)origin fitEntireRect:(BOOL)fitEntireRect minimumScale:(double)minimumScale maximumScale:(double)maximumScale minimumScrollDistance:(float)minimumScrollDistance
+{
+    const float maximumScaleFactorDeltaForPanScroll = 0.02;
+
+    double currentScale = contentZoomScale(self);
+    double targetScale = [self _targetContentZoomScaleForRect:targetRect currentScale:currentScale fitEntireRect:fitEntireRect minimumScale:minimumScale maximumScale:maximumScale];
+
     if (fabs(targetScale - currentScale) < maximumScaleFactorDeltaForPanScroll) {
         if ([self _scrollToRect:targetRect origin:origin minimumScrollDistance:minimumScrollDistance])
             return true;
@@ -3066,6 +3076,11 @@
     return _viewportMetaTagWidth;
 }
 
+- (BOOL)_viewportIsUserScalable
+{
+    return [_scrollView isZoomEnabled] && [_scrollView minimumZoomScale] < [_scrollView maximumZoomScale];
+}
+
 - (_WKWebViewPrintFormatter *)_webViewPrintFormatter
 {
     UIViewPrintFormatter *viewPrintFormatter = self.viewPrintFormatter;

Modified: trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebViewInternal.h (191308 => 191309)


--- trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebViewInternal.h	2015-10-19 19:37:48 UTC (rev 191308)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebViewInternal.h	2015-10-19 19:53:45 UTC (rev 191309)
@@ -109,6 +109,9 @@
 - (void)_navigationGestureDidBegin;
 - (void)_navigationGestureDidEnd;
 
+- (CGFloat)_contentZoomScale;
+- (CGFloat)_targetContentZoomScaleForRect:(const WebCore::FloatRect&)targetRect currentScale:(double)currentScale fitEntireRect:(BOOL)fitEntireRect minimumScale:(double)minimumScale maximumScale:(double)maximumScale;
+
 @property (nonatomic, readonly) UIEdgeInsets _computedContentInset;
 #else
 @property (nonatomic, setter=_setIgnoresNonWheelEvents:) BOOL _ignoresNonWheelEvents;

Modified: trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebViewPrivate.h (191308 => 191309)


--- trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebViewPrivate.h	2015-10-19 19:37:48 UTC (rev 191308)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/WKWebViewPrivate.h	2015-10-19 19:53:45 UTC (rev 191309)
@@ -135,6 +135,7 @@
 
 // The viewport meta tag width is negative if the value is not defined.
 @property (nonatomic, readonly) CGFloat _viewportMetaTagWidth;
+@property (nonatomic, readonly) BOOL _viewportIsUserScalable;
 
 @property (nonatomic, readonly) _WKWebViewPrintFormatter *_webViewPrintFormatter;
 

Modified: trunk/Source/WebKit2/UIProcess/PageClient.h (191308 => 191309)


--- trunk/Source/WebKit2/UIProcess/PageClient.h	2015-10-19 19:37:48 UTC (rev 191308)
+++ trunk/Source/WebKit2/UIProcess/PageClient.h	2015-10-19 19:53:45 UTC (rev 191309)
@@ -294,6 +294,7 @@
     virtual void showPlaybackTargetPicker(bool hasVideo, const WebCore::IntRect& elementRect) = 0;
     virtual void zoomToRect(WebCore::FloatRect, double minimumScale, double maximumScale) = 0;
     virtual void didChangeViewportMetaTagWidth(float) = 0;
+    virtual void disableDoubleTapGesturesUntilTapIsFinishedIfNecessary(uint64_t requestID, bool allowsDoubleTapZoom, const WebCore::FloatRect& targetRect, bool isReplacedElement, double minimumScale, double maximumScale) = 0;
     virtual double minimumZoomScale() const = 0;
     virtual WebCore::FloatRect documentRect() const = 0;
     virtual void overflowScrollViewWillStartPanGesture() = 0;

Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.h (191308 => 191309)


--- trunk/Source/WebKit2/UIProcess/WebPageProxy.h	2015-10-19 19:37:48 UTC (rev 191308)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.h	2015-10-19 19:53:45 UTC (rev 191309)
@@ -509,6 +509,7 @@
     void commitPotentialTapFailed();
     void didNotHandleTapAsClick(const WebCore::IntPoint&);
     void viewportMetaTagWidthDidChange(float width);
+    void disableDoubleTapGesturesUntilTapIsFinishedIfNecessary(uint64_t requestID, bool allowsDoubleTapZoom, const WebCore::FloatRect& targetRect, bool isReplacedElement, double minimumScale, double maximumScale);
     void didFinishDrawingPagesToPDF(const IPC::DataReference&);
     void contentSizeCategoryDidChange(const String& contentSizeCategory);
     void getLookupContextAtPoint(const WebCore::IntPoint&, std::function<void(const String&, CallbackBase::Error)>);

Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.messages.in (191308 => 191309)


--- trunk/Source/WebKit2/UIProcess/WebPageProxy.messages.in	2015-10-19 19:37:48 UTC (rev 191308)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.messages.in	2015-10-19 19:53:45 UTC (rev 191309)
@@ -188,6 +188,7 @@
     CommitPotentialTapFailed()
     DidNotHandleTapAsClick(WebCore::IntPoint point)
     ViewportMetaTagWidthDidChange(float width)
+    DisableDoubleTapGesturesUntilTapIsFinishedIfNecessary(uint64_t requestID, bool allowsDoubleTapZoom, WebCore::FloatRect targetRect, bool isReplacedElement, double minimumScale, double maximumScale)
     DidFinishDrawingPagesToPDF(IPC::DataReference pdfData)
 #endif
 #if PLATFORM(GTK)

Modified: trunk/Source/WebKit2/UIProcess/ios/PageClientImplIOS.h (191308 => 191309)


--- trunk/Source/WebKit2/UIProcess/ios/PageClientImplIOS.h	2015-10-19 19:37:48 UTC (rev 191308)
+++ trunk/Source/WebKit2/UIProcess/ios/PageClientImplIOS.h	2015-10-19 19:53:45 UTC (rev 191309)
@@ -134,6 +134,7 @@
 
     virtual bool handleRunOpenPanel(WebPageProxy*, WebFrameProxy*, WebOpenPanelParameters*, WebOpenPanelResultListenerProxy*) override;
     virtual void didChangeViewportMetaTagWidth(float) override;
+    virtual void disableDoubleTapGesturesUntilTapIsFinishedIfNecessary(uint64_t requestID, bool allowsDoubleTapZoom, const WebCore::FloatRect& targetRect, bool isReplacedElement, double minimumScale, double maximumScale) override;
     virtual double minimumZoomScale() const override;
     virtual WebCore::FloatRect documentRect() const override;
 

Modified: trunk/Source/WebKit2/UIProcess/ios/PageClientImplIOS.mm (191308 => 191309)


--- trunk/Source/WebKit2/UIProcess/ios/PageClientImplIOS.mm	2015-10-19 19:37:48 UTC (rev 191308)
+++ trunk/Source/WebKit2/UIProcess/ios/PageClientImplIOS.mm	2015-10-19 19:53:45 UTC (rev 191309)
@@ -259,6 +259,14 @@
     [m_webView _setViewportMetaTagWidth:newWidth];
 }
 
+void PageClientImpl::disableDoubleTapGesturesUntilTapIsFinishedIfNecessary(uint64_t requestID, bool allowsDoubleTapZoom, const WebCore::FloatRect& targetRect, bool isReplacedElement, double minimumScale, double maximumScale)
+{
+    if (!m_webView._viewportIsUserScalable)
+        return;
+
+    [m_contentView _disableDoubleTapGesturesUntilTapIsFinishedIfNecessary:requestID allowsDoubleTapZoom:allowsDoubleTapZoom targetRect:targetRect isReplaced:isReplacedElement minimumScale:minimumScale maximumScale:maximumScale];
+}
+
 double PageClientImpl::minimumZoomScale() const
 {
     if (UIScrollView *scroller = [m_webView scrollView])

Modified: trunk/Source/WebKit2/UIProcess/ios/SmartMagnificationController.h (191308 => 191309)


--- trunk/Source/WebKit2/UIProcess/ios/SmartMagnificationController.h	2015-10-19 19:37:48 UTC (rev 191308)
+++ trunk/Source/WebKit2/UIProcess/ios/SmartMagnificationController.h	2015-10-19 19:53:45 UTC (rev 191309)
@@ -48,6 +48,7 @@
 
     void handleSmartMagnificationGesture(WebCore::FloatPoint origin);
     void handleResetMagnificationGesture(WebCore::FloatPoint origin);
+    void adjustSmartMagnificationTargetRectAndZoomScales(bool addMagnificationPadding, WebCore::FloatRect& targetRect, double& minimumScale, double& maximumScale);
 
 private:
     // IPC::MessageReceiver.

Modified: trunk/Source/WebKit2/UIProcess/ios/SmartMagnificationController.mm (191308 => 191309)


--- trunk/Source/WebKit2/UIProcess/ios/SmartMagnificationController.mm	2015-10-19 19:37:48 UTC (rev 191308)
+++ trunk/Source/WebKit2/UIProcess/ios/SmartMagnificationController.mm	2015-10-19 19:53:45 UTC (rev 191309)
@@ -78,6 +78,17 @@
     [m_contentView _zoomOutWithOrigin:origin];
 }
 
+void SmartMagnificationController::adjustSmartMagnificationTargetRectAndZoomScales(bool addMagnificationPadding, WebCore::FloatRect& targetRect, double& minimumScale, double& maximumScale)
+{
+    if (addMagnificationPadding) {
+        targetRect.inflateX(smartMagnificationElementPadding * targetRect.width());
+        targetRect.inflateY(smartMagnificationElementPadding * targetRect.height());
+    }
+
+    minimumScale = std::max(minimumScale, smartMagnificationMinimumScale);
+    maximumScale = std::min(maximumScale, smartMagnificationMaximumScale);
+}
+
 void SmartMagnificationController::didCollectGeometryForSmartMagnificationGesture(FloatPoint origin, FloatRect targetRect, FloatRect visibleContentRect, bool isReplacedElement, double viewportMinimumScale, double viewportMaximumScale)
 {
     if (targetRect.isEmpty()) {
@@ -85,15 +96,10 @@
         [m_contentView _zoomOutWithOrigin:origin];
         return;
     }
+    double minimumScale = viewportMinimumScale;
+    double maximumScale = viewportMaximumScale;
+    adjustSmartMagnificationTargetRectAndZoomScales(!isReplacedElement, targetRect, minimumScale, maximumScale);
 
-    if (!isReplacedElement) {
-        targetRect.inflateX(smartMagnificationElementPadding * targetRect.width());
-        targetRect.inflateY(smartMagnificationElementPadding * targetRect.height());
-    }
-
-    double maximumScale = std::min(viewportMaximumScale, smartMagnificationMaximumScale);
-    double minimumScale = std::max(viewportMinimumScale, smartMagnificationMinimumScale);
-
     // FIXME: Check if text selection wants to consume the double tap before we attempt magnification.
 
     // If the content already fits in the scroll view and we're already zoomed in to the target scale,
@@ -118,12 +124,9 @@
 
 void SmartMagnificationController::magnify(FloatPoint origin, FloatRect targetRect, FloatRect visibleContentRect, double viewportMinimumScale, double viewportMaximumScale)
 {
-    targetRect.inflateX(smartMagnificationElementPadding * targetRect.width());
-    targetRect.inflateY(smartMagnificationElementPadding * targetRect.height());
-
-    double maximumScale = std::min(viewportMaximumScale, smartMagnificationMaximumScale);
-    double minimumScale = std::max(viewportMinimumScale, smartMagnificationMinimumScale);
-
+    double maximumScale = viewportMaximumScale;
+    double minimumScale = viewportMinimumScale;
+    adjustSmartMagnificationTargetRectAndZoomScales(true, targetRect, minimumScale, maximumScale);
     [m_contentView _zoomToRect:targetRect withOrigin:origin fitEntireRect:NO minimumScale:minimumScale maximumScale:maximumScale minimumScrollDistance:0];
 }
 

Modified: trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.h (191308 => 191309)


--- trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.h	2015-10-19 19:37:48 UTC (rev 191308)
+++ trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.h	2015-10-19 19:53:45 UTC (rev 191309)
@@ -126,7 +126,7 @@
 
     id <UITextInputDelegate> _inputDelegate;
 
-    uint64_t _latestTapHighlightID;
+    uint64_t _latestTapID;
     struct TapHighlightInformation {
         WebCore::Color color;
         Vector<WebCore::FloatQuad> quads;
@@ -182,6 +182,7 @@
 - (void)_commitPotentialTapFailed;
 - (void)_didGetTapHighlightForRequest:(uint64_t)requestID color:(const WebCore::Color&)color quads:(const Vector<WebCore::FloatQuad>&)highlightedQuads topLeftRadius:(const WebCore::IntSize&)topLeftRadius topRightRadius:(const WebCore::IntSize&)topRightRadius bottomLeftRadius:(const WebCore::IntSize&)bottomLeftRadius bottomRightRadius:(const WebCore::IntSize&)bottomRightRadius;
 
+- (void)_disableDoubleTapGesturesUntilTapIsFinishedIfNecessary:(uint64_t)requestID allowsDoubleTapZoom:(bool)allowsDoubleTapZoom targetRect:(WebCore::FloatRect)targetRect isReplaced:(BOOL)isReplacedElement minimumScale:(double)minimumScale maximumScale:(double)maximumScale;
 - (void)_startAssistingNode:(const WebKit::AssistedNodeInformation&)information userIsInteracting:(BOOL)userIsInteracting blurPreviousNode:(BOOL)blurPreviousNode userObject:(NSObject <NSSecureCoding> *)userObject;
 - (void)_stopAssistingNode;
 - (void)_selectionChanged;

Modified: trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.mm (191308 => 191309)


--- trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.mm	2015-10-19 19:37:48 UTC (rev 191308)
+++ trunk/Source/WebKit2/UIProcess/ios/WKContentViewInteraction.mm	2015-10-19 19:53:45 UTC (rev 191309)
@@ -831,7 +831,7 @@
 
 - (void)_didGetTapHighlightForRequest:(uint64_t)requestID color:(const WebCore::Color&)color quads:(const Vector<WebCore::FloatQuad>&)highlightedQuads topLeftRadius:(const WebCore::IntSize&)topLeftRadius topRightRadius:(const WebCore::IntSize&)topRightRadius bottomLeftRadius:(const WebCore::IntSize&)bottomLeftRadius bottomRightRadius:(const WebCore::IntSize&)bottomRightRadius
 {
-    if (!_isTapHighlightIDValid || _latestTapHighlightID != requestID)
+    if (!_isTapHighlightIDValid || _latestTapID != requestID)
         return;
 
     _isTapHighlightIDValid = NO;
@@ -851,6 +851,44 @@
     [self _showTapHighlight];
 }
 
+- (CGFloat)_fastClickZoomThreshold
+{
+    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
+    if (![defaults boolForKey:@"WebKitFastClickingEnabled"])
+        return 0;
+
+    return [defaults floatForKey:@"WebKitFastClickZoomThreshold"];
+}
+
+- (BOOL)_allowDoubleTapToZoomForCurrentZoomScale:(CGFloat)currentZoomScale andTargetZoomScale:(CGFloat)targetZoomScale
+{
+    CGFloat zoomThreshold = [self _fastClickZoomThreshold];
+    if (!zoomThreshold)
+        return YES;
+
+    CGFloat minimumZoomRatioForDoubleTapToZoomIn = 1 + zoomThreshold;
+    CGFloat maximumZoomRatioForDoubleTapToZoomOut = 1 / minimumZoomRatioForDoubleTapToZoomIn;
+    CGFloat zoomRatio = targetZoomScale / currentZoomScale;
+    return zoomRatio < maximumZoomRatioForDoubleTapToZoomOut || zoomRatio > minimumZoomRatioForDoubleTapToZoomIn;
+}
+
+- (void)_disableDoubleTapGesturesUntilTapIsFinishedIfNecessary:(uint64_t)requestID allowsDoubleTapZoom:(bool)allowsDoubleTapZoom targetRect:(WebCore::FloatRect)targetRect isReplaced:(BOOL)isReplacedElement minimumScale:(double)minimumScale maximumScale:(double)maximumScale
+{
+    if (!_potentialTapInProgress || _latestTapID != requestID)
+        return;
+
+    if (allowsDoubleTapZoom) {
+        // Though the element allows us to zoom in on double tap, we avoid this behavior in favor of fast clicking if the difference in scale is insignificant.
+        _smartMagnificationController->adjustSmartMagnificationTargetRectAndZoomScales(!isReplacedElement, targetRect, minimumScale, maximumScale);
+        CGFloat currentZoomScale = [_webView _contentZoomScale];
+        CGFloat targetZoomScale = [_webView _targetContentZoomScaleForRect:targetRect currentScale:currentZoomScale fitEntireRect:isReplacedElement minimumScale:minimumScale maximumScale:maximumScale];
+        if ([self _allowDoubleTapToZoomForCurrentZoomScale:currentZoomScale andTargetZoomScale:targetZoomScale])
+            return;
+    }
+
+    [self _setDoubleTapGesturesEnabled:NO];
+}
+
 - (void)_cancelLongPressGestureRecognizer
 {
     [_highlightLongPressGestureRecognizer cancel];
@@ -1155,7 +1193,7 @@
     case UIGestureRecognizerStateBegan:
         _highlightLongPressCanClick = YES;
         cancelPotentialTapIfNecessary(self);
-        _page->tapHighlightAtPosition([gestureRecognizer startPoint], ++_latestTapHighlightID);
+        _page->tapHighlightAtPosition([gestureRecognizer startPoint], ++_latestTapID);
         _isTapHighlightIDValid = YES;
         break;
     case UIGestureRecognizerStateEnded:
@@ -1190,12 +1228,20 @@
     }
 }
 
+- (void)_endPotentialTapAndEnableDoubleTapGesturesIfNecessary
+{
+    if (_webView._viewportIsUserScalable)
+        [self _setDoubleTapGesturesEnabled:YES];
+
+    _potentialTapInProgress = NO;
+}
+
 - (void)_singleTapRecognized:(UITapGestureRecognizer *)gestureRecognizer
 {
     ASSERT(gestureRecognizer == _singleTapGestureRecognizer);
     ASSERT(!_potentialTapInProgress);
 
-    _page->potentialTapAtPosition(gestureRecognizer.location, ++_latestTapHighlightID);
+    _page->potentialTapAtPosition(gestureRecognizer.location, ++_latestTapID);
     _potentialTapInProgress = YES;
     _isTapHighlightIDValid = YES;
 }
@@ -1203,7 +1249,7 @@
 static void cancelPotentialTapIfNecessary(WKContentView* contentView)
 {
     if (contentView->_potentialTapInProgress) {
-        contentView->_potentialTapInProgress = NO;
+        [contentView _endPotentialTapAndEnableDoubleTapGesturesIfNecessary];
         [contentView _cancelInteraction];
         contentView->_page->cancelPotentialTap();
     }
@@ -1242,7 +1288,7 @@
 
     _lastInteractionLocation = gestureRecognizer.location;
 
-    _potentialTapInProgress = NO;
+    [self _endPotentialTapAndEnableDoubleTapGesturesIfNecessary];
 
     if (_hasTapHighlightForPotentialTap) {
         [self _showTapHighlight];

Modified: trunk/Source/WebKit2/UIProcess/ios/WebPageProxyIOS.mm (191308 => 191309)


--- trunk/Source/WebKit2/UIProcess/ios/WebPageProxyIOS.mm	2015-10-19 19:37:48 UTC (rev 191308)
+++ trunk/Source/WebKit2/UIProcess/ios/WebPageProxyIOS.mm	2015-10-19 19:53:45 UTC (rev 191309)
@@ -937,6 +937,11 @@
     m_pageClient.didChangeViewportMetaTagWidth(width);
 }
 
+void WebPageProxy::disableDoubleTapGesturesUntilTapIsFinishedIfNecessary(uint64_t requestID, bool allowsDoubleTapZoom, const WebCore::FloatRect& targetRect, bool isReplacedElement, double minimumScale, double maximumScale)
+{
+    m_pageClient.disableDoubleTapGesturesUntilTapIsFinishedIfNecessary(requestID, allowsDoubleTapZoom, targetRect, isReplacedElement, minimumScale, maximumScale);
+}
+
 void WebPageProxy::didFinishDrawingPagesToPDF(const IPC::DataReference& pdfData)
 {
     m_pageClient.didFinishDrawingPagesToPDF(pdfData);

Modified: trunk/Source/WebKit2/WebProcess/WebPage/ViewGestureGeometryCollector.cpp (191308 => 191309)


--- trunk/Source/WebKit2/WebProcess/WebPage/ViewGestureGeometryCollector.cpp	2015-10-19 19:37:48 UTC (rev 191308)
+++ trunk/Source/WebKit2/WebProcess/WebPage/ViewGestureGeometryCollector.cpp	2015-10-19 19:53:45 UTC (rev 191309)
@@ -86,39 +86,45 @@
     HitTestResult hitTestResult = HitTestResult(originInContentsSpace);
 
     m_webPage.mainFrameView()->renderView()->hitTest(HitTestRequest(), hitTestResult);
+    Node* node = hitTestResult.innerNode();
+    if (!node) {
+        dispatchDidCollectGeometryForSmartMagnificationGesture(FloatPoint(), FloatRect(), FloatRect(), false, 0, 0);
+        return;
+    }
 
-    if (Node* node = hitTestResult.innerNode()) {
-        bool isReplaced;
-        FloatRect renderRect = node->renderRect(&isReplaced);
+    bool isReplaced;
+    FloatRect renderRect;
+    double viewportMinimumScale;
+    double viewportMaximumScale;
 
-        if (node->document().isImageDocument()) {
-            if (HTMLImageElement* imageElement = static_cast<ImageDocument&>(node->document()).imageElement()) {
-                if (node != imageElement) {
-                    renderRect = imageElement->renderRect(&isReplaced);
-                    FloatPoint newOrigin = origin;
-                    if (origin.x() < renderRect.x() || origin.x() > renderRect.maxX())
-                        newOrigin.setX(renderRect.x() + renderRect.width() / 2);
-                    if (origin.y() < renderRect.y() || origin.y() > renderRect.maxY())
-                        newOrigin.setY(renderRect.y() + renderRect.height() / 2);
-                    origin = newOrigin;
-                }
-                isReplaced = true;
+    computeZoomInformationForNode(*node, origin, renderRect, isReplaced, viewportMinimumScale, viewportMaximumScale);
+    dispatchDidCollectGeometryForSmartMagnificationGesture(origin, renderRect, visibleContentRect, isReplaced, viewportMinimumScale, viewportMaximumScale);
+}
+
+void ViewGestureGeometryCollector::computeZoomInformationForNode(Node& node, FloatPoint& origin, FloatRect& renderRect, bool& isReplaced, double& viewportMinimumScale, double& viewportMaximumScale)
+{
+    renderRect = node.renderRect(&isReplaced);
+    if (node.document().isImageDocument()) {
+        if (HTMLImageElement* imageElement = static_cast<ImageDocument&>(node.document()).imageElement()) {
+            if (&node != imageElement) {
+                renderRect = imageElement->renderRect(&isReplaced);
+                FloatPoint newOrigin = origin;
+                if (origin.x() < renderRect.x() || origin.x() > renderRect.maxX())
+                    newOrigin.setX(renderRect.x() + renderRect.width() / 2);
+                if (origin.y() < renderRect.y() || origin.y() > renderRect.maxY())
+                    newOrigin.setY(renderRect.y() + renderRect.height() / 2);
+                origin = newOrigin;
             }
+            isReplaced = true;
         }
-
+    }
 #if PLATFORM(MAC)
-        double viewportMinimumScale = 0;
-        double viewportMaximumScale = std::numeric_limits<double>::max();
+    viewportMinimumScale = 0;
+    viewportMaximumScale = std::numeric_limits<double>::max();
 #else
-        double viewportMinimumScale = m_webPage.minimumPageScaleFactor();
-        double viewportMaximumScale = m_webPage.maximumPageScaleFactor();
+    viewportMinimumScale = m_webPage.minimumPageScaleFactor();
+    viewportMaximumScale = m_webPage.maximumPageScaleFactor();
 #endif
-
-        dispatchDidCollectGeometryForSmartMagnificationGesture(origin, renderRect, visibleContentRect, isReplaced, viewportMinimumScale, viewportMaximumScale);
-        return;
-    }
-
-    dispatchDidCollectGeometryForSmartMagnificationGesture(FloatPoint(), FloatRect(), FloatRect(), false, 0, 0);
 }
 
 #if PLATFORM(MAC)

Modified: trunk/Source/WebKit2/WebProcess/WebPage/ViewGestureGeometryCollector.h (191308 => 191309)


--- trunk/Source/WebKit2/WebProcess/WebPage/ViewGestureGeometryCollector.h	2015-10-19 19:37:48 UTC (rev 191308)
+++ trunk/Source/WebKit2/WebProcess/WebPage/ViewGestureGeometryCollector.h	2015-10-19 19:53:45 UTC (rev 191309)
@@ -32,6 +32,7 @@
 namespace WebCore {
 class FloatPoint;
 class FloatRect;
+class Node;
 }
 
 namespace WebKit {
@@ -44,6 +45,7 @@
     ~ViewGestureGeometryCollector();
 
     void mainFrameDidLayout();
+    void computeZoomInformationForNode(WebCore::Node&, WebCore::FloatPoint& origin, WebCore::FloatRect& renderRect, bool& isReplaced, double& viewportMinimumScale, double& viewportMaximumScale);
 
 private:
     // IPC::MessageReceiver.

Modified: trunk/Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm (191308 => 191309)


--- trunk/Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm	2015-10-19 19:37:48 UTC (rev 191308)
+++ trunk/Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm	2015-10-19 19:53:45 UTC (rev 191309)
@@ -662,6 +662,16 @@
 {
     m_potentialTapNode = m_page->mainFrame().nodeRespondingToClickEvents(position, m_potentialTapLocation);
     sendTapHighlightForNodeIfNecessary(requestID, m_potentialTapNode.get());
+    if (m_potentialTapNode) {
+        FloatPoint origin = position;
+        FloatRect renderRect;
+        bool isReplaced;
+        double viewportMinimumScale;
+        double viewportMaximumScale;
+
+        m_viewGestureGeometryCollector.computeZoomInformationForNode(*m_potentialTapNode.get(), origin, renderRect, isReplaced, viewportMinimumScale, viewportMaximumScale);
+        send(Messages::WebPageProxy::DisableDoubleTapGesturesUntilTapIsFinishedIfNecessary(requestID, true, renderRect, isReplaced, viewportMinimumScale, viewportMaximumScale));
+    }
 }
 
 void WebPage::commitPotentialTap(uint64_t lastLayerTreeTransactionId)
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to