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;