Title: [202536] trunk
Revision
202536
Author
[email protected]
Date
2016-06-27 19:58:16 -0700 (Mon, 27 Jun 2016)

Log Message

[iOS] -webkit-overflow-scrolling: touch prevents repaint with RTL
https://bugs.webkit.org/show_bug.cgi?id=159186
rdar://problem/26659341

Reviewed by Zalan Bujtas.
Source/WebCore:

There were two issues with repaints in -webkit-overflow-scrolling:touch scrolling
layers.

First, if the scrolled contents were inline (e.g. a <span>), then repaints were
broken because RenderInline didn't call shouldApplyClipAndScrollPositionForRepaint().
Fix by making shouldApplyClipAndScrollPositionForRepaint() a member function of RenderBox
and calling it from RenderBox::computeRectForRepaint() and RenderInline::clippedOverflowRectForRepaint().

Second, repaints were broken in RTL because RenderLayerBacking::setContentsNeedDisplayInRect()
confused scroll offset and scroll position; it needs to subtract scrollPosition.

Finally renamed to applyCachedClipAndScrollOffsetForRepaint() to applyCachedClipAndScrollPositionForRepaint()
to make it clear that it uses scrollPosition, not scrollOffset.

Tests: compositing/scrolling/touch-scrolling-repaint-spans.html
       compositing/scrolling/touch-scrolling-repaint.html

* rendering/RenderBox.cpp:
(WebCore::RenderBox::applyCachedClipAndScrollPositionForRepaint):
(WebCore::RenderBox::shouldApplyClipAndScrollPositionForRepaint):
(WebCore::RenderBox::computeRectForRepaint):
(WebCore::RenderBox::applyCachedClipAndScrollOffsetForRepaint): Deleted.
(WebCore::shouldApplyContainersClipAndOffset): Deleted.
* rendering/RenderBox.h:
* rendering/RenderInline.cpp:
(WebCore::RenderInline::clippedOverflowRectForRepaint):
(WebCore::RenderInline::computeRectForRepaint):
* rendering/RenderLayerBacking.cpp:
(WebCore::RenderLayerBacking::setContentsNeedDisplayInRect):
* rendering/RenderObject.cpp:
(WebCore::RenderObject::computeRectForRepaint):

LayoutTests:

* compositing/scrolling/touch-scrolling-repaint-expected.html: Added.
* compositing/scrolling/touch-scrolling-repaint-spans-expected.html: Added.
* compositing/scrolling/touch-scrolling-repaint-spans.html: Added.
* compositing/scrolling/touch-scrolling-repaint.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (202535 => 202536)


--- trunk/LayoutTests/ChangeLog	2016-06-28 02:47:23 UTC (rev 202535)
+++ trunk/LayoutTests/ChangeLog	2016-06-28 02:58:16 UTC (rev 202536)
@@ -1,5 +1,18 @@
 2016-06-27  Simon Fraser  <[email protected]>
 
+        [iOS] -webkit-overflow-scrolling: touch prevents repaint with RTL
+        https://bugs.webkit.org/show_bug.cgi?id=159186
+        rdar://problem/26659341
+
+        Reviewed by Zalan Bujtas.
+
+        * compositing/scrolling/touch-scrolling-repaint-expected.html: Added.
+        * compositing/scrolling/touch-scrolling-repaint-spans-expected.html: Added.
+        * compositing/scrolling/touch-scrolling-repaint-spans.html: Added.
+        * compositing/scrolling/touch-scrolling-repaint.html: Added.
+
+2016-06-27  Simon Fraser  <[email protected]>
+
         [iOS] Make DumpRenderTree and WebKitTestRunner in the simulator use render server snapshotting
         https://bugs.webkit.org/show_bug.cgi?id=159077
 

Added: trunk/LayoutTests/compositing/scrolling/touch-scrolling-repaint-expected.html (0 => 202536)


--- trunk/LayoutTests/compositing/scrolling/touch-scrolling-repaint-expected.html	                        (rev 0)
+++ trunk/LayoutTests/compositing/scrolling/touch-scrolling-repaint-expected.html	2016-06-28 02:58:16 UTC (rev 202536)
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <meta name="viewport" content="width=device-width, initial-scale=1">
+        <style>
+            .scroller {
+                margin: 10px;
+                width: 300px;
+                padding: 10px;
+                overflow-y: hidden;
+                overflow-x: scroll;
+                border: 8px solid black;
+                -webkit-overflow-scrolling: touch;
+            }
+            
+            .contents {
+                height: 100px;
+                width: 480px;
+                background-color: green;
+                letter-spacing: 12px;
+                color: white;
+                font-size: 28pt;
+            }
+        </style>
+        <script>
+            function doTest()
+            {
+                document.getElementById('scroller2').scrollLeft = 120;
+                document.getElementById('scroller4').scrollLeft = -120;
+            }
+            window.addEventListener('load', doTest, false);
+        </script>
+    </head>
+    <body>
+        <div class="scroller" id="scroller1">
+            <div class='contents'>ABCDEFGHIJKLM</div>
+        </div>
+
+        <div class="scroller" id="scroller2">
+            <div class='contents'>ABCDEFGHIJKLM</div>
+        </div>
+
+        <div class="scroller" id="scroller3" dir="rtl">
+            <div class='contents'>ABCDEFGHIJKLM</div>
+        </div>
+
+        <div class="scroller" id="scroller4" dir="rtl">
+            <div class='contents'>ABCDEFGHIJKLM</div>
+        </div>
+    </body>
+</html>

Added: trunk/LayoutTests/compositing/scrolling/touch-scrolling-repaint-spans-expected.html (0 => 202536)


--- trunk/LayoutTests/compositing/scrolling/touch-scrolling-repaint-spans-expected.html	                        (rev 0)
+++ trunk/LayoutTests/compositing/scrolling/touch-scrolling-repaint-spans-expected.html	2016-06-28 02:58:16 UTC (rev 202536)
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <meta name="viewport" content="width=device-width, initial-scale=1">
+        <style>
+            .scroller {
+                margin: 10px;
+                width: 300px;
+                padding: 10px;
+                overflow-y: hidden;
+                overflow-x: scroll;
+                border: 8px solid black;
+                -webkit-overflow-scrolling: touch;
+            }
+            
+            .contents {
+                height: 100px;
+                width: 480px;
+                background-color: green;
+                letter-spacing: 12px;
+                color: white;
+                font-size: 28pt;
+            }
+        </style>
+        <script>
+            function doTest()
+            {
+                document.getElementById('scroller2').scrollLeft = 120;
+                document.getElementById('scroller4').scrollLeft = -120;
+            }
+            window.addEventListener('load', doTest, false);
+        </script>
+    </head>
+    <body>
+        <div class="scroller" id="scroller1">
+            <span class='contents'>ABCDEFGHIJKLM</span>
+        </div>
+
+        <div class="scroller" id="scroller2">
+            <span class='contents'>ABCDEFGHIJKLM</span>
+        </div>
+
+        <div class="scroller" id="scroller3" dir="rtl">
+            <span class='contents'>ABCDEFGHIJKLM</span>
+        </div>
+
+        <div class="scroller" id="scroller4" dir="rtl">
+            <span class='contents'>ABCDEFGHIJKLM</span>
+        </div>
+    </body>
+</html>

Added: trunk/LayoutTests/compositing/scrolling/touch-scrolling-repaint-spans.html (0 => 202536)


--- trunk/LayoutTests/compositing/scrolling/touch-scrolling-repaint-spans.html	                        (rev 0)
+++ trunk/LayoutTests/compositing/scrolling/touch-scrolling-repaint-spans.html	2016-06-28 02:58:16 UTC (rev 202536)
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <meta name="viewport" content="width=device-width, initial-scale=1">
+        <style>
+            .scroller {
+                margin: 10px;
+                width: 300px;
+                padding: 10px;
+                overflow-y: hidden;
+                overflow-x: scroll;
+                border: 8px solid black;
+                -webkit-overflow-scrolling: touch;
+            }
+            
+            .contents {
+                height: 100px;
+                width: 480px;
+                background-color: red;
+                letter-spacing: 12px;
+                color: white;
+                font-size: 28pt;
+            }
+            
+            body.changed .contents {
+                background-color: green;
+            }
+        </style>
+        <script>
+            if (window.testRunner)
+                testRunner.waitUntilDone();
+
+            function doTest()
+            {
+                document.getElementById('scroller2').scrollLeft = 120;
+                document.getElementById('scroller4').scrollLeft = -120;
+                
+                window.setTimeout(function() {
+                    document.body.classList.add('changed');
+                    if (window.testRunner)
+                        testRunner.notifyDone();
+                }, 0);
+            }
+            window.addEventListener('load', doTest, false);
+        </script>
+    </head>
+    <body>
+        <div class="scroller" id="scroller1">
+            <span class='contents'>ABCDEFGHIJKLM</span>
+        </div>
+
+        <div class="scroller" id="scroller2">
+            <span class='contents'>ABCDEFGHIJKLM</span>
+        </div>
+
+        <div class="scroller" id="scroller3" dir="rtl">
+            <span class='contents'>ABCDEFGHIJKLM</span>
+        </div>
+
+        <div class="scroller" id="scroller4" dir="rtl">
+            <span class='contents'>ABCDEFGHIJKLM</span>
+        </div>
+    </body>
+</html>

Added: trunk/LayoutTests/compositing/scrolling/touch-scrolling-repaint.html (0 => 202536)


--- trunk/LayoutTests/compositing/scrolling/touch-scrolling-repaint.html	                        (rev 0)
+++ trunk/LayoutTests/compositing/scrolling/touch-scrolling-repaint.html	2016-06-28 02:58:16 UTC (rev 202536)
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <meta name="viewport" content="width=device-width, initial-scale=1">
+        <style>
+            .scroller {
+                margin: 10px;
+                width: 300px;
+                padding: 10px;
+                overflow-y: hidden;
+                overflow-x: scroll;
+                border: 8px solid black;
+                -webkit-overflow-scrolling: touch;
+            }
+            
+            .contents {
+                height: 100px;
+                width: 480px;
+                background-color: red;
+                letter-spacing: 12px;
+                color: white;
+                font-size: 28pt;
+            }
+            
+            body.changed .contents {
+                background-color: green;
+            }
+        </style>
+        <script>
+            if (window.testRunner)
+                testRunner.waitUntilDone();
+
+            function doTest()
+            {
+                document.getElementById('scroller2').scrollLeft = 120;
+                document.getElementById('scroller4').scrollLeft = -120;
+                
+                window.setTimeout(function() {
+                    document.body.classList.add('changed');
+                    if (window.testRunner)
+                        testRunner.notifyDone();
+                }, 0);
+            }
+            window.addEventListener('load', doTest, false);
+        </script>
+    </head>
+    <body>
+        <div class="scroller" id="scroller1">
+            <div class='contents'>ABCDEFGHIJKLM</div>
+        </div>
+
+        <div class="scroller" id="scroller2">
+            <div class='contents'>ABCDEFGHIJKLM</div>
+        </div>
+
+        <div class="scroller" id="scroller3" dir="rtl">
+            <div class='contents'>ABCDEFGHIJKLM</div>
+        </div>
+
+        <div class="scroller" id="scroller4" dir="rtl">
+            <div class='contents'>ABCDEFGHIJKLM</div>
+        </div>
+    </body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (202535 => 202536)


--- trunk/Source/WebCore/ChangeLog	2016-06-28 02:47:23 UTC (rev 202535)
+++ trunk/Source/WebCore/ChangeLog	2016-06-28 02:58:16 UTC (rev 202536)
@@ -1,3 +1,43 @@
+2016-06-27  Simon Fraser  <[email protected]>
+
+        [iOS] -webkit-overflow-scrolling: touch prevents repaint with RTL
+        https://bugs.webkit.org/show_bug.cgi?id=159186
+        rdar://problem/26659341
+
+        Reviewed by Zalan Bujtas.
+        
+        There were two issues with repaints in -webkit-overflow-scrolling:touch scrolling
+        layers.
+
+        First, if the scrolled contents were inline (e.g. a <span>), then repaints were
+        broken because RenderInline didn't call shouldApplyClipAndScrollPositionForRepaint().
+        Fix by making shouldApplyClipAndScrollPositionForRepaint() a member function of RenderBox
+        and calling it from RenderBox::computeRectForRepaint() and RenderInline::clippedOverflowRectForRepaint().
+
+        Second, repaints were broken in RTL because RenderLayerBacking::setContentsNeedDisplayInRect()
+        confused scroll offset and scroll position; it needs to subtract scrollPosition.
+        
+        Finally renamed to applyCachedClipAndScrollOffsetForRepaint() to applyCachedClipAndScrollPositionForRepaint()
+        to make it clear that it uses scrollPosition, not scrollOffset.
+
+        Tests: compositing/scrolling/touch-scrolling-repaint-spans.html
+               compositing/scrolling/touch-scrolling-repaint.html
+
+        * rendering/RenderBox.cpp:
+        (WebCore::RenderBox::applyCachedClipAndScrollPositionForRepaint):
+        (WebCore::RenderBox::shouldApplyClipAndScrollPositionForRepaint):
+        (WebCore::RenderBox::computeRectForRepaint):
+        (WebCore::RenderBox::applyCachedClipAndScrollOffsetForRepaint): Deleted.
+        (WebCore::shouldApplyContainersClipAndOffset): Deleted.
+        * rendering/RenderBox.h:
+        * rendering/RenderInline.cpp:
+        (WebCore::RenderInline::clippedOverflowRectForRepaint):
+        (WebCore::RenderInline::computeRectForRepaint):
+        * rendering/RenderLayerBacking.cpp:
+        (WebCore::RenderLayerBacking::setContentsNeedDisplayInRect):
+        * rendering/RenderObject.cpp:
+        (WebCore::RenderObject::computeRectForRepaint):
+
 2016-06-27  Commit Queue  <[email protected]>
 
         Unreviewed, rolling out r202436.

Modified: trunk/Source/WebCore/rendering/RenderBox.cpp (202535 => 202536)


--- trunk/Source/WebCore/rendering/RenderBox.cpp	2016-06-28 02:47:23 UTC (rev 202535)
+++ trunk/Source/WebCore/rendering/RenderBox.cpp	2016-06-28 02:58:16 UTC (rev 202536)
@@ -1012,7 +1012,7 @@
     return layer()->size();
 }
 
-void RenderBox::applyCachedClipAndScrollOffsetForRepaint(LayoutRect& paintRect) const
+void RenderBox::applyCachedClipAndScrollPositionForRepaint(LayoutRect& paintRect) const
 {
     flipForWritingMode(paintRect);
     paintRect.moveBy(-scrollPosition()); // For overflow:auto/scroll/hidden.
@@ -2194,16 +2194,15 @@
     return computeRectForRepaint(r, repaintContainer);
 }
 
-static inline bool shouldApplyContainersClipAndOffset(const RenderLayerModelObject* repaintContainer, RenderBox* containerBox)
+bool RenderBox::shouldApplyClipAndScrollPositionForRepaint(const RenderLayerModelObject* repaintContainer) const
 {
 #if PLATFORM(IOS)
-    if (!repaintContainer || repaintContainer != containerBox)
+    if (!repaintContainer || repaintContainer != this)
         return true;
 
-    return !containerBox->hasLayer() || !containerBox->layer()->usesCompositedScrolling();
+    return !hasLayer() || !layer()->usesCompositedScrolling();
 #else
     UNUSED_PARAM(repaintContainer);
-    UNUSED_PARAM(containerBox);
     return true;
 #endif
 }
@@ -2309,8 +2308,8 @@
     adjustedRect.setLocation(topLeft);
     if (container->hasOverflowClip()) {
         RenderBox& containerBox = downcast<RenderBox>(*container);
-        if (shouldApplyContainersClipAndOffset(repaintContainer, &containerBox)) {
-            containerBox.applyCachedClipAndScrollOffsetForRepaint(adjustedRect);
+        if (containerBox.shouldApplyClipAndScrollPositionForRepaint(repaintContainer)) {
+            containerBox.applyCachedClipAndScrollPositionForRepaint(adjustedRect);
             if (adjustedRect.isEmpty())
                 return adjustedRect;
         }

Modified: trunk/Source/WebCore/rendering/RenderBox.h (202535 => 202536)


--- trunk/Source/WebCore/rendering/RenderBox.h	2016-06-28 02:47:23 UTC (rev 202535)
+++ trunk/Source/WebCore/rendering/RenderBox.h	2016-06-28 02:58:16 UTC (rev 202536)
@@ -577,8 +577,10 @@
 
     ScrollPosition scrollPosition() const;
     LayoutSize cachedSizeForOverflowClip() const;
-    void applyCachedClipAndScrollOffsetForRepaint(LayoutRect& paintRect) const;
 
+    bool shouldApplyClipAndScrollPositionForRepaint(const RenderLayerModelObject* repaintContainer) const;
+    void applyCachedClipAndScrollPositionForRepaint(LayoutRect& paintRect) const;
+
     virtual bool hasRelativeDimensions() const;
     virtual bool hasRelativeLogicalHeight() const;
     virtual bool hasRelativeLogicalWidth() const;

Modified: trunk/Source/WebCore/rendering/RenderInline.cpp (202535 => 202536)


--- trunk/Source/WebCore/rendering/RenderInline.cpp	2016-06-28 02:47:23 UTC (rev 202535)
+++ trunk/Source/WebCore/rendering/RenderInline.cpp	2016-06-28 02:58:16 UTC (rev 202536)
@@ -1234,8 +1234,8 @@
     if (hitRepaintContainer || !containingBlock)
         return repaintRect;
 
-    if (containingBlock->hasOverflowClip())
-        containingBlock->applyCachedClipAndScrollOffsetForRepaint(repaintRect);
+    if (containingBlock->hasOverflowClip() && containingBlock->shouldApplyClipAndScrollPositionForRepaint(repaintContainer))
+        containingBlock->applyCachedClipAndScrollPositionForRepaint(repaintRect);
 
     repaintRect = containingBlock->computeRectForRepaint(repaintRect, repaintContainer);
 
@@ -1296,7 +1296,7 @@
     // its controlClipRect will be wrong. For overflow clip we use the values cached by the layer.
     adjustedRect.setLocation(topLeft);
     if (container->hasOverflowClip()) {
-        downcast<RenderBox>(*container).applyCachedClipAndScrollOffsetForRepaint(adjustedRect);
+        downcast<RenderBox>(*container).applyCachedClipAndScrollPositionForRepaint(adjustedRect);
         if (adjustedRect.isEmpty())
             return adjustedRect;
     }

Modified: trunk/Source/WebCore/rendering/RenderLayerBacking.cpp (202535 => 202536)


--- trunk/Source/WebCore/rendering/RenderLayerBacking.cpp	2016-06-28 02:47:23 UTC (rev 202535)
+++ trunk/Source/WebCore/rendering/RenderLayerBacking.cpp	2016-06-28 02:58:16 UTC (rev 202536)
@@ -2284,8 +2284,9 @@
         FloatRect layerDirtyRect = pixelSnappedRectForPainting;
         layerDirtyRect.move(-m_scrollingContentsLayer->offsetFromRenderer() + m_devicePixelFractionFromRenderer);
 #if PLATFORM(IOS)
-        // Account for the fact that RenderLayerBacking::updateGeometry() bakes scrollOffset into offsetFromRenderer on iOS.
-        layerDirtyRect.moveBy(-m_owningLayer.scrollOffset() + m_devicePixelFractionFromRenderer);
+        // Account for the fact that RenderLayerBacking::updateGeometry() bakes scrollOffset into offsetFromRenderer on iOS,
+        // but the repaint rect is computed without taking the scroll position into account (see shouldApplyClipAndScrollPositionForRepaint()).
+        layerDirtyRect.moveBy(-m_owningLayer.scrollPosition());
 #endif
         m_scrollingContentsLayer->setNeedsDisplayInRect(layerDirtyRect, shouldClip);
     }

Modified: trunk/Source/WebCore/rendering/RenderObject.cpp (202535 => 202536)


--- trunk/Source/WebCore/rendering/RenderObject.cpp	2016-06-28 02:47:23 UTC (rev 202535)
+++ trunk/Source/WebCore/rendering/RenderObject.cpp	2016-06-28 02:58:16 UTC (rev 202536)
@@ -978,7 +978,7 @@
 
     LayoutRect adjustedRect = rect;
     if (parent->hasOverflowClip()) {
-        downcast<RenderBox>(*parent).applyCachedClipAndScrollOffsetForRepaint(adjustedRect);
+        downcast<RenderBox>(*parent).applyCachedClipAndScrollPositionForRepaint(adjustedRect);
         if (adjustedRect.isEmpty())
             return adjustedRect;
     }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to