Chromium Code Reviews| Index: Source/web/WebViewImpl.cpp | 
| diff --git a/Source/web/WebViewImpl.cpp b/Source/web/WebViewImpl.cpp | 
| index eaa7eab729498ecb75673326c935e7de35609570..486a9c54a4b5e664c42f4a5df460c73e5e1a7cc9 100644 | 
| --- a/Source/web/WebViewImpl.cpp | 
| +++ b/Source/web/WebViewImpl.cpp | 
| @@ -190,6 +190,9 @@ static const float doubleTapZoomContentMinimumMargin = 2; | 
| static const double doubleTapZoomAnimationDurationInSeconds = 0.25; | 
| static const float doubleTapZoomAlreadyLegibleRatio = 1.2f; | 
| +static const double multipleTargetsZoomAnimationDurationInSeconds = 0.25; | 
| +static const double findInPageAnimationDurationInSeconds = 0; | 
| + | 
| // Constants for viewport anchoring on resize. | 
| static const float viewportAnchorXCoord = 0.5f; | 
| static const float viewportAnchorYCoord = 0; | 
| @@ -383,9 +386,9 @@ WebViewImpl::WebViewImpl(WebViewClient* client) | 
| , m_exitFullscreenPageScaleFactor(0) | 
| , m_doubleTapZoomPageScaleFactor(0) | 
| , m_doubleTapZoomPending(false) | 
| - , m_enableFakeDoubleTapAnimationForTesting(false) | 
| - , m_fakeDoubleTapPageScaleFactor(0) | 
| - , m_fakeDoubleTapUseAnchor(false) | 
| + , m_enableFakePageScaleAnimationForTesting(false) | 
| + , m_fakePageScaleAnimationPageScaleFactor(0) | 
| + , m_fakePageScaleAnimationUseAnchor(false) | 
| , m_contextMenuAllowed(false) | 
| , m_doingDragAndDrop(false) | 
| , m_ignoreInputEvents(false) | 
| @@ -773,7 +776,7 @@ bool WebViewImpl::handleGestureEvent(const WebGestureEvent& event) | 
| case WebInputEvent::GestureDoubleTap: | 
| if (m_webSettings->doubleTapToZoomEnabled() && minimumPageScaleFactor() != maximumPageScaleFactor()) { | 
| m_client->cancelScheduledContentIntents(); | 
| - animateZoomAroundPoint(platformEvent.position(), DoubleTap); | 
| + animateDoubleTapZoom(platformEvent.position()); | 
| } | 
| // GestureDoubleTap is currently only used by Android for zooming. For WebCore, | 
| // GestureTap with tap count = 2 is used instead. So we drop GestureDoubleTap here. | 
| @@ -824,10 +827,10 @@ bool WebViewImpl::startPageScaleAnimation(const IntPoint& targetPosition, bool u | 
| if (useAnchor && newScale == pageScaleFactor()) | 
| return false; | 
| - if (m_enableFakeDoubleTapAnimationForTesting) { | 
| - m_fakeDoubleTapTargetPosition = targetPosition; | 
| - m_fakeDoubleTapUseAnchor = useAnchor; | 
| - m_fakeDoubleTapPageScaleFactor = newScale; | 
| + if (m_enableFakePageScaleAnimationForTesting) { | 
| + m_fakePageScaleAnimationTargetPosition = targetPosition; | 
| + m_fakePageScaleAnimationUseAnchor = useAnchor; | 
| + m_fakePageScaleAnimationPageScaleFactor = newScale; | 
| } else { | 
| if (!m_layerTreeView) | 
| return false; | 
| @@ -836,9 +839,9 @@ bool WebViewImpl::startPageScaleAnimation(const IntPoint& targetPosition, bool u | 
| return true; | 
| } | 
| -void WebViewImpl::enableFakeDoubleTapAnimationForTesting(bool enable) | 
| +void WebViewImpl::enableFakePageScaleAnimationForTesting(bool enable) | 
| { | 
| - m_enableFakeDoubleTapAnimationForTesting = enable; | 
| + m_enableFakePageScaleAnimationForTesting = enable; | 
| } | 
| WebViewBenchmarkSupport* WebViewImpl::benchmarkSupport() | 
| @@ -1065,15 +1068,20 @@ bool WebViewImpl::handleCharEvent(const WebKeyboardEvent& event) | 
| return true; | 
| } | 
| -WebRect WebViewImpl::computeBlockBounds(const WebRect& rect, AutoZoomType zoomType) | 
| +WebRect WebViewImpl::computeBlockBounds( | 
| + const WebRect& rect, | 
| + bool ignoreClipping) | 
| { | 
| if (!mainFrameImpl()) | 
| return WebRect(); | 
| // Use the rect-based hit test to find the node. | 
| IntPoint point = mainFrameImpl()->frameView()->windowToContents(IntPoint(rect.x, rect.y)); | 
| - HitTestRequest::HitTestRequestType hitType = HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::DisallowShadowContent | 
| - | ((zoomType == FindInPage) ? HitTestRequest::IgnoreClipping : 0); | 
| + HitTestRequest::HitTestRequestType hitType = | 
| + HitTestRequest::ReadOnly | | 
| + HitTestRequest::Active | | 
| + HitTestRequest::DisallowShadowContent | | 
| + (ignoreClipping ? HitTestRequest::IgnoreClipping : 0); | 
| HitTestResult result = mainFrameImpl()->frame()->eventHandler()->hitTestResultAtPoint(point, hitType, IntSize(rect.width, rect.height)); | 
| Node* node = result.innerNonSharedNode(); | 
| @@ -1125,21 +1133,17 @@ WebRect WebViewImpl::widenRectWithinPageBounds(const WebRect& source, int target | 
| return WebRect(newX, source.y, newWidth, source.height); | 
| } | 
| -void WebViewImpl::computeScaleAndScrollForHitRect(const WebRect& hitRect, AutoZoomType zoomType, float& scale, WebPoint& scroll, bool& isAnchor) | 
| +void WebViewImpl::computeScaleAndScrollForHitRect( | 
| + const WebRect& hitRect, | 
| 
 
aelias_OOO_until_Jul13
2013/07/27 05:59:24
Since this doesn't really take a hitrect anymore,
 
 | 
| + float padding, | 
| + float& scale, | 
| + WebPoint& scroll, | 
| + bool& doubleTapShouldZoomOut) | 
| { | 
| scale = pageScaleFactor(); | 
| scroll.x = scroll.y = 0; | 
| - WebRect targetRect = hitRect; | 
| - // Padding only depends on page scale when triggered by manually tapping | 
| - int padding = (zoomType == DoubleTap) ? touchPointPadding : nonUserInitiatedPointPadding; | 
| - if (targetRect.isEmpty()) | 
| - targetRect.width = targetRect.height = padding; | 
| - WebRect rect = computeBlockBounds(targetRect, zoomType); | 
| - if (zoomType == FindInPage && rect.isEmpty()) { | 
| - // Keep current scale (no need to scroll as x,y will normally already | 
| - // be visible). FIXME: Revisit this if it isn't always true. | 
| - return; | 
| - } | 
| + | 
| + WebRect rect = hitRect; | 
| bool scaleUnchanged = true; | 
| if (!rect.isEmpty()) { | 
| @@ -1176,46 +1180,40 @@ void WebViewImpl::computeScaleAndScrollForHitRect(const WebRect& hitRect, AutoZo | 
| bool stillAtPreviousDoubleTapScale = (pageScaleFactor() == m_doubleTapZoomPageScaleFactor | 
| && m_doubleTapZoomPageScaleFactor != minimumPageScaleFactor()) | 
| || m_doubleTapZoomPending; | 
| - if (zoomType == DoubleTap && (rect.isEmpty() || scaleUnchanged || stillAtPreviousDoubleTapScale)) { | 
| - // Zoom out to minimum scale. | 
| - scale = minimumPageScaleFactor(); | 
| - scroll = WebPoint(hitRect.x, hitRect.y); | 
| - isAnchor = true; | 
| + | 
| + doubleTapShouldZoomOut = | 
| + rect.isEmpty() || scaleUnchanged || stillAtPreviousDoubleTapScale; | 
| + | 
| + // FIXME: If this is being called for auto zoom during find in page, | 
| + // then if the user manually zooms in it'd be nice to preserve the | 
| + // relative increase in zoom they caused (if they zoom out then it's ok | 
| + // to zoom them back in again). This isn't compatible with our current | 
| + // double-tap zoom strategy (fitting the containing block to the screen) | 
| + // though. | 
| + | 
| + float screenWidth = m_size.width / scale; | 
| + float screenHeight = m_size.height / scale; | 
| + | 
| + // Scroll to vertically align the block. | 
| + if (rect.height < screenHeight) { | 
| + // Vertically center short blocks. | 
| + rect.y -= 0.5 * (screenHeight - rect.height); | 
| } else { | 
| - // FIXME: If this is being called for auto zoom during find in page, | 
| - // then if the user manually zooms in it'd be nice to preserve the | 
| - // relative increase in zoom they caused (if they zoom out then it's ok | 
| - // to zoom them back in again). This isn't compatible with our current | 
| - // double-tap zoom strategy (fitting the containing block to the screen) | 
| - // though. | 
| - | 
| - float screenWidth = m_size.width / scale; | 
| - float screenHeight = m_size.height / scale; | 
| - | 
| - // Scroll to vertically align the block. | 
| - if (rect.height < screenHeight) { | 
| - // Vertically center short blocks. | 
| - rect.y -= 0.5 * (screenHeight - rect.height); | 
| - } else { | 
| - // Ensure position we're zooming to (+ padding) isn't off the bottom of | 
| - // the screen. | 
| - rect.y = max<float>(rect.y, hitRect.y + padding - screenHeight); | 
| - } // Otherwise top align the block. | 
| - | 
| - // Do the same thing for horizontal alignment. | 
| - if (rect.width < screenWidth) | 
| - rect.x -= 0.5 * (screenWidth - rect.width); | 
| - else | 
| - rect.x = max<float>(rect.x, hitRect.x + padding - screenWidth); | 
| - scroll.x = rect.x; | 
| - scroll.y = rect.y; | 
| - isAnchor = false; | 
| - } | 
| + // Ensure position we're zooming to (+ padding) isn't off the bottom of | 
| + // the screen. | 
| + rect.y = max<float>(rect.y, hitRect.y + padding - screenHeight); | 
| + } // Otherwise top align the block. | 
| + | 
| + // Do the same thing for horizontal alignment. | 
| + if (rect.width < screenWidth) | 
| + rect.x -= 0.5 * (screenWidth - rect.width); | 
| + else | 
| + rect.x = max<float>(rect.x, hitRect.x + padding - screenWidth); | 
| + scroll.x = rect.x; | 
| + scroll.y = rect.y; | 
| scale = clampPageScaleFactorToLimits(scale); | 
| scroll = mainFrameImpl()->frameView()->windowToContents(scroll); | 
| - if (!isAnchor) | 
| - scroll = clampOffsetAtScale(scroll, scale); | 
| 
 
aelias_OOO_until_Jul13
2013/07/27 05:59:24
This line should still be there since we want to m
 
 | 
| } | 
| static bool invokesHandCursor(Node* node, bool shiftKey, Frame* frame) | 
| @@ -1274,22 +1272,35 @@ void WebViewImpl::enableTapHighlight(const PlatformGestureEvent& tapEvent) | 
| m_linkHighlight = LinkHighlight::create(touchNode, this); | 
| } | 
| -void WebViewImpl::animateZoomAroundPoint(const IntPoint& point, AutoZoomType zoomType) | 
| +void WebViewImpl::animateDoubleTapZoom(const IntPoint& point) | 
| { | 
| if (!mainFrameImpl()) | 
| return; | 
| + WebRect rect(point.x(), point.y(), touchPointPadding, touchPointPadding); | 
| + WebRect blockBounds = computeBlockBounds(rect, false); | 
| + | 
| float scale; | 
| WebPoint scroll; | 
| - bool isAnchor; | 
| - WebPoint webPoint = point; | 
| - computeScaleAndScrollForHitRect(WebRect(webPoint.x, webPoint.y, 0, 0), zoomType, scale, scroll, isAnchor); | 
| + bool doubleTapShouldZoomOut; | 
| - bool isDoubleTap = (zoomType == DoubleTap); | 
| - double durationInSeconds = isDoubleTap ? doubleTapZoomAnimationDurationInSeconds : 0; | 
| - bool isAnimating = startPageScaleAnimation(scroll, isAnchor, scale, durationInSeconds); | 
| + computeScaleAndScrollForHitRect( | 
| + blockBounds, touchPointPadding, scale, scroll, doubleTapShouldZoomOut); | 
| - if (isDoubleTap && isAnimating) { | 
| + bool isAnimating; | 
| + | 
| + if (doubleTapShouldZoomOut) { | 
| + isAnimating = startPageScaleAnimation( | 
| + mainFrameImpl()->frameView()->windowToContents(point), | 
| + true, | 
| + minimumPageScaleFactor(), | 
| + doubleTapZoomAnimationDurationInSeconds); | 
| + } else { | 
| + isAnimating = startPageScaleAnimation( | 
| + scroll, false, scale, doubleTapZoomAnimationDurationInSeconds); | 
| + } | 
| + | 
| + if (isAnimating) { | 
| m_doubleTapZoomPageScaleFactor = scale; | 
| m_doubleTapZoomPending = true; | 
| } | 
| @@ -1297,7 +1308,46 @@ void WebViewImpl::animateZoomAroundPoint(const IntPoint& point, AutoZoomType zoo | 
| void WebViewImpl::zoomToFindInPageRect(const WebRect& rect) | 
| { | 
| - animateZoomAroundPoint(IntRect(rect).center(), FindInPage); | 
| + if (!mainFrameImpl()) | 
| + return; | 
| + | 
| + WebRect blockBounds = computeBlockBounds(rect, true); | 
| + | 
| + if (blockBounds.isEmpty()) { | 
| + // Keep current scale (no need to scroll as x,y will normally already | 
| + // be visible). FIXME: Revisit this if it isn't always true. | 
| + return; | 
| + } | 
| + | 
| + float scale; | 
| + WebPoint scroll; | 
| + bool doubleTapShouldZoomOut; | 
| + | 
| + computeScaleAndScrollForHitRect(blockBounds, nonUserInitiatedPointPadding, | 
| + scale, scroll, doubleTapShouldZoomOut); | 
| + | 
| + startPageScaleAnimation( | 
| + scroll, false, scale, findInPageAnimationDurationInSeconds); | 
| +} | 
| + | 
| +bool WebViewImpl::zoomToMultipleTargetsRect(const WebRect& rect) | 
| +{ | 
| + if (!mainFrameImpl()) | 
| + return false; | 
| + | 
| + float scale; | 
| + WebPoint scroll; | 
| + bool doubleTapShouldZoomOut; | 
| + | 
| + computeScaleAndScrollForHitRect(rect, nonUserInitiatedPointPadding, | 
| + scale, scroll, doubleTapShouldZoomOut); | 
| + | 
| + if (scale <= pageScaleFactor()) | 
| + return false; | 
| + | 
| + startPageScaleAnimation( | 
| + scroll, false, scale, multipleTargetsZoomAnimationDurationInSeconds); | 
| + return true; | 
| } | 
| void WebViewImpl::numberOfWheelEventHandlersChanged(unsigned numberOfWheelHandlers) |