https://bugs.webkit.org/show_bug.cgi?id=56493
Drag-scrolling overlay scrollbars thumb in overflow regions does not work
-and corresponding-
<rdar://problem/9112688>
Reviewed by Simon Fraser.
There was an original change to fix this in the normal hit-testing case, but hit
testing of transformed and/or positioned objects was still broken. The transformed
case is fixed by sending an OverlayScrollbarSizeRelevancy parameter to
calculateRects(). Getting positioned objects right is a little trickier. Those need
to opt into using temporary clip rects during hit testing. To avoid doing that when
it is not necessary, I added a new bit to ScrollView to track whether there are
currently overlay scrollbars painted in the view.
* platform/ScrollView.cpp:
(WebCore::ScrollView::ScrollView):
(WebCore::ScrollView::wheelEvent):
* platform/ScrollView.h:
(WebCore::ScrollView::containsScrollableAreaWithOverlayScrollbars):
(WebCore::ScrollView::setContainsScrollableAreaWithOverlayScrollbars):
* rendering/RenderLayer.cpp:
(WebCore::RenderLayer::paintOverflowControls):
(WebCore::RenderLayer::hitTestLayer):
(WebCore::RenderLayer::updateClipRects):
(WebCore::RenderLayer::calculateClipRects):
(WebCore::RenderLayer::parentClipRects):
(WebCore::RenderLayer::backgroundClipRect):
(WebCore::RenderLayer::calculateRects):
* rendering/RenderLayer.h:
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@83899 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index c934aad..54098cb 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,35 @@
+2011-04-14 Beth Dakin <bdakin@apple.com>
+
+ Reviewed by Simon Fraser.
+
+ https://bugs.webkit.org/show_bug.cgi?id=56493
+ Drag-scrolling overlay scrollbars thumb in overflow regions does not work
+ -and corresponding-
+ <rdar://problem/9112688>
+
+ There was an original change to fix this in the normal hit-testing case, but hit
+ testing of transformed and/or positioned objects was still broken. The transformed
+ case is fixed by sending an OverlayScrollbarSizeRelevancy parameter to
+ calculateRects(). Getting positioned objects right is a little trickier. Those need
+ to opt into using temporary clip rects during hit testing. To avoid doing that when
+ it is not necessary, I added a new bit to ScrollView to track whether there are
+ currently overlay scrollbars painted in the view.
+ * platform/ScrollView.cpp:
+ (WebCore::ScrollView::ScrollView):
+ (WebCore::ScrollView::wheelEvent):
+ * platform/ScrollView.h:
+ (WebCore::ScrollView::containsScrollableAreaWithOverlayScrollbars):
+ (WebCore::ScrollView::setContainsScrollableAreaWithOverlayScrollbars):
+ * rendering/RenderLayer.cpp:
+ (WebCore::RenderLayer::paintOverflowControls):
+ (WebCore::RenderLayer::hitTestLayer):
+ (WebCore::RenderLayer::updateClipRects):
+ (WebCore::RenderLayer::calculateClipRects):
+ (WebCore::RenderLayer::parentClipRects):
+ (WebCore::RenderLayer::backgroundClipRect):
+ (WebCore::RenderLayer::calculateRects):
+ * rendering/RenderLayer.h:
+
2011-04-14 Antti Koivisto <antti@apple.com>
Reviewed by Oliver Hunt.
diff --git a/Source/WebCore/platform/ScrollView.cpp b/Source/WebCore/platform/ScrollView.cpp
index 14d961b..7caf820 100644
--- a/Source/WebCore/platform/ScrollView.cpp
+++ b/Source/WebCore/platform/ScrollView.cpp
@@ -57,6 +57,7 @@
, m_paintsEntireContents(false)
, m_clipsRepaints(true)
, m_delegatesScrolling(false)
+ , m_containsScrollableAreaWithOverlayScrollbars(false)
{
platformInit();
}
@@ -982,6 +983,9 @@
return;
notifyPageThatContentAreaWillPaint();
+
+ // If we encounter any overlay scrollbars as we paint, this will be set to true.
+ m_containsScrollableAreaWithOverlayScrollbars = false;
IntRect documentDirtyRect = rect;
documentDirtyRect.intersect(frameRect());
diff --git a/Source/WebCore/platform/ScrollView.h b/Source/WebCore/platform/ScrollView.h
index 91f384b..796b741 100644
--- a/Source/WebCore/platform/ScrollView.h
+++ b/Source/WebCore/platform/ScrollView.h
@@ -282,6 +282,9 @@
virtual IntPoint convertFromScrollbarToContainingView(const Scrollbar*, const IntPoint&) const;
virtual IntPoint convertFromContainingViewToScrollbar(const Scrollbar*, const IntPoint&) const;
+ bool containsScrollableAreaWithOverlayScrollbars() const { return m_containsScrollableAreaWithOverlayScrollbars; }
+ void setContainsScrollableAreaWithOverlayScrollbars(bool contains) { m_containsScrollableAreaWithOverlayScrollbars = contains; }
+
protected:
ScrollView();
@@ -352,6 +355,8 @@
bool m_clipsRepaints;
bool m_delegatesScrolling;
+ bool m_containsScrollableAreaWithOverlayScrollbars;
+
IntSize m_boundsSize;
void init();
diff --git a/Source/WebCore/rendering/RenderLayer.cpp b/Source/WebCore/rendering/RenderLayer.cpp
index 1cfefa3..4ea3868 100644
--- a/Source/WebCore/rendering/RenderLayer.cpp
+++ b/Source/WebCore/rendering/RenderLayer.cpp
@@ -2242,9 +2242,10 @@
// 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) {
- RenderLayer* rootLayer = renderer()->view()->layer();
- rootLayer->setContainsDirtyOverlayScrollbars(true);
+ RenderView* renderView = renderer()->view();
+ renderView->layer()->setContainsDirtyOverlayScrollbars(true);
m_cachedOverlayScrollbarOffset = IntPoint(tx, ty);
+ renderView->frameView()->setContainsScrollableAreaWithOverlayScrollbars(true);
return;
}
@@ -2937,6 +2938,7 @@
#if USE(ACCELERATED_COMPOSITING)
useTemporaryClipRects = compositor()->inCompositingMode();
#endif
+ useTemporaryClipRects |= renderer()->view()->frameView()->containsScrollableAreaWithOverlayScrollbars();
IntRect hitTestArea = result.rectForPoint(hitTestPoint);
@@ -2944,7 +2946,7 @@
if (transform() && !appliedTransform) {
// Make sure the parent's clip rects have been calculated.
if (parent()) {
- IntRect clipRect = backgroundClipRect(rootLayer, useTemporaryClipRects);
+ IntRect clipRect = backgroundClipRect(rootLayer, useTemporaryClipRects, IncludeOverlayScrollbarSize);
// Go ahead and test the enclosing clip now.
if (!clipRect.intersects(hitTestArea))
return 0;
@@ -3012,7 +3014,7 @@
IntRect bgRect;
IntRect fgRect;
IntRect outlineRect;
- calculateRects(rootLayer, hitTestRect, layerBounds, bgRect, fgRect, outlineRect, useTemporaryClipRects);
+ calculateRects(rootLayer, hitTestRect, layerBounds, bgRect, fgRect, outlineRect, useTemporaryClipRects, IncludeOverlayScrollbarSize);
// The following are used for keeping track of the z-depth of the hit point of 3d-transformed
// descendants.
@@ -3273,7 +3275,7 @@
return 0;
}
-void RenderLayer::updateClipRects(const RenderLayer* rootLayer)
+void RenderLayer::updateClipRects(const RenderLayer* rootLayer, OverlayScrollbarSizeRelevancy relevancy)
{
if (m_clipRects) {
ASSERT(rootLayer == m_clipRectsRoot);
@@ -3284,10 +3286,10 @@
// examine the parent. We want to cache clip rects with us as the root.
RenderLayer* parentLayer = rootLayer != this ? parent() : 0;
if (parentLayer)
- parentLayer->updateClipRects(rootLayer);
+ parentLayer->updateClipRects(rootLayer, relevancy);
ClipRects clipRects;
- calculateClipRects(rootLayer, clipRects, true);
+ calculateClipRects(rootLayer, clipRects, true, relevancy);
if (parentLayer && parentLayer->clipRects() && clipRects == *parentLayer->clipRects())
m_clipRects = parentLayer->clipRects();
@@ -3299,7 +3301,7 @@
#endif
}
-void RenderLayer::calculateClipRects(const RenderLayer* rootLayer, ClipRects& clipRects, bool useCached) const
+void RenderLayer::calculateClipRects(const RenderLayer* rootLayer, ClipRects& clipRects, bool useCached, OverlayScrollbarSizeRelevancy relevancy) const
{
if (!parent()) {
// The root layer's clip rect is always infinite.
@@ -3347,7 +3349,7 @@
}
if (renderer()->hasOverflowClip()) {
- IntRect newOverflowClip = toRenderBox(renderer())->overflowClipRect(x, y);
+ IntRect newOverflowClip = toRenderBox(renderer())->overflowClipRect(x, y, relevancy);
clipRects.setOverflowClipRect(intersection(newOverflowClip, clipRects.overflowClipRect()));
if (renderer()->isPositioned() || renderer()->isRelPositioned())
clipRects.setPosClipRect(intersection(newOverflowClip, clipRects.posClipRect()));
@@ -3361,24 +3363,24 @@
}
}
-void RenderLayer::parentClipRects(const RenderLayer* rootLayer, ClipRects& clipRects, bool temporaryClipRects) const
+void RenderLayer::parentClipRects(const RenderLayer* rootLayer, ClipRects& clipRects, bool temporaryClipRects, OverlayScrollbarSizeRelevancy relevancy) const
{
ASSERT(parent());
if (temporaryClipRects) {
- parent()->calculateClipRects(rootLayer, clipRects);
+ parent()->calculateClipRects(rootLayer, clipRects, false, relevancy);
return;
}
- parent()->updateClipRects(rootLayer);
+ parent()->updateClipRects(rootLayer, relevancy);
clipRects = *parent()->clipRects();
}
-IntRect RenderLayer::backgroundClipRect(const RenderLayer* rootLayer, bool temporaryClipRects) const
+IntRect RenderLayer::backgroundClipRect(const RenderLayer* rootLayer, bool temporaryClipRects, OverlayScrollbarSizeRelevancy relevancy) const
{
IntRect backgroundRect;
if (parent()) {
ClipRects parentRects;
- parentClipRects(rootLayer, parentRects, temporaryClipRects);
+ parentClipRects(rootLayer, parentRects, temporaryClipRects, relevancy);
backgroundRect = renderer()->style()->position() == FixedPosition ? parentRects.fixedClipRect() :
(renderer()->isPositioned() ? parentRects.posClipRect() :
parentRects.overflowClipRect());
@@ -3391,10 +3393,11 @@
}
void RenderLayer::calculateRects(const RenderLayer* rootLayer, const IntRect& paintDirtyRect, IntRect& layerBounds,
- IntRect& backgroundRect, IntRect& foregroundRect, IntRect& outlineRect, bool temporaryClipRects) const
+ IntRect& backgroundRect, IntRect& foregroundRect, IntRect& outlineRect, bool temporaryClipRects,
+ OverlayScrollbarSizeRelevancy relevancy) const
{
if (rootLayer != this && parent()) {
- backgroundRect = backgroundClipRect(rootLayer, temporaryClipRects);
+ backgroundRect = backgroundClipRect(rootLayer, temporaryClipRects, relevancy);
backgroundRect.intersect(paintDirtyRect);
} else
backgroundRect = paintDirtyRect;
@@ -3411,7 +3414,7 @@
if (renderer()->hasOverflowClip() || renderer()->hasClip()) {
// This layer establishes a clip of some kind.
if (renderer()->hasOverflowClip())
- foregroundRect.intersect(toRenderBox(renderer())->overflowClipRect(x, y));
+ foregroundRect.intersect(toRenderBox(renderer())->overflowClipRect(x, y, relevancy));
if (renderer()->hasClip()) {
// Clip applies to *us* as well, so go ahead and update the damageRect.
IntRect newPosClip = toRenderBox(renderer())->clipRect(x, y);
diff --git a/Source/WebCore/rendering/RenderLayer.h b/Source/WebCore/rendering/RenderLayer.h
index 4811930..802ac87 100644
--- a/Source/WebCore/rendering/RenderLayer.h
+++ b/Source/WebCore/rendering/RenderLayer.h
@@ -256,8 +256,8 @@
virtual Scrollbar* horizontalScrollbar() const { return m_hBar.get(); }
virtual Scrollbar* verticalScrollbar() const { return m_vBar.get(); }
- int verticalScrollbarWidth(OverlayScrollbarSizeRelevancy relevancy = IgnoreOverlayScrollbarSize) const;
- int horizontalScrollbarHeight(OverlayScrollbarSizeRelevancy relevancy = IgnoreOverlayScrollbarSize) const;
+ int verticalScrollbarWidth(OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize) const;
+ int horizontalScrollbarHeight(OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize) const;
bool hasOverflowControls() const;
bool isPointInResizeControl(const IntPoint& absolutePoint) const;
@@ -367,13 +367,14 @@
// |rootLayer}. It also computes our background and foreground clip rects
// for painting/event handling.
void calculateRects(const RenderLayer* rootLayer, const IntRect& paintDirtyRect, IntRect& layerBounds,
- IntRect& backgroundRect, IntRect& foregroundRect, IntRect& outlineRect, bool temporaryClipRects = false) const;
+ IntRect& backgroundRect, IntRect& foregroundRect, IntRect& outlineRect, bool temporaryClipRects = false,
+ OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize) const;
// Compute and cache clip rects computed with the given layer as the root
- void updateClipRects(const RenderLayer* rootLayer);
+ void updateClipRects(const RenderLayer* rootLayer, OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize);
// Compute and return the clip rects. If useCached is true, will used previously computed clip rects on ancestors
// (rather than computing them all from scratch up the parent chain).
- void calculateClipRects(const RenderLayer* rootLayer, ClipRects&, bool useCached = false) const;
+ void calculateClipRects(const RenderLayer* rootLayer, ClipRects&, bool useCached = false, OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize) const;
ClipRects* clipRects() const { return m_clipRects; }
IntRect childrenClipRect() const; // Returns the foreground clip rect of the layer in the document's coordinate space.
@@ -571,8 +572,8 @@
bool paintingInsideReflection() const { return m_paintingInsideReflection; }
void setPaintingInsideReflection(bool b) { m_paintingInsideReflection = b; }
- void parentClipRects(const RenderLayer* rootLayer, ClipRects&, bool temporaryClipRects = false) const;
- IntRect backgroundClipRect(const RenderLayer* rootLayer, bool temporaryClipRects) const;
+ void parentClipRects(const RenderLayer* rootLayer, ClipRects&, bool temporaryClipRects = false, OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize) const;
+ IntRect backgroundClipRect(const RenderLayer* rootLayer, bool temporaryClipRects, OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize) const;
RenderLayer* enclosingTransformedAncestor() const;