Web Automation: elements larger than the viewport have incorrect in-view center point
[WebKit-https.git] / Source / WebCore / platform / ScrollView.cpp
index b89d566..61bb518 100644 (file)
 #include "ScrollAnimator.h"
 #include "Scrollbar.h"
 #include "ScrollbarTheme.h"
-#include "TextStream.h"
 #include <wtf/StdLibExtras.h>
+#include <wtf/text/TextStream.h>
 
 namespace WebCore {
 
-ScrollView::ScrollView()
-    : m_horizontalScrollbarMode(ScrollbarAuto)
-    , m_verticalScrollbarMode(ScrollbarAuto)
-    , m_horizontalScrollbarLock(false)
-    , m_verticalScrollbarLock(false)
-    , m_prohibitsScrolling(false)
-    , m_canBlitOnScroll(true)
-    , m_scrollbarsSuppressed(false)
-    , m_inUpdateScrollbars(false)
-    , m_updateScrollbarsPass(0)
-    , m_drawPanScrollIcon(false)
-    , m_useFixedLayout(false)
-    , m_paintsEntireContents(false)
-    , m_clipsRepaints(true)
-    , m_delegatesScrolling(false)
-{
-}
+ScrollView::ScrollView() = default;
 
-ScrollView::~ScrollView()
-{
-}
+ScrollView::~ScrollView() = default;
 
 void ScrollView::addChild(Widget& child)
 {
@@ -206,11 +188,6 @@ void ScrollView::setPaintsEntireContents(bool paintsEntireContents)
     m_paintsEntireContents = paintsEntireContents;
 }
 
-void ScrollView::setClipsRepaints(bool clipsRepaints)
-{
-    m_clipsRepaints = clipsRepaints;
-}
-
 void ScrollView::setDelegatesScrolling(bool delegatesScrolling)
 {
     if (m_delegatesScrolling == delegatesScrolling)
@@ -222,7 +199,7 @@ void ScrollView::setDelegatesScrolling(bool delegatesScrolling)
 
 IntPoint ScrollView::contentsScrollPosition() const
 {
-#if PLATFORM(IOS)
+#if PLATFORM(IOS_FAMILY)
     if (platformWidget())
         return actualScrollPosition();
 #endif
@@ -231,14 +208,14 @@ IntPoint ScrollView::contentsScrollPosition() const
 
 void ScrollView::setContentsScrollPosition(const IntPoint& position)
 {
-#if PLATFORM(IOS)
+#if PLATFORM(IOS_FAMILY)
     if (platformWidget())
         setActualScrollPosition(position);
 #endif
     setScrollPosition(position);
 }
 
-#if !PLATFORM(IOS)
+#if !PLATFORM(IOS_FAMILY)
 IntRect ScrollView::unobscuredContentRect(VisibleContentRectIncludesScrollbars scrollbarInclusion) const
 {
     return unobscuredContentRectInternal(scrollbarInclusion);
@@ -287,7 +264,7 @@ IntSize ScrollView::sizeForUnobscuredContent(VisibleContentRectIncludesScrollbar
 
 IntRect ScrollView::visibleContentRectInternal(VisibleContentRectIncludesScrollbars scrollbarInclusion, VisibleContentRectBehavior visibleContentRectBehavior) const
 {
-#if PLATFORM(IOS)
+#if PLATFORM(IOS_FAMILY)
     if (visibleContentRectBehavior == LegacyIOSDocumentViewRect) {
         if (platformWidget())
             return platformVisibleContentRect(scrollbarInclusion == IncludeScrollbars);
@@ -324,6 +301,8 @@ void ScrollView::setFixedLayoutSize(const IntSize& newSize)
 {
     if (fixedLayoutSize() == newSize)
         return;
+
+    LOG_WITH_STREAM(Layout, stream << "ScrollView " << this << " setFixedLayoutSize " << newSize);
     m_fixedLayoutSize = newSize;
     if (m_useFixedLayout)
         availableContentSizeChanged(AvailableSizeChangeReason::AreaSizeChanged);
@@ -381,7 +360,7 @@ ScrollPosition ScrollView::maximumScrollPosition() const
 
 ScrollPosition ScrollView::adjustScrollPositionWithinRange(const ScrollPosition& scrollPoint) const
 {
-    if (!constrainsScrollingToContentEdge())
+    if (!constrainsScrollingToContentEdge() || m_allowsUnclampedScrollPosition)
         return scrollPoint;
 
     return scrollPoint.constrainedBetween(minimumScrollPosition(), maximumScrollPosition());
@@ -418,7 +397,7 @@ void ScrollView::notifyPageThatContentAreaWillPaint() const
 
 void ScrollView::setScrollOffset(const ScrollOffset& offset)
 {
-    LOG_WITH_STREAM(Scrolling, stream << "\nScrollView::setScrollOffset " << offset);
+    LOG_WITH_STREAM(Scrolling, stream << "\nScrollView::setScrollOffset " << offset << " constrains " << constrainsScrollingToContentEdge());
 
     IntPoint constrainedOffset = offset;
     if (constrainsScrollingToContentEdge())
@@ -454,8 +433,8 @@ void ScrollView::handleDeferredScrollUpdateAfterContentSizeChange()
     else if (m_deferredScrollOffsets)
         scrollOffsetChangedViaPlatformWidgetImpl(m_deferredScrollOffsets.value().first, m_deferredScrollOffsets.value().second);
     
-    m_deferredScrollDelta = std::nullopt;
-    m_deferredScrollOffsets = std::nullopt;
+    m_deferredScrollDelta = WTF::nullopt;
+    m_deferredScrollOffsets = WTF::nullopt;
 }
 
 void ScrollView::scrollTo(const ScrollPosition& newPosition)
@@ -522,7 +501,7 @@ void ScrollView::setScrollPosition(const ScrollPosition& scrollPosition)
 
     ScrollPosition newScrollPosition = !delegatesScrolling() ? adjustScrollPositionWithinRange(scrollPosition) : scrollPosition;
 
-    if ((!delegatesScrolling() || !inProgrammaticScroll()) && newScrollPosition == this->scrollPosition())
+    if ((!delegatesScrolling() || currentScrollType() == ScrollType::User) && newScrollPosition == this->scrollPosition())
         return;
 
     if (requestScrollPositionUpdate(newScrollPosition))
@@ -563,6 +542,19 @@ IntSize ScrollView::overhangAmount() const
     return stretch;
 }
 
+bool ScrollView::managesScrollbars() const
+{
+#if PLATFORM(IOS_FAMILY)
+    return false;
+#else
+    if (platformWidget())
+        return false;
+    if (delegatesScrolling())
+        return false;
+    return true;
+#endif
+}
+
 void ScrollView::updateScrollbars(const ScrollPosition& desiredPosition)
 {
     LOG_WITH_STREAM(Scrolling, stream << "ScrollView::updateScrollbars " << desiredPosition);
@@ -570,7 +562,7 @@ void ScrollView::updateScrollbars(const ScrollPosition& desiredPosition)
     if (m_inUpdateScrollbars || prohibitsScrolling() || platformWidget())
         return;
     
-    if (delegatesScrolling()) {
+    if (!managesScrollbars()) {
         if (scrollOriginChanged()) {
             ScrollableArea::scrollToOffsetWithoutAnimation(scrollOffsetFromPosition(desiredPosition));
             resetScrollOriginChanged();
@@ -630,7 +622,7 @@ void ScrollView::updateScrollbars(const ScrollPosition& desiredPosition)
 
         bool needAnotherPass = false;
         if (!hasOverlayScrollbars) {
-            // If we ever turn one scrollbar off, always turn the other one off too.  Never ever
+            // If we ever turn one scrollbar off, do not turn the other one on. Never ever
             // try to both gain/lose a scrollbar in the same pass.
             if (!m_updateScrollbarsPass && docSize.width() <= fullVisibleSize.width() && docSize.height() <= fullVisibleSize.height()) {
                 if (hScroll == ScrollbarAuto)
@@ -638,11 +630,11 @@ void ScrollView::updateScrollbars(const ScrollPosition& desiredPosition)
                 if (vScroll == ScrollbarAuto)
                     newHasVerticalScrollbar = false;
             }
-            if (!newHasHorizontalScrollbar && hasHorizontalScrollbar && vScroll != ScrollbarAlwaysOn) {
+            if (!newHasHorizontalScrollbar && hasHorizontalScrollbar && vScroll != ScrollbarAlwaysOn && !hasVerticalScrollbar) {
                 newHasVerticalScrollbar = false;
                 needAnotherPass = true;
             }
-            if (!newHasVerticalScrollbar && hasVerticalScrollbar && hScroll != ScrollbarAlwaysOn) {
+            if (!newHasVerticalScrollbar && hasVerticalScrollbar && hScroll != ScrollbarAlwaysOn && !hasHorizontalScrollbar) {
                 newHasHorizontalScrollbar = false;
                 needAnotherPass = true;
             }
@@ -836,22 +828,68 @@ void ScrollView::scrollContentsSlowPath(const IntRect& updateRect)
 
 IntPoint ScrollView::viewToContents(const IntPoint& point) const
 {
+    if (delegatesScrolling())
+        return point;
+
     return point + toIntSize(documentScrollPositionRelativeToViewOrigin());
 }
 
 IntPoint ScrollView::contentsToView(const IntPoint& point) const
 {
+    if (delegatesScrolling())
+        return point;
+
     return point - toIntSize(documentScrollPositionRelativeToViewOrigin());
 }
 
+FloatPoint ScrollView::viewToContents(const FloatPoint& point) const
+{
+    if (delegatesScrolling())
+        return point;
+
+    return viewToContents(IntPoint(point));
+}
+
+FloatPoint ScrollView::contentsToView(const FloatPoint& point) const
+{
+    if (delegatesScrolling())
+        return point;
+
+    return contentsToView(IntPoint(point));
+}
+
 IntRect ScrollView::viewToContents(IntRect rect) const
 {
+    if (delegatesScrolling())
+        return rect;
+
+    rect.moveBy(documentScrollPositionRelativeToViewOrigin());
+    return rect;
+}
+
+FloatRect ScrollView::viewToContents(FloatRect rect) const
+{
+    if (delegatesScrolling())
+        return rect;
+
     rect.moveBy(documentScrollPositionRelativeToViewOrigin());
     return rect;
 }
 
 IntRect ScrollView::contentsToView(IntRect rect) const
 {
+    if (delegatesScrolling())
+        return rect;
+
+    rect.moveBy(-documentScrollPositionRelativeToViewOrigin());
+    return rect;
+}
+
+FloatRect ScrollView::contentsToView(FloatRect rect) const
+{
+    if (delegatesScrolling())
+        return rect;
+
     rect.moveBy(-documentScrollPositionRelativeToViewOrigin());
     return rect;
 }
@@ -878,28 +916,34 @@ IntRect ScrollView::contentsToContainingViewContents(IntRect rect) const
 
 IntPoint ScrollView::rootViewToContents(const IntPoint& rootViewPoint) const
 {
-    if (delegatesScrolling())
-        return convertFromRootView(rootViewPoint);
-
     return viewToContents(convertFromRootView(rootViewPoint));
 }
 
 IntPoint ScrollView::contentsToRootView(const IntPoint& contentsPoint) const
 {
-    if (delegatesScrolling())
-        return convertToRootView(contentsPoint);
+    return convertToRootView(contentsToView(contentsPoint));
+}
 
+FloatPoint ScrollView::contentsToRootView(const FloatPoint& contentsPoint) const
+{
     return convertToRootView(contentsToView(contentsPoint));
 }
 
 IntRect ScrollView::rootViewToContents(const IntRect& rootViewRect) const
 {
-    if (delegatesScrolling())
-        return convertFromRootView(rootViewRect);
+    return viewToContents(convertFromRootView(rootViewRect));
+}
 
+FloatRect ScrollView::rootViewToContents(const FloatRect& rootViewRect) const
+{
     return viewToContents(convertFromRootView(rootViewRect));
 }
 
+FloatRect ScrollView::contentsToRootView(const FloatRect& contentsRect) const
+{
+    return convertToRootView(contentsToView(contentsRect));
+}
+
 IntPoint ScrollView::rootViewToTotalContents(const IntPoint& rootViewPoint) const
 {
     if (delegatesScrolling())
@@ -912,41 +956,26 @@ IntPoint ScrollView::rootViewToTotalContents(const IntPoint& rootViewPoint) cons
 
 IntRect ScrollView::contentsToRootView(const IntRect& contentsRect) const
 {
-    if (delegatesScrolling())
-        return convertToRootView(contentsRect);
-
     return convertToRootView(contentsToView(contentsRect));
 }
 
 IntPoint ScrollView::windowToContents(const IntPoint& windowPoint) const
 {
-    if (delegatesScrolling())
-        return convertFromContainingWindow(windowPoint);
-
     return viewToContents(convertFromContainingWindow(windowPoint));
 }
 
 IntPoint ScrollView::contentsToWindow(const IntPoint& contentsPoint) const
 {
-    if (delegatesScrolling())
-        return convertToContainingWindow(contentsPoint);
-
     return convertToContainingWindow(contentsToView(contentsPoint));
 }
 
 IntRect ScrollView::windowToContents(const IntRect& windowRect) const
 {
-    if (delegatesScrolling())
-        return convertFromContainingWindow(windowRect);
-
     return viewToContents(convertFromContainingWindow(windowRect));
 }
 
 IntRect ScrollView::contentsToWindow(const IntRect& contentsRect) const
 {
-    if (delegatesScrolling())
-        return convertToContainingWindow(contentsRect);
-
     return convertToContainingWindow(contentsToView(contentsRect));
 }
 
@@ -1085,7 +1114,7 @@ void ScrollView::positionScrollbarLayers()
 void ScrollView::repaintContentRectangle(const IntRect& rect)
 {
     IntRect paintRect = rect;
-    if (clipsRepaints() && !paintsEntireContents())
+    if (!paintsEntireContents())
         paintRect.intersect(visibleContentRect(LegacyIOSDocumentVisibleRect));
     if (paintRect.isEmpty())
         return;
@@ -1143,7 +1172,7 @@ void ScrollView::scrollbarStyleChanged(ScrollbarStyle newStyle, bool forceUpdate
 
 void ScrollView::paintScrollCorner(GraphicsContext& context, const IntRect& cornerRect)
 {
-    ScrollbarTheme::theme().paintScrollCorner(this, context, cornerRect);
+    ScrollbarTheme::theme().paintScrollCorner(context, cornerRect);
 }
 
 void ScrollView::paintScrollbar(GraphicsContext& context, Scrollbar& bar, const IntRect& rect)
@@ -1171,23 +1200,21 @@ void ScrollView::paintScrollbars(GraphicsContext& context, const IntRect& rect)
 
 void ScrollView::paintPanScrollIcon(GraphicsContext& context)
 {
-    static Image* panScrollIcon = Image::loadPlatformResource("panIcon").leakRef();
-    if (!panScrollIcon)
-        return;
+    static Image& panScrollIcon = Image::loadPlatformResource("panIcon").leakRef();
     IntPoint iconGCPoint = m_panScrollIconPoint;
     if (parent())
         iconGCPoint = parent()->windowToContents(iconGCPoint);
-    context.drawImage(*panScrollIcon, iconGCPoint);
+    context.drawImage(panScrollIcon, iconGCPoint);
 }
 
-void ScrollView::paint(GraphicsContext& context, const IntRect& rect)
+void ScrollView::paint(GraphicsContext& context, const IntRect& rect, SecurityOriginPaintPolicy securityOriginPaintPolicy)
 {
     if (platformWidget()) {
         Widget::paint(context, rect);
         return;
     }
 
-    if (context.paintingDisabled() && !context.updatingControlTints())
+    if (context.paintingDisabled() && !context.performingPaintInvalidation())
         return;
 
     notifyPageThatContentAreaWillPaint();
@@ -1212,7 +1239,7 @@ void ScrollView::paint(GraphicsContext& context, const IntRect& rect)
             context.clip(visibleContentRect(LegacyIOSDocumentVisibleRect));
         }
 
-        paintContents(context, documentDirtyRect);
+        paintContents(context, documentDirtyRect, securityOriginPaintPolicy);
     }
 
 #if ENABLE(RUBBER_BANDING)