Changeset 141153 in webkit


Ignore:
Timestamp:
Jan 29, 2013 1:08:37 PM (11 years ago)
Author:
wangxianzhu@chromium.org
Message:

[Chromium] Correct zoom for focused node when using compositor scaling
https://bugs.webkit.org/show_bug.cgi?id=107599

Reviewed by Adam Barth.

When applyDeviceScaleFactorInCompositor, targetScale should exclude device scale factor.
When applyPageScaleFactorInCompositor, caret size and content sizes are in css pixels and they should be in the viewport of the new scale.

  • src/WebViewImpl.cpp:

(WebKit::WebViewImpl::scrollFocusedNodeIntoRect):
(WebKit):
(WebKit::WebViewImpl::computeScaleAndScrollForFocusedNode): Extracted from scrollFocusedNodeIntoRect() to ease testing.

  • src/WebViewImpl.h:

(WebViewImpl):

  • tests/WebFrameTest.cpp: Updated test DivScrollEditableTest
  • tests/data/get_scale_for_zoom_into_editable_test.html: Moved the logic of onload script (which seems not to work) into WebFrameTest.cpp.
Location:
trunk/Source/WebKit/chromium
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/chromium/ChangeLog

    r141142 r141153  
     12013-01-29  Xianzhu Wang  <wangxianzhu@chromium.org>
     2
     3        [Chromium] Correct zoom for focused node when using compositor scaling
     4        https://bugs.webkit.org/show_bug.cgi?id=107599
     5
     6        Reviewed by Adam Barth.
     7
     8        When applyDeviceScaleFactorInCompositor, targetScale should exclude device scale factor.
     9        When applyPageScaleFactorInCompositor, caret size and content sizes are in css pixels and they should be in the viewport of the new scale.
     10
     11        * src/WebViewImpl.cpp:
     12        (WebKit::WebViewImpl::scrollFocusedNodeIntoRect):
     13        (WebKit):
     14        (WebKit::WebViewImpl::computeScaleAndScrollForFocusedNode): Extracted from scrollFocusedNodeIntoRect() to ease testing.
     15        * src/WebViewImpl.h:
     16        (WebViewImpl):
     17        * tests/WebFrameTest.cpp: Updated test DivScrollEditableTest
     18        * tests/data/get_scale_for_zoom_into_editable_test.html: Moved the logic of onload script (which seems not to work) into WebFrameTest.cpp.
     19
    1202013-01-29  Alec Flett  <alecflett@chromium.org>
    221
  • trunk/Source/WebKit/chromium/src/WebViewImpl.cpp

    r141134 r141153  
    27892789
    27902790#if ENABLE(GESTURE_EVENTS)
     2791    float scale;
     2792    IntPoint scroll;
     2793    bool needAnimation;
     2794    computeScaleAndScrollForFocusedNode(focusedNode, scale, scroll, needAnimation);
     2795    if (needAnimation)
     2796        startPageScaleAnimation(scroll, false, scale, scrollAndScaleAnimationDurationInSeconds);
     2797#endif
     2798}
     2799
     2800#if ENABLE(GESTURE_EVENTS)
     2801void WebViewImpl::computeScaleAndScrollForFocusedNode(Node* focusedNode, float& newScale, IntPoint& newScroll, bool& needAnimation)
     2802{
    27912803    focusedNode->document()->updateLayoutIgnorePendingStylesheets();
    27922804
     
    27992811    // the caret height will become minReadableCaretHeight (adjusted for dpi
    28002812    // and font scale factor).
    2801     float targetScale = deviceScaleFactor();
     2813    float targetScale = settingsImpl()->applyDeviceScaleFactorInCompositor() ? 1 : deviceScaleFactor();
    28022814#if ENABLE(TEXT_AUTOSIZING)
    28032815    if (page() && page()->settings())
    28042816        targetScale *= page()->settings()->textAutosizingFontScaleFactor();
    28052817#endif
    2806     const float newScale = clampPageScaleFactorToLimits(pageScaleFactor() * minReadableCaretHeight * targetScale / caret.height);
     2818    const float caretHeight = settingsImpl()->applyPageScaleFactorInCompositor() ? caret.height : caret.height / pageScaleFactor();
     2819    newScale = clampPageScaleFactorToLimits(minReadableCaretHeight * targetScale / caretHeight);
    28072820    const float deltaScale = newScale / pageScaleFactor();
    28082821
     
    28102823    IntRect textboxRectInDocumentCoordinates = textboxRect;
    28112824    textboxRectInDocumentCoordinates.move(mainFrame()->scrollOffset());
    2812     textboxRectInDocumentCoordinates.scale(deltaScale);
    28132825    IntRect caretInDocumentCoordinates = caret;
    28142826    caretInDocumentCoordinates.move(mainFrame()->scrollOffset());
    2815     caretInDocumentCoordinates.scale(deltaScale);
    2816 
    2817     IntPoint newOffset;
    2818     if (textboxRectInDocumentCoordinates.width() <= m_size.width) {
     2827
     2828    int viewWidth = m_size.width;
     2829    int viewHeight = m_size.height;
     2830    if (settingsImpl()->applyPageScaleFactorInCompositor()) {
     2831        viewWidth /= newScale;
     2832        viewHeight /= newScale;
     2833    } else {
     2834        textboxRectInDocumentCoordinates.scale(deltaScale);
     2835        caretInDocumentCoordinates.scale(deltaScale);
     2836    }
     2837
     2838    if (textboxRectInDocumentCoordinates.width() <= viewWidth) {
    28192839        // Field is narrower than screen. Try to leave padding on left so field's
    28202840        // label is visible, but it's more important to ensure entire field is
    28212841        // onscreen.
    2822         int idealLeftPadding = m_size.width * leftBoxRatio;
    2823         int maxLeftPaddingKeepingBoxOnscreen = m_size.width - textboxRectInDocumentCoordinates.width();
    2824         newOffset.setX(textboxRectInDocumentCoordinates.x() - min<int>(idealLeftPadding, maxLeftPaddingKeepingBoxOnscreen));
     2842        int idealLeftPadding = viewWidth * leftBoxRatio;
     2843        int maxLeftPaddingKeepingBoxOnscreen = viewWidth - textboxRectInDocumentCoordinates.width();
     2844        newScroll.setX(textboxRectInDocumentCoordinates.x() - min<int>(idealLeftPadding, maxLeftPaddingKeepingBoxOnscreen));
    28252845    } else {
    28262846        // Field is wider than screen. Try to left-align field, unless caret would
    28272847        // be offscreen, in which case right-align the caret.
    2828         newOffset.setX(max<int>(textboxRectInDocumentCoordinates.x(), caretInDocumentCoordinates.x() + caretInDocumentCoordinates.width() + caretPadding - m_size.width));
    2829     }
    2830     if (textboxRectInDocumentCoordinates.height() <= m_size.height) {
     2848        newScroll.setX(max<int>(textboxRectInDocumentCoordinates.x(), caretInDocumentCoordinates.x() + caretInDocumentCoordinates.width() + caretPadding - viewWidth));
     2849    }
     2850    if (textboxRectInDocumentCoordinates.height() <= viewHeight) {
    28312851        // Field is shorter than screen. Vertically center it.
    2832         newOffset.setY(textboxRectInDocumentCoordinates.y() - (m_size.height - textboxRectInDocumentCoordinates.height()) / 2);
     2852        newScroll.setY(textboxRectInDocumentCoordinates.y() - (viewHeight - textboxRectInDocumentCoordinates.height()) / 2);
    28332853    } else {
    28342854        // Field is taller than screen. Try to top align field, unless caret would
    28352855        // be offscreen, in which case bottom-align the caret.
    2836         newOffset.setY(max<int>(textboxRectInDocumentCoordinates.y(), caretInDocumentCoordinates.y() + caretInDocumentCoordinates.height() + caretPadding - m_size.height));
    2837     }
    2838 
    2839     bool needAnimation = false;
     2856        newScroll.setY(max<int>(textboxRectInDocumentCoordinates.y(), caretInDocumentCoordinates.y() + caretInDocumentCoordinates.height() + caretPadding - viewHeight));
     2857    }
     2858
     2859    needAnimation = false;
    28402860    // If we are at less than the target zoom level, zoom in.
    28412861    if (deltaScale > minScaleChangeToTriggerZoom)
    28422862        needAnimation = true;
    28432863    // If the caret is offscreen, then animate.
    2844     IntRect sizeRect(0, 0, m_size.width, m_size.height);
     2864    IntRect sizeRect(0, 0, viewWidth, viewHeight);
    28452865    if (!sizeRect.contains(caret))
    28462866        needAnimation = true;
     
    28492869    if (sizeRect.contains(textboxRectInDocumentCoordinates.width(), textboxRectInDocumentCoordinates.height()) && !sizeRect.contains(textboxRect))
    28502870        needAnimation = true;
    2851 
    2852     if (needAnimation)
    2853         startPageScaleAnimation(newOffset, false, newScale, scrollAndScaleAnimationDurationInSeconds);
    2854 #endif
    2855 }
     2871}
     2872#endif
    28562873
    28572874void WebViewImpl::advanceFocus(bool reverse)
  • trunk/Source/WebKit/chromium/src/WebViewImpl.h

    r141053 r141153  
    580580    WebCore::Node* bestTouchLinkNode(const WebGestureEvent& touchEvent);
    581581    void enableTouchHighlight(const WebGestureEvent& touchEvent);
     582    void computeScaleAndScrollForFocusedNode(WebCore::Node* focusedNode, float& scale, WebCore::IntPoint& scroll, bool& needAnimation);
    582583#endif
    583584    void animateZoomAroundPoint(const WebCore::IntPoint&, AutoZoomType);
  • trunk/Source/WebKit/chromium/tests/WebFrameTest.cpp

    r141125 r141153  
    929929#endif
    930930
    931 // This test depends on code that is compiled conditionally. We likely need to
    932 // add the proper ifdef when re-enabling it. See
    933 // https://bugs.webkit.org/show_bug.cgi?id=98558
    934 TEST_F(WebFrameTest, DISABLED_DivScrollIntoEditableTest)
     931TEST_F(WebFrameTest, DivScrollIntoEditableTest)
    935932{
    936933    registerMockedHttpURLLoad("get_scale_for_zoom_into_editable_test.html");
    937934
    938     int viewportWidth = 640;
    939     int viewportHeight = 480;
     935    int viewportWidth = 450;
     936    int viewportHeight = 300;
    940937    float leftBoxRatio = 0.3f;
    941938    int caretPadding = 10;
    942     int minReadableCaretHeight = 18;
     939    float minReadableCaretHeight = 18.0f;
    943940    WebKit::WebView* webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "get_scale_for_zoom_into_editable_test.html");
     941    webView->settings()->setApplyDeviceScaleFactorInCompositor(true);
     942    webView->settings()->setApplyPageScaleFactorInCompositor(true);
    944943    webView->enableFixedLayoutMode(true);
    945944    webView->resize(WebSize(viewportWidth, viewportHeight));
    946     webView->setPageScaleFactorLimits(1, 10);
     945    webView->setPageScaleFactorLimits(1, 4);
    947946    webView->layout();
    948947    webView->setDeviceScaleFactor(1.5f);
     
    957956    // Test scrolling the focused node
    958957    // The edit box is shorter and narrower than the viewport when legible.
     958    webView->advanceFocus(false);
     959    // Set the caret to the end of the input box.
     960    webView->mainFrame()->document().getElementById("EditBoxWithText").to<WebInputElement>().setSelectionRange(1000, 1000);
    959961    setScaleAndScrollAndLayout(webView, WebPoint(0, 0), 1);
    960962    WebRect rect, caret;
    961963    webViewImpl->selectionBounds(caret, rect);
    962     webView->scrollFocusedNodeIntoRect(rect);
     964
     965    float scale;
     966    WebCore::IntPoint scroll;
     967    bool needAnimation;
     968    webViewImpl->computeScaleAndScrollForFocusedNode(webViewImpl->focusedWebCoreNode(), scale, scroll, needAnimation);
     969    EXPECT_TRUE(needAnimation);
    963970    // The edit box should be left aligned with a margin for possible label.
    964     int hScroll = editBoxWithText.x * webView->pageScaleFactor() - leftBoxRatio * viewportWidth;
    965     EXPECT_EQ(hScroll, webView->mainFrame()->scrollOffset().width);
    966     int vScroll = editBoxWithText.y * webView->pageScaleFactor() - (viewportHeight - editBoxWithText.height * webView->pageScaleFactor()) / 2;
    967     EXPECT_EQ(vScroll, webView->mainFrame()->scrollOffset().height);
    968     EXPECT_FLOAT_EQ(webView->deviceScaleFactor() * minReadableCaretHeight / caret.height, webView->pageScaleFactor());
     971    int hScroll = editBoxWithText.x - leftBoxRatio * viewportWidth / scale;
     972    EXPECT_NEAR(hScroll, scroll.x(), 1);
     973    int vScroll = editBoxWithText.y - (viewportHeight / scale - editBoxWithText.height * scale) / 2;
     974    EXPECT_NEAR(vScroll, scroll.y(), 1);
     975    EXPECT_NEAR(minReadableCaretHeight / caret.height, scale, 0.1);
    969976
    970977    // The edit box is wider than the viewport when legible.
    971     webView->setDeviceScaleFactor(4);
     978    viewportWidth = 200;
     979    viewportHeight = 150;
     980    webView->resize(WebSize(viewportWidth, viewportHeight));
    972981    setScaleAndScrollAndLayout(webView, WebPoint(0, 0), 1);
    973982    webViewImpl->selectionBounds(caret, rect);
    974     webView->scrollFocusedNodeIntoRect(rect);
     983    webViewImpl->computeScaleAndScrollForFocusedNode(webViewImpl->focusedWebCoreNode(), scale, scroll, needAnimation);
     984    EXPECT_TRUE(needAnimation);
    975985    // The caret should be right aligned since the caret would be offscreen when the edit box is left aligned.
    976     hScroll = (caret.x + caret.width) * webView->pageScaleFactor() + caretPadding - viewportWidth;
    977     EXPECT_EQ(hScroll, webView->mainFrame()->scrollOffset().width);
    978     EXPECT_FLOAT_EQ(webView->deviceScaleFactor() * minReadableCaretHeight / caret.height, webView->pageScaleFactor());
     986    hScroll = caret.x + caret.width + caretPadding - viewportWidth / scale;
     987    EXPECT_NEAR(hScroll, scroll.x(), 1);
     988    EXPECT_NEAR(minReadableCaretHeight / caret.height, scale, 0.1);
    979989
    980990    setScaleAndScrollAndLayout(webView, WebPoint(0, 0), 1);
     
    982992    webView->advanceFocus(false);
    983993    webViewImpl->selectionBounds(caret, rect);
    984     webView->scrollFocusedNodeIntoRect(rect);
     994    webViewImpl->computeScaleAndScrollForFocusedNode(webViewImpl->focusedWebCoreNode(), scale, scroll, needAnimation);
     995    EXPECT_TRUE(needAnimation);
    985996    // The edit box should be left aligned.
    986     hScroll = editBoxWithNoText.x * webView->pageScaleFactor();
    987     EXPECT_EQ(hScroll, webView->mainFrame()->scrollOffset().width);
    988     vScroll = editBoxWithNoText.y * webView->pageScaleFactor() - (viewportHeight - editBoxWithNoText.height * webView->pageScaleFactor()) / 2;
    989     EXPECT_EQ(vScroll, webView->mainFrame()->scrollOffset().height);
    990     EXPECT_FLOAT_EQ(webView->deviceScaleFactor() * minReadableCaretHeight / caret.height, webView->pageScaleFactor());
     997    hScroll = editBoxWithNoText.x;
     998    EXPECT_NEAR(hScroll, scroll.x(), 1);
     999    vScroll = editBoxWithNoText.y - (viewportHeight / scale - editBoxWithNoText.height) / 2;
     1000    EXPECT_NEAR(vScroll, scroll.y(), 1);
     1001    EXPECT_NEAR(minReadableCaretHeight / caret.height, scale, 0.1);
     1002
     1003    setScaleAndScrollAndLayout(webViewImpl, scroll, scale);
    9911004
    9921005    // Move focus back to the first edit box.
    9931006    webView->advanceFocus(true);
    994     webViewImpl->selectionBounds(caret, rect);
     1007    webViewImpl->computeScaleAndScrollForFocusedNode(webViewImpl->focusedWebCoreNode(), scale, scroll, needAnimation);
    9951008    // The position should have stayed the same since this box was already on screen with the right scale.
    996     EXPECT_EQ(vScroll, webView->mainFrame()->scrollOffset().height);
    997     EXPECT_EQ(hScroll, webView->mainFrame()->scrollOffset().width);
    998 }
     1009    EXPECT_FALSE(needAnimation);
     1010}
     1011
    9991012#endif
    10001013
  • trunk/Source/WebKit/chromium/tests/data/get_scale_for_zoom_into_editable_test.html

    r141080 r141153  
    11<html>
    22<head>
    3 <script>
    4 function getfocus()
    5 {
    6 var textfield = document.getElementById('EditBoxWithText');
    7 textfield.focus();
    8 textfield.setSelectionRange(textfield.value.length,textfield.value.length);
    9 }
    10 </script>
    113</head>
    12   <body onload="getfocus()">
    13       <input id="EditBoxWithText" style=" position: absolute; left: 200px; top: 200px; width: 250; height:20" value = "Long text to fill the edit box" type="text">
    14       <input id="EditBoxWithNoText" style=" position: absolute; left: 200px; top: 250px; width: 250; height:20" type="text">
     4  <body>
     5      <input id="EditBoxWithText" style=" position: absolute; left: 200px; top: 200px; width: 250px; height:20" value = "Long long long long text to fill the edit box" type="text">
     6      <input id="EditBoxWithNoText" style=" position: absolute; left: 200px; top: 250px; width: 250px; height:20" type="text">
    157  </body>
    168</html>
Note: See TracChangeset for help on using the changeset viewer.