void ScrollableAreaPainter::paintOverflowControls( GraphicsContext& context, const IntPoint& paintOffset, const CullRect& cullRect, bool paintingOverlayControls) { // Don't do anything if we have no overflow. if (!getScrollableArea().box().hasOverflowClip()) return; IntPoint adjustedPaintOffset = paintOffset; if (paintingOverlayControls) adjustedPaintOffset = getScrollableArea().cachedOverlayScrollbarOffset(); CullRect adjustedCullRect(cullRect, -adjustedPaintOffset); // Overlay scrollbars paint in a second pass through the layer tree so that // they will paint on top of everything else. If this is the normal painting // pass, paintingOverlayControls will be false, and we should just tell the // root layer that there are overlay scrollbars that need to be painted. That // will cause the second pass through the layer tree to run, and we'll paint // the scrollbars then. In the meantime, cache tx and ty so that the second // pass doesn't need to re-enter the LayoutTree to get it right. if (getScrollableArea().hasOverlayScrollbars() && !paintingOverlayControls) { getScrollableArea().setCachedOverlayScrollbarOffset(paintOffset); // It's not necessary to do the second pass if the scrollbars paint into // layers. if ((getScrollableArea().horizontalScrollbar() && getScrollableArea().layerForHorizontalScrollbar()) || (getScrollableArea().verticalScrollbar() && getScrollableArea().layerForVerticalScrollbar())) return; if (!overflowControlsIntersectRect(adjustedCullRect)) return; LayoutView* layoutView = getScrollableArea().box().view(); PaintLayer* paintingRoot = getScrollableArea().layer()->enclosingLayerWithCompositedLayerMapping( IncludeSelf); if (!paintingRoot) paintingRoot = layoutView->layer(); paintingRoot->setContainsDirtyOverlayScrollbars(true); return; } // This check is required to avoid painting custom CSS scrollbars twice. if (paintingOverlayControls && !getScrollableArea().hasOverlayScrollbars()) return; { Optional<ScopedPaintChunkProperties> scopedTransformProperty; if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { const auto* objectProperties = getScrollableArea().box().paintProperties(); if (objectProperties && objectProperties->scrollbarPaintOffset()) { PaintChunkProperties properties( context.getPaintController().currentPaintChunkProperties()); properties.transform = objectProperties->scrollbarPaintOffset(); scopedTransformProperty.emplace( context.getPaintController(), getScrollableArea().box(), DisplayItem::kScrollOverflowControls, properties); } } if (getScrollableArea().horizontalScrollbar() && !getScrollableArea().layerForHorizontalScrollbar()) { TransformRecorder translateRecorder( context, *getScrollableArea().horizontalScrollbar(), AffineTransform::translation(adjustedPaintOffset.x(), adjustedPaintOffset.y())); getScrollableArea().horizontalScrollbar()->paint(context, adjustedCullRect); } if (getScrollableArea().verticalScrollbar() && !getScrollableArea().layerForVerticalScrollbar()) { TransformRecorder translateRecorder( context, *getScrollableArea().verticalScrollbar(), AffineTransform::translation(adjustedPaintOffset.x(), adjustedPaintOffset.y())); getScrollableArea().verticalScrollbar()->paint(context, adjustedCullRect); } } if (getScrollableArea().layerForScrollCorner()) return; // We fill our scroll corner with white if we have a scrollbar that doesn't // run all the way up to the edge of the box. paintScrollCorner(context, adjustedPaintOffset, cullRect); // Paint our resizer last, since it sits on top of the scroll corner. paintResizer(context, adjustedPaintOffset, cullRect); }
void ScrollableAreaPainter::paintOverflowControls(GraphicsContext* context, const IntPoint& paintOffset, const IntRect& damageRect, bool paintingOverlayControls) { // Don't do anything if we have no overflow. if (!scrollableArea().box().hasOverflowClip()) return; IntPoint adjustedPaintOffset = paintOffset; if (paintingOverlayControls) adjustedPaintOffset = scrollableArea().cachedOverlayScrollbarOffset(); IntRect localDamageRect = damageRect; localDamageRect.moveBy(-adjustedPaintOffset); // Overlay scrollbars paint in a second pass through the layer tree so that they will paint // on top of everything else. If this is the normal painting pass, paintingOverlayControls // will be false, and we should just tell the root layer that there are overlay scrollbars // that need to be painted. That will cause the second pass through the layer tree to run, // and we'll paint the scrollbars then. In the meantime, cache tx and ty so that the // second pass doesn't need to re-enter the LayoutTree to get it right. if (scrollableArea().hasOverlayScrollbars() && !paintingOverlayControls) { scrollableArea().setCachedOverlayScrollbarOffset(paintOffset); // It's not necessary to do the second pass if the scrollbars paint into layers. if ((scrollableArea().horizontalScrollbar() && scrollableArea().layerForHorizontalScrollbar()) || (scrollableArea().verticalScrollbar() && scrollableArea().layerForVerticalScrollbar())) return; if (!overflowControlsIntersectRect(localDamageRect)) return; LayoutView* layoutView = scrollableArea().box().view(); PaintLayer* paintingRoot = scrollableArea().layer()->enclosingLayerWithCompositedLayerMapping(IncludeSelf); if (!paintingRoot) paintingRoot = layoutView->layer(); paintingRoot->setContainsDirtyOverlayScrollbars(true); return; } // This check is required to avoid painting custom CSS scrollbars twice. if (paintingOverlayControls && !scrollableArea().hasOverlayScrollbars()) return; { if (scrollableArea().horizontalScrollbar() && !scrollableArea().layerForHorizontalScrollbar()) { TransformRecorder translateRecorder(*context, *scrollableArea().horizontalScrollbar(), AffineTransform::translation(adjustedPaintOffset.x(), adjustedPaintOffset.y())); scrollableArea().horizontalScrollbar()->paint(context, localDamageRect); } if (scrollableArea().verticalScrollbar() && !scrollableArea().layerForVerticalScrollbar()) { TransformRecorder translateRecorder(*context, *scrollableArea().verticalScrollbar(), AffineTransform::translation(adjustedPaintOffset.x(), adjustedPaintOffset.y())); scrollableArea().verticalScrollbar()->paint(context, localDamageRect); } } if (scrollableArea().layerForScrollCorner()) return; // We fill our scroll corner with white if we have a scrollbar that doesn't run all the way up to the // edge of the box. paintScrollCorner(context, adjustedPaintOffset, damageRect); // Paint our resizer last, since it sits on top of the scroll corner. paintResizer(context, adjustedPaintOffset, damageRect); }