| Index: Source/core/rendering/RenderLayerScrollableArea.cpp
|
| diff --git a/Source/core/rendering/RenderLayerScrollableArea.cpp b/Source/core/rendering/RenderLayerScrollableArea.cpp
|
| index acc68cb9bafcab9a91912e66d5370f5602760a1c..4cf3890fe14df858b41138b01400a4ce51739c60 100644
|
| --- a/Source/core/rendering/RenderLayerScrollableArea.cpp
|
| +++ b/Source/core/rendering/RenderLayerScrollableArea.cpp
|
| @@ -44,16 +44,22 @@
|
| #include "config.h"
|
| #include "core/rendering/RenderLayer.h"
|
|
|
| +#include "core/editing/FrameSelection.h"
|
| +#include "core/inspector/InspectorInstrumentation.h"
|
| +#include "core/page/EventHandler.h"
|
| #include "core/page/Frame.h"
|
| #include "core/page/FrameView.h"
|
| #include "core/page/Page.h"
|
| #include "core/page/scrolling/ScrollingCoordinator.h"
|
| #include "core/platform/ScrollAnimator.h"
|
| +#include "core/rendering/RenderLayerCompositor.h"
|
| +#include "core/rendering/RenderView.h"
|
|
|
| namespace WebCore {
|
|
|
| RenderLayerScrollableArea::RenderLayerScrollableArea(RenderLayer* layer)
|
| : m_layer(layer)
|
| + , m_scrollDimensionsDirty(true)
|
| {
|
| ScrollableArea::setConstrainsScrollingToContentEdge(false);
|
|
|
| @@ -185,9 +191,67 @@ int RenderLayerScrollableArea::scrollSize(ScrollbarOrientation orientation) cons
|
| return m_layer->scrollSize(orientation);
|
| }
|
|
|
| -void RenderLayerScrollableArea::setScrollOffset(const IntPoint& offset)
|
| +void RenderLayerScrollableArea::setScrollOffset(const IntPoint& newScrollOffset)
|
| {
|
| - m_layer->setScrollOffset(offset);
|
| + if (!toRenderBox(renderer())->isMarquee()) {
|
| + // Ensure that the dimensions will be computed if they need to be (for overflow:hidden blocks).
|
| + if (m_scrollDimensionsDirty)
|
| + computeScrollDimensions();
|
| + }
|
| +
|
| + if (scrollOffset() == toIntSize(newScrollOffset))
|
| + return;
|
| +
|
| + setScrollOffset(toIntSize(newScrollOffset));
|
| +
|
| + Frame* frame = renderer()->frame();
|
| + InspectorInstrumentation::willScrollLayer(renderer());
|
| +
|
| + RenderView* view = renderer()->view();
|
| +
|
| + // We should have a RenderView if we're trying to scroll.
|
| + ASSERT(view);
|
| +
|
| + // Update the positions of our child layers (if needed as only fixed layers should be impacted by a scroll).
|
| + // We don't update compositing layers, because we need to do a deep update from the compositing ancestor.
|
| + bool inLayout = view ? view->frameView()->isInLayout() : false;
|
| + if (!inLayout) {
|
| + // If we're in the middle of layout, we'll just update layers once layout has finished.
|
| + m_layer->updateLayerPositionsAfterOverflowScroll();
|
| + if (view) {
|
| + // Update regions, scrolling may change the clip of a particular region.
|
| + view->frameView()->updateAnnotatedRegions();
|
| + view->updateWidgetPositions();
|
| + }
|
| +
|
| + m_layer->updateCompositingLayersAfterScroll();
|
| + }
|
| +
|
| + RenderLayerModelObject* repaintContainer = renderer()->containerForRepaint();
|
| + if (frame) {
|
| + // The caret rect needs to be invalidated after scrolling
|
| + frame->selection().setCaretRectNeedsUpdate();
|
| +
|
| + FloatQuad quadForFakeMouseMoveEvent = FloatQuad(m_layer->m_repaintRect);
|
| + if (repaintContainer)
|
| + quadForFakeMouseMoveEvent = repaintContainer->localToAbsoluteQuad(quadForFakeMouseMoveEvent);
|
| + frame->eventHandler()->dispatchFakeMouseMoveEventSoonInQuad(quadForFakeMouseMoveEvent);
|
| + }
|
| +
|
| + bool requiresRepaint = true;
|
| +
|
| + if (m_layer->compositor()->inCompositingMode() && m_layer->usesCompositedScrolling())
|
| + requiresRepaint = false;
|
| +
|
| + // Just schedule a full repaint of our object.
|
| + if (view && requiresRepaint)
|
| + renderer()->repaintUsingContainer(repaintContainer, pixelSnappedIntRect(m_layer->m_repaintRect));
|
| +
|
| + // Schedule the scroll DOM event.
|
| + if (renderer()->node())
|
| + renderer()->node()->document().eventQueue()->enqueueOrDispatchScrollEvent(renderer()->node(), DocumentEventQueue::ScrollEventElementTarget);
|
| +
|
| + InspectorInstrumentation::didScrollLayer(renderer());
|
| }
|
|
|
| IntPoint RenderLayerScrollableArea::scrollPosition() const
|
| @@ -197,12 +261,17 @@ IntPoint RenderLayerScrollableArea::scrollPosition() const
|
|
|
| IntPoint RenderLayerScrollableArea::minimumScrollPosition() const
|
| {
|
| - return m_layer->minimumScrollPosition();
|
| + return -scrollOrigin();
|
| }
|
|
|
| IntPoint RenderLayerScrollableArea::maximumScrollPosition() const
|
| {
|
| - return m_layer->maximumScrollPosition();
|
| + RenderBox* box = toRenderBox(renderer());
|
| +
|
| + if (!box->hasOverflowClip())
|
| + return -scrollOrigin();
|
| +
|
| + return -scrollOrigin() + enclosingIntRect(m_overflowRect).size() - enclosingIntRect(box->clientBoxRect()).size();
|
| }
|
|
|
| IntRect RenderLayerScrollableArea::visibleContentRect(VisibleContentRectIncludesScrollbars scrollbarInclusion) const
|
| @@ -230,7 +299,7 @@ int RenderLayerScrollableArea::visibleWidth() const
|
|
|
| IntSize RenderLayerScrollableArea::contentsSize() const
|
| {
|
| - return m_layer->contentsSize();
|
| + return IntSize(scrollWidth(), scrollHeight());
|
| }
|
|
|
| IntSize RenderLayerScrollableArea::overhangAmount() const
|
| @@ -275,4 +344,102 @@ RenderLayerModelObject* RenderLayerScrollableArea::renderer() const
|
| return m_layer->renderer();
|
| }
|
|
|
| +int RenderLayerScrollableArea::scrollWidth() const
|
| +{
|
| + RenderBox* box = toRenderBox(renderer());
|
| + if (m_scrollDimensionsDirty)
|
| + const_cast<RenderLayerScrollableArea*>(this)->computeScrollDimensions();
|
| + return snapSizeToPixel(m_overflowRect.width(), box->clientLeft() + box->x());
|
| +}
|
| +
|
| +int RenderLayerScrollableArea::scrollHeight() const
|
| +{
|
| + RenderBox* box = toRenderBox(renderer());
|
| + if (m_scrollDimensionsDirty)
|
| + const_cast<RenderLayerScrollableArea*>(this)->computeScrollDimensions();
|
| + return snapSizeToPixel(m_overflowRect.height(), box->clientTop() + box->y());
|
| +}
|
| +
|
| +void RenderLayerScrollableArea::computeScrollDimensions()
|
| +{
|
| + RenderBox* box = toRenderBox(renderer());
|
| +
|
| + m_scrollDimensionsDirty = false;
|
| +
|
| + m_overflowRect = box->layoutOverflowRect();
|
| + box->flipForWritingMode(m_overflowRect);
|
| +
|
| + int scrollableLeftOverflow = m_overflowRect.x() - box->borderLeft();
|
| + int scrollableTopOverflow = m_overflowRect.y() - box->borderTop();
|
| + setScrollOrigin(IntPoint(-scrollableLeftOverflow, -scrollableTopOverflow));
|
| +}
|
| +
|
| +void RenderLayerScrollableArea::scrollToOffset(const IntSize& scrollOffset, ScrollOffsetClamping clamp)
|
| +{
|
| + IntSize newScrollOffset = clamp == ScrollOffsetClamped ? clampScrollOffset(scrollOffset) : scrollOffset;
|
| + if (newScrollOffset != adjustedScrollOffset())
|
| + scrollToOffsetWithoutAnimation(-scrollOrigin() + newScrollOffset);
|
| +}
|
| +
|
| +void RenderLayerScrollableArea::updateAfterLayout()
|
| +{
|
| + m_scrollDimensionsDirty = true;
|
| + IntSize originalScrollOffset = adjustedScrollOffset();
|
| +
|
| + computeScrollDimensions();
|
| +
|
| + if (!toRenderBox(renderer())->isMarquee()) {
|
| + // 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).
|
| + IntSize clampedScrollOffset = clampScrollOffset(adjustedScrollOffset());
|
| + if (clampedScrollOffset != adjustedScrollOffset())
|
| + scrollToOffset(clampedScrollOffset);
|
| + }
|
| +
|
| + if (originalScrollOffset != adjustedScrollOffset())
|
| + scrollToOffsetWithoutAnimation(-scrollOrigin() + adjustedScrollOffset());
|
| +}
|
| +
|
| +bool RenderLayerScrollableArea::hasHorizontalOverflow() const
|
| +{
|
| + ASSERT(!m_scrollDimensionsDirty);
|
| +
|
| + return scrollWidth() > toRenderBox(renderer())->pixelSnappedClientWidth();
|
| +}
|
| +
|
| +bool RenderLayerScrollableArea::hasVerticalOverflow() const
|
| +{
|
| + ASSERT(!m_scrollDimensionsDirty);
|
| +
|
| + return scrollHeight() > toRenderBox(renderer())->pixelSnappedClientHeight();
|
| +}
|
| +
|
| +bool RenderLayerScrollableArea::hasScrollableHorizontalOverflow() const
|
| +{
|
| + return hasHorizontalOverflow() && toRenderBox(renderer())->scrollsOverflowX();
|
| +}
|
| +
|
| +bool RenderLayerScrollableArea::hasScrollableVerticalOverflow() const
|
| +{
|
| + return hasVerticalOverflow() && toRenderBox(renderer())->scrollsOverflowY();
|
| +}
|
| +
|
| +void RenderLayerScrollableArea::updateAfterStyleChange(const RenderStyle*)
|
| +{
|
| + if (!m_scrollDimensionsDirty)
|
| + m_layer->updateScrollableAreaSet(hasScrollableHorizontalOverflow() || hasScrollableVerticalOverflow());
|
| +}
|
| +
|
| +IntSize RenderLayerScrollableArea::clampScrollOffset(const IntSize& scrollOffset) const
|
| +{
|
| + RenderBox* box = toRenderBox(renderer());
|
| +
|
| + int maxX = scrollWidth() - box->pixelSnappedClientWidth();
|
| + int maxY = scrollHeight() - box->pixelSnappedClientHeight();
|
| +
|
| + int x = std::max(std::min(scrollOffset.width(), maxX), 0);
|
| + int y = std::max(std::min(scrollOffset.height(), maxY), 0);
|
| + return IntSize(x, y);
|
| +}
|
| +
|
| } // Namespace WebCore
|
|
|