Title: [101752] trunk/Source/WebCore
Revision
101752
Author
le...@chromium.org
Date
2011-12-01 23:47:14 -0800 (Thu, 01 Dec 2011)

Log Message

Add a way to automatically size a single frame to fit its content.
https://bugs.webkit.org/show_bug.cgi?id=73420

Reviewed by Dmitry Titov.

No new functionality exposed so no new tests. (There is a Chromium
specific test in https://bugs.webkit.org/show_bug.cgi?id=73058.)

* page/FrameView.cpp:
(WebCore::FrameView::FrameView): Initialized the new variables.
(WebCore::FrameView::layout):
(WebCore::FrameView::autoSizeIfEnabled):
(WebCore::FrameView::enableAutoSizeMode):
* page/FrameView.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (101751 => 101752)


--- trunk/Source/WebCore/ChangeLog	2011-12-02 07:33:40 UTC (rev 101751)
+++ trunk/Source/WebCore/ChangeLog	2011-12-02 07:47:14 UTC (rev 101752)
@@ -1,3 +1,20 @@
+2011-12-01  David Levin  <le...@chromium.org>
+
+        Add a way to automatically size a single frame to fit its content.
+        https://bugs.webkit.org/show_bug.cgi?id=73420
+
+        Reviewed by Dmitry Titov.
+
+        No new functionality exposed so no new tests. (There is a Chromium
+        specific test in https://bugs.webkit.org/show_bug.cgi?id=73058.)
+
+        * page/FrameView.cpp:
+        (WebCore::FrameView::FrameView): Initialized the new variables.
+        (WebCore::FrameView::layout):
+        (WebCore::FrameView::autoSizeIfEnabled):
+        (WebCore::FrameView::enableAutoSizeMode):
+        * page/FrameView.h:
+
 2011-12-01  Hajime Morrita  <morr...@chromium.org>
 
         JS_INLINE and WTF_INLINE should be visible from WebCore

Modified: trunk/Source/WebCore/page/FrameView.cpp (101751 => 101752)


--- trunk/Source/WebCore/page/FrameView.cpp	2011-12-02 07:33:40 UTC (rev 101751)
+++ trunk/Source/WebCore/page/FrameView.cpp	2011-12-02 07:47:14 UTC (rev 101752)
@@ -146,6 +146,8 @@
     , m_deferSetNeedsLayouts(0)
     , m_setNeedsLayoutWasDeferred(false)
     , m_scrollCorner(0)
+    , m_shouldAutoSize(false)
+    , m_inAutoSize(false)
 {
     init();
 
@@ -1035,6 +1037,8 @@
 #endif        
         }
 
+        autoSizeIfEnabled();
+
         ScrollbarMode hMode;
         ScrollbarMode vMode;    
         calculateScrollbarModesForLayout(hMode, vMode);
@@ -2288,6 +2292,94 @@
     performPostLayoutTasks();
 }
 
+void FrameView::autoSizeIfEnabled()
+{
+    if (!m_shouldAutoSize)
+        return;
+
+    if (m_inAutoSize)
+        return;
+
+    TemporarilyChange<bool> changeInAutoSize(m_inAutoSize, true);
+
+    Document* document = frame()->document();
+    if (!document)
+        return;
+
+    RenderView* documentView = document->renderView();
+    Element* documentElement = document->documentElement();
+    if (!documentView || !documentElement)
+        return;
+
+    RenderBox* documentRenderBox = documentElement->renderBox();
+    if (!documentRenderBox)
+        return;
+
+    // Do the resizing twice. The first time is basically a rough calculation using the preferred width
+    // which may result in a height change during the second iteration.
+    for (int i = 0; i < 2; i++) {
+        // Update various sizes including contentsSize, scrollHeight, etc.
+        document->updateLayoutIgnorePendingStylesheets();
+        IntSize size = frameRect().size();
+        int width = documentView->minPreferredLogicalWidth();
+        int height = documentRenderBox->scrollHeight();
+        IntSize newSize(width, height);
+
+        // Ensure the size is at least the min bounds.
+        newSize = newSize.expandedTo(m_minAutoSize);
+
+        // Check to see if a scrollbar is needed for a given dimension and
+        // if so, increase the other dimension to account for the scrollbar.
+        // Since the dimensions are only for the view rectangle, once a
+        // dimension exceeds the maximum, there is no need to increase it further.
+        if (newSize.width() > m_maxAutoSize.width()) {
+            RefPtr<Scrollbar> localHorizontalScrollbar = horizontalScrollbar();
+            if (!localHorizontalScrollbar)
+                localHorizontalScrollbar = createScrollbar(HorizontalScrollbar);
+            if (!localHorizontalScrollbar->isOverlayScrollbar())
+                newSize.setHeight(newSize.height() + localHorizontalScrollbar->height());
+
+            // Don't bother checking for a vertical scrollbar because the width is at
+            // already greater the maximum.
+        } else if (newSize.height() > m_maxAutoSize.height()) {
+            RefPtr<Scrollbar> localVerticalScrollbar = verticalScrollbar();
+            if (!localVerticalScrollbar)
+                localVerticalScrollbar = createScrollbar(VerticalScrollbar);
+            if (!localVerticalScrollbar->isOverlayScrollbar())
+                newSize.setWidth(newSize.width() + localVerticalScrollbar->width());
+
+            // Don't bother checking for a horizontal scrollbar because the height is
+            // already greater the maximum.
+        }
+
+        // Bound the dimensions by the max bounds and determine what scrollbars to show.
+        ScrollbarMode horizonalScrollbarMode = ScrollbarAlwaysOff;
+        if (newSize.width() > m_maxAutoSize.width()) {
+            newSize.setWidth(m_maxAutoSize.width());
+            horizonalScrollbarMode = ScrollbarAlwaysOn;
+        }
+        ScrollbarMode verticalScrollbarMode = ScrollbarAlwaysOff;
+        if (newSize.height() > m_maxAutoSize.height()) {
+            newSize.setHeight(m_maxAutoSize.height());
+            verticalScrollbarMode = ScrollbarAlwaysOn;
+        }
+
+        if (newSize == size)
+            continue;
+
+        // Avoid doing resizing to a smaller size while the frame is loading to avoid switching to a small size
+        // during an intermediate state (and then changing back to a bigger size as the load progresses).
+        if (!frame()->loader()->isComplete() && (newSize.height() < size.height() || newSize.width() < size.width()))
+            break;
+        resize(newSize.width(), newSize.height());
+        // Force the scrollbar state to avoid the scrollbar code adding them and causing them to be needed. For example,
+        // a vertical scrollbar may cause text to wrap and thus increase the height (which is the only reason the scollbar is needed).
+        setVerticalScrollbarLock(false);
+        setHorizontalScrollbarLock(false);
+        setScrollbarModes(horizonalScrollbarMode, verticalScrollbarMode, true, true);
+    }
+}
+
 void FrameView::updateOverflowStatus(bool horizontalOverflow, bool verticalOverflow)
 {
     if (!m_viewportRenderer)
@@ -2888,6 +2980,26 @@
     doDeferredRepaints();
 }
 
+void FrameView::enableAutoSizeMode(bool enable, const IntSize& minSize, const IntSize& maxSize)
+{
+    ASSERT(!enable || !minSize.isEmpty());
+    ASSERT(minSize.width() <= maxSize.width());
+    ASSERT(minSize.height() <= maxSize.height());
+
+    if (m_shouldAutoSize == enable && m_minAutoSize == minSize && m_maxAutoSize == maxSize)
+        return;
+
+    m_shouldAutoSize = enable;
+    m_minAutoSize = minSize;
+    m_maxAutoSize = maxSize;
+
+    if (!m_shouldAutoSize)
+        return;
+
+    setNeedsLayout();
+    scheduleRelayout();
+}
+
 void FrameView::forceLayout(bool allowSubtree)
 {
     layout(allowSubtree);

Modified: trunk/Source/WebCore/page/FrameView.h (101751 => 101752)


--- trunk/Source/WebCore/page/FrameView.h	2011-12-02 07:33:40 UTC (rev 101751)
+++ trunk/Source/WebCore/page/FrameView.h	2011-12-02 07:47:14 UTC (rev 101752)
@@ -240,6 +240,7 @@
     void incrementVisuallyNonEmptyPixelCount(const IntSize&);
     void setIsVisuallyNonEmpty() { m_isVisuallyNonEmpty = true; }
     bool isVisuallyNonEmpty() const { return m_isVisuallyNonEmpty; }
+    void enableAutoSizeMode(bool enable, const IntSize& minSize, const IntSize& maxSize);
 
     void forceLayout(bool allowSubtree = false);
     void forceLayoutForPagination(const FloatSize& pageSize, const FloatSize& originalPageSize, float maximumShrinkFactor, AdjustViewSizeOrNot);
@@ -336,6 +337,7 @@
 
     void forceLayoutParentViewIfNeeded();
     void performPostLayoutTasks();
+    void autoSizeIfEnabled();
 
     virtual void repaintContentRectangle(const IntRect&, bool immediate);
     virtual void contentsResized();
@@ -481,6 +483,14 @@
 
     Page* m_page;
 
+    // If true, automatically resize the frame view around its content.
+    bool m_shouldAutoSize;
+    bool m_inAutoSize;
+    // The lower bound on the size when autosizing.
+    IntSize m_minAutoSize;
+    // The upper bound on the size when autosizing.
+    IntSize m_maxAutoSize;
+
     static double s_deferredRepaintDelay;
     static double s_initialDeferredRepaintDelayDuringLoading;
     static double s_maxDeferredRepaintDelayDuringLoading;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to