Index: third_party/WebKit/Source/core/paint/PaintInvalidationCapableScrollableArea.cpp |
diff --git a/third_party/WebKit/Source/core/paint/PaintInvalidationCapableScrollableArea.cpp b/third_party/WebKit/Source/core/paint/PaintInvalidationCapableScrollableArea.cpp |
index 8b1831a065130648a8329c5998bcbce4a11851fa..94168ae109b119a24206173229e2de3df6d1952b 100644 |
--- a/third_party/WebKit/Source/core/paint/PaintInvalidationCapableScrollableArea.cpp |
+++ b/third_party/WebKit/Source/core/paint/PaintInvalidationCapableScrollableArea.cpp |
@@ -12,6 +12,7 @@ |
#include "core/layout/LayoutScrollbarPart.h" |
#include "core/layout/PaintInvalidationState.h" |
#include "core/paint/PaintLayer.h" |
+#include "platform/graphics/GraphicsLayer.h" |
namespace blink { |
@@ -24,37 +25,81 @@ void PaintInvalidationCapableScrollableArea::willRemoveScrollbar(Scrollbar* scro |
ScrollableArea::willRemoveScrollbar(scrollbar, orientation); |
} |
-// Returns true if the scroll control is invalidated. |
-static bool invalidatePaintOfScrollControlIfNeeded(const IntRect& scrollControlRect, LayoutRect& previousPaintInvalidationRect, bool needsPaintInvalidation, LayoutBox& box, const PaintInvalidationState& paintInvalidationState, const LayoutBoxModelObject& paintInvalidationContainer) |
+static LayoutRect scrollControlPaintInvalidationRect(const IntRect& scrollControlRect, const LayoutBox& box, const PaintInvalidationState& paintInvalidationState, const LayoutBoxModelObject& paintInvalidationContainer) |
{ |
LayoutRect paintInvalidationRect(scrollControlRect); |
if (!paintInvalidationRect.isEmpty()) |
PaintLayer::mapRectToPaintInvalidationBacking(&box, &paintInvalidationContainer, paintInvalidationRect, &paintInvalidationState); |
+ return paintInvalidationRect; |
+} |
- if (paintInvalidationRect != previousPaintInvalidationRect) { |
+// Returns true if the scroll control is invalidated. |
+static bool invalidatePaintOfScrollControlIfNeeded(const LayoutRect& newPaintInvalidationRect, const LayoutRect& previousPaintInvalidationRect, bool needsPaintInvalidation, LayoutBox& box, const LayoutBoxModelObject& paintInvalidationContainer) |
+{ |
+ bool shouldInvalidateNewRect = needsPaintInvalidation; |
+ if (newPaintInvalidationRect != previousPaintInvalidationRect) { |
box.invalidatePaintUsingContainer(paintInvalidationContainer, previousPaintInvalidationRect, PaintInvalidationScroll); |
- previousPaintInvalidationRect = paintInvalidationRect; |
- needsPaintInvalidation = true; |
+ shouldInvalidateNewRect = true; |
} |
- |
- if (needsPaintInvalidation) { |
- box.invalidatePaintUsingContainer(paintInvalidationContainer, paintInvalidationRect, PaintInvalidationScroll); |
+ if (shouldInvalidateNewRect) { |
+ box.invalidatePaintUsingContainer(paintInvalidationContainer, newPaintInvalidationRect, PaintInvalidationScroll); |
+ box.enclosingLayer()->setNeedsRepaint(); |
return true; |
} |
- |
return false; |
} |
-static void invalidatePaintOfScrollbarIfNeeded(Scrollbar* scrollbar, GraphicsLayer* scrollbarGraphicsLayer, LayoutRect& previousPaintInvalidationRect, bool needsPaintInvalidation, LayoutBox& box, const PaintInvalidationState& paintInvalidationState, const LayoutBoxModelObject& paintInvalidationContainer) |
+struct ScrollbarPaintInvalidationData { |
+ Scrollbar* scrollbar; |
+ GraphicsLayer* graphicsLayer; |
+ LayoutRect& previousPaintInvalidatioRect; |
+ |
+}; |
+ |
+static void invalidatePaintOfScrollbarIfNeeded(Scrollbar* scrollbar, GraphicsLayer* graphicsLayer, bool& previouslyWasOverlay, LayoutRect& previousPaintInvalidationRect, bool needsPaintInvalidationArg, LayoutBox& box, const PaintInvalidationState& paintInvalidationState, const LayoutBoxModelObject& paintInvalidationContainer) |
{ |
- IntRect scrollbarRect = scrollbar && !scrollbarGraphicsLayer ? scrollbar->frameRect() : IntRect(); |
- if (!invalidatePaintOfScrollControlIfNeeded(scrollbarRect, previousPaintInvalidationRect, needsPaintInvalidation, box, paintInvalidationState, paintInvalidationContainer)) |
- return; |
- if (!scrollbar) |
+ bool isOverlay = scrollbar && scrollbar->isOverlayScrollbar(); |
+ |
+ // Calculate paint invalidation rect of the scrollbar, except overlay composited scrollbars because we invalidate the graphics layer only. |
+ LayoutRect newPaintInvalidationRect; |
+ if (scrollbar && !(graphicsLayer && isOverlay)) |
+ newPaintInvalidationRect = scrollControlPaintInvalidationRect(scrollbar->frameRect(), box, paintInvalidationState, paintInvalidationContainer); |
+ |
+ bool needsPaintInvalidation = needsPaintInvalidationArg; |
+ if (graphicsLayer && needsPaintInvalidation) { |
+ graphicsLayer->setNeedsDisplay(); |
+ graphicsLayer->setContentsNeedsDisplay(); |
+ // If the scrollbar needs paint invalidation but didn't change location/size or the scrollbar is an |
+ // overlay scrollbar (paint invalidation rect is empty), invalidating the graphics layer is enough. |
+ // Otherwise invalidatePaintOfScrollControlIfNeeded() below will invalidate the old and new location |
+ // of the scrollbar on the box's paint invalidation container to ensure newly expanded/shrunk areas |
+ // of the box to be invalidated. |
+ needsPaintInvalidation = false; |
+ } |
+ |
+ // Invalidate the box's display item client if the box's padding box size is affected by change of the |
+ // non-overlay scrollbar width. We detect change of paint invalidation rect size instead of change of |
+ // scrollbar width change, which may have some false-positives (e.g. the scrollbar changed length but |
+ // not width) but won't invalidate more than expected because in the false-positive case the box must |
+ // have changed size and have been invalidated. |
+ LayoutSize newScrollbarUsedSpaceInBox; |
+ if (!isOverlay) |
+ newScrollbarUsedSpaceInBox = newPaintInvalidationRect.size(); |
+ LayoutSize previousScrollbarUsedSpaceInBox; |
+ if (!previouslyWasOverlay) |
+ previousScrollbarUsedSpaceInBox= previousPaintInvalidationRect.size(); |
+ if (newScrollbarUsedSpaceInBox != previousScrollbarUsedSpaceInBox) |
+ paintInvalidationContainer.invalidateDisplayItemClientOnBacking(box, PaintInvalidationScroll, nullptr); |
+ |
+ bool invalidated = invalidatePaintOfScrollControlIfNeeded(newPaintInvalidationRect, previousPaintInvalidationRect, needsPaintInvalidation, box, paintInvalidationContainer); |
+ |
+ previousPaintInvalidationRect = newPaintInvalidationRect; |
+ previouslyWasOverlay = isOverlay; |
+ |
+ if (!invalidated || !scrollbar || graphicsLayer) |
return; |
paintInvalidationContainer.invalidateDisplayItemClientOnBacking(*scrollbar, PaintInvalidationScroll, &previousPaintInvalidationRect); |
- box.enclosingLayer()->setNeedsRepaint(); |
if (scrollbar->isCustomScrollbar()) |
toLayoutScrollbar(scrollbar)->invalidateDisplayItemClientsOfScrollbarParts(paintInvalidationContainer, previousPaintInvalidationRect); |
} |
@@ -62,18 +107,12 @@ static void invalidatePaintOfScrollbarIfNeeded(Scrollbar* scrollbar, GraphicsLay |
void PaintInvalidationCapableScrollableArea::invalidatePaintOfScrollControlsIfNeeded(const PaintInvalidationState& paintInvalidationState, const LayoutBoxModelObject& paintInvalidationContainer) |
{ |
LayoutBox& box = boxForScrollControlPaintInvalidation(); |
- LayoutRect oldRect = m_horizontalScrollbarPreviousPaintInvalidationRect; |
- invalidatePaintOfScrollbarIfNeeded(horizontalScrollbar(), layerForHorizontalScrollbar(), m_horizontalScrollbarPreviousPaintInvalidationRect, horizontalScrollbarNeedsPaintInvalidation(), box, paintInvalidationState, paintInvalidationContainer); |
- bool scrollbarGeometryChanged = oldRect != m_horizontalScrollbarPreviousPaintInvalidationRect; |
- |
- oldRect = m_verticalScrollbarPreviousPaintInvalidationRect; |
- invalidatePaintOfScrollbarIfNeeded(verticalScrollbar(), layerForVerticalScrollbar(), m_verticalScrollbarPreviousPaintInvalidationRect, verticalScrollbarNeedsPaintInvalidation(), box, paintInvalidationState, paintInvalidationContainer); |
- scrollbarGeometryChanged |= oldRect != m_verticalScrollbarPreviousPaintInvalidationRect; |
+ invalidatePaintOfScrollbarIfNeeded(horizontalScrollbar(), layerForHorizontalScrollbar(), m_horizontalScrollbarPreviouslyWasOverlay, m_horizontalScrollbarPreviousPaintInvalidationRect, horizontalScrollbarNeedsPaintInvalidation(), box, paintInvalidationState, paintInvalidationContainer); |
+ invalidatePaintOfScrollbarIfNeeded(verticalScrollbar(), layerForVerticalScrollbar(), m_verticalScrollbarPreviouslyWasOverlay, m_verticalScrollbarPreviousPaintInvalidationRect, verticalScrollbarNeedsPaintInvalidation(), box, paintInvalidationState, paintInvalidationContainer); |
- if (scrollbarGeometryChanged) |
- paintInvalidationContainer.invalidateDisplayItemClientOnBacking(box, PaintInvalidationScroll, nullptr); |
- |
- if (invalidatePaintOfScrollControlIfNeeded(scrollCornerRect(), m_scrollCornerPreviousPaintInvalidationRect, scrollCornerNeedsPaintInvalidation(), box, paintInvalidationState, paintInvalidationContainer)) { |
+ LayoutRect scrollCornerPaintInvalidationRect = scrollControlPaintInvalidationRect(scrollCornerRect(), box, paintInvalidationState, paintInvalidationContainer); |
+ if (invalidatePaintOfScrollControlIfNeeded(scrollCornerPaintInvalidationRect, m_scrollCornerPreviousPaintInvalidationRect, scrollCornerNeedsPaintInvalidation(), box, paintInvalidationContainer)) { |
+ m_scrollCornerPreviousPaintInvalidationRect = scrollCornerPaintInvalidationRect; |
if (LayoutScrollbarPart* scrollCorner = this->scrollCorner()) |
scrollCorner->invalidateDisplayItemClientsIncludingNonCompositingDescendants(&paintInvalidationContainer, PaintInvalidationScroll, &m_scrollCornerPreviousPaintInvalidationRect); |
if (LayoutScrollbarPart* resizer = this->resizer()) |
@@ -83,4 +122,11 @@ void PaintInvalidationCapableScrollableArea::invalidatePaintOfScrollControlsIfNe |
clearNeedsPaintInvalidationForScrollControls(); |
} |
+void PaintInvalidationCapableScrollableArea::clearPreviousPaintInvalidationRects() |
+{ |
+ m_horizontalScrollbarPreviousPaintInvalidationRect = LayoutRect(); |
+ m_verticalScrollbarPreviousPaintInvalidationRect = LayoutRect(); |
+ m_scrollCornerPreviousPaintInvalidationRect = LayoutRect(); |
+} |
+ |
} // namespace blink |