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:
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@173014
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2014-08-27 Beth Dakin <bdakin@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 <bpoulain@apple.com>
Updating attributes on HTML elements do not invalidate the style correctly unless the attribute name is lowercase in the stylesheet
return ownerRenderer->absoluteContentQuad().enclosingBoundingBox();
}
-bool FrameView::isScrollable()
+bool FrameView::isScrollable(Scrollability definitionOfScrollable)
{
// Check for:
// 1) If there an actual overflow.
// 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();
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.
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);
// 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;
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:
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:
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(); }
{
return canBeProgramaticallyScrolled() && (scrollHeight() != clientHeight() || scrollWidth() != clientWidth());
}
-
+
+bool RenderBox::isScrollableOrRubberbandable() const
+{
+ return canBeScrolledAndHasScrollableArea();
+}
+
bool RenderBox::canBeProgramaticallyScrolled() const
{
if (isRenderView())
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;
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()
{
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
return 0;
}
+bool RenderListBox::hasScrollableOrRubberbandableAncestor()
+{
+ return enclosingLayer() && enclosingLayer()->hasScrollableOrRubberbandableAncestor();
+}
+
IntRect RenderListBox::scrollableAreaBoundingBox() const
{
return absoluteBoundingBoxRect();
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.
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()));
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);
+2014-08-27 Beth Dakin <bdakin@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 <mrl@apple.com>
Add WebKit SPI to control the navigator.standalone property
// 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;