/*
 * Copyright (C) 2006-2020 Apple Inc. All rights reserved.
 * Copyright (C) 2019 Adobe. All rights reserved.
 * Copyright (C) 2020 Igalia S.L.
 *
 * Portions are Copyright (C) 1998 Netscape Communications Corporation.
 *
 * Other contributors:
 *   Robert O'Callahan <roc+@cs.cmu.edu>
 *   David Baron <dbaron@fas.harvard.edu>
 *   Christian Biesinger <cbiesinger@web.de>
 *   Randall Jesup <rjesup@wgate.com>
 *   Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
 *   Josh Soref <timeless@mac.com>
 *   Boris Zbarsky <bzbarsky@mit.edu>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * Alternatively, the contents of this file may be used under the terms
 * of either the Mozilla Public License Version 1.1, found at
 * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
 * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
 * (the "GPL"), in which case the provisions of the MPL or the GPL are
 * applicable instead of those above.  If you wish to allow use of your
 * version of this file only under the terms of one of those two
 * licenses (the MPL or the GPL) and not to allow others to use your
 * version of this file under the LGPL, indicate your decision by
 * deletingthe provisions above and replace them with the notice and
 * other provisions required by the MPL or the GPL, as the case may be.
 * If you do not delete the provisions above, a recipient may use your
 * version of this file under any of the LGPL, the MPL or the GPL.
 */

#include "config.h"
#include "RenderLayerScrollableArea.h"

#include "Chrome.h"
#include "DebugPageOverlays.h"
#include "DeprecatedGlobalSettings.h"
#include "Editor.h"
#include "ElementRuleCollector.h"
#include "EventHandler.h"
#include "FocusController.h"
#include "FrameSelection.h"
#include "HitTestResult.h"
#include "Logging.h"
#include "RenderFlexibleBox.h"
#include "RenderGeometryMap.h"
#include "RenderLayerBacking.h"
#include "RenderLayerCompositor.h"
#include "RenderMarquee.h"
#include "RenderScrollbar.h"
#include "RenderScrollbarPart.h"
#include "RenderView.h"
#include "ScrollAnimator.h"
#include "ScrollbarTheme.h"
#include "ScrollingCoordinator.h"
#include "ShadowRoot.h"
#include <wtf/SetForScope.h>

namespace WebCore {

RenderLayerScrollableArea::RenderLayerScrollableArea(RenderLayer& layer)
    : m_layer(layer)
{
}

RenderLayerScrollableArea::~RenderLayerScrollableArea()
{
}

void RenderLayerScrollableArea::clear()
{
    auto& renderer = m_layer.renderer();
    ASSERT(m_registeredScrollableArea == renderer.view().frameView().containsScrollableArea(this));

    if (m_registeredScrollableArea)
        renderer.view().frameView().removeScrollableArea(this);

#if ENABLE(IOS_TOUCH_EVENTS)
    unregisterAsTouchEventListenerForScrolling();
#endif
    if (Element* element = renderer.element())
        element->setSavedLayerScrollPosition(m_scrollPosition);

    destroyScrollbar(HorizontalScrollbar);
    destroyScrollbar(VerticalScrollbar);

    if (auto* scrollingCoordinator = renderer.page().scrollingCoordinator())
        scrollingCoordinator->willDestroyScrollableArea(*this);

    clearScrollCorner();
    clearResizer();
}

void RenderLayerScrollableArea::restoreScrollPosition()
{
    auto* element = m_layer.renderer().element();
    if (!element)
        return;

    if (m_layer.renderBox()) {
        // We save and restore only the scrollOffset as the other scroll values are recalculated.
        m_scrollPosition = element->savedLayerScrollPosition();
        if (!m_scrollPosition.isZero())
            scrollAnimator().setCurrentPosition(m_scrollPosition);
    }

    element->setSavedLayerScrollPosition(IntPoint());
}

bool RenderLayerScrollableArea::shouldPlaceVerticalScrollbarOnLeft() const
{
    return m_layer.renderer().shouldPlaceVerticalScrollbarOnLeft();
}

#if ENABLE(IOS_TOUCH_EVENTS)
bool RenderLayerScrollableArea::handleTouchEvent(const PlatformTouchEvent& touchEvent)
{
    // If we have accelerated scrolling, let the scrolling be handled outside of WebKit.
    if (hasCompositedScrollableOverflow())
        return false;

    return ScrollableArea::handleTouchEvent(touchEvent);
}

void RenderLayerScrollableArea::registerAsTouchEventListenerForScrolling()
{
    auto& renderer = m_layer.renderer();
    if (!renderer.element() || m_registeredAsTouchEventListenerForScrolling)
        return;

    renderer.document().addTouchEventHandler(*renderer.element());
    m_registeredAsTouchEventListenerForScrolling = true;
}

void RenderLayerScrollableArea::unregisterAsTouchEventListenerForScrolling()
{
    auto& renderer = m_layer.renderer();
    if (!renderer.element() || !m_registeredAsTouchEventListenerForScrolling)
        return;

    renderer.document().removeTouchEventHandler(*renderer.element());
    m_registeredAsTouchEventListenerForScrolling = false;
}
#endif // ENABLE(IOS_TOUCH_EVENTS)

IntRect RenderLayerScrollableArea::scrollableAreaBoundingBox(bool* isInsideFixed) const
{
    return m_layer.renderer().absoluteBoundingBoxRect(/* useTransforms */ true, isInsideFixed);
}

bool RenderLayerScrollableArea::isUserScrollInProgress() const
{
    if (!scrollsOverflow())
        return false;

    if (auto scrollingCoordinator = m_layer.page().scrollingCoordinator()) {
        if (scrollingCoordinator->isUserScrollInProgress(scrollingNodeID()))
            return true;
    }

    if (auto scrollAnimator = existingScrollAnimator())
        return scrollAnimator->isUserScrollInProgress();

    return false;
}

bool RenderLayerScrollableArea::isRubberBandInProgress() const
{
#if ENABLE(RUBBER_BANDING)
    if (!scrollsOverflow())
        return false;

    if (auto scrollingCoordinator = m_layer.page().scrollingCoordinator()) {
        if (scrollingCoordinator->isRubberBandInProgress(scrollingNodeID()))
            return true;
    }

    if (auto scrollAnimator = existingScrollAnimator())
        return scrollAnimator->isRubberBandInProgress();
#endif

    return false;
}

bool RenderLayerScrollableArea::forceUpdateScrollbarsOnMainThreadForPerformanceTesting() const
{
    return m_layer.renderer().settings().scrollingPerformanceTestingEnabled();
}

// FIXME: this is only valid after we've made layers.
bool RenderLayerScrollableArea::usesAsyncScrolling() const
{
    return m_layer.compositor().useCoordinatedScrollingForLayer(m_layer);
}

void RenderLayerScrollableArea::setPostLayoutScrollPosition(std::optional<ScrollPosition> position)
{
    m_postLayoutScrollPosition = position;
}

void RenderLayerScrollableArea::applyPostLayoutScrollPositionIfNeeded()
{
    if (!m_postLayoutScrollPosition)
        return;

    scrollToOffset(scrollOffsetFromPosition(m_postLayoutScrollPosition.value()));
    m_postLayoutScrollPosition = std::nullopt;
}

void RenderLayerScrollableArea::scrollToXPosition(int x, const ScrollPositionChangeOptions& options)
{
    ScrollPosition position(x, m_scrollPosition.y());
    setScrollPosition(position, options);
}

void RenderLayerScrollableArea::scrollToYPosition(int y, const ScrollPositionChangeOptions& options)
{
    ScrollPosition position(m_scrollPosition.x(), y);
    setScrollPosition(position, options);
}

void RenderLayerScrollableArea::setScrollPosition(const ScrollPosition& position, const ScrollPositionChangeOptions& options)
{
    scrollToOffset(scrollOffsetFromPosition(position), options);
}

ScrollOffset RenderLayerScrollableArea::clampScrollOffset(const ScrollOffset& scrollOffset) const
{
    return scrollOffset.constrainedBetween(IntPoint(), maximumScrollOffset());
}

bool RenderLayerScrollableArea::requestScrollPositionUpdate(const ScrollPosition& position, ScrollType scrollType, ScrollClamping clamping)
{
#if ENABLE(ASYNC_SCROLLING)
    LOG_WITH_STREAM(Scrolling, stream << m_layer << " requestScrollPositionUpdate " << position);

    if (auto* scrollingCoordinator = m_layer.page().scrollingCoordinator())
        return scrollingCoordinator->requestScrollPositionUpdate(*this, position, scrollType, clamping);
#endif
    return false;
}

ScrollOffset RenderLayerScrollableArea::scrollToOffset(const ScrollOffset& scrollOffset, const ScrollPositionChangeOptions& options)
{
    if (currentScrollBehaviorStatus() == ScrollBehaviorStatus::InNonNativeAnimation)
        scrollAnimator().cancelAnimations();

    ScrollOffset clampedScrollOffset = options.clamping == ScrollClamping::Clamped ? clampScrollOffset(scrollOffset) : scrollOffset;
    if (clampedScrollOffset == this->scrollOffset())
        return clampedScrollOffset;

    auto previousScrollType = currentScrollType();
    setCurrentScrollType(options.type);

    ScrollOffset snappedOffset = ceiledIntPoint(scrollAnimator().adjustScrollOffsetForSnappingIfNeeded(clampedScrollOffset, options.snapPointSelectionMethod));
    auto snappedPosition = scrollPositionFromOffset(snappedOffset);
    if (options.animated == AnimatedScroll::Yes)
        ScrollableArea::scrollToPositionWithAnimation(snappedPosition);
    else {
        if (!requestScrollPositionUpdate(snappedPosition, options.type, options.clamping))
            scrollToPositionWithoutAnimation(snappedPosition, options.clamping);
        setScrollBehaviorStatus(ScrollBehaviorStatus::NotInAnimation);
    }

    setCurrentScrollType(previousScrollType);
    return snappedOffset;
}

void RenderLayerScrollableArea::scrollTo(const ScrollPosition& position)
{
    RenderBox* box = m_layer.renderBox();
    if (!box)
        return;

    LOG_WITH_STREAM(Scrolling, stream << "RenderLayerScrollableArea  [" << scrollingNodeID() << "] scrollTo " << position << " from " << m_scrollPosition << " (is user scroll " << (currentScrollType() == ScrollType::User) << ")");

    ScrollPosition newPosition = position;
    if (!box->isHTMLMarquee()) {
        // Ensure that the dimensions will be computed if they need to be (for overflow:hidden blocks).
        if (m_scrollDimensionsDirty)
            computeScrollDimensions();
#if PLATFORM(IOS_FAMILY)
        if (adjustForIOSCaretWhenScrolling()) {
            // FIXME: It's not clear what this code is trying to do. Behavior seems reasonable with it removed.
            int maxOffset = scrollWidth() - roundToInt(box->clientWidth());
            ScrollOffset newOffset = scrollOffsetFromPosition(newPosition);
            int scrollXOffset = newOffset.x();
            if (scrollXOffset > maxOffset - caretWidth) {
                scrollXOffset += caretWidth;
                if (scrollXOffset <= caretWidth)
                    scrollXOffset = 0;
            } else if (scrollXOffset < m_scrollPosition.x() - caretWidth)
                scrollXOffset -= caretWidth;

            newOffset.setX(scrollXOffset);
            newPosition = scrollPositionFromOffset(newOffset);
        }
#endif
    }

    if (m_scrollPosition == newPosition && currentScrollBehaviorStatus() == ScrollBehaviorStatus::NotInAnimation) {
        // FIXME: Nothing guarantees we get a scrollTo() with an unchanged position at the end of a user gesture.
        // The ScrollingCoordinator probably needs to message the main thread when a gesture ends.
        if (requiresScrollPositionReconciliation()) {
            m_layer.setNeedsCompositingGeometryUpdate();
            updateCompositingLayersAfterScroll();
        }
        return;
    }

    m_scrollPosition = newPosition;

    auto& renderer = m_layer.renderer();
    RenderView& view = renderer.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.
    if (!view.frameView().layoutContext().isInRenderTreeLayout()) {
        // If we're in the middle of layout, we'll just update layers once layout has finished.
        updateLayerPositionsAfterOverflowScroll();

        view.frameView().scheduleUpdateWidgetPositions();

        if (!m_updatingMarqueePosition) {
            // Avoid updating compositing layers if, higher on the stack, we're already updating layer
            // positions. Updating layer positions requires a full walk of up-to-date RenderLayers, and
            // in this case we're still updating their positions; we'll update compositing layers later
            // when that completes.
            if (usesCompositedScrolling()) {
                m_layer.setNeedsCompositingGeometryUpdate();

                // Scroll position can affect the location of a composited descendant (which may be a sibling in z-order),
                // so trigger a descendant walk from the stacking context.
                if (auto* paintParent = m_layer.stackingContext())
                    paintParent->setDescendantsNeedUpdateBackingAndHierarchyTraversal();
            }

            updateCompositingLayersAfterScroll();
        }

        // Update regions, scrolling may change the clip of a particular region.
        renderer.document().invalidateRenderingDependentRegions();
        DebugPageOverlays::didLayout(renderer.frame());
    }

    Frame& frame = renderer.frame();
    RenderLayerModelObject* repaintContainer = renderer.containerForRepaint();
    // The caret rect needs to be invalidated after scrolling
    frame.selection().setCaretRectNeedsUpdate();

    LayoutRect rectForRepaint = layer().repaintRects() ? layer().repaintRects()->clippedOverflowRect : renderer.clippedOverflowRectForRepaint(repaintContainer);

    FloatQuad quadForFakeMouseMoveEvent = FloatQuad(rectForRepaint);
    if (repaintContainer)
        quadForFakeMouseMoveEvent = repaintContainer->localToAbsoluteQuad(quadForFakeMouseMoveEvent);
    frame.eventHandler().dispatchFakeMouseMoveEventSoonInQuad(quadForFakeMouseMoveEvent);

    bool requiresRepaint = true;
    if (usesCompositedScrolling()) {
        m_layer.setNeedsCompositingGeometryUpdate();
        m_layer.setDescendantsNeedUpdateBackingAndHierarchyTraversal();
        requiresRepaint = m_layer.backing()->needsRepaintOnCompositedScroll();
    }

    // Just schedule a full repaint of our object.
    if (requiresRepaint)
        renderer.repaintUsingContainer(repaintContainer, rectForRepaint);

    // Schedule the scroll and scroll-related DOM events.
    if (Element* element = renderer.element())
        element->document().addPendingScrollEventTarget(*element);

    if (scrollsOverflow())
        view.frameView().didChangeScrollOffset();

    view.frameView().viewportContentsChanged();
    frame.editor().renderLayerDidScroll(m_layer);
}

void RenderLayerScrollableArea::updateCompositingLayersAfterScroll()
{
    if (m_layer.compositor().hasContentCompositingLayers()) {
        // Our stacking container is guaranteed to contain all of our descendants that may need
        // repositioning, so update compositing layers from there.
        if (RenderLayer* compositingAncestor = m_layer.stackingContext()->enclosingCompositingLayer()) {
            if (usesCompositedScrolling())
                m_layer.compositor().updateCompositingLayers(CompositingUpdateType::OnCompositedScroll, compositingAncestor);
            else {
                // FIXME: would be nice to only dirty layers whose positions were affected by scrolling.
                compositingAncestor->setDescendantsNeedUpdateBackingAndHierarchyTraversal();
                m_layer.compositor().updateCompositingLayers(CompositingUpdateType::OnScroll, compositingAncestor);
            }
        }
    }
}

int RenderLayerScrollableArea::scrollWidth() const
{
    ASSERT(m_layer.renderBox());
    if (m_scrollDimensionsDirty)
        const_cast<RenderLayerScrollableArea*>(this)->computeScrollDimensions();
    // FIXME: This should use snappedIntSize() instead with absolute coordinates.
    return m_scrollWidth;
}

int RenderLayerScrollableArea::scrollHeight() const
{
    ASSERT(m_layer.renderBox());
    if (m_scrollDimensionsDirty)
        const_cast<RenderLayerScrollableArea*>(this)->computeScrollDimensions();
    // FIXME: This should use snappedIntSize() instead with absolute coordinates.
    return m_scrollHeight;
}

void RenderLayerScrollableArea::updateMarqueePosition()
{
    if (!m_marquee)
        return;

    // FIXME: would like to use SetForScope<> but it doesn't work with bitfields.
    bool oldUpdatingMarqueePosition = m_updatingMarqueePosition;
    m_updatingMarqueePosition = true;
    m_marquee->updateMarqueePosition();
    m_updatingMarqueePosition = oldUpdatingMarqueePosition;
}

void RenderLayerScrollableArea::createOrDestroyMarquee()
{
    auto& renderer = m_layer.renderer();
    if (renderer.isHTMLMarquee() && renderer.style().marqueeBehavior() != MarqueeBehavior::None && renderer.isBox()) {
        if (!m_marquee)
            m_marquee = makeUnique<RenderMarquee>(&m_layer);
        m_marquee->updateMarqueeStyle();
    } else if (m_marquee)
        m_marquee = nullptr;
}

bool RenderLayerScrollableArea::scrollsOverflow() const
{
    auto& renderer = m_layer.renderer();
    if (!is<RenderBox>(renderer))
        return false;

    return downcast<RenderBox>(renderer).scrollsOverflow();
}

bool RenderLayerScrollableArea::canUseCompositedScrolling() const
{
    auto& renderer = m_layer.renderer();
    bool isVisible = renderer.style().visibility() == Visibility::Visible;
    if (renderer.settings().asyncOverflowScrollingEnabled())
        return isVisible && scrollsOverflow() && !m_layer.isInsideSVGForeignObject();

#if PLATFORM(IOS_FAMILY) && ENABLE(OVERFLOW_SCROLLING_TOUCH)
    return isVisible && scrollsOverflow() && (renderer.style().useTouchOverflowScrolling() || renderer.settings().alwaysUseAcceleratedOverflowScroll());
#else
    return false;
#endif
}

void RenderLayerScrollableArea::setScrollOffset(const ScrollOffset& offset)
{
    scrollTo(scrollPositionFromOffset(offset));
}

ScrollingNodeID RenderLayerScrollableArea::scrollingNodeID() const
{
    if (!m_layer.isComposited())
        return 0;

    return m_layer.backing()->scrollingNodeIDForRole(ScrollCoordinationRole::Scrolling);
}

bool RenderLayerScrollableArea::handleWheelEventForScrolling(const PlatformWheelEvent& wheelEvent, std::optional<WheelScrollGestureState> gestureState)
{
    if (!isScrollableOrRubberbandable())
        return false;

#if ENABLE(ASYNC_SCROLLING)
    if (usesAsyncScrolling() && scrollingNodeID()) {
        if (auto* scrollingCoordinator = m_layer.page().scrollingCoordinator())
            return scrollingCoordinator->handleWheelEventForScrolling(wheelEvent, scrollingNodeID(), gestureState);
    }
#endif

    return ScrollableArea::handleWheelEventForScrolling(wheelEvent, gestureState);
}

IntRect RenderLayerScrollableArea::visibleContentRectInternal(VisibleContentRectIncludesScrollbars scrollbarInclusion, VisibleContentRectBehavior) const
{
    IntSize scrollbarSpace;
    if (showsOverflowControls() && scrollbarInclusion == IncludeScrollbars)
        scrollbarSpace = scrollbarIntrusion();

    auto visibleSize = this->visibleSize();
    return { scrollPosition(), { std::max(0, visibleSize.width() - scrollbarSpace.width()), std::max(0, visibleSize.height() - scrollbarSpace.height()) } };
}

IntSize RenderLayerScrollableArea::overhangAmount() const
{
#if ENABLE(RUBBER_BANDING)
    auto& renderer = m_layer.renderer();
    if (!renderer.settings().rubberBandingForSubScrollableRegionsEnabled())
        return IntSize();

    IntSize stretch;

    // FIXME: use maximumScrollOffset(), or just move this to ScrollableArea.
    ScrollOffset scrollOffset = scrollOffsetFromPosition(scrollPosition());
    auto reachableSize = reachableTotalContentsSize();
    if (scrollOffset.y() < 0)
        stretch.setHeight(scrollOffset.y());
    else if (reachableSize.height() && scrollOffset.y() > reachableSize.height() - visibleHeight())
        stretch.setHeight(scrollOffset.y() - (reachableSize.height() - visibleHeight()));

    if (scrollOffset.x() < 0)
        stretch.setWidth(scrollOffset.x());
    else if (reachableSize.width() && scrollOffset.x() > reachableSize.width() - visibleWidth())
        stretch.setWidth(scrollOffset.x() - (reachableSize.width() - visibleWidth()));

    return stretch;
#else
    return IntSize();
#endif
}

IntRect RenderLayerScrollableArea::scrollCornerRect() const
{
    return overflowControlsRects().scrollCorner;
}

bool RenderLayerScrollableArea::isScrollCornerVisible() const
{
    ASSERT(m_layer.renderer().isBox());
    return !scrollCornerRect().isEmpty();
}

IntRect RenderLayerScrollableArea::convertFromScrollbarToContainingView(const Scrollbar& scrollbar, const IntRect& scrollbarRect) const
{
    auto& renderer = m_layer.renderer();
    IntRect rect = scrollbarRect;
    rect.move(scrollbarOffset(scrollbar));
    return renderer.view().frameView().convertFromRendererToContainingView(&renderer, rect);
}

IntRect RenderLayerScrollableArea::convertFromContainingViewToScrollbar(const Scrollbar& scrollbar, const IntRect& parentRect) const
{
    auto& renderer = m_layer.renderer();
    IntRect rect = renderer.view().frameView().convertFromContainingViewToRenderer(&renderer, parentRect);
    rect.move(-scrollbarOffset(scrollbar));
    return rect;
}

IntPoint RenderLayerScrollableArea::convertFromScrollbarToContainingView(const Scrollbar& scrollbar, const IntPoint& scrollbarPoint) const
{
    auto& renderer = m_layer.renderer();
    IntPoint point = scrollbarPoint;
    point.move(scrollbarOffset(scrollbar));
    return renderer.view().frameView().convertFromRendererToContainingView(&renderer, point);
}

IntPoint RenderLayerScrollableArea::convertFromContainingViewToScrollbar(const Scrollbar& scrollbar, const IntPoint& parentPoint) const
{
    auto& renderer = m_layer.renderer();
    IntPoint point = renderer.view().frameView().convertFromContainingViewToRenderer(&renderer, parentPoint);
    point.move(-scrollbarOffset(scrollbar));
    return point;
}

IntSize RenderLayerScrollableArea::visibleSize() const
{
    return m_layer.visibleSize();
}

IntSize RenderLayerScrollableArea::contentsSize() const
{
    return IntSize(scrollWidth(), scrollHeight());
}

IntSize RenderLayerScrollableArea::reachableTotalContentsSize() const
{
    IntSize contentsSize = this->contentsSize();

    if (!hasScrollableHorizontalOverflow())
        contentsSize.setWidth(std::min(contentsSize.width(), visibleSize().width()));

    if (!hasScrollableVerticalOverflow())
        contentsSize.setHeight(std::min(contentsSize.height(), visibleSize().height()));

    return contentsSize;
}

void RenderLayerScrollableArea::availableContentSizeChanged(AvailableSizeChangeReason reason)
{
    ScrollableArea::availableContentSizeChanged(reason);

    auto& renderer = m_layer.renderer();
    if (reason == AvailableSizeChangeReason::ScrollbarsChanged) {
        if (is<RenderBlock>(renderer))
            downcast<RenderBlock>(renderer).setShouldForceRelayoutChildren(true);
        renderer.setNeedsLayout();
    }
}

bool RenderLayerScrollableArea::shouldSuspendScrollAnimations() const
{
    auto& renderer = m_layer.renderer();
    return renderer.view().frameView().shouldSuspendScrollAnimations();
}

#if PLATFORM(IOS_FAMILY)
void RenderLayerScrollableArea::didStartScroll()
{
    m_layer.page().chrome().client().didStartOverflowScroll();
}

void RenderLayerScrollableArea::didEndScroll()
{
    m_layer.page().chrome().client().didEndOverflowScroll();
}

void RenderLayerScrollableArea::didUpdateScroll()
{
    // Send this notification when we scroll, since this is how we keep selection updated.
    m_layer.page().chrome().client().didLayout(ChromeClient::Scroll);
}
#endif

RenderLayer::OverflowControlRects RenderLayerScrollableArea::overflowControlsRects() const
{
    auto& renderer = m_layer.renderer();
    ASSERT(is<RenderBox>(renderer));
    auto& renderBox = downcast<RenderBox>(renderer);
    // Scrollbars sit inside the border box.
    auto overflowControlsPositioningRect = snappedIntRect(renderBox.paddingBoxRectIncludingScrollbar());

    auto horizontalScrollbarHeight = m_hBar ? m_hBar->height() : 0;
    auto verticalScrollbarWidth = m_vBar ? m_vBar->width() : 0;

    auto isNonOverlayScrollbar = [](const Scrollbar* scrollbar) {
        return scrollbar && !scrollbar->isOverlayScrollbar();
    };

    bool haveNonOverlayHorizontalScrollbar = isNonOverlayScrollbar(m_hBar.get());
    bool haveNonOverlayVerticalScrollbar = isNonOverlayScrollbar(m_vBar.get());
    bool placeVerticalScrollbarOnTheLeft = shouldPlaceVerticalScrollbarOnLeft();
    bool haveResizer = renderer.style().resize() != Resize::None;
    bool scrollbarsAvoidCorner = (haveNonOverlayHorizontalScrollbar && haveNonOverlayVerticalScrollbar) || (haveResizer && (haveNonOverlayHorizontalScrollbar || haveNonOverlayVerticalScrollbar));

    IntSize cornerSize;
    if (scrollbarsAvoidCorner) {
        // If only one scrollbar is present, the corner is square.
        cornerSize = IntSize {
            verticalScrollbarWidth ? verticalScrollbarWidth : horizontalScrollbarHeight,
            horizontalScrollbarHeight ? horizontalScrollbarHeight : verticalScrollbarWidth
        };
    }

    RenderLayer::OverflowControlRects result;

    if (m_hBar) {
        auto barRect = overflowControlsPositioningRect;
        barRect.shiftYEdgeTo(barRect.maxY() - horizontalScrollbarHeight);
        if (scrollbarsAvoidCorner) {
            if (placeVerticalScrollbarOnTheLeft)
                barRect.shiftXEdgeTo(barRect.x() + cornerSize.width());
            else
                barRect.contract(cornerSize.width(), 0);
        }

        result.horizontalScrollbar = barRect;
    }

    if (m_vBar) {
        auto barRect = overflowControlsPositioningRect;
        if (placeVerticalScrollbarOnTheLeft)
            barRect.setWidth(verticalScrollbarWidth);
        else
            barRect.shiftXEdgeTo(barRect.maxX() - verticalScrollbarWidth);

        if (scrollbarsAvoidCorner)
            barRect.contract(0, cornerSize.height());

        result.verticalScrollbar = barRect;
    }

    auto cornerRect = [&](IntSize cornerSize) {
        if (placeVerticalScrollbarOnTheLeft) {
            auto bottomLeftCorner = overflowControlsPositioningRect.minXMaxYCorner();
            return IntRect { { bottomLeftCorner.x(), bottomLeftCorner.y() - cornerSize.height(), }, cornerSize };
        }
        return IntRect { overflowControlsPositioningRect.maxXMaxYCorner() - cornerSize, cornerSize };
    };

    if (scrollbarsAvoidCorner)
        result.scrollCorner = cornerRect(cornerSize);

    if (haveResizer) {
        if (scrollbarsAvoidCorner)
            result.resizer = result.scrollCorner;
        else {
            auto scrollbarThickness = ScrollbarTheme::theme().scrollbarThickness();
            result.resizer = cornerRect({ scrollbarThickness, scrollbarThickness });
        }
    }

    return result;
}

IntSize RenderLayerScrollableArea::scrollbarOffset(const Scrollbar& scrollbar) const
{
    auto rects = overflowControlsRects();

    if (&scrollbar == m_vBar.get())
        return toIntSize(rects.verticalScrollbar.location());

    if (&scrollbar == m_hBar.get())
        return toIntSize(rects.horizontalScrollbar.location());

    ASSERT_NOT_REACHED();
    return { };
}

void RenderLayerScrollableArea::invalidateScrollbarRect(Scrollbar& scrollbar, const IntRect& rect)
{
    if (!showsOverflowControls())
        return;

    if (&scrollbar == m_vBar.get()) {
        if (GraphicsLayer* layer = layerForVerticalScrollbar()) {
            layer->setNeedsDisplayInRect(rect);
            return;
        }
    } else {
        if (GraphicsLayer* layer = layerForHorizontalScrollbar()) {
            layer->setNeedsDisplayInRect(rect);
            return;
        }
    }

    auto scrollRect = rect;
    RenderBox* box = m_layer.renderBox();
    ASSERT(box);
    // If we are not yet inserted into the tree, there is no need to repaint.
    if (!box->parent())
        return;

    auto rects = overflowControlsRects();

    if (&scrollbar == m_vBar.get())
        scrollRect.moveBy(rects.verticalScrollbar.location());
    else
        scrollRect.moveBy(rects.horizontalScrollbar.location());

    LayoutRect repaintRect = scrollRect;
    box->flipForWritingMode(repaintRect);
    box->repaintRectangle(repaintRect);
}

void RenderLayerScrollableArea::invalidateScrollCornerRect(const IntRect& rect)
{
    if (!showsOverflowControls())
        return;

    if (GraphicsLayer* layer = layerForScrollCorner()) {
        layer->setNeedsDisplayInRect(rect);
        return;
    }

    if (m_scrollCorner)
        m_scrollCorner->repaintRectangle(rect);
    if (m_resizer)
        m_resizer->repaintRectangle(rect);
}

static bool scrollbarHiddenByStyle(Scrollbar* scrollbar)
{
    return scrollbar && scrollbar->isHiddenByStyle();
}

bool RenderLayerScrollableArea::horizontalScrollbarHiddenByStyle() const
{
    return scrollbarHiddenByStyle(horizontalScrollbar());
}

bool RenderLayerScrollableArea::verticalScrollbarHiddenByStyle() const
{
    return scrollbarHiddenByStyle(verticalScrollbar());
}

static inline RenderElement* rendererForScrollbar(RenderLayerModelObject& renderer)
{
    if (Element* element = renderer.element()) {
        if (ShadowRoot* shadowRoot = element->containingShadowRoot()) {
            if (shadowRoot->mode() == ShadowRootMode::UserAgent)
                return shadowRoot->host()->renderer();
        }
    }

    return &renderer;
}

Ref<Scrollbar> RenderLayerScrollableArea::createScrollbar(ScrollbarOrientation orientation)
{
    auto& renderer = m_layer.renderer();
    RefPtr<Scrollbar> widget;
    ASSERT(rendererForScrollbar(renderer));
    auto& actualRenderer = *rendererForScrollbar(renderer);
    bool hasCustomScrollbarStyle = is<RenderBox>(actualRenderer) && downcast<RenderBox>(actualRenderer).style().hasPseudoStyle(PseudoId::Scrollbar);
    auto element = downcast<RenderBox>(actualRenderer).element();
    if (hasCustomScrollbarStyle && element)
        widget = RenderScrollbar::createCustomScrollbar(*this, orientation, element);
    else {
        widget = Scrollbar::createNativeScrollbar(*this, orientation, ScrollbarControlSize::Regular);
        didAddScrollbar(widget.get(), orientation);
        if (m_layer.page().isMonitoringWheelEvents())
            scrollAnimator().setWheelEventTestMonitor(m_layer.page().wheelEventTestMonitor());
    }
    renderer.view().frameView().addChild(*widget);
    return widget.releaseNonNull();
}

void RenderLayerScrollableArea::destroyScrollbar(ScrollbarOrientation orientation)
{
    RefPtr<Scrollbar>& scrollbar = orientation == HorizontalScrollbar ? m_hBar : m_vBar;
    if (!scrollbar)
        return;

    if (!scrollbar->isCustomScrollbar())
        willRemoveScrollbar(scrollbar.get(), orientation);

    scrollbar->removeFromParent();
    scrollbar = nullptr;
}

void RenderLayerScrollableArea::setHasHorizontalScrollbar(bool hasScrollbar)
{
    if (hasScrollbar == hasHorizontalScrollbar())
        return;

    if (hasScrollbar) {
        m_hBar = createScrollbar(HorizontalScrollbar);
#if ENABLE(RUBBER_BANDING)
        auto& renderer = m_layer.renderer();
        ScrollElasticity elasticity = scrollsOverflow() && renderer.settings().rubberBandingForSubScrollableRegionsEnabled() ? ScrollElasticityAutomatic : ScrollElasticityNone;
        ScrollableArea::setHorizontalScrollElasticity(elasticity);
#endif
    } else {
        destroyScrollbar(HorizontalScrollbar);
#if ENABLE(RUBBER_BANDING)
        ScrollableArea::setHorizontalScrollElasticity(ScrollElasticityNone);
#endif
    }

    // Destroying or creating one bar can cause our scrollbar corner to come and go. We need to update the opposite scrollbar's style.
    if (m_hBar)
        m_hBar->styleChanged();
    if (m_vBar)
        m_vBar->styleChanged();
}

void RenderLayerScrollableArea::setHasVerticalScrollbar(bool hasScrollbar)
{
    if (hasScrollbar == hasVerticalScrollbar())
        return;

    if (hasScrollbar) {
        m_vBar = createScrollbar(VerticalScrollbar);
#if ENABLE(RUBBER_BANDING)
        auto& renderer = m_layer.renderer();
        ScrollElasticity elasticity = scrollsOverflow() && renderer.settings().rubberBandingForSubScrollableRegionsEnabled() ? ScrollElasticityAutomatic : ScrollElasticityNone;
        ScrollableArea::setVerticalScrollElasticity(elasticity);
#endif
    } else {
        destroyScrollbar(VerticalScrollbar);
#if ENABLE(RUBBER_BANDING)
        ScrollableArea::setVerticalScrollElasticity(ScrollElasticityNone);
#endif
    }

    // Destroying or creating one bar can cause our scrollbar corner to come and go. We need to update the opposite scrollbar's style.
    if (m_hBar)
        m_hBar->styleChanged();
    if (m_vBar)
        m_vBar->styleChanged();
}

ScrollableArea* RenderLayerScrollableArea::enclosingScrollableArea() const
{
    if (auto* scrollableLayer = m_layer.enclosingScrollableLayer(IncludeSelfOrNot::ExcludeSelf, CrossFrameBoundaries::No))
        return scrollableLayer->scrollableArea();

    auto& renderer = m_layer.renderer();
    return &renderer.view().frameView();
}

bool RenderLayerScrollableArea::isScrollableOrRubberbandable()
{
    auto& renderer = m_layer.renderer();
    return renderer.isScrollableOrRubberbandableBox();
}

bool RenderLayerScrollableArea::hasScrollableOrRubberbandableAncestor()
{
    for (auto* nextLayer = m_layer.enclosingContainingBlockLayer(CrossFrameBoundaries::Yes); nextLayer; nextLayer = nextLayer->enclosingContainingBlockLayer(CrossFrameBoundaries::Yes)) {
        if (nextLayer->renderer().isScrollableOrRubberbandableBox())
            return true;
    }

    return false;
}

int RenderLayerScrollableArea::verticalScrollbarWidth(OverlayScrollbarSizeRelevancy relevancy) const
{
    if (!m_vBar
        || !showsOverflowControls()
        || (m_vBar->isOverlayScrollbar() && (relevancy == IgnoreOverlayScrollbarSize || !m_vBar->shouldParticipateInHitTesting())))
        return 0;

    return m_vBar->width();
}

int RenderLayerScrollableArea::horizontalScrollbarHeight(OverlayScrollbarSizeRelevancy relevancy) const
{
    if (!m_hBar
        || !showsOverflowControls()
        || (m_hBar->isOverlayScrollbar() && (relevancy == IgnoreOverlayScrollbarSize || !m_hBar->shouldParticipateInHitTesting())))
        return 0;

    return m_hBar->height();
}

bool RenderLayerScrollableArea::hasOverflowControls() const
{
    return m_hBar || m_vBar || m_scrollCorner || m_layer.renderer().style().resize() != Resize::None;
}

void RenderLayerScrollableArea::positionOverflowControls(const IntSize& offsetFromRoot)
{
    if (!m_hBar && !m_vBar && !m_layer.canResize())
        return;

    if (!m_layer.renderBox())
        return;

    auto rects = overflowControlsRects();

    if (m_vBar) {
        rects.verticalScrollbar.move(offsetFromRoot);
        m_vBar->setFrameRect(rects.verticalScrollbar);
    }

    if (m_hBar) {
        rects.horizontalScrollbar.move(offsetFromRoot);
        m_hBar->setFrameRect(rects.horizontalScrollbar);
    }

    if (m_scrollCorner)
        m_scrollCorner->setFrameRect(rects.scrollCorner);

    if (m_resizer)
        m_resizer->setFrameRect(rects.resizer);
}

LayoutUnit RenderLayerScrollableArea::overflowTop() const
{
    RenderBox* box = m_layer.renderBox();
    LayoutRect overflowRect(box->layoutOverflowRect());
    box->flipForWritingMode(overflowRect);
    return overflowRect.y();
}

LayoutUnit RenderLayerScrollableArea::overflowBottom() const
{
    RenderBox* box = m_layer.renderBox();
    LayoutRect overflowRect(box->layoutOverflowRect());
    box->flipForWritingMode(overflowRect);
    return overflowRect.maxY();
}

LayoutUnit RenderLayerScrollableArea::overflowLeft() const
{
    RenderBox* box = m_layer.renderBox();
    LayoutRect overflowRect(box->layoutOverflowRect());
    box->flipForWritingMode(overflowRect);
    return overflowRect.x();
}

LayoutUnit RenderLayerScrollableArea::overflowRight() const
{
    RenderBox* box = m_layer.renderBox();
    LayoutRect overflowRect(box->layoutOverflowRect());
    box->flipForWritingMode(overflowRect);
    return overflowRect.maxX();
}

void RenderLayerScrollableArea::computeScrollDimensions()
{
    m_scrollDimensionsDirty = false;

    m_scrollWidth = roundToInt(overflowRight() - overflowLeft());
    m_scrollHeight = roundToInt(overflowBottom() - overflowTop());

    computeScrollOrigin();
    computeHasCompositedScrollableOverflow();
}

void RenderLayerScrollableArea::computeScrollOrigin()
{
    RenderBox* box = m_layer.renderBox();
    ASSERT(box);

    int scrollableLeftOverflow = roundToInt(overflowLeft() - box->borderLeft());
    if (shouldPlaceVerticalScrollbarOnLeft() /*|| box->style().writingMode() == WritingMode::RightToLeft*/)
        scrollableLeftOverflow -= verticalScrollbarWidth();
    int scrollableTopOverflow = roundToInt(overflowTop() - box->borderTop());
    setScrollOrigin(IntPoint(-scrollableLeftOverflow, -scrollableTopOverflow));

    // Horizontal scrollbar offsets depend on the scroll origin when vertical
    // scrollbars are on the left.
    if (m_hBar)
        m_hBar->offsetDidChange();
}

void RenderLayerScrollableArea::computeHasCompositedScrollableOverflow()
{
    m_hasCompositedScrollableOverflow = canUseCompositedScrolling() && (hasScrollableHorizontalOverflow() || hasScrollableVerticalOverflow());
}

bool RenderLayerScrollableArea::hasScrollableHorizontalOverflow() const
{
    return hasHorizontalOverflow() && m_layer.renderBox()->scrollsOverflowX();
}

bool RenderLayerScrollableArea::hasScrollableVerticalOverflow() const
{
    return hasVerticalOverflow() && m_layer.renderBox()->scrollsOverflowY();
}

bool RenderLayerScrollableArea::hasHorizontalOverflow() const
{
    ASSERT(!m_scrollDimensionsDirty);

    return scrollWidth() > roundToInt(m_layer.renderBox()->clientWidth());
}

bool RenderLayerScrollableArea::hasVerticalOverflow() const
{
    ASSERT(!m_scrollDimensionsDirty);

    return scrollHeight() > roundToInt(m_layer.renderBox()->clientHeight());
}

void RenderLayerScrollableArea::updateScrollbarPresenceAndState(std::optional<bool> hasHorizontalOverflow, std::optional<bool> hasVerticalOverflow)
{
    auto* box = m_layer.renderBox();
    ASSERT(box);

    enum class ScrollbarState {
        NoScrollbar,
        Enabled,
        Disabled
    };

    auto scrollbarForAxis = [&](ScrollbarOrientation orientation) -> RefPtr<Scrollbar>& {
        return orientation == ScrollbarOrientation::HorizontalScrollbar ? m_hBar : m_vBar;
    };

    auto stateForScrollbar = [&](ScrollbarOrientation orientation, std::optional<bool> hasOverflow, ScrollbarState nonScrollableState) {
        if (hasOverflow)
            return *hasOverflow ? ScrollbarState::Enabled : nonScrollableState;
        
        // If we don't have information about overflow (because we haven't done layout yet), just return the current state of the scrollbar.
        auto existingScrollbar = scrollbarForAxis(orientation);
        return (existingScrollbar && existingScrollbar->enabled()) ? ScrollbarState::Enabled : nonScrollableState;
    };

    auto stateForScrollbarOnAxis = [&](ScrollbarOrientation orientation, std::optional<bool> hasOverflow) {
        if (box->hasAlwaysPresentScrollbar(orientation))
            return stateForScrollbar(orientation, hasOverflow, ScrollbarState::Disabled);

        if (box->hasAutoScrollbar(orientation))
            return stateForScrollbar(orientation, hasOverflow, ScrollbarState::NoScrollbar);

        return ScrollbarState::NoScrollbar;
    };

    auto horizontalBarState = stateForScrollbarOnAxis(ScrollbarOrientation::HorizontalScrollbar, hasHorizontalOverflow);
    setHasHorizontalScrollbar(horizontalBarState != ScrollbarState::NoScrollbar);
    if (horizontalBarState != ScrollbarState::NoScrollbar)
        m_hBar->setEnabled(horizontalBarState == ScrollbarState::Enabled);

    auto verticalBarState = stateForScrollbarOnAxis(ScrollbarOrientation::VerticalScrollbar, hasVerticalOverflow);
    setHasVerticalScrollbar(verticalBarState != ScrollbarState::NoScrollbar);
    if (verticalBarState != ScrollbarState::NoScrollbar)
        m_vBar->setEnabled(verticalBarState == ScrollbarState::Enabled);
}

void RenderLayerScrollableArea::updateScrollbarsAfterStyleChange(const RenderStyle* oldStyle)
{
    // Overflow is a box concept.
    RenderBox* box = m_layer.renderBox();
    if (!box)
        return;

    // List box parts handle the scrollbars by themselves so we have nothing to do.
    if (box->style().appearance() == ListboxPart)
        return;

    bool hadVerticalScrollbar = hasVerticalScrollbar();
    updateScrollbarPresenceAndState();
    bool hasVerticalScrollbar = this->hasVerticalScrollbar();

    if (hadVerticalScrollbar != hasVerticalScrollbar || (hasVerticalScrollbar && oldStyle && oldStyle->shouldPlaceVerticalScrollbarOnLeft() != box->style().shouldPlaceVerticalScrollbarOnLeft()))
        computeScrollOrigin();

    if (!m_scrollDimensionsDirty)
        updateScrollableAreaSet(hasScrollableHorizontalOverflow() || hasScrollableVerticalOverflow());
}

void RenderLayerScrollableArea::updateScrollbarsAfterLayout()
{
    RenderBox* box = m_layer.renderBox();
    ASSERT(box);

    // List box parts handle the scrollbars by themselves so we have nothing to do.
    if (box->style().appearance() == ListboxPart)
        return;

    bool hadHorizontalScrollbar = hasHorizontalScrollbar();
    bool hadVerticalScrollbar = hasVerticalScrollbar();

    updateScrollbarPresenceAndState(hasHorizontalOverflow(), hasVerticalOverflow());

    // Scrollbars with auto behavior may need to lay out again if scrollbars got added or removed.
    bool autoHorizontalScrollBarChanged = box->hasAutoScrollbar(ScrollbarOrientation::HorizontalScrollbar) && (hadHorizontalScrollbar != hasHorizontalScrollbar());
    bool autoVerticalScrollBarChanged = box->hasAutoScrollbar(ScrollbarOrientation::VerticalScrollbar) && (hadVerticalScrollbar != hasVerticalScrollbar());

    if (autoHorizontalScrollBarChanged || autoVerticalScrollBarChanged) {
        if (autoVerticalScrollBarChanged && shouldPlaceVerticalScrollbarOnLeft())
            computeScrollOrigin();

        m_layer.updateSelfPaintingLayer();

        auto& renderer = m_layer.renderer();
        renderer.repaint();

        if (renderer.style().overflowX() == Overflow::Auto || renderer.style().overflowY() == Overflow::Auto) {
            if (!m_inOverflowRelayout) {
                SetForScope<bool> inOverflowRelayoutScope(m_inOverflowRelayout, true);
                renderer.setNeedsLayout(MarkOnlyThis);
                if (is<RenderBlock>(renderer)) {
                    auto& block = downcast<RenderBlock>(renderer);
                    block.scrollbarsChanged(autoHorizontalScrollBarChanged, autoVerticalScrollBarChanged);
                    block.layoutBlock(true);
                } else
                    renderer.layout();
            }
        }

        // FIXME: This does not belong here.
        RenderObject* parent = renderer.parent();
        if (parent && parent->isFlexibleBox() && renderer.isBox())
            downcast<RenderFlexibleBox>(parent)->clearCachedMainSizeForChild(*m_layer.renderBox());
    }

    // Set up the range.
    if (m_hBar)
        m_hBar->setProportion(roundToInt(box->clientWidth()), m_scrollWidth);
    if (m_vBar)
        m_vBar->setProportion(roundToInt(box->clientHeight()), m_scrollHeight);

    updateScrollbarSteps();

    updateScrollableAreaSet(hasScrollableHorizontalOverflow() || hasScrollableVerticalOverflow());
}

void RenderLayerScrollableArea::updateScrollbarSteps()
{
    RenderBox* box = m_layer.renderBox();
    ASSERT(box);

    LayoutRect paddedLayerBounds(0_lu, 0_lu, box->clientWidth(), box->clientHeight());
    paddedLayerBounds.contract(box->scrollPaddingForViewportRect(paddedLayerBounds));

    // Set up the  page step/line step.
    if (m_hBar) {
        int pageStep = Scrollbar::pageStep(roundToInt(paddedLayerBounds.width()));
        m_hBar->setSteps(Scrollbar::pixelsPerLineStep(), pageStep);
    }
    if (m_vBar) {
        int pageStep = Scrollbar::pageStep(roundToInt(paddedLayerBounds.height()));
        m_vBar->setSteps(Scrollbar::pixelsPerLineStep(), pageStep);
    }
}


// This is called from layout code (before updateLayerPositions).
void RenderLayerScrollableArea::updateScrollInfoAfterLayout()
{
    RenderBox* box = m_layer.renderBox();
    if (!box)
        return;

    m_scrollDimensionsDirty = true;
    ScrollPosition originalScrollPosition = scrollPosition();

    computeScrollDimensions();
    m_layer.updateSelfPaintingLayer();

    // FIXME: Ensure that offsets are also updated in case of programmatic style changes.
    // https://bugs.webkit.org/show_bug.cgi?id=135964
    updateSnapOffsets();

    if (!box->isHTMLMarquee() && !isRubberBandInProgress() && !isUserScrollInProgress()) {
        // 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).
        ScrollOffset clampedScrollOffset = clampScrollOffset(scrollOffset());
#if PLATFORM(IOS_FAMILY)
        // FIXME: This looks wrong. The caret adjust mode should only be enabled on editing related entry points.
        // This code was added to fix an issue where the text insertion point would always be drawn on the right edge
        // of a text field whose content overflowed its bounds. See <rdar://problem/15579797> for more details.
        setAdjustForIOSCaretWhenScrolling(true);
#endif
        if (clampedScrollOffset != scrollOffset())
            scrollToOffset(clampedScrollOffset);

#if PLATFORM(IOS_FAMILY)
        setAdjustForIOSCaretWhenScrolling(false);
#endif
    }

    updateScrollbarsAfterLayout();

    if (originalScrollPosition != scrollPosition())
        scrollToPositionWithoutAnimation(IntPoint(scrollPosition()));

    if (m_layer.isComposited()) {
        m_layer.setNeedsCompositingGeometryUpdate();
        m_layer.setNeedsCompositingConfigurationUpdate();
    }

    if (canUseCompositedScrolling())
        m_layer.setNeedsPostLayoutCompositingUpdate();

    resnapAfterLayout();
}

bool RenderLayerScrollableArea::overflowControlsIntersectRect(const IntRect& localRect) const
{
    auto rects = overflowControlsRects();

    if (rects.horizontalScrollbar.intersects(localRect))
        return true;

    if (rects.verticalScrollbar.intersects(localRect))
        return true;

    if (rects.scrollCorner.intersects(localRect))
        return true;

    if (rects.resizer.intersects(localRect))
        return true;

    return false;
}

bool RenderLayerScrollableArea::showsOverflowControls() const
{
#if PLATFORM(IOS_FAMILY)
    // On iOS, the scrollbars are made in the UI process.
    return !canUseCompositedScrolling();
#endif

    return true;
}

void RenderLayerScrollableArea::paintOverflowControls(GraphicsContext& context, const IntPoint& paintOffset, const IntRect& damageRect, bool paintingOverlayControls)
{
    // Don't do anything if we have no overflow.
    auto& renderer = m_layer.renderer();
    if (!renderer.hasNonVisibleOverflow())
        return;

    if (!showsOverflowControls())
        return;

    // 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 RenderTree to get it right.
    if (hasOverlayScrollbars() && !paintingOverlayControls) {
        m_cachedOverlayScrollbarOffset = paintOffset;

        // It's not necessary to do the second pass if the scrollbars paint into layers.
        if ((m_hBar && layerForHorizontalScrollbar()) || (m_vBar && layerForVerticalScrollbar()))
            return;
        IntRect localDamgeRect = damageRect;
        localDamgeRect.moveBy(-paintOffset);
        if (!overflowControlsIntersectRect(localDamgeRect))
            return;

        RenderLayer* paintingRoot = m_layer.enclosingCompositingLayer();
        if (!paintingRoot)
            paintingRoot = renderer.view().layer();

        if (auto* scrollableArea = paintingRoot->scrollableArea())
            scrollableArea->setContainsDirtyOverlayScrollbars(true);
        return;
    }

    // This check is required to avoid painting custom CSS scrollbars twice.
    if (paintingOverlayControls && !hasOverlayScrollbars())
        return;

    IntPoint adjustedPaintOffset = paintOffset;
    if (paintingOverlayControls)
        adjustedPaintOffset = m_cachedOverlayScrollbarOffset;

    // Move the scrollbar widgets if necessary. We normally move and resize widgets during layout, but sometimes
    // widgets can move without layout occurring (most notably when you scroll a document that
    // contains fixed positioned elements).
    positionOverflowControls(toIntSize(adjustedPaintOffset));

    // Now that we're sure the scrollbars are in the right place, paint them.
    if (m_hBar && !layerForHorizontalScrollbar())
        m_hBar->paint(context, damageRect);
    if (m_vBar && !layerForVerticalScrollbar())
        m_vBar->paint(context, damageRect);

    if (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);
}

void RenderLayerScrollableArea::paintScrollCorner(GraphicsContext& context, const IntPoint& paintOffset, const IntRect& damageRect)
{
    IntRect absRect = scrollCornerRect();
    absRect.moveBy(paintOffset);
    if (!absRect.intersects(damageRect))
        return;

    if (context.invalidatingControlTints()) {
        updateScrollCornerStyle();
        return;
    }

    if (m_scrollCorner) {
        m_scrollCorner->paintIntoRect(context, paintOffset, absRect);
        return;
    }

    // We don't want to paint a corner if we have overlay scrollbars, since we need
    // to see what is behind it.
    if (!hasOverlayScrollbars())
        ScrollbarTheme::theme().paintScrollCorner(*this, context, absRect);
}

void RenderLayerScrollableArea::drawPlatformResizerImage(GraphicsContext& context, const LayoutRect& resizerCornerRect)
{
    auto& renderer = m_layer.renderer();
    RefPtr<Image> resizeCornerImage;
    FloatSize cornerResizerSize;
    if (renderer.document().deviceScaleFactor() >= 2) {
        static NeverDestroyed<Image*> resizeCornerImageHiRes(&Image::loadPlatformResource("textAreaResizeCorner@2x").leakRef());
        resizeCornerImage = resizeCornerImageHiRes;
        cornerResizerSize = resizeCornerImage->size();
        cornerResizerSize.scale(0.5f);
    } else {
        static NeverDestroyed<Image*> resizeCornerImageLoRes(&Image::loadPlatformResource("textAreaResizeCorner").leakRef());
        resizeCornerImage = resizeCornerImageLoRes;
        cornerResizerSize = resizeCornerImage->size();
    }

    if (shouldPlaceVerticalScrollbarOnLeft()) {
        context.save();
        context.translate(resizerCornerRect.x() + cornerResizerSize.width(), resizerCornerRect.y() + resizerCornerRect.height() - cornerResizerSize.height());
        context.scale(FloatSize(-1.0, 1.0));
        if (resizeCornerImage)
            context.drawImage(*resizeCornerImage, FloatRect(FloatPoint(), cornerResizerSize));
        context.restore();
        return;
    }

    if (!resizeCornerImage)
        return;
    FloatRect imageRect = snapRectToDevicePixels(LayoutRect(resizerCornerRect.maxXMaxYCorner() - cornerResizerSize, cornerResizerSize), renderer.document().deviceScaleFactor());
    context.drawImage(*resizeCornerImage, imageRect);
}

void RenderLayerScrollableArea::paintResizer(GraphicsContext& context, const LayoutPoint& paintOffset, const LayoutRect& damageRect)
{
    auto& renderer = m_layer.renderer();
    if (renderer.style().resize() == Resize::None)
        return;

    auto rects = overflowControlsRects();

    LayoutRect resizerAbsRect = rects.resizer;
    resizerAbsRect.moveBy(paintOffset);
    if (!resizerAbsRect.intersects(damageRect))
        return;

    if (context.invalidatingControlTints()) {
        updateResizerStyle();
        return;
    }

    if (m_resizer) {
        m_resizer->paintIntoRect(context, paintOffset, resizerAbsRect);
        return;
    }

    drawPlatformResizerImage(context, resizerAbsRect);

    // Draw a frame around the resizer (1px grey line) if there are any scrollbars present.
    // Clipping will exclude the right and bottom edges of this frame.
    if (!hasOverlayScrollbars() && (m_vBar || m_hBar)) {
        GraphicsContextStateSaver stateSaver(context);
        context.clip(resizerAbsRect);
        LayoutRect largerCorner = resizerAbsRect;
        largerCorner.setSize(LayoutSize(largerCorner.width() + 1_lu, largerCorner.height() + 1_lu));
        context.setStrokeColor(SRGBA<uint8_t> { 217, 217, 217 });
        context.setStrokeThickness(1.0f);
        context.setFillColor(Color::transparentBlack);
        context.drawRect(snappedIntRect(largerCorner));
    }
}

bool RenderLayerScrollableArea::hitTestOverflowControls(HitTestResult& result, const IntPoint& localPoint)
{
    if (!m_hBar && !m_vBar && !m_layer.canResize())
        return false;

    auto rects = overflowControlsRects();

    IntRect resizeControlRect;
    auto& renderer = m_layer.renderer();
    if (renderer.style().resize() != Resize::None) {
        if (rects.resizer.contains(localPoint))
            return true;
    }

    // FIXME: We should hit test the m_scrollCorner and pass it back through the result.
    if (m_vBar && m_vBar->shouldParticipateInHitTesting()) {
        if (rects.verticalScrollbar.contains(localPoint)) {
            result.setScrollbar(m_vBar.get());
            return true;
        }
    }

    if (m_hBar && m_hBar->shouldParticipateInHitTesting()) {
        if (rects.horizontalScrollbar.contains(localPoint)) {
            result.setScrollbar(m_hBar.get());
            return true;
        }
    }

    return false;
}

bool RenderLayerScrollableArea::scroll(ScrollDirection direction, ScrollGranularity granularity, float multiplier)
{
    return ScrollableArea::scroll(direction, granularity, multiplier);
}

bool RenderLayerScrollableArea::isActive() const
{
    return m_layer.page().focusController().isActive();
}

IntPoint RenderLayerScrollableArea::lastKnownMousePositionInView() const
{
    return m_layer.renderer().view().frameView().lastKnownMousePositionInView();
}

bool RenderLayerScrollableArea::isHandlingWheelEvent() const
{
    return m_layer.renderer().frame().eventHandler().isHandlingWheelEvent();
}

bool RenderLayerScrollableArea::useDarkAppearance() const
{
    return m_layer.renderer().useDarkAppearance();
}

void RenderLayerScrollableArea::updateSnapOffsets()
{
    // FIXME: Extend support beyond HTMLElements.
    if (!is<HTMLElement>(m_layer.enclosingElement()) || !m_layer.enclosingElement()->renderBox())
        return;

    RenderBox* box = m_layer.enclosingElement()->renderBox();
    updateSnapOffsetsForScrollableArea(*this, *box, box->style(), box->paddingBoxRect(), box->style().writingMode(), box->style().direction());
}

bool RenderLayerScrollableArea::isScrollSnapInProgress() const
{
    if (!scrollsOverflow())
        return false;

    if (auto* scrollingCoordinator = m_layer.page().scrollingCoordinator()) {
        if (scrollingCoordinator->isScrollSnapInProgress(scrollingNodeID()))
            return true;
    }

    if (auto* scrollAnimator = existingScrollAnimator())
        return scrollAnimator->isScrollSnapInProgress();

    return false;
}

void RenderLayerScrollableArea::paintOverlayScrollbars(GraphicsContext& context, const LayoutRect& damageRect, OptionSet<PaintBehavior> paintBehavior, RenderObject* subtreePaintRoot)
{
    if (!m_containsDirtyOverlayScrollbars)
        return;

    RenderLayer::LayerPaintingInfo paintingInfo(&m_layer, enclosingIntRect(damageRect), paintBehavior, LayoutSize(), subtreePaintRoot);
    m_layer.paintLayer(context, paintingInfo, RenderLayer::PaintLayerFlag::PaintingOverlayScrollbars);

    m_containsDirtyOverlayScrollbars = false;
}

bool RenderLayerScrollableArea::hitTestResizerInFragments(const LayerFragments& layerFragments, const HitTestLocation& hitTestLocation, LayoutPoint& pointInFragment) const
{
    if (layerFragments.isEmpty())
        return false;

    auto& renderer = m_layer.renderer();
    auto borderBoxRect = snappedIntRect(downcast<RenderBox>(renderer).borderBoxRect());
    auto rects = overflowControlsRects();

    auto cornerRectInFragment = [&](const IntRect& fragmentBounds, const IntRect& resizerRect) {
        if (shouldPlaceVerticalScrollbarOnLeft()) {
            IntSize offsetFromBottomLeft = borderBoxRect.minXMaxYCorner() - resizerRect.minXMaxYCorner();
            return IntRect { fragmentBounds.minXMaxYCorner() - offsetFromBottomLeft - IntSize { 0, resizerRect.height() }, resizerRect.size() };
        }
        IntSize offsetFromBottomRight = borderBoxRect.maxXMaxYCorner() - resizerRect.maxXMaxYCorner();
        return IntRect { fragmentBounds.maxXMaxYCorner() - offsetFromBottomRight - resizerRect.size(), resizerRect.size() };
    };

    for (int i = layerFragments.size() - 1; i >= 0; --i) {
        const LayerFragment& fragment = layerFragments.at(i);
        auto resizerRectInFragment = cornerRectInFragment(snappedIntRect(fragment.layerBounds), rects.resizer);
        if (fragment.backgroundRect.intersects(hitTestLocation) && resizerRectInFragment.contains(hitTestLocation.roundedPoint())) {
            pointInFragment = toLayoutPoint(hitTestLocation.point() - fragment.layerBounds.location());
            return true;
        }
    }

    return false;
}

GraphicsLayer* RenderLayerScrollableArea::layerForHorizontalScrollbar() const
{
    return m_layer.backing() ? m_layer.backing()->layerForHorizontalScrollbar() : nullptr;
}

GraphicsLayer* RenderLayerScrollableArea::layerForVerticalScrollbar() const
{
    return m_layer.backing() ? m_layer.backing()->layerForVerticalScrollbar() : nullptr;
}

GraphicsLayer* RenderLayerScrollableArea::layerForScrollCorner() const
{
    return m_layer.backing() ? m_layer.backing()->layerForScrollCorner() : nullptr;
}

bool RenderLayerScrollableArea::scrollingMayRevealBackground() const
{
    return scrollsOverflow() || usesCompositedScrolling();
}

void RenderLayerScrollableArea::updateScrollableAreaSet(bool hasOverflow)
{
    auto& renderer = m_layer.renderer();
    FrameView& frameView = renderer.view().frameView();

    bool isVisibleToHitTest = renderer.visibleToHitTesting();
    if (HTMLFrameOwnerElement* owner = frameView.frame().ownerElement())
        isVisibleToHitTest &= owner->renderer() && owner->renderer()->visibleToHitTesting();

    bool isScrollable = hasOverflow && isVisibleToHitTest;
    bool addedOrRemoved = false;

    ASSERT(m_registeredScrollableArea == frameView.containsScrollableArea(this));

    if (isScrollable) {
        if (!m_registeredScrollableArea) {
            addedOrRemoved = frameView.addScrollableArea(this);
            m_registeredScrollableArea = true;
        }
    } else if (m_registeredScrollableArea) {
        addedOrRemoved = frameView.removeScrollableArea(this);
        m_registeredScrollableArea = false;
    }

#if ENABLE(IOS_TOUCH_EVENTS)
    if (addedOrRemoved) {
        if (isScrollable && !canUseCompositedScrolling())
            registerAsTouchEventListenerForScrolling();
        else {
            // We only need the touch listener for unaccelerated overflow scrolling, so if we became
            // accelerated, remove ourselves as a touch event listener.
            unregisterAsTouchEventListenerForScrolling();
        }
    }
#else
    UNUSED_VARIABLE(addedOrRemoved);
#endif
}

void RenderLayerScrollableArea::updateScrollCornerStyle()
{
    auto& renderer = m_layer.renderer();
    RenderElement* actualRenderer = rendererForScrollbar(renderer);
    auto corner = renderer.hasNonVisibleOverflow() ? actualRenderer->getUncachedPseudoStyle({ PseudoId::ScrollbarCorner }, &actualRenderer->style()) : nullptr;

    if (!corner) {
        clearScrollCorner();
        return;
    }

    if (!m_scrollCorner) {
        m_scrollCorner = createRenderer<RenderScrollbarPart>(renderer.document(), WTFMove(*corner));
        // FIXME: A renderer should be a child of its parent!
        m_scrollCorner->setParent(&renderer);
        m_scrollCorner->initializeStyle();
    } else
        m_scrollCorner->setStyle(WTFMove(*corner));
}

void RenderLayerScrollableArea::clearScrollCorner()
{
    if (!m_scrollCorner)
        return;
    m_scrollCorner->setParent(nullptr);
    m_scrollCorner = nullptr;
}

void RenderLayerScrollableArea::updateResizerStyle()
{
    auto& renderer = m_layer.renderer();
    RenderElement* actualRenderer = rendererForScrollbar(renderer);
    auto resizer = renderer.hasNonVisibleOverflow() ? actualRenderer->getUncachedPseudoStyle({ PseudoId::Resizer }, &actualRenderer->style()) : nullptr;

    if (!resizer) {
        clearResizer();
        return;
    }

    if (!m_resizer) {
        m_resizer = createRenderer<RenderScrollbarPart>(renderer.document(), WTFMove(*resizer));
        // FIXME: A renderer should be a child of its parent!
        m_resizer->setParent(&renderer);
        m_resizer->initializeStyle();
    } else
        m_resizer->setStyle(WTFMove(*resizer));
}

void RenderLayerScrollableArea::clearResizer()
{
    if (!m_resizer)
        return;
    m_resizer->setParent(nullptr);
    m_resizer = nullptr;
}

void RenderLayerScrollableArea::updateAllScrollbarRelatedStyle()
{
    if (m_hBar)
        m_hBar->styleChanged();
    if (m_vBar)
        m_vBar->styleChanged();
    updateScrollCornerStyle();
    updateResizerStyle();
}

// FIXME: this is only valid after we've made layers.
bool RenderLayerScrollableArea::usesCompositedScrolling() const
{
    return m_layer.isComposited() && m_layer.backing()->hasScrollingLayer();
}

static inline int adjustedScrollDelta(int beginningDelta)
{
    // This implemention matches Firefox's.
    // http://mxr.mozilla.org/firefox/source/toolkit/content/widgets/browser.xml#856.
    const int speedReducer = 12;

    int adjustedDelta = beginningDelta / speedReducer;
    if (adjustedDelta > 1)
        adjustedDelta = static_cast<int>(adjustedDelta * sqrt(static_cast<double>(adjustedDelta))) - 1;
    else if (adjustedDelta < -1)
        adjustedDelta = static_cast<int>(adjustedDelta * sqrt(static_cast<double>(-adjustedDelta))) + 1;

    return adjustedDelta;
}

static inline IntSize adjustedScrollDelta(const IntSize& delta)
{
    return IntSize(adjustedScrollDelta(delta.width()), adjustedScrollDelta(delta.height()));
}

void RenderLayerScrollableArea::panScrollFromPoint(const IntPoint& sourcePoint)
{
    IntPoint lastKnownMousePosition = m_layer.renderer().frame().eventHandler().lastKnownMousePosition();

    // We need to check if the last known mouse position is out of the window. When the mouse is out of the window, the position is incoherent
    static IntPoint previousMousePosition;
    if (lastKnownMousePosition.x() < 0 || lastKnownMousePosition.y() < 0)
        lastKnownMousePosition = previousMousePosition;
    else
        previousMousePosition = lastKnownMousePosition;

    IntSize delta = lastKnownMousePosition - sourcePoint;

    if (abs(delta.width()) <= ScrollView::noPanScrollRadius) // at the center we let the space for the icon
        delta.setWidth(0);
    if (abs(delta.height()) <= ScrollView::noPanScrollRadius)
        delta.setHeight(0);

    scrollByRecursively(adjustedScrollDelta(delta));
}

std::optional<LayoutRect> RenderLayerScrollableArea::updateScrollPosition(const ScrollPositionChangeOptions& options, const LayoutRect& revealRect, const LayoutRect& localExposeRect)
{
    ASSERT(m_layer.allowsCurrentScroll());

    RenderBox* box = m_layer.renderBox();
    ASSERT(box);

    ScrollOffset clampedScrollOffset = clampScrollOffset(scrollOffset() + toIntSize(roundedIntRect(revealRect).location()));
    if (clampedScrollOffset != scrollOffset() || currentScrollBehaviorStatus() != ScrollBehaviorStatus::NotInAnimation) {
        ScrollOffset oldScrollOffset = scrollOffset();
        ScrollOffset realScrollOffset = scrollToOffset(clampedScrollOffset, options);

        IntSize scrollOffsetDifference = realScrollOffset - oldScrollOffset;
        auto localExposeRectScrolled = localExposeRect;
        localExposeRectScrolled.move(-scrollOffsetDifference);
        return LayoutRect(box->localToAbsoluteQuad(FloatQuad(FloatRect(localExposeRectScrolled)), UseTransforms).boundingBox());
    }

    return std::nullopt;
}

void RenderLayerScrollableArea::scrollByRecursively(const IntSize& delta, ScrollableArea** scrolledArea)
{
    if (delta.isZero())
        return;

    auto& renderer = m_layer.renderer();
    bool restrictedByLineClamp = false;
    if (renderer.parent())
        restrictedByLineClamp = !renderer.parent()->style().lineClamp().isNone();

    if (renderer.hasNonVisibleOverflow() && !restrictedByLineClamp) {
        ScrollOffset newScrollOffset = scrollOffset() + delta;
        scrollToOffset(newScrollOffset);
        if (scrolledArea)
            *scrolledArea = this;

        // If this layer can't do the scroll we ask the next layer up that can scroll to try
        IntSize remainingScrollOffset = newScrollOffset - scrollOffset();
        if (!remainingScrollOffset.isZero() && renderer.parent()) {
            // FIXME: This skips scrollable frames.
            if (auto* enclosingScrollableLayer = m_layer.enclosingScrollableLayer(IncludeSelfOrNot::ExcludeSelf, CrossFrameBoundaries::Yes)) {
                if (auto* scrollableArea = enclosingScrollableLayer->scrollableArea())
                    scrollableArea->scrollByRecursively(remainingScrollOffset, scrolledArea);
            }

            renderer.frame().eventHandler().updateAutoscrollRenderer();
        }
    } else {
        // If we are here, we were called on a renderer that can be programmatically scrolled, but doesn't
        // have an overflow clip. Which means that it is a document node that can be scrolled.
        renderer.view().frameView().scrollBy(delta);
        if (scrolledArea)
            *scrolledArea = &renderer.view().frameView();

        // FIXME: If we didn't scroll the whole way, do we want to try looking at the frames ownerElement?
        // https://bugs.webkit.org/show_bug.cgi?id=28237
    }
}

void RenderLayerScrollableArea::updateLayerPositionsAfterDocumentScroll()
{
    ASSERT(&m_layer == m_layer.renderer().view().layer());

    LOG(Scrolling, "RenderLayerScrollableArea::updateLayerPositionsAfterDocumentScroll");

    RenderGeometryMap geometryMap(UseTransforms);
    m_layer.updateLayerPositionsAfterScroll(&geometryMap);
}

void RenderLayerScrollableArea::updateLayerPositionsAfterOverflowScroll()
{
    RenderGeometryMap geometryMap(UseTransforms);
    if (&m_layer != m_layer.renderer().view().layer())
        geometryMap.pushMappingsToAncestor(m_layer.parent(), nullptr);

    // FIXME: why is it OK to not check the ancestors of this layer in order to
    // initialize the HasSeenViewportConstrainedAncestor and HasSeenAncestorWithOverflowClip flags?
    m_layer.updateLayerPositionsAfterScroll(&geometryMap, RenderLayer::IsOverflowScroll);
}

bool RenderLayerScrollableArea::usesMockScrollAnimator() const
{
    return DeprecatedGlobalSettings::usesMockScrollAnimator();
}

void RenderLayerScrollableArea::logMockScrollAnimatorMessage(const String& message) const
{
    m_layer.renderer().document().addConsoleMessage(MessageSource::Other, MessageLevel::Debug, "RenderLayer: " + message);
}

String RenderLayerScrollableArea::debugDescription() const
{
    return m_layer.debugDescription();
}

} // namespace WebCore
