| Index: Source/web/WebViewImpl.cpp
|
| diff --git a/Source/web/WebViewImpl.cpp b/Source/web/WebViewImpl.cpp
|
| index 63acb394798b362fc0514ee09f7d47747ad05755..7fbcfc2b4074522e1913fa69c4acca3ee164b521 100644
|
| --- a/Source/web/WebViewImpl.cpp
|
| +++ b/Source/web/WebViewImpl.cpp
|
| @@ -191,6 +191,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;
|
| @@ -384,9 +387,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)
|
| @@ -771,7 +774,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.
|
| @@ -822,10 +825,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;
|
| @@ -834,9 +837,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()
|
| @@ -1062,15 +1065,14 @@ 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();
|
| @@ -1122,21 +1124,12 @@ 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::computeScaleAndScrollForBlockRect(const WebRect& blockRect, 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 = blockRect;
|
|
|
| bool scaleUnchanged = true;
|
| if (!rect.isEmpty()) {
|
| @@ -1173,46 +1166,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, blockRect.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, blockRect.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);
|
| + scroll = clampOffsetAtScale(scroll, scale);
|
| }
|
|
|
| static bool invokesHandCursor(Node* node, bool shiftKey, Frame* frame)
|
| @@ -1271,22 +1258,29 @@ 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);
|
| + computeScaleAndScrollForBlockRect(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;
|
| }
|
| @@ -1294,7 +1288,42 @@ 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;
|
| +
|
| + computeScaleAndScrollForBlockRect(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;
|
| +
|
| + computeScaleAndScrollForBlockRect(rect, nonUserInitiatedPointPadding, scale, scroll, doubleTapShouldZoomOut);
|
| +
|
| + if (scale <= pageScaleFactor())
|
| + return false;
|
| +
|
| + startPageScaleAnimation(scroll, false, scale, multipleTargetsZoomAnimationDurationInSeconds);
|
| + return true;
|
| }
|
|
|
| void WebViewImpl::numberOfWheelEventHandlersChanged(unsigned numberOfWheelHandlers)
|
|
|