Title: [173014] trunk/Source
Revision
173014
Author
bda...@apple.com
Date
2014-08-27 12:53:31 -0700 (Wed, 27 Aug 2014)

Log Message

overflow:scroll elements should not latch to the body if the body is 
overflow:hidden
https://bugs.webkit.org/show_bug.cgi?id=136273

Reviewed by Darin Adler.

Source/WebCore:

This patch adds an optional parameter to isScrollable(). The Scrollability 
parameter that allows the caller to define what they mean by 'scrollable.' Most 
callers are interested in the default value, Scrollability::Scrollable, which 
means that there is actually content to scroll to, and a scrollbar that will allow 
you to access it. In some cases, such as this latching case, callers want to know 
if the FrameView is allowed to rubber-band, which the main frame might be allowed 
to do even if there is no content to scroll to. In that case, callers use 
Scrollability::ScrollableOrRubberbandable.
* page/FrameView.cpp:
(WebCore::FrameView::isScrollable):
(WebCore::FrameView::hasScrollableOrRubberbandableAncestor):

New virtual function on ScrollableArea answers whether a ScrollableArea has any 
scrollable or rubber-bandable ancestor.
* page/FrameView.h:
* platform/ScrollableArea.h:

Events should only be allowed to prevent stretching if there is some ancestor 
ScrollableArea that will be able to make use of the event. 
* platform/mac/ScrollAnimatorMac.mm:
(WebCore::ScrollAnimatorMac::allowsVerticalStretching):
(WebCore::ScrollAnimatorMac::allowsHorizontalStretching):

New ScrollableArea virtual function.
* platform/win/PopupMenuWin.h:

New RenderBox isScrollableOrRubberbandable() returns just 
canBeScrolledAndHasScrollableArea() for most RenderBox, but will be overridden by 
RenderView.
* rendering/RenderBox.cpp:
(WebCore::RenderBox::isScrollableOrRubberbandable):
* rendering/RenderBox.h:

Recurse up the parent chain to find out if anything is scrollable or just rubber-
bandable.
* rendering/RenderLayer.cpp:
(WebCore::RenderLayer::hasScrollableOrRubberbandableAncestor):
* rendering/RenderLayer.h:

Call into RenderLayer.
* rendering/RenderListBox.cpp:
(WebCore::RenderListBox::hasScrollableOrRubberbandableAncestor):
* rendering/RenderListBox.h:

Override isScrollableOrRubberbandable() to handle the main frame case where the 
main frame is typically allowed to rubber-band even if there is no content to 
scroll to.
* rendering/RenderView.cpp:
(WebCore::RenderView::isScrollableOrRubberbandable):
* rendering/RenderView.h:

Source/WebKit2:

New ScrollabeArea virtual function.
* WebProcess/Plugins/PDF/PDFPlugin.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (173013 => 173014)


--- trunk/Source/WebCore/ChangeLog	2014-08-27 19:37:16 UTC (rev 173013)
+++ trunk/Source/WebCore/ChangeLog	2014-08-27 19:53:31 UTC (rev 173014)
@@ -1,3 +1,62 @@
+2014-08-27  Beth Dakin  <bda...@apple.com>
+
+        overflow:scroll elements should not latch to the body if the body is 
+        overflow:hidden
+        https://bugs.webkit.org/show_bug.cgi?id=136273
+
+        Reviewed by Darin Adler.
+
+        This patch adds an optional parameter to isScrollable(). The Scrollability 
+        parameter that allows the caller to define what they mean by 'scrollable.' Most 
+        callers are interested in the default value, Scrollability::Scrollable, which 
+        means that there is actually content to scroll to, and a scrollbar that will allow 
+        you to access it. In some cases, such as this latching case, callers want to know 
+        if the FrameView is allowed to rubber-band, which the main frame might be allowed 
+        to do even if there is no content to scroll to. In that case, callers use 
+        Scrollability::ScrollableOrRubberbandable.
+        * page/FrameView.cpp:
+        (WebCore::FrameView::isScrollable):
+        (WebCore::FrameView::hasScrollableOrRubberbandableAncestor):
+
+        New virtual function on ScrollableArea answers whether a ScrollableArea has any 
+        scrollable or rubber-bandable ancestor.
+        * page/FrameView.h:
+        * platform/ScrollableArea.h:
+
+        Events should only be allowed to prevent stretching if there is some ancestor 
+        ScrollableArea that will be able to make use of the event. 
+        * platform/mac/ScrollAnimatorMac.mm:
+        (WebCore::ScrollAnimatorMac::allowsVerticalStretching):
+        (WebCore::ScrollAnimatorMac::allowsHorizontalStretching):
+
+        New ScrollableArea virtual function.
+        * platform/win/PopupMenuWin.h:
+
+        New RenderBox isScrollableOrRubberbandable() returns just 
+        canBeScrolledAndHasScrollableArea() for most RenderBox, but will be overridden by 
+        RenderView.
+        * rendering/RenderBox.cpp:
+        (WebCore::RenderBox::isScrollableOrRubberbandable):
+        * rendering/RenderBox.h:
+
+        Recurse up the parent chain to find out if anything is scrollable or just rubber-
+        bandable.
+        * rendering/RenderLayer.cpp:
+        (WebCore::RenderLayer::hasScrollableOrRubberbandableAncestor):
+        * rendering/RenderLayer.h:
+
+        Call into RenderLayer.
+        * rendering/RenderListBox.cpp:
+        (WebCore::RenderListBox::hasScrollableOrRubberbandableAncestor):
+        * rendering/RenderListBox.h:
+
+        Override isScrollableOrRubberbandable() to handle the main frame case where the 
+        main frame is typically allowed to rubber-band even if there is no content to 
+        scroll to.
+        * rendering/RenderView.cpp:
+        (WebCore::RenderView::isScrollableOrRubberbandable):
+        * rendering/RenderView.h:
+
 2014-08-27  Benjamin Poulain  <bpoul...@apple.com>
 
         Updating attributes on HTML elements do not invalidate the style correctly unless the attribute name is lowercase in the stylesheet

Modified: trunk/Source/WebCore/page/FrameView.cpp (173013 => 173014)


--- trunk/Source/WebCore/page/FrameView.cpp	2014-08-27 19:37:16 UTC (rev 173013)
+++ trunk/Source/WebCore/page/FrameView.cpp	2014-08-27 19:53:31 UTC (rev 173014)
@@ -3265,7 +3265,7 @@
     return ownerRenderer->absoluteContentQuad().enclosingBoundingBox();
 }
 
-bool FrameView::isScrollable()
+bool FrameView::isScrollable(Scrollability definitionOfScrollable)
 {
     // Check for:
     // 1) If there an actual overflow.
@@ -3273,11 +3273,18 @@
     // 3) overflow{-x,-y}: hidden;
     // 4) scrolling: no;
 
+    bool requiresActualOverflowToBeConsideredScrollable = !frame().isMainFrame() || definitionOfScrollable != Scrollability::ScrollableOrRubberbandable;
+#if !ENABLE(RUBBER_BANDING)
+    requiresActualOverflowToBeConsideredScrollable = true;
+#endif
+
     // Covers #1
-    IntSize totalContentsSize = this->totalContentsSize();
-    IntSize visibleContentSize = visibleContentRect(LegacyIOSDocumentVisibleRect).size();
-    if ((totalContentsSize.height() <= visibleContentSize.height() && totalContentsSize.width() <= visibleContentSize.width()))
-        return false;
+    if (requiresActualOverflowToBeConsideredScrollable) {
+        IntSize totalContentsSize = this->totalContentsSize();
+        IntSize visibleContentSize = visibleContentRect(LegacyIOSDocumentVisibleRect).size();
+        if ((totalContentsSize.height() <= visibleContentSize.height() && totalContentsSize.width() <= visibleContentSize.width()))
+            return false;
+    }
 
     // Covers #2.
     HTMLFrameOwnerElement* owner = frame().ownerElement();
@@ -3294,6 +3301,23 @@
     return true;
 }
 
+bool FrameView::hasScrollableOrRubberbandableAncestor()
+{
+    if (frame().isMainFrame())
+        return isScrollable(Scrollability::ScrollableOrRubberbandable);
+
+    FrameView* parentFrameView = this->parentFrameView();
+    if (!parentFrameView)
+        return false;
+
+    RenderView* parentRenderView = parentFrameView->renderView();
+    if (!parentRenderView)
+        return false;
+
+    RenderLayer* enclosingLayer = parentRenderView->enclosingLayer();
+    return enclosingLayer && enclosingLayer->hasScrollableOrRubberbandableAncestor();
+}
+
 void FrameView::updateScrollableAreaSet()
 {
     // That ensures that only inner frames are cached.

Modified: trunk/Source/WebCore/page/FrameView.h (173013 => 173014)


--- trunk/Source/WebCore/page/FrameView.h	2014-08-27 19:37:16 UTC (rev 173013)
+++ trunk/Source/WebCore/page/FrameView.h	2014-08-27 19:53:31 UTC (rev 173014)
@@ -396,7 +396,14 @@
 
     bool isFrameViewScrollCorner(RenderScrollbarPart* scrollCorner) const { return m_scrollCorner == scrollCorner; }
 
-    bool isScrollable();
+    // isScrollable() takes an optional Scrollability parameter that allows the caller to define what they mean by 'scrollable.'
+    // Most callers are interested in the default value, Scrollability::Scrollable, which means that there is actually content
+    // to scroll to, and a scrollbar that will allow you to access it. In some cases, callers want to know if the FrameView is allowed
+    // to rubber-band, which the main frame might be allowed to do even if there is no content to scroll to. In that case,
+    // callers use Scrollability::ScrollableOrRubberbandable.
+    enum class Scrollability { Scrollable, ScrollableOrRubberbandable };
+    bool isScrollable(Scrollability definitionOfScrollable = Scrollability::Scrollable);
+    virtual bool hasScrollableOrRubberbandableAncestor() override;
 
     enum ScrollbarModesCalculationStrategy { RulesFromWebContentOnly, AnyRule };
     void calculateScrollbarModesForLayout(ScrollbarMode& hMode, ScrollbarMode& vMode, ScrollbarModesCalculationStrategy = AnyRule);

Modified: trunk/Source/WebCore/platform/ScrollableArea.h (173013 => 173014)


--- trunk/Source/WebCore/platform/ScrollableArea.h	2014-08-27 19:37:16 UTC (rev 173013)
+++ trunk/Source/WebCore/platform/ScrollableArea.h	2014-08-27 19:53:31 UTC (rev 173014)
@@ -207,6 +207,8 @@
     // Note that this only returns scrollable areas that can actually be scrolled.
     virtual ScrollableArea* enclosingScrollableArea() const = 0;
 
+    virtual bool hasScrollableOrRubberbandableAncestor() = 0;
+
     // Returns the bounding box of this scrollable area, in the coordinate system of the enclosing scroll view.
     virtual IntRect scrollableAreaBoundingBox() const = 0;
 

Modified: trunk/Source/WebCore/platform/mac/ScrollAnimatorMac.mm (173013 => 173014)


--- trunk/Source/WebCore/platform/mac/ScrollAnimatorMac.mm	2014-08-27 19:37:16 UTC (rev 173013)
+++ trunk/Source/WebCore/platform/mac/ScrollAnimatorMac.mm	2014-08-27 19:53:31 UTC (rev 173014)
@@ -1158,7 +1158,7 @@
         Scrollbar* hScroller = m_scrollableArea->horizontalScrollbar();
         Scrollbar* vScroller = m_scrollableArea->verticalScrollbar();
         bool scrollbarsAllowStretching = ((vScroller && vScroller->enabled()) || (!hScroller || !hScroller->enabled()));
-        bool eventPreventsStretching = newGestureIsStarting(wheelEvent) && isAlreadyPinnedInDirectionOfGesture(wheelEvent, ScrollEventAxis::Vertical);
+        bool eventPreventsStretching = m_scrollableArea->hasScrollableOrRubberbandableAncestor() && newGestureIsStarting(wheelEvent) && isAlreadyPinnedInDirectionOfGesture(wheelEvent, ScrollEventAxis::Vertical);
         return scrollbarsAllowStretching && !eventPreventsStretching;
     }
     case ScrollElasticityNone:
@@ -1178,7 +1178,7 @@
         Scrollbar* hScroller = m_scrollableArea->horizontalScrollbar();
         Scrollbar* vScroller = m_scrollableArea->verticalScrollbar();
         bool scrollbarsAllowStretching = ((hScroller && hScroller->enabled()) || (!vScroller || !vScroller->enabled()));
-        bool eventPreventsStretching = newGestureIsStarting(wheelEvent) && isAlreadyPinnedInDirectionOfGesture(wheelEvent, ScrollEventAxis::Horizontal);
+        bool eventPreventsStretching = m_scrollableArea->hasScrollableOrRubberbandableAncestor() && newGestureIsStarting(wheelEvent) && isAlreadyPinnedInDirectionOfGesture(wheelEvent, ScrollEventAxis::Horizontal);
         return scrollbarsAllowStretching && !eventPreventsStretching;
     }
     case ScrollElasticityNone:

Modified: trunk/Source/WebCore/platform/win/PopupMenuWin.h (173013 => 173014)


--- trunk/Source/WebCore/platform/win/PopupMenuWin.h	2014-08-27 19:37:16 UTC (rev 173013)
+++ trunk/Source/WebCore/platform/win/PopupMenuWin.h	2014-08-27 19:53:31 UTC (rev 173014)
@@ -95,6 +95,7 @@
     virtual void invalidateScrollCornerRect(const IntRect&) override { }
     virtual bool isActive() const override { return true; }
     ScrollableArea* enclosingScrollableArea() const override { return 0; }
+    virtual bool hasScrollableOrRubberbandableAncestor() override { return true; }
     virtual bool isScrollCornerVisible() const override { return false; }
     virtual IntRect scrollCornerRect() const override { return IntRect(); }
     virtual Scrollbar* verticalScrollbar() const override { return m_scrollbar.get(); }

Modified: trunk/Source/WebCore/rendering/RenderBox.cpp (173013 => 173014)


--- trunk/Source/WebCore/rendering/RenderBox.cpp	2014-08-27 19:37:16 UTC (rev 173013)
+++ trunk/Source/WebCore/rendering/RenderBox.cpp	2014-08-27 19:53:31 UTC (rev 173014)
@@ -835,7 +835,12 @@
 {
     return canBeProgramaticallyScrolled() && (scrollHeight() != clientHeight() || scrollWidth() != clientWidth());
 }
-    
+
+bool RenderBox::isScrollableOrRubberbandable() const
+{
+    return canBeScrolledAndHasScrollableArea();
+}
+
 bool RenderBox::canBeProgramaticallyScrolled() const
 {
     if (isRenderView())

Modified: trunk/Source/WebCore/rendering/RenderBox.h (173013 => 173014)


--- trunk/Source/WebCore/rendering/RenderBox.h	2014-08-27 19:37:16 UTC (rev 173013)
+++ trunk/Source/WebCore/rendering/RenderBox.h	2014-08-27 19:53:31 UTC (rev 173014)
@@ -462,6 +462,7 @@
     virtual bool scroll(ScrollDirection, ScrollGranularity, float multiplier = 1, Element** stopElement = nullptr, RenderBox* startBox = nullptr, const IntPoint& wheelEventAbsolutePoint = IntPoint());
     virtual bool logicalScroll(ScrollLogicalDirection, ScrollGranularity, float multiplier = 1, Element** stopElement = 0);
     bool canBeScrolledAndHasScrollableArea() const;
+    virtual bool isScrollableOrRubberbandable() const;
     virtual bool canBeProgramaticallyScrolled() const;
     virtual void autoscroll(const IntPoint&);
     bool canAutoscroll() const;

Modified: trunk/Source/WebCore/rendering/RenderLayer.cpp (173013 => 173014)


--- trunk/Source/WebCore/rendering/RenderLayer.cpp	2014-08-27 19:37:16 UTC (rev 173013)
+++ trunk/Source/WebCore/rendering/RenderLayer.cpp	2014-08-27 19:53:31 UTC (rev 173014)
@@ -3065,6 +3065,16 @@
     return 0;
 }
 
+bool RenderLayer::hasScrollableOrRubberbandableAncestor()
+{
+    for (RenderLayer* nextLayer = parentLayerCrossFrame(this); nextLayer; nextLayer = parentLayerCrossFrame(nextLayer)) {
+        if (nextLayer->renderer().isBox() && toRenderBox(nextLayer->renderer()).isScrollableOrRubberbandable())
+            return true;
+    }
+
+    return false;
+}
+
 #if ENABLE(CSS_SCROLL_SNAP)
 void RenderLayer::updateSnapOffsets()
 {

Modified: trunk/Source/WebCore/rendering/RenderLayer.h (173013 => 173014)


--- trunk/Source/WebCore/rendering/RenderLayer.h	2014-08-27 19:37:16 UTC (rev 173013)
+++ trunk/Source/WebCore/rendering/RenderLayer.h	2014-08-27 19:53:31 UTC (rev 173014)
@@ -439,6 +439,7 @@
     virtual Scrollbar* horizontalScrollbar() const override { return m_hBar.get(); }
     virtual Scrollbar* verticalScrollbar() const override { return m_vBar.get(); }
     virtual ScrollableArea* enclosingScrollableArea() const override;
+    virtual bool hasScrollableOrRubberbandableAncestor() override;
 #if ENABLE(CSS_SCROLL_SNAP)
     virtual void updateSnapOffsets() override;
 #endif

Modified: trunk/Source/WebCore/rendering/RenderListBox.cpp (173013 => 173014)


--- trunk/Source/WebCore/rendering/RenderListBox.cpp	2014-08-27 19:37:16 UTC (rev 173013)
+++ trunk/Source/WebCore/rendering/RenderListBox.cpp	2014-08-27 19:53:31 UTC (rev 173014)
@@ -787,6 +787,11 @@
     return 0;
 }
 
+bool RenderListBox::hasScrollableOrRubberbandableAncestor()
+{
+    return enclosingLayer() && enclosingLayer()->hasScrollableOrRubberbandableAncestor();
+}
+
 IntRect RenderListBox::scrollableAreaBoundingBox() const
 {
     return absoluteBoundingBoxRect();

Modified: trunk/Source/WebCore/rendering/RenderListBox.h (173013 => 173014)


--- trunk/Source/WebCore/rendering/RenderListBox.h	2014-08-27 19:37:16 UTC (rev 173013)
+++ trunk/Source/WebCore/rendering/RenderListBox.h	2014-08-27 19:53:31 UTC (rev 173014)
@@ -131,6 +131,7 @@
     virtual bool forceUpdateScrollbarsOnMainThreadForPerformanceTesting() const override;
 
     virtual ScrollableArea* enclosingScrollableArea() const override;
+    virtual bool hasScrollableOrRubberbandableAncestor() override;
     virtual IntRect scrollableAreaBoundingBox() const override;
 
     // NOTE: This should only be called by the overriden setScrollOffset from ScrollableArea.

Modified: trunk/Source/WebCore/rendering/RenderView.cpp (173013 => 173014)


--- trunk/Source/WebCore/rendering/RenderView.cpp	2014-08-27 19:37:16 UTC (rev 173013)
+++ trunk/Source/WebCore/rendering/RenderView.cpp	2014-08-27 19:53:31 UTC (rev 173014)
@@ -710,6 +710,14 @@
         rect = LayoutRect(layer()->transform()->mapRect(pixelSnappedForPainting(rect, document().deviceScaleFactor())));
 }
 
+bool RenderView::isScrollableOrRubberbandable() const
+{
+    // The main frame might be allowed to rubber-band even if there is no content to scroll to. This is unique to
+    // the main frame; subframes and overflow areas have to have content that can be scrolled to in order to rubber-band.
+    FrameView::Scrollability defineScrollable = frame().ownerElement() ? FrameView::Scrollability::Scrollable : FrameView::Scrollability::ScrollableOrRubberbandable;
+    return frameView().isScrollable(defineScrollable);
+}
+
 void RenderView::absoluteRects(Vector<IntRect>& rects, const LayoutPoint& accumulatedOffset) const
 {
     rects.append(pixelSnappedIntRect(accumulatedOffset, layer()->size()));

Modified: trunk/Source/WebCore/rendering/RenderView.h (173013 => 173014)


--- trunk/Source/WebCore/rendering/RenderView.h	2014-08-27 19:37:16 UTC (rev 173013)
+++ trunk/Source/WebCore/rendering/RenderView.h	2014-08-27 19:53:31 UTC (rev 173014)
@@ -303,6 +303,8 @@
     friend class LayoutStateMaintainer;
     friend class LayoutStateDisabler;
 
+    virtual bool isScrollableOrRubberbandable() const;
+
     void splitSelectionBetweenSubtrees(RenderObject* start, int startPos, RenderObject* end, int endPos, SelectionRepaintMode blockRepaintMode);
     void clearSubtreeSelection(const SelectionSubtreeRoot&, SelectionRepaintMode, OldSelectionData&);
     void updateSelectionForSubtrees(RenderSubtreesMap&, SelectionRepaintMode);

Modified: trunk/Source/WebKit2/ChangeLog (173013 => 173014)


--- trunk/Source/WebKit2/ChangeLog	2014-08-27 19:37:16 UTC (rev 173013)
+++ trunk/Source/WebKit2/ChangeLog	2014-08-27 19:53:31 UTC (rev 173014)
@@ -1,3 +1,14 @@
+2014-08-27  Beth Dakin  <bda...@apple.com>
+
+        overflow:scroll elements should not latch to the body if the body is 
+        overflow:hidden
+        https://bugs.webkit.org/show_bug.cgi?id=136273
+
+        Reviewed by Darin Adler.
+
+        New ScrollabeArea virtual function.
+        * WebProcess/Plugins/PDF/PDFPlugin.h:
+
 2014-08-26  Matt Lilek  <m...@apple.com>
 
         Add WebKit SPI to control the navigator.standalone property

Modified: trunk/Source/WebKit2/WebProcess/Plugins/PDF/PDFPlugin.h (173013 => 173014)


--- trunk/Source/WebKit2/WebProcess/Plugins/PDF/PDFPlugin.h	2014-08-27 19:37:16 UTC (rev 173013)
+++ trunk/Source/WebKit2/WebProcess/Plugins/PDF/PDFPlugin.h	2014-08-27 19:53:31 UTC (rev 173014)
@@ -175,6 +175,7 @@
     // ScrollableArea functions.
     virtual WebCore::IntRect scrollCornerRect() const override;
     virtual WebCore::ScrollableArea* enclosingScrollableArea() const override;
+    virtual bool hasScrollableOrRubberbandableAncestor() override { return true; }
     virtual WebCore::IntRect scrollableAreaBoundingBox() const override;
     virtual void setScrollOffset(const WebCore::IntPoint&) override;
     virtual void invalidateScrollbarRect(WebCore::Scrollbar*, const WebCore::IntRect&) override;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to