Changeset 130545 in webkit


Ignore:
Timestamp:
Oct 5, 2012, 1:30:59 PM (13 years ago)
Author:
commit-queue@webkit.org
Message:

[chromium] Support zooming focused node for mobile devices
https://bugs.webkit.org/show_bug.cgi?id=97958

Patch by Yusuf Ozuysal <yusufo@google.com> on 2012-10-05
Reviewed by Adam Barth.

This unforks the Android version of scrollFocusedNodeIntoRect().A new setting
autoZoomFocusedNodeToLegibleScale was added to turn it on, since not all
platforms with ENABLE(GESTURE_EVENTS) want this.

Test: WebFrameTest.DivScrollIntoEditableTest

  • public/WebSettings.h:
  • src/WebSettingsImpl.cpp:

(WebKit::WebSettingsImpl::WebSettingsImpl):
(WebKit::WebSettingsImpl::setAutoZoomFocusedNodeToLegibleScale):
(WebKit):

  • src/WebSettingsImpl.h:

(WebSettingsImpl):
(WebKit::WebSettingsImpl::autoZoomFocusedNodeToLegibleScale):

  • src/WebViewImpl.cpp:

(WebKit::WebViewImpl::scrollFocusedNodeIntoRect):

  • tests/WebFrameTest.cpp:
  • tests/data/get_scale_for_zoom_into_editable_test.html: Added.
Location:
trunk/Source/WebKit/chromium
Files:
1 added
6 edited

Legend:

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

    r130539 r130545  
     12012-10-05  Yusuf Ozuysal  <yusufo@google.com>
     2
     3        [chromium] Support zooming focused node for mobile devices
     4        https://bugs.webkit.org/show_bug.cgi?id=97958
     5
     6        Reviewed by Adam Barth.
     7
     8        This unforks the Android version of scrollFocusedNodeIntoRect().A new setting
     9        autoZoomFocusedNodeToLegibleScale was added to turn it on, since not all
     10        platforms with ENABLE(GESTURE_EVENTS) want this.
     11
     12        Test: WebFrameTest.DivScrollIntoEditableTest
     13
     14        * public/WebSettings.h:
     15        * src/WebSettingsImpl.cpp:
     16        (WebKit::WebSettingsImpl::WebSettingsImpl):
     17        (WebKit::WebSettingsImpl::setAutoZoomFocusedNodeToLegibleScale):
     18        (WebKit):
     19        * src/WebSettingsImpl.h:
     20        (WebSettingsImpl):
     21        (WebKit::WebSettingsImpl::autoZoomFocusedNodeToLegibleScale):
     22        * src/WebViewImpl.cpp:
     23        (WebKit::WebViewImpl::scrollFocusedNodeIntoRect):
     24        * tests/WebFrameTest.cpp:
     25        * tests/data/get_scale_for_zoom_into_editable_test.html: Added.
     26
    1272012-10-05  W. James MacLean  <wjmaclean@chromium.org>
    228
  • trunk/Source/WebKit/chromium/public/WebSettings.h

    r130321 r130545  
    7575    virtual void setApplyPageScaleFactorInCompositor(bool) = 0;
    7676    virtual void setAsynchronousSpellCheckingEnabled(bool) = 0;
     77    virtual void setAutoZoomFocusedNodeToLegibleScale(bool) = 0;
    7778    virtual void setAuthorAndUserStylesEnabled(bool) = 0;
    7879    virtual void setCaretBrowsingEnabled(bool) = 0;
  • trunk/Source/WebKit/chromium/src/WebSettingsImpl.cpp

    r130530 r130545  
    5555    , m_applyDefaultDeviceScaleFactorInCompositor(false)
    5656    , m_gestureTapHighlightEnabled(true)
     57    , m_autoZoomFocusedNodeToLegibleScale(false)
    5758    , m_defaultTileSize(WebSize(256, 256))
    5859    , m_maxUntiledLayerSize(WebSize(512, 512))
     
    146147}
    147148
     149void WebSettingsImpl::setAutoZoomFocusedNodeToLegibleScale(bool autoZoomFocusedNodeToLegibleScale)
     150{
     151    m_autoZoomFocusedNodeToLegibleScale = autoZoomFocusedNodeToLegibleScale;
     152}
     153
    148154void WebSettingsImpl::setTextAutosizingEnabled(bool enabled)
    149155{
  • trunk/Source/WebKit/chromium/src/WebSettingsImpl.h

    r130321 r130545  
    6868    virtual void setAsynchronousSpellCheckingEnabled(bool);
    6969    virtual void setAuthorAndUserStylesEnabled(bool);
     70    virtual void setAutoZoomFocusedNodeToLegibleScale(bool);
    7071    virtual void setCaretBrowsingEnabled(bool);
    7172    virtual void setCookieEnabled(bool);
     
    163164    bool applyDefaultDeviceScaleFactorInCompositor() const { return m_applyDefaultDeviceScaleFactorInCompositor; }
    164165    bool applyPageScaleFactorInCompositor() const;
     166    bool autoZoomFocusedNodeToLegibleScale() const { return m_autoZoomFocusedNodeToLegibleScale; }
    165167    bool gestureTapHighlightEnabled() { return m_gestureTapHighlightEnabled; }
    166168    WebSize defaultTileSize() const { return m_defaultTileSize; }
     
    176178    bool m_applyDefaultDeviceScaleFactorInCompositor;
    177179    bool m_gestureTapHighlightEnabled;
     180    bool m_autoZoomFocusedNodeToLegibleScale;
    178181    WebSize m_defaultTileSize;
    179182    WebSize m_maxUntiledLayerSize;
  • trunk/Source/WebKit/chromium/src/WebViewImpl.cpp

    r130539 r130545  
    201201// Constants for zooming in on a focused text field.
    202202static const double scrollAndScaleAnimationDurationInSeconds = 0.2;
     203static const int minReadableCaretHeight = 18;
     204static const float minScaleChangeToTriggerZoom = 1.05f;
     205static const float leftBoxRatio = 0.3f;
     206static const int caretPadding = 10;
    203207
    204208namespace WebKit {
     
    26392643    if (!frame || !frame->view() || !focusedNode || !focusedNode->isElementNode())
    26402644        return;
    2641     Element* elementNode = static_cast<Element*>(focusedNode);
    2642     frame->view()->scrollElementToRect(elementNode, IntRect(rect.x, rect.y, rect.width, rect.height));
     2645
     2646    if (!m_webSettings->autoZoomFocusedNodeToLegibleScale()) {
     2647        Element* elementNode = static_cast<Element*>(focusedNode);
     2648        frame->view()->scrollElementToRect(elementNode, IntRect(rect.x, rect.y, rect.width, rect.height));
     2649        return;
     2650    }
     2651
     2652#if ENABLE(GESTURE_EVENTS)
     2653    focusedNode->document()->updateLayoutIgnorePendingStylesheets();
     2654
     2655    // 'caret' is rect encompassing the blinking cursor.
     2656    IntRect textboxRect = focusedNode->document()->view()->contentsToWindow(pixelSnappedIntRect(focusedNode->Node::boundingBox()));
     2657    WebRect caret, end;
     2658    selectionBounds(caret, end);
     2659
     2660    // Pick a scale which is reasonably readable. This is the scale at which
     2661    // the caret height will become minReadableCaretHeight (adjusted for dpi
     2662    // and font scale factor).
     2663    float targetScale = deviceScaleFactor();
     2664#if ENABLE(TEXT_AUTOSIZING)
     2665    if (page() && page()->settings())
     2666        targetScale *= page()->settings()->textAutosizingFontScaleFactor();
     2667#endif
     2668    const float newScale = clampPageScaleFactorToLimits(pageScaleFactor() * minReadableCaretHeight * targetScale / caret.height);
     2669    const float deltaScale = newScale / pageScaleFactor();
     2670
     2671    // Convert the rects to absolute space in the new scale.
     2672    IntRect textboxRectInDocumentCoordinates = textboxRect;
     2673    textboxRectInDocumentCoordinates.move(mainFrame()->scrollOffset());
     2674    textboxRectInDocumentCoordinates.scale(deltaScale);
     2675    IntRect caretInDocumentCoordinates = caret;
     2676    caretInDocumentCoordinates.move(mainFrame()->scrollOffset());
     2677    caretInDocumentCoordinates.scale(deltaScale);
     2678
     2679    IntPoint newOffset;
     2680    if (textboxRectInDocumentCoordinates.width() <= m_size.width) {
     2681        // Field is narrower than screen. Try to leave padding on left so field's
     2682        // label is visible, but it's more important to ensure entire field is
     2683        // onscreen.
     2684        int idealLeftPadding = m_size.width * leftBoxRatio;
     2685        int maxLeftPaddingKeepingBoxOnscreen = m_size.width - textboxRectInDocumentCoordinates.width();
     2686        newOffset.setX(textboxRectInDocumentCoordinates.x() - min<int>(idealLeftPadding, maxLeftPaddingKeepingBoxOnscreen));
     2687    } else {
     2688        // Field is wider than screen. Try to left-align field, unless caret would
     2689        // be offscreen, in which case right-align the caret.
     2690        newOffset.setX(max<int>(textboxRectInDocumentCoordinates.x(), caretInDocumentCoordinates.x() + caretInDocumentCoordinates.width() + caretPadding - m_size.width));
     2691    }
     2692    if (textboxRectInDocumentCoordinates.height() <= m_size.height) {
     2693        // Field is shorter than screen. Vertically center it.
     2694        newOffset.setY(textboxRectInDocumentCoordinates.y() - (m_size.height - textboxRectInDocumentCoordinates.height()) / 2);
     2695    } else {
     2696        // Field is taller than screen. Try to top align field, unless caret would
     2697        // be offscreen, in which case bottom-align the caret.
     2698        newOffset.setY(max<int>(textboxRectInDocumentCoordinates.y(), caretInDocumentCoordinates.y() + caretInDocumentCoordinates.height() + caretPadding - m_size.height));
     2699    }
     2700
     2701    bool needAnimation = false;
     2702    // If we are at less than the target zoom level, zoom in.
     2703    if (deltaScale > minScaleChangeToTriggerZoom)
     2704        needAnimation = true;
     2705    // If the caret is offscreen, then animate.
     2706    IntRect sizeRect(0, 0, m_size.width, m_size.height);
     2707    if (!sizeRect.contains(caret))
     2708        needAnimation = true;
     2709    // If the box is partially offscreen and it's possible to bring it fully
     2710    // onscreen, then animate.
     2711    if (sizeRect.contains(textboxRectInDocumentCoordinates.width(), textboxRectInDocumentCoordinates.height()) && !sizeRect.contains(textboxRect))
     2712        needAnimation = true;
     2713
     2714    if (needAnimation)
     2715        startPageScaleAnimation(newOffset, false, newScale, scrollAndScaleAnimationDurationInSeconds);
     2716#endif
    26432717}
    26442718
  • trunk/Source/WebKit/chromium/tests/WebFrameTest.cpp

    r130141 r130545  
    497497    EXPECT_FLOAT_EQ(webViewImpl->minimumPageScaleFactor(), scale);
    498498}
     499
     500TEST_F(WebFrameTest, DivScrollIntoEditableTest)
     501{
     502    registerMockedHttpURLLoad("get_scale_for_zoom_into_editable_test.html");
     503
     504    DivAutoZoomTestWebViewClient client;
     505    int viewportWidth = 640;
     506    int viewportHeight = 480;
     507    float LeftBoxRatio = 0.3;
     508    int caretPadding = 10;
     509    int minReadableCaretHeight = 18;
     510    client.m_windowRect = WebRect(0, 0, viewportWidth, viewportHeight);
     511    WebKit::WebView* webView = FrameTestHelpers::createWebViewAndLoad(m_baseURL + "get_scale_for_zoom_into_editable_test.html", true, 0, &client);
     512    webView->enableFixedLayoutMode(true);
     513    webView->resize(WebSize(viewportWidth, viewportHeight));
     514    webView->setPageScaleFactorLimits(1, 10);
     515    webView->layout();
     516    webView->setDeviceScaleFactor(1.5f);
     517    webView->settings()->setAutoZoomFocusedNodeToLegibleScale(true);
     518
     519    WebViewImpl* webViewImpl = static_cast<WebViewImpl*>(webView);
     520    webViewImpl->shouldUseAnimateDoubleTapTimeZeroForTesting(true);
     521
     522    WebRect editBoxWithText(200, 200, 250, 20);
     523    WebRect editBoxWithNoText(200, 250, 250, 20);
     524
     525    // Test scrolling the focused node
     526    // The edit box is shorter and narrower than the viewport when legible.
     527    setScaleAndScrollAndLayout(webView, WebPoint(0, 0), 1);
     528    WebRect rect, caret;
     529    webViewImpl->selectionBounds(caret, rect);
     530    webView->scrollFocusedNodeIntoRect(rect);
     531    // The edit box should be left aligned with a margin for possible label.
     532    int hScroll = editBoxWithText.x * webView->pageScaleFactor() - LeftBoxRatio * viewportWidth;
     533    EXPECT_EQ(hScroll, webView->mainFrame()->scrollOffset().width);
     534    int vScroll = editBoxWithText.y * webView->pageScaleFactor() - (viewportHeight - editBoxWithText.height * webView->pageScaleFactor()) / 2;
     535    EXPECT_EQ(vScroll, webView->mainFrame()->scrollOffset().height);
     536    EXPECT_FLOAT_EQ(webView->deviceScaleFactor() * minReadableCaretHeight / caret.height, webView->pageScaleFactor());
     537
     538    // The edit box is wider than the viewport when legible.
     539    webView->setDeviceScaleFactor(4);
     540    setScaleAndScrollAndLayout(webView, WebPoint(0, 0), 1);
     541    webViewImpl->selectionBounds(caret, rect);
     542    webView->scrollFocusedNodeIntoRect(rect);
     543    // The caret should be right aligned since the caret would be offscreen when the edit box is left aligned.
     544    hScroll = (caret.x + caret.width) * webView->pageScaleFactor() + caretPadding - viewportWidth;
     545    EXPECT_EQ(hScroll, webView->mainFrame()->scrollOffset().width);
     546    EXPECT_FLOAT_EQ(webView->deviceScaleFactor() * minReadableCaretHeight / caret.height, webView->pageScaleFactor());
     547
     548    setScaleAndScrollAndLayout(webView, WebPoint(0, 0), 1);
     549    // Move focus to edit box with text.
     550    webView->advanceFocus(false);
     551    webViewImpl->selectionBounds(caret, rect);
     552    webView->scrollFocusedNodeIntoRect(rect);
     553    // The edit box should be left aligned.
     554    hScroll = editBoxWithNoText.x * webView->pageScaleFactor();
     555    EXPECT_EQ(hScroll, webView->mainFrame()->scrollOffset().width);
     556    vScroll = editBoxWithNoText.y * webView->pageScaleFactor() - (viewportHeight - editBoxWithNoText.height * webView->pageScaleFactor()) / 2;
     557    EXPECT_EQ(vScroll, webView->mainFrame()->scrollOffset().height);
     558    EXPECT_FLOAT_EQ(webView->deviceScaleFactor() * minReadableCaretHeight / caret.height, webView->pageScaleFactor());
     559
     560    // Move focus back to the first edit box.
     561    webView->advanceFocus(true);
     562    webViewImpl->selectionBounds(caret, rect);
     563    // The position should have stayed the same since this box was already on screen with the right scale.
     564    EXPECT_EQ(vScroll, webView->mainFrame()->scrollOffset().height);
     565    EXPECT_EQ(hScroll, webView->mainFrame()->scrollOffset().width);
     566}
    499567#endif
    500568
Note: See TracChangeset for help on using the changeset viewer.