Modified: trunk/Source/WebCore/ChangeLog (113288 => 113289)
--- trunk/Source/WebCore/ChangeLog 2012-04-05 04:28:38 UTC (rev 113288)
+++ trunk/Source/WebCore/ChangeLog 2012-04-05 04:30:23 UTC (rev 113289)
@@ -1,3 +1,52 @@
+2012-04-04 Julien Chaffraix <jchaffr...@webkit.org>
+
+ RenderLayer scrollbars' updates should be split between layout induced and style change induced
+ https://bugs.webkit.org/show_bug.cgi?id=83213
+
+ Reviewed by Simon Fraser.
+
+ Refactoring only, no change in behavior.
+
+ This patches splits up the 2 reasons for modifying the scrollbars:
+ - style updates, handled in updateScrollbarsAfterStyleChange.
+ - layout time, handled in updateScrollbarsAfterLayout.
+
+ * rendering/RenderLayer.cpp:
+ (WebCore::RenderLayer::contentsSize):
+ Removed now unneeded const-casts.
+
+ (WebCore::RenderLayer::setHasHorizontalScrollbar):
+ (WebCore::RenderLayer::setHasVerticalScrollbar):
+ Updated to use hasHorizontalScrollbar / hasVerticalScrollbar.
+
+ (WebCore::RenderLayer::scrollWidth):
+ (WebCore::RenderLayer::scrollHeight):
+ Made those functions |const|.
+
+ (WebCore::RenderLayer::computeScrollDimensions):
+ Removed the unneeded booleans and move the do-we-have-overflow-logic
+ into hasHorizontalOverflow and hasVerticalOverflow.
+
+ (WebCore::RenderLayer::hasHorizontalOverflow):
+ (WebCore::RenderLayer::hasVerticalOverflow):
+ Added those new helper functions.
+
+ (WebCore::RenderLayer::updateScrollbarsAfterLayout):
+ (WebCore::RenderLayer::updateScrollInfoAfterLayout):
+ Updated the latter to call the former.
+
+ (WebCore::RenderLayer::updateScrollbarsAfterStyleChange):
+ (WebCore::RenderLayer::styleChanged):
+ Ditto.
+
+ (WebCore::overflowCanHaveAScrollbar):
+ Add this helper function for updateScrollbarsAfterStyleChange.
+
+ * rendering/RenderLayer.h:
+ (WebCore::RenderLayer::hasHorizontalScrollbar):
+ (WebCore::RenderLayer::hasVerticalScrollbar):
+ Added those 2 new helper functions.
+
2012-04-04 Andrei Burago <abur...@chromium.org>
Auto-size may not work on first load
Modified: trunk/Source/WebCore/rendering/RenderLayer.cpp (113288 => 113289)
--- trunk/Source/WebCore/rendering/RenderLayer.cpp 2012-04-05 04:28:38 UTC (rev 113288)
+++ trunk/Source/WebCore/rendering/RenderLayer.cpp 2012-04-05 04:30:23 UTC (rev 113289)
@@ -2055,7 +2055,7 @@
IntSize RenderLayer::contentsSize() const
{
- return IntSize(const_cast<RenderLayer*>(this)->scrollWidth(), const_cast<RenderLayer*>(this)->scrollHeight());
+ return IntSize(scrollWidth(), scrollHeight());
}
int RenderLayer::visibleHeight() const
@@ -2208,7 +2208,7 @@
void RenderLayer::setHasHorizontalScrollbar(bool hasScrollbar)
{
- if (hasScrollbar == (m_hBar != 0))
+ if (hasScrollbar == hasHorizontalScrollbar())
return;
if (hasScrollbar)
@@ -2231,7 +2231,7 @@
void RenderLayer::setHasVerticalScrollbar(bool hasScrollbar)
{
- if (hasScrollbar == (m_vBar != 0))
+ if (hasScrollbar == hasVerticalScrollbar())
return;
if (hasScrollbar)
@@ -2347,19 +2347,19 @@
m_resizer->setFrameRect(resizerCornerRect(this, borderBox));
}
-int RenderLayer::scrollWidth()
+int RenderLayer::scrollWidth() const
{
ASSERT(renderBox());
if (m_scrollDimensionsDirty)
- computeScrollDimensions();
+ const_cast<RenderLayer*>(this)->computeScrollDimensions();
return snapSizeToPixel(m_scrollSize.width(), renderBox()->clientLeft());
}
-int RenderLayer::scrollHeight()
+int RenderLayer::scrollHeight() const
{
ASSERT(renderBox());
if (m_scrollDimensionsDirty)
- computeScrollDimensions();
+ const_cast<RenderLayer*>(this)->computeScrollDimensions();
return snapSizeToPixel(m_scrollSize.height(), renderBox()->clientTop());
}
@@ -2395,7 +2395,7 @@
return overflowRect.maxX();
}
-void RenderLayer::computeScrollDimensions(bool* needHBar, bool* needVBar)
+void RenderLayer::computeScrollDimensions()
{
RenderBox* box = renderBox();
ASSERT(box);
@@ -2409,58 +2409,45 @@
m_scrollSize.setHeight(overflowBottom() - overflowTop());
setScrollOrigin(IntPoint(-m_scrollOverflow.width(), -m_scrollOverflow.height()));
+}
- if (needHBar)
- *needHBar = scrollWidth() > box->pixelSnappedClientWidth();
- if (needVBar)
- *needVBar = scrollHeight() > box->pixelSnappedClientHeight();
+bool RenderLayer::hasHorizontalOverflow() const
+{
+ ASSERT(!m_scrollDimensionsDirty);
+
+ return scrollWidth() > renderBox()->pixelSnappedClientWidth();
}
-void RenderLayer::updateScrollInfoAfterLayout()
+bool RenderLayer::hasVerticalOverflow() const
{
- RenderBox* box = renderBox();
- if (!box)
- return;
+ ASSERT(!m_scrollDimensionsDirty);
- m_scrollDimensionsDirty = true;
- IntSize scrollOffsetOriginal(scrollXOffset(), scrollYOffset());
+ return scrollHeight() > renderBox()->pixelSnappedClientHeight();
+}
- bool horizontalOverflow, verticalOverflow;
- computeScrollDimensions(&horizontalOverflow, &verticalOverflow);
+void RenderLayer::updateScrollbarsAfterLayout()
+{
+ RenderBox* box = renderBox();
+ ASSERT(box);
- if (box->style()->overflowX() != OMARQUEE) {
- // Layout may cause us to be in an invalid scroll position. In this case we need
- // to pull our scroll offsets back to the max (or push them up to the min).
- int newX = max(0, min<int>(scrollXOffset(), scrollWidth() - box->clientWidth()));
- int newY = max(0, min<int>(scrollYOffset(), scrollHeight() - box->clientHeight()));
- if (newX != scrollXOffset() || newY != scrollYOffset())
- scrollToOffset(newX, newY);
- }
+ bool hasHorizontalOverflow = this->hasHorizontalOverflow();
+ bool hasVerticalOverflow = this->hasVerticalOverflow();
- bool haveHorizontalBar = m_hBar;
- bool haveVerticalBar = m_vBar;
-
// overflow:scroll should just enable/disable.
if (m_hBar && renderer()->style()->overflowX() == OSCROLL)
- m_hBar->setEnabled(horizontalOverflow);
+ m_hBar->setEnabled(hasHorizontalOverflow);
if (m_vBar && renderer()->style()->overflowY() == OSCROLL)
- m_vBar->setEnabled(verticalOverflow);
+ m_vBar->setEnabled(hasVerticalOverflow);
- // A dynamic change from a scrolling overflow to overflow:hidden means we need to get rid of any
- // scrollbars that may be present.
- if (renderer()->style()->overflowX() == OHIDDEN && haveHorizontalBar)
- setHasHorizontalScrollbar(false);
- if (renderer()->style()->overflowY() == OHIDDEN && haveVerticalBar)
- setHasVerticalScrollbar(false);
-
// overflow:auto may need to lay out again if scrollbars got added/removed.
- bool scrollbarsChanged = (box->hasAutoHorizontalScrollbar() && haveHorizontalBar != horizontalOverflow) ||
- (box->hasAutoVerticalScrollbar() && haveVerticalBar != verticalOverflow);
- if (scrollbarsChanged) {
+ bool autoHorizontalScrollBarChanged = box->hasAutoHorizontalScrollbar() && (hasHorizontalScrollbar() != hasHorizontalOverflow);
+ bool autoVerticalScrollBarChanged = box->hasAutoVerticalScrollbar() && (hasVerticalScrollbar() != hasVerticalOverflow);
+
+ if (autoHorizontalScrollBarChanged || autoVerticalScrollBarChanged) {
if (box->hasAutoHorizontalScrollbar())
- setHasHorizontalScrollbar(horizontalOverflow);
+ setHasHorizontalScrollbar(hasHorizontalOverflow);
if (box->hasAutoVerticalScrollbar())
- setHasVerticalScrollbar(verticalOverflow);
+ setHasVerticalScrollbar(hasVerticalOverflow);
#if ENABLE(DASHBOARD_SUPPORT)
// Force an update since we know the scrollbars have changed things.
@@ -2477,8 +2464,7 @@
renderer()->setNeedsLayout(true, MarkOnlyThis);
if (renderer()->isRenderBlock()) {
RenderBlock* block = toRenderBlock(renderer());
- block->scrollbarsChanged(box->hasAutoHorizontalScrollbar() && haveHorizontalBar != horizontalOverflow,
- box->hasAutoVerticalScrollbar() && haveVerticalBar != verticalOverflow);
+ block->scrollbarsChanged(autoHorizontalScrollBarChanged, autoVerticalScrollBarChanged);
block->layoutBlock(true); // FIXME: Need to handle positioned floats triggering extra relayouts.
} else
renderer()->layout();
@@ -2486,12 +2472,6 @@
}
}
}
-
- // If overflow:scroll is turned into overflow:auto a bar might still be disabled (Bug 11985).
- if (m_hBar && box->hasAutoHorizontalScrollbar())
- m_hBar->setEnabled(true);
- if (m_vBar && box->hasAutoVerticalScrollbar())
- m_vBar->setEnabled(true);
// Set up the range (and page step/line step).
if (m_hBar) {
@@ -2506,7 +2486,30 @@
m_vBar->setSteps(Scrollbar::pixelsPerLineStep(), pageStep);
m_vBar->setProportion(clientHeight, m_scrollSize.height());
}
+}
+void RenderLayer::updateScrollInfoAfterLayout()
+{
+ RenderBox* box = renderBox();
+ if (!box)
+ return;
+
+ m_scrollDimensionsDirty = true;
+ IntSize scrollOffsetOriginal(scrollXOffset(), scrollYOffset());
+
+ computeScrollDimensions();
+
+ if (box->style()->overflowX() != OMARQUEE) {
+ // Layout may cause us to be at an invalid scroll position. In this case we need
+ // to pull our scroll offsets back to the max (or push them up to the min).
+ int newX = max(0, min<int>(scrollXOffset(), scrollWidth() - box->clientWidth()));
+ int newY = max(0, min<int>(scrollYOffset(), scrollHeight() - box->clientHeight()));
+ if (newX != scrollXOffset() || newY != scrollYOffset())
+ scrollToOffset(newX, newY);
+ }
+
+ updateScrollbarsAfterLayout();
+
if (scrollOffsetOriginal != scrollOffset())
scrollToOffsetWithoutAnimation(IntPoint(scrollXOffset(), scrollYOffset()));
}
@@ -4603,6 +4606,37 @@
|| renderer()->isRenderIFrame();
}
+static bool overflowCanHaveAScrollbar(EOverflow overflow)
+{
+ return overflow == OAUTO || overflow == OSCROLL || overflow == OOVERLAY;
+}
+
+void RenderLayer::updateScrollbarsAfterStyleChange(const RenderStyle* oldStyle)
+{
+ // Overflow are a box concept.
+ if (!renderBox())
+ return;
+
+ EOverflow overflowX = renderBox()->style()->overflowX();
+ EOverflow overflowY = renderBox()->style()->overflowY();
+ if (hasHorizontalScrollbar() && !overflowCanHaveAScrollbar(overflowX))
+ setHasHorizontalScrollbar(false);
+ if (hasVerticalScrollbar() && !overflowCanHaveAScrollbar(overflowY))
+ setHasVerticalScrollbar(false);
+
+ // With overflow: scroll, scrollbars are always visible but may be disabled.
+ // When switching to another value, we need to re-enable them (see bug 11985).
+ if (hasHorizontalScrollbar() && oldStyle->overflowX() == OSCROLL && overflowX != OSCROLL) {
+ ASSERT(overflowCanHaveAScrollbar(overflowX));
+ m_hBar->setEnabled(true);
+ }
+
+ if (hasVerticalScrollbar() && oldStyle->overflowY() == OSCROLL && overflowY != OSCROLL) {
+ ASSERT(overflowCanHaveAScrollbar(overflowY));
+ m_vBar->setEnabled(true);
+ }
+}
+
void RenderLayer::styleChanged(StyleDifference, const RenderStyle* oldStyle)
{
bool isNormalFlowOnly = shouldBeNormalFlowOnly();
@@ -4624,6 +4658,8 @@
m_marquee = 0;
}
+ updateScrollbarsAfterStyleChange(oldStyle);
+
if (!hasReflection() && m_reflection)
removeReflection();
else if (hasReflection()) {
Modified: trunk/Source/WebCore/rendering/RenderLayer.h (113288 => 113289)
--- trunk/Source/WebCore/rendering/RenderLayer.h 2012-04-05 04:28:38 UTC (rev 113288)
+++ trunk/Source/WebCore/rendering/RenderLayer.h 2012-04-05 04:30:23 UTC (rev 113289)
@@ -280,8 +280,8 @@
LayoutRect rect() const { return LayoutRect(location(), size()); }
- int scrollWidth();
- int scrollHeight();
+ int scrollWidth() const;
+ int scrollHeight() const;
void panScrollFromPoint(const LayoutPoint&);
@@ -314,6 +314,9 @@
PassRefPtr<Scrollbar> createScrollbar(ScrollbarOrientation);
void destroyScrollbar(ScrollbarOrientation);
+ bool hasHorizontalScrollbar() const { return horizontalScrollbar(); }
+ bool hasVerticalScrollbar() const { return verticalScrollbar(); }
+
// ScrollableArea overrides
virtual Scrollbar* horizontalScrollbar() const { return m_hBar.get(); }
virtual Scrollbar* verticalScrollbar() const { return m_vBar.get(); }
@@ -585,6 +588,9 @@
bool shouldRepaintAfterLayout() const;
+ void updateScrollbarsAfterStyleChange(const RenderStyle* oldStyle);
+ void updateScrollbarsAfterLayout();
+
friend IntSize RenderBox::scrolledContentOffset() const;
IntSize scrolledContentOffset() const { return scrollOffset() + m_scrollOverflow; }
@@ -649,7 +655,9 @@
bool hitTestContents(const HitTestRequest&, HitTestResult&, const LayoutRect& layerBounds, const LayoutPoint& hitTestPoint, HitTestFilter) const;
- void computeScrollDimensions(bool* needHBar = 0, bool* needVBar = 0);
+ void computeScrollDimensions();
+ bool hasHorizontalOverflow() const;
+ bool hasVerticalOverflow() const;
bool shouldBeNormalFlowOnly() const;