Update touch-action region on property changes
authorantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 8 Apr 2019 20:32:53 +0000 (20:32 +0000)
committerantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 8 Apr 2019 20:32:53 +0000 (20:32 +0000)
https://bugs.webkit.org/show_bug.cgi?id=196608

Reviewed by Simon Fraser.

Source/WebCore:

Test: pointerevents/ios/touch-action-region-dynamic.html

* rendering/EventRegion.cpp:
(WebCore::EventRegion::touchActionsForPoint const):

Correctly return 'auto' when nothing is found from the regions (this code is not used yet).

* rendering/RenderElement.cpp:
(WebCore::RenderElement::styleWillChange):

React to 'touch-action' property changes, similarly to 'pointer-events'.

* rendering/RenderLayer.cpp:
(WebCore::RenderLayer::invalidateEventRegion):

Test if need to invalidate.

* rendering/RenderLayerBacking.cpp:
(WebCore::RenderLayerBacking::setContentsNeedDisplay):
(WebCore::RenderLayerBacking::setContentsNeedDisplayInRect):

Call invalidateEventRegion explicitly instead of relying on compositing update. This ensures
that we update the top level event region correctly when we have touch-actions.

LayoutTests:

* pointerevents/ios/touch-action-region-dynamic-expected.txt: Added.
* pointerevents/ios/touch-action-region-dynamic.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@244037 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/pointerevents/ios/touch-action-region-dynamic-expected.txt [new file with mode: 0644]
LayoutTests/pointerevents/ios/touch-action-region-dynamic.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/rendering/EventRegion.cpp
Source/WebCore/rendering/RenderElement.cpp
Source/WebCore/rendering/RenderLayer.cpp
Source/WebCore/rendering/RenderLayerBacking.cpp

index 3a6e520..773d64a 100644 (file)
@@ -1,3 +1,13 @@
+2019-04-08  Antti Koivisto  <antti@apple.com>
+
+        Update touch-action region on property changes
+        https://bugs.webkit.org/show_bug.cgi?id=196608
+
+        Reviewed by Simon Fraser.
+
+        * pointerevents/ios/touch-action-region-dynamic-expected.txt: Added.
+        * pointerevents/ios/touch-action-region-dynamic.html: Added.
+
 2019-04-08  Javier Fernandez  <jfernandez@igalia.com>
 
         Implement white-space:break-spaces value
diff --git a/LayoutTests/pointerevents/ios/touch-action-region-dynamic-expected.txt b/LayoutTests/pointerevents/ios/touch-action-region-dynamic-expected.txt
new file mode 100644 (file)
index 0000000..f5c3ab1
--- /dev/null
@@ -0,0 +1,73 @@
+before
+(GraphicsLayer
+  (anchor 0.00 0.00)
+  (bounds 800.00 600.00)
+  (children 1
+    (GraphicsLayer
+      (bounds 800.00 600.00)
+      (contentsOpaque 1)
+      (drawsContent 1)
+      (backgroundColor #FFFFFF)
+      (event region
+        (rect (0,0) width=800 height=183)
+        (rect (-17,183) width=817 height=100)
+        (rect (0,283) width=800 height=317)
+        (touch-action
+          (none          
+            (rect (83,208) width=25 height=75)
+            (rect (8,283) width=100 height=25)
+          )
+        )
+      )
+    )
+  )
+)
+mutation 1
+(GraphicsLayer
+  (anchor 0.00 0.00)
+  (bounds 800.00 784.00)
+  (children 1
+    (GraphicsLayer
+      (bounds 800.00 784.00)
+      (contentsOpaque 1)
+      (drawsContent 1)
+      (backgroundColor #FFFFFF)
+      (event region
+        (rect (0,0) width=800 height=183)
+        (rect (-17,183) width=817 height=100)
+        (rect (0,283) width=800 height=501)
+        (touch-action
+          (none          
+            (rect (8,8) width=100 height=100)
+            (rect (83,208) width=25 height=75)
+            (rect (8,283) width=100 height=25)
+          )
+        )
+      )
+    )
+  )
+)
+mutation 2
+(GraphicsLayer
+  (anchor 0.00 0.00)
+  (bounds 800.00 1134.00)
+  (children 1
+    (GraphicsLayer
+      (bounds 800.00 1134.00)
+      (contentsOpaque 1)
+      (drawsContent 1)
+      (backgroundColor #FFFFFF)
+      (event region
+        (rect (0,0) width=800 height=1134)
+        (touch-action
+          (none          
+            (rect (8,8) width=100 height=100)
+            (rect (8,208) width=100 height=50)
+            (rect (8,258) width=50 height=50)
+          )
+        )
+      )
+    )
+  )
+)
+
diff --git a/LayoutTests/pointerevents/ios/touch-action-region-dynamic.html b/LayoutTests/pointerevents/ios/touch-action-region-dynamic.html
new file mode 100644 (file)
index 0000000..72ee148
--- /dev/null
@@ -0,0 +1,57 @@
+<html>
+<style>
+.test {
+    width: 200px;
+    height: 200px;
+    position: relative;
+}
+.box {
+    width: 100px;
+    height: 100px;
+    background: green;
+    position: absolute;
+}
+.none {
+    touch-action:none;
+}
+
+.red {
+    background: red;
+}
+</style>
+<script>
+window.onload = function () {
+    if (window.testRunner)
+        testRunner.dumpAsText();
+
+    results.innerText = "before\n";
+
+    if (window.internals)
+        results.innerText += internals.layerTreeAsText(document, internals.LAYER_TREE_INCLUDES_EVENT_REGION | internals.LAYER_TREE_INCLUDES_ROOT_LAYER_PROPERTIES);
+
+    results.innerText += "mutation 1\n";
+    document.body.offsetLeft;
+    mutation1.classList.add("none");
+
+    if (window.internals)
+        results.innerText += internals.layerTreeAsText(document, internals.LAYER_TREE_INCLUDES_EVENT_REGION | internals.LAYER_TREE_INCLUDES_ROOT_LAYER_PROPERTIES);
+
+    results.innerText += "mutation 2\n";
+    document.body.offsetLeft;
+    mutation2.setAttribute("style", "top:50px;left:50px;")
+
+    if (window.internals)
+        results.innerText += internals.layerTreeAsText(document, internals.LAYER_TREE_INCLUDES_EVENT_REGION | internals.LAYER_TREE_INCLUDES_ROOT_LAYER_PROPERTIES);
+}
+</script>
+<body>
+<div class="test">
+    <div id="mutation1" class="box red"></div>
+</div>
+<div class="test">
+    <div class="box red none"></div>
+    <div id="mutation2" class="box" style="top:-25px;left:-25px;"></div>
+</div>
+<pre id="results"></pre>
+</body>
+</html>
index 84febe2..cfda389 100644 (file)
@@ -1,3 +1,34 @@
+2019-04-08  Antti Koivisto  <antti@apple.com>
+
+        Update touch-action region on property changes
+        https://bugs.webkit.org/show_bug.cgi?id=196608
+
+        Reviewed by Simon Fraser.
+
+        Test: pointerevents/ios/touch-action-region-dynamic.html
+
+        * rendering/EventRegion.cpp:
+        (WebCore::EventRegion::touchActionsForPoint const):
+
+        Correctly return 'auto' when nothing is found from the regions (this code is not used yet).
+
+        * rendering/RenderElement.cpp:
+        (WebCore::RenderElement::styleWillChange):
+
+        React to 'touch-action' property changes, similarly to 'pointer-events'.
+
+        * rendering/RenderLayer.cpp:
+        (WebCore::RenderLayer::invalidateEventRegion):
+
+        Test if need to invalidate.
+
+        * rendering/RenderLayerBacking.cpp:
+        (WebCore::RenderLayerBacking::setContentsNeedDisplay):
+        (WebCore::RenderLayerBacking::setContentsNeedDisplayInRect):
+
+        Call invalidateEventRegion explicitly instead of relying on compositing update. This ensures
+        that we update the top level event region correctly when we have touch-actions.
+
 2019-04-08  Javier Fernandez  <jfernandez@igalia.com>
 
         Implement white-space:break-spaces value
index e9c5a9d..878a4e1 100644 (file)
@@ -136,6 +136,9 @@ OptionSet<TouchAction> EventRegion::touchActionsForPoint(const IntPoint& point)
         }
     }
 
+    if (actions.isEmpty())
+        return { TouchAction::Auto };
+
     return actions;
 }
 
index 5ae8e0f..fbce49b 100644 (file)
@@ -730,7 +730,17 @@ void RenderElement::styleWillChange(StyleDifference diff, const RenderStyle& new
             }
         }
 
-        if (m_style.pointerEvents() != newStyle.pointerEvents()) {
+        auto needsInvalidateEventRegion = [&] {
+            if (m_style.pointerEvents() != newStyle.pointerEvents())
+                return true;
+#if ENABLE(POINTER_EVENTS)
+            if (m_style.effectiveTouchActions() != newStyle.effectiveTouchActions())
+                return true;
+#endif
+            return false;
+        };
+
+        if (needsInvalidateEventRegion()) {
             // Usually the event region gets updated as a result of paint invalidation. Here we need to request an update explicitly.
             if (auto* layer = enclosingLayer())
                 layer->invalidateEventRegion();
index b2eb23e..54fc398 100644 (file)
@@ -6685,8 +6685,28 @@ bool RenderLayer::isTransparentOrFullyClippedRespectingParentFrames() const
 
 void RenderLayer::invalidateEventRegion()
 {
-    if (auto* compositingLayer = enclosingCompositingLayerForRepaint())
-        compositingLayer->setNeedsCompositingConfigurationUpdate();
+#if PLATFORM(IOS_FAMILY)
+    auto* compositingLayer = enclosingCompositingLayerForRepaint();
+    if (!compositingLayer)
+        return;
+
+    auto maintainsEventRegion = [&] {
+        // UI side scroll overlap testing.
+        if (!compositingLayer->isRenderViewLayer())
+            return true;
+#if ENABLE(POINTER_EVENTS)
+        // UI side touch-action resolution.
+        if (renderer().document().touchActionElements())
+            return true;
+#endif
+        return false;
+    };
+
+    if (!maintainsEventRegion())
+        return;
+
+    compositingLayer->setNeedsCompositingConfigurationUpdate();
+#endif
 }
 
 TextStream& operator<<(TextStream& ts, const RenderLayer& layer)
index f9c5f6e..2aa27cf 100644 (file)
@@ -2486,6 +2486,8 @@ void RenderLayerBacking::setContentsNeedDisplay(GraphicsLayer::ShouldClipToLayer
     if (!m_owningLayer.isRenderViewLayer())
         m_owningLayer.setNeedsCompositingConfigurationUpdate();
 
+    m_owningLayer.invalidateEventRegion();
+
     auto& frameView = renderer().view().frameView();
     if (m_isMainFrameRenderViewLayer && frameView.isTrackingRepaints())
         frameView.addTrackedRepaintRect(owningLayer().absoluteBoundingBoxForPainting());
@@ -2524,6 +2526,8 @@ void RenderLayerBacking::setContentsNeedDisplayInRect(const LayoutRect& r, Graph
     if (!m_owningLayer.isRenderViewLayer())
         m_owningLayer.setNeedsCompositingConfigurationUpdate();
 
+    m_owningLayer.invalidateEventRegion();
+
     FloatRect pixelSnappedRectForPainting = snapRectToDevicePixels(r, deviceScaleFactor());
     auto& frameView = renderer().view().frameView();
     if (m_isMainFrameRenderViewLayer && frameView.isTrackingRepaints())