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;