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):
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@191309
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2015-10-17 Wenson Hsieh <wenson_hsieh@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_horton@apple.com>
WKView being inside WKWebView leads to weird API issues
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];
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;
-
- double currentScale = contentZoomScale(self);
+ return 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();
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;
return _viewportMetaTagWidth;
}
+- (BOOL)_viewportIsUserScalable
+{
+ return [_scrollView isZoomEnabled] && [_scrollView minimumZoomScale] < [_scrollView maximumZoomScale];
+}
+
- (_WKWebViewPrintFormatter *)_webViewPrintFormatter
{
UIViewPrintFormatter *viewPrintFormatter = self.viewPrintFormatter;
- (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;
// 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;
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;
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)>);
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)
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;
[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])
void handleSmartMagnificationGesture(WebCore::FloatPoint origin);
void handleResetMagnificationGesture(WebCore::FloatPoint origin);
+ void adjustSmartMagnificationTargetRectAndZoomScales(bool addMagnificationPadding, WebCore::FloatRect& targetRect, double& minimumScale, double& maximumScale);
private:
// IPC::MessageReceiver.
[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()) {
[m_contentView _zoomOutWithOrigin:origin];
return;
}
-
- if (!isReplacedElement) {
- targetRect.inflateX(smartMagnificationElementPadding * targetRect.width());
- targetRect.inflateY(smartMagnificationElementPadding * targetRect.height());
- }
-
- double maximumScale = std::min(viewportMaximumScale, smartMagnificationMaximumScale);
- double minimumScale = std::max(viewportMinimumScale, smartMagnificationMinimumScale);
+ double minimumScale = viewportMinimumScale;
+ double maximumScale = viewportMaximumScale;
+ adjustSmartMagnificationTargetRectAndZoomScales(!isReplacedElement, targetRect, minimumScale, maximumScale);
// FIXME: Check if text selection wants to consume the double tap before we attempt magnification.
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];
}
id <UITextInputDelegate> _inputDelegate;
- uint64_t _latestTapHighlightID;
+ uint64_t _latestTapID;
struct TapHighlightInformation {
WebCore::Color color;
Vector<WebCore::FloatQuad> quads;
- (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;
- (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;
[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];
case UIGestureRecognizerStateBegan:
_highlightLongPressCanClick = YES;
cancelPotentialTapIfNecessary(self);
- _page->tapHighlightAtPosition([gestureRecognizer startPoint], ++_latestTapHighlightID);
+ _page->tapHighlightAtPosition([gestureRecognizer startPoint], ++_latestTapID);
_isTapHighlightIDValid = YES;
break;
case UIGestureRecognizerStateEnded:
}
}
+- (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;
}
static void cancelPotentialTapIfNecessary(WKContentView* contentView)
{
if (contentView->_potentialTapInProgress) {
- contentView->_potentialTapInProgress = NO;
+ [contentView _endPotentialTapAndEnableDoubleTapGesturesIfNecessary];
[contentView _cancelInteraction];
contentView->_page->cancelPotentialTap();
}
_lastInteractionLocation = gestureRecognizer.location;
- _potentialTapInProgress = NO;
+ [self _endPotentialTapAndEnableDoubleTapGesturesIfNecessary];
if (_hasTapHighlightForPotentialTap) {
[self _showTapHighlight];
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);
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;
+ }
+
+ bool isReplaced;
+ FloatRect renderRect;
+ double viewportMinimumScale;
+ double viewportMaximumScale;
- if (Node* node = hitTestResult.innerNode()) {
- bool isReplaced;
- FloatRect 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;
+ 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)
namespace WebCore {
class FloatPoint;
class FloatRect;
+class Node;
}
namespace WebKit {
~ViewGestureGeometryCollector();
void mainFrameDidLayout();
+ void computeZoomInformationForNode(WebCore::Node&, WebCore::FloatPoint& origin, WebCore::FloatRect& renderRect, bool& isReplaced, double& viewportMinimumScale, double& viewportMaximumScale);
private:
// IPC::MessageReceiver.
{
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)