Compute accurate regions for touch-action
authorantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 4 Apr 2019 20:28:46 +0000 (20:28 +0000)
committerantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 4 Apr 2019 20:28:46 +0000 (20:28 +0000)
https://bugs.webkit.org/show_bug.cgi?id=196536
<rdar://problem/49516022>

Reviewed by Simon Fraser.

Source/WebCore:

Tests: pointerevents/ios/touch-action-region-basic.html
       pointerevents/ios/touch-action-region-layers.html
       pointerevents/ios/touch-action-region-pan-x-y.html

- Use style system to compute effective touch-action without additional tree walks.
- Compute touch-action region in a fake paint, at the same time with the event region.

This patch doesn't yet use the computed region for anything except test output.

* Sources.txt:
* WebCore.xcodeproj/project.pbxproj:
* css/StyleResolver.cpp:
(WebCore::computeEffectiveTouchActions):
(WebCore::StyleResolver::adjustRenderStyle):

Update RenderStyle::effectiveTouchAction.

* dom/Element.cpp:
(WebCore::Element::computedTouchActions const):

Just get it from the style.

* platform/graphics/GraphicsLayer.cpp:
(WebCore::GraphicsLayer::setEventRegion):
(WebCore::GraphicsLayer::setTouchActionRegion):
(WebCore::GraphicsLayer::dumpProperties const):
* platform/graphics/GraphicsLayer.h:
(WebCore::GraphicsLayer::touchActionRegion const):
* platform/graphics/ca/GraphicsLayerCA.cpp:
(WebCore::GraphicsLayerCA::setTouchActionRegion):
* platform/graphics/ca/GraphicsLayerCA.h:
* rendering/PaintInfo.h:
* rendering/RenderBlock.cpp:
(WebCore::RenderBlock::paintObject):
* rendering/RenderLayer.cpp:
(WebCore::RenderLayer::collectEventRegionForFragments):
* rendering/RenderLayer.h:
* rendering/RenderLayerBacking.cpp:
(WebCore::RenderLayerBacking::updateConfiguration):

Need to do this for the top compositing layer too.

(WebCore::RenderLayerBacking::updateEventRegion):

Compute touch-action region too.
As a basic optimization avoid doing any extra work if there are no elements with non-default touch-action property.

* rendering/TouchActionRegion.cpp: Added.
(WebCore::toIndex):
(WebCore::toTouchAction):
(WebCore::toString):
(WebCore::TouchActionRegion::unite):
(WebCore::TouchActionRegion::actionsForPoint const):
(WebCore::TouchActionRegion::translate):
(WebCore::operator<<):
* rendering/TouchActionRegion.h: Added.

Class for collecting and maintaining touch-action region.

(WebCore::TouchActionRegion::isEmpty const):
(WebCore::TouchActionRegion::operator== const):
* rendering/style/RenderStyle.h:
(WebCore::RenderStyle::effectiveTouchActions const):
(WebCore::RenderStyle::setEffectiveTouchActions):

Implement as inherited property for efficiency (touch-action itself is non-inherited).

* rendering/style/StyleRareInheritedData.cpp:
(WebCore::StyleRareInheritedData::StyleRareInheritedData):
(WebCore::StyleRareInheritedData::operator== const):
* rendering/style/StyleRareInheritedData.h:

LayoutTests:

* pointerevents/ios/touch-action-region-basic-expected.txt: Added.
* pointerevents/ios/touch-action-region-basic.html: Added.
* pointerevents/ios/touch-action-region-layers-expected.txt: Added.
* pointerevents/ios/touch-action-region-layers.html: Added.
* pointerevents/ios/touch-action-region-pan-x-y-expected.txt: Added.
* pointerevents/ios/touch-action-region-pan-x-y.html: Added.

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

27 files changed:
LayoutTests/ChangeLog
LayoutTests/pointerevents/ios/touch-action-region-basic-expected.txt [new file with mode: 0644]
LayoutTests/pointerevents/ios/touch-action-region-basic.html [new file with mode: 0644]
LayoutTests/pointerevents/ios/touch-action-region-layers-expected.txt [new file with mode: 0644]
LayoutTests/pointerevents/ios/touch-action-region-layers.html [new file with mode: 0644]
LayoutTests/pointerevents/ios/touch-action-region-pan-x-y-expected.txt [new file with mode: 0644]
LayoutTests/pointerevents/ios/touch-action-region-pan-x-y.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/Sources.txt
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/css/StyleResolver.cpp
Source/WebCore/dom/Element.cpp
Source/WebCore/platform/TouchAction.h
Source/WebCore/platform/graphics/GraphicsLayer.cpp
Source/WebCore/platform/graphics/GraphicsLayer.h
Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp
Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h
Source/WebCore/rendering/PaintInfo.h
Source/WebCore/rendering/RenderBlock.cpp
Source/WebCore/rendering/RenderLayer.cpp
Source/WebCore/rendering/RenderLayer.h
Source/WebCore/rendering/RenderLayerBacking.cpp
Source/WebCore/rendering/TouchActionRegion.cpp [new file with mode: 0644]
Source/WebCore/rendering/TouchActionRegion.h [new file with mode: 0644]
Source/WebCore/rendering/style/RenderStyle.h
Source/WebCore/rendering/style/StyleRareInheritedData.cpp
Source/WebCore/rendering/style/StyleRareInheritedData.h

index 06065c0..55c4601 100644 (file)
@@ -1,3 +1,18 @@
+2019-04-04  Antti Koivisto  <antti@apple.com>
+
+        Compute accurate regions for touch-action
+        https://bugs.webkit.org/show_bug.cgi?id=196536
+        <rdar://problem/49516022>
+
+        Reviewed by Simon Fraser.
+
+        * pointerevents/ios/touch-action-region-basic-expected.txt: Added.
+        * pointerevents/ios/touch-action-region-basic.html: Added.
+        * pointerevents/ios/touch-action-region-layers-expected.txt: Added.
+        * pointerevents/ios/touch-action-region-layers.html: Added.
+        * pointerevents/ios/touch-action-region-pan-x-y-expected.txt: Added.
+        * pointerevents/ios/touch-action-region-pan-x-y.html: Added.
+
 2019-04-04  Manuel Rego Casasnovas  <rego@igalia.com>
 
         [css-grid] Scroll reset position when updating inner html on content
diff --git a/LayoutTests/pointerevents/ios/touch-action-region-basic-expected.txt b/LayoutTests/pointerevents/ios/touch-action-region-basic-expected.txt
new file mode 100644 (file)
index 0000000..42af6c3
--- /dev/null
@@ -0,0 +1,25 @@
+(GraphicsLayer
+  (anchor 0.00 0.00)
+  (bounds 800.00 621.00)
+  (children 1
+    (GraphicsLayer
+      (bounds 800.00 621.00)
+      (contentsOpaque 1)
+      (drawsContent 1)
+      (backgroundColor #FFFFFF)
+      (event region
+        (rect (0,0) width=800 height=621)
+      )
+      (touch-action region
+        (none        
+          (rect (8,8) width=100 height=100)
+          (rect (8,208) width=200 height=25)
+          (rect (8,233) width=100 height=75)
+          (rect (8,408) width=100 height=50)
+          (rect (8,458) width=50 height=50)
+        )
+      )
+    )
+  )
+)
+
diff --git a/LayoutTests/pointerevents/ios/touch-action-region-basic.html b/LayoutTests/pointerevents/ios/touch-action-region-basic.html
new file mode 100644 (file)
index 0000000..9a9a522
--- /dev/null
@@ -0,0 +1,46 @@
+<html>
+<style>
+.test {
+    width: 200px;
+    height: 200px;
+    position: relative;
+}
+.box {
+    width: 100px;
+    height: 100px;
+    background: green;
+    position: absolute;
+}
+.none {
+    touch-action:none;
+    background: red;
+}
+
+.red {
+    background: red;
+}
+</style>
+<script>
+window.onload = function () {
+    if (window.testRunner)
+        testRunner.dumpAsText();
+    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 class="box none"></div>
+</div>
+<div class="test">
+    <div class="none" style="height:25px;">
+        <div class="box red"></div>
+    </div>
+</div>
+<div class="test">
+    <div class="box none"></div>
+    <div class="box" style="top:50px;left:50px;"></div>
+</div>
+<pre id="results"></pre>
+</body>
+</html>
diff --git a/LayoutTests/pointerevents/ios/touch-action-region-layers-expected.txt b/LayoutTests/pointerevents/ios/touch-action-region-layers-expected.txt
new file mode 100644 (file)
index 0000000..55fef70
--- /dev/null
@@ -0,0 +1,104 @@
+(GraphicsLayer
+  (anchor 0.00 0.00)
+  (bounds 800.00 821.00)
+  (children 1
+    (GraphicsLayer
+      (bounds 800.00 821.00)
+      (contentsOpaque 1)
+      (drawsContent 1)
+      (backgroundColor #FFFFFF)
+      (event region
+        (rect (0,0) width=800 height=821)
+      )
+      (children 5
+        (GraphicsLayer
+          (position 8.00 8.00)
+          (bounds 100.00 100.00)
+          (contentsOpaque 1)
+          (event region
+            (rect (0,0) width=100 height=100)
+          )
+          (touch-action region
+            (none            
+              (rect (0,0) width=100 height=100)
+            )
+          )
+        )
+        (GraphicsLayer
+          (position 8.00 208.00)
+          (bounds 200.00 100.00)
+          (drawsContent 1)
+          (event region
+            (rect (0,0) width=200 height=25)
+            (rect (0,25) width=100 height=75)
+          )
+          (touch-action region
+            (none            
+              (rect (0,0) width=200 height=25)
+              (rect (0,25) width=100 height=75)
+            )
+          )
+        )
+        (GraphicsLayer
+          (position 8.00 408.00)
+          (bounds 100.00 100.00)
+          (contentsOpaque 1)
+          (event region
+            (rect (0,0) width=100 height=100)
+          )
+          (touch-action region
+            (none            
+              (rect (0,0) width=100 height=100)
+            )
+          )
+        )
+        (GraphicsLayer
+          (position 58.00 458.00)
+          (bounds 100.00 100.00)
+          (contentsOpaque 1)
+          (event region
+            (rect (0,0) width=100 height=100)
+          )
+        )
+        (GraphicsLayer
+          (position 8.00 608.00)
+          (bounds 150.00 150.00)
+          (opacity 0.90)
+          (drawsContent 1)
+          (event region
+            (rect (0,0) width=100 height=50)
+            (rect (0,50) width=150 height=50)
+            (rect (50,100) width=100 height=50)
+          )
+          (touch-action region
+            (none            
+              (rect (0,0) width=100 height=50)
+              (rect (0,50) width=150 height=50)
+              (rect (50,100) width=100 height=50)
+            )
+          )
+          (children 2
+            (GraphicsLayer
+              (bounds 150.00 150.00)
+              (drawsContent 1)
+            )
+            (GraphicsLayer
+              (position 25.00 25.00)
+              (bounds 100.00 100.00)
+              (contentsOpaque 1)
+              (event region
+                (rect (0,0) width=100 height=100)
+              )
+              (touch-action region
+                (none                
+                  (rect (0,0) width=100 height=100)
+                )
+              )
+            )
+          )
+        )
+      )
+    )
+  )
+)
+
diff --git a/LayoutTests/pointerevents/ios/touch-action-region-layers.html b/LayoutTests/pointerevents/ios/touch-action-region-layers.html
new file mode 100644 (file)
index 0000000..d2fb179
--- /dev/null
@@ -0,0 +1,54 @@
+<html>
+<style>
+.test {
+    width: 200px;
+    height: 200px;
+    position: relative;
+}
+.box {
+    width: 100px;
+    height: 100px;
+    background: green;
+    position: absolute;
+}
+.layer {
+    will-change:transform;
+}
+.none {
+    touch-action:none;
+    background: red;
+}
+.red {
+    background: red;
+}
+</style>
+<script>
+window.onload = function () {
+    if (window.testRunner)
+        testRunner.dumpAsText();
+    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 class="box layer none"></div>
+</div>
+<div class="test">
+    <div class="none layer" style="height:25px;">
+        <div class="box red"></div>
+    </div>
+</div>
+<div class="test">
+    <div class="box none layer"></div>
+    <div class="box" style="top:50px;left:50px;"></div>
+</div>
+<div class="test">
+    <div class="box none" style="opacity:0.9">
+        <div class="box layer" style="top:25px;left:25px;"></div>
+        <div class="box" style="z-index:-1;top:50px;left:50px;"></div>
+    </div>
+</div>
+<pre id="results"></pre>
+</body>
+</html>
diff --git a/LayoutTests/pointerevents/ios/touch-action-region-pan-x-y-expected.txt b/LayoutTests/pointerevents/ios/touch-action-region-pan-x-y-expected.txt
new file mode 100644 (file)
index 0000000..fad2c56
--- /dev/null
@@ -0,0 +1,34 @@
+(GraphicsLayer
+  (anchor 0.00 0.00)
+  (bounds 800.00 1021.00)
+  (children 1
+    (GraphicsLayer
+      (bounds 800.00 1021.00)
+      (contentsOpaque 1)
+      (drawsContent 1)
+      (backgroundColor #FFFFFF)
+      (event region
+        (rect (0,0) width=800 height=1021)
+      )
+      (touch-action region
+        (none        
+          (rect (8,808) width=100 height=100)
+        )
+        (pan-x        
+          (rect (8,8) width=100 height=100)
+          (rect (8,208) width=200 height=25)
+          (rect (8,233) width=100 height=75)
+          (rect (108,408) width=100 height=25)
+          (rect (8,608) width=200 height=25)
+          (rect (8,633) width=100 height=75)
+          (rect (108,808) width=100 height=25)
+        )
+        (pan-y        
+          (rect (8,408) width=200 height=25)
+          (rect (8,433) width=100 height=75)
+        )
+      )
+    )
+  )
+)
+
diff --git a/LayoutTests/pointerevents/ios/touch-action-region-pan-x-y.html b/LayoutTests/pointerevents/ios/touch-action-region-pan-x-y.html
new file mode 100644 (file)
index 0000000..b0c8822
--- /dev/null
@@ -0,0 +1,62 @@
+<html>
+<style>
+.test {
+    width: 200px;
+    height: 200px;
+    position: relative;
+}
+.box {
+    width: 100px;
+    height: 100px;
+    background: green;
+    position: absolute;
+}
+.pan-x {
+    touch-action:pan-x;
+    background: green;
+}
+
+.pan-y {
+    touch-action:pan-y;
+    background: blue;
+}
+.pan-x-y {
+    touch-action:pan-x pan-y;
+    background: blue;
+}
+</style>
+<script>
+window.onload = function () {
+    if (window.testRunner)
+        testRunner.dumpAsText();
+    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 class="box pan-x"></div>
+</div>
+<div class="test">
+    <div class="pan-x" style="height:25px;">
+        <div class="box pan-x"></div>
+    </div>
+</div>
+<div class="test">
+    <div class="pan-x-y" style="height:25px;">
+        <div class="box pan-y"></div>
+    </div>
+</div>
+<div class="test">
+    <div class="pan-x" style="height:25px;">
+        <div class="box pan-x-y"></div>
+    </div>
+</div>
+<div class="test">
+    <div class="pan-x" style="height:25px;">
+        <div class="box pan-y"></div>
+    </div>
+</div>
+<pre id="results"></pre>
+</body>
+</html>
index ad8ef38..b4ac7f1 100644 (file)
@@ -1,3 +1,83 @@
+2019-04-04  Antti Koivisto  <antti@apple.com>
+
+        Compute accurate regions for touch-action
+        https://bugs.webkit.org/show_bug.cgi?id=196536
+        <rdar://problem/49516022>
+
+        Reviewed by Simon Fraser.
+
+        Tests: pointerevents/ios/touch-action-region-basic.html
+               pointerevents/ios/touch-action-region-layers.html
+               pointerevents/ios/touch-action-region-pan-x-y.html
+
+        - Use style system to compute effective touch-action without additional tree walks.
+        - Compute touch-action region in a fake paint, at the same time with the event region.
+
+        This patch doesn't yet use the computed region for anything except test output.
+
+        * Sources.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * css/StyleResolver.cpp:
+        (WebCore::computeEffectiveTouchActions):
+        (WebCore::StyleResolver::adjustRenderStyle):
+
+        Update RenderStyle::effectiveTouchAction.
+
+        * dom/Element.cpp:
+        (WebCore::Element::computedTouchActions const):
+
+        Just get it from the style.
+
+        * platform/graphics/GraphicsLayer.cpp:
+        (WebCore::GraphicsLayer::setEventRegion):
+        (WebCore::GraphicsLayer::setTouchActionRegion):
+        (WebCore::GraphicsLayer::dumpProperties const):
+        * platform/graphics/GraphicsLayer.h:
+        (WebCore::GraphicsLayer::touchActionRegion const):
+        * platform/graphics/ca/GraphicsLayerCA.cpp:
+        (WebCore::GraphicsLayerCA::setTouchActionRegion):
+        * platform/graphics/ca/GraphicsLayerCA.h:
+        * rendering/PaintInfo.h:
+        * rendering/RenderBlock.cpp:
+        (WebCore::RenderBlock::paintObject):
+        * rendering/RenderLayer.cpp:
+        (WebCore::RenderLayer::collectEventRegionForFragments):
+        * rendering/RenderLayer.h:
+        * rendering/RenderLayerBacking.cpp:
+        (WebCore::RenderLayerBacking::updateConfiguration):
+
+        Need to do this for the top compositing layer too.
+
+        (WebCore::RenderLayerBacking::updateEventRegion):
+
+        Compute touch-action region too.
+        As a basic optimization avoid doing any extra work if there are no elements with non-default touch-action property.
+
+        * rendering/TouchActionRegion.cpp: Added.
+        (WebCore::toIndex):
+        (WebCore::toTouchAction):
+        (WebCore::toString):
+        (WebCore::TouchActionRegion::unite):
+        (WebCore::TouchActionRegion::actionsForPoint const):
+        (WebCore::TouchActionRegion::translate):
+        (WebCore::operator<<):
+        * rendering/TouchActionRegion.h: Added.
+
+        Class for collecting and maintaining touch-action region.
+
+        (WebCore::TouchActionRegion::isEmpty const):
+        (WebCore::TouchActionRegion::operator== const):
+        * rendering/style/RenderStyle.h:
+        (WebCore::RenderStyle::effectiveTouchActions const):
+        (WebCore::RenderStyle::setEffectiveTouchActions):
+
+        Implement as inherited property for efficiency (touch-action itself is non-inherited).
+
+        * rendering/style/StyleRareInheritedData.cpp:
+        (WebCore::StyleRareInheritedData::StyleRareInheritedData):
+        (WebCore::StyleRareInheritedData::operator== const):
+        * rendering/style/StyleRareInheritedData.h:
+
 2019-04-04  Yusuke Suzuki  <ysuzuki@apple.com>
 
         Unreviewed, fix linking error because the build of RTCIceTransport.cpp is handled in Xcode project side accidentally
index 325707b..3334e4a 100644 (file)
@@ -2068,6 +2068,7 @@ rendering/SimpleLineLayoutTextFragmentIterator.cpp
 rendering/TextDecorationPainter.cpp
 rendering/TextPaintStyle.cpp
 rendering/TextPainter.cpp
+rendering/TouchActionRegion.cpp
 rendering/TrailingFloatsRootInlineBox.cpp
 
 rendering/line/LineBreaker.cpp
index 4deaf20..5d7b3de 100644 (file)
                E4A814D41C6DEC4000BF85AC /* ClassChangeInvalidation.h in Headers */ = {isa = PBXBuildFile; fileRef = E4A814D31C6DEC4000BF85AC /* ClassChangeInvalidation.h */; };
                E4A814DA1C70E10D00BF85AC /* AttributeChangeInvalidation.h in Headers */ = {isa = PBXBuildFile; fileRef = E4A814D91C70E10D00BF85AC /* AttributeChangeInvalidation.h */; };
                E4A814E01C7338EB00BF85AC /* IdChangeInvalidation.h in Headers */ = {isa = PBXBuildFile; fileRef = E4A814DF1C7338EB00BF85AC /* IdChangeInvalidation.h */; };
+               E4A8D21022538FD200A8463C /* TouchActionRegion.h in Headers */ = {isa = PBXBuildFile; fileRef = E4A8D20F22538FD100A8463C /* TouchActionRegion.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E4AE7C1617D1BB950009FB31 /* ElementIterator.h in Headers */ = {isa = PBXBuildFile; fileRef = E4AE7C1517D1BB950009FB31 /* ElementIterator.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E4AE7C1A17D232350009FB31 /* ElementAncestorIterator.h in Headers */ = {isa = PBXBuildFile; fileRef = E4AE7C1917D232350009FB31 /* ElementAncestorIterator.h */; settings = {ATTRIBUTES = (Private, ); }; };
                E4AFCFA50DAF29A300F5F55C /* UnitBezier.h in Headers */ = {isa = PBXBuildFile; fileRef = E4AFCFA40DAF29A300F5F55C /* UnitBezier.h */; };
                E4A814D91C70E10D00BF85AC /* AttributeChangeInvalidation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AttributeChangeInvalidation.h; sourceTree = "<group>"; };
                E4A814DD1C7338D100BF85AC /* IdChangeInvalidation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IdChangeInvalidation.cpp; sourceTree = "<group>"; };
                E4A814DF1C7338EB00BF85AC /* IdChangeInvalidation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IdChangeInvalidation.h; sourceTree = "<group>"; };
+               E4A8D20C22538FC700A8463C /* TouchActionRegion.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TouchActionRegion.cpp; sourceTree = "<group>"; };
+               E4A8D20F22538FD100A8463C /* TouchActionRegion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TouchActionRegion.h; sourceTree = "<group>"; };
                E4AE7C1517D1BB950009FB31 /* ElementIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ElementIterator.h; sourceTree = "<group>"; };
                E4AE7C1917D232350009FB31 /* ElementAncestorIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ElementAncestorIterator.h; sourceTree = "<group>"; };
                E4AFCFA40DAF29A300F5F55C /* UnitBezier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnitBezier.h; sourceTree = "<group>"; };
                                1C18DA57181AF6A500C4EF22 /* TextPainter.h */,
                                E4C91A0F1802343900A17F6D /* TextPaintStyle.cpp */,
                                E4C91A0D1802343100A17F6D /* TextPaintStyle.h */,
+                               E4A8D20C22538FC700A8463C /* TouchActionRegion.cpp */,
+                               E4A8D20F22538FD100A8463C /* TouchActionRegion.h */,
                                1100FC6E1FDB3C4D00DD961B /* TrailingFloatsRootInlineBox.cpp */,
                                37FC96DA1104ED71003E1FAD /* TrailingFloatsRootInlineBox.h */,
                                BCA257141293C010007A263D /* VerticalPositionCache.h */,
                                FDA15EA812B03EE1003A583A /* JSAudioDestinationNode.h in Headers */,
                                FDA15EAE12B03EE1003A583A /* JSAudioListener.h in Headers */,
                                FDA15EB012B03EE1003A583A /* JSAudioNode.h in Headers */,
+                               E4A8D21022538FD200A8463C /* TouchActionRegion.h in Headers */,
                                FDA15EB412B03EE1003A583A /* JSAudioParam.h in Headers */,
                                FDA15EB612B03EE1003A583A /* JSAudioProcessingEvent.h in Headers */,
                                BE8EF043171C8FF9009B48C3 /* JSAudioTrack.h in Headers */,
index 999d40e..ae51e2c 100644 (file)
@@ -745,7 +745,7 @@ static bool doesNotInheritTextDecoration(const RenderStyle& style, const Element
         || style.isFloating() || style.hasOutOfFlowPosition();
 }
 
-#if ENABLE(OVERFLOW_SCROLLING_TOUCH)
+#if ENABLE(OVERFLOW_SCROLLING_TOUCH) || ENABLE(POINTER_EVENTS)
 static bool isScrollableOverflow(Overflow overflow)
 {
     return overflow == Overflow::Scroll || overflow == Overflow::Auto;
@@ -842,6 +842,36 @@ void StyleResolver::adjustSVGElementStyle(const SVGElement& svgElement, RenderSt
         style.setDisplay(DisplayType::Block);
 }
 
+#if ENABLE(POINTER_EVENTS)
+static OptionSet<TouchAction> computeEffectiveTouchActions(const RenderStyle& style, OptionSet<TouchAction> effectiveTouchActions)
+{
+    // https://w3c.github.io/pointerevents/#determining-supported-touch-behavior
+    // "A touch behavior is supported if it conforms to the touch-action property of each element between
+    // the hit tested element and its nearest ancestor with the default touch behavior (including both the
+    // hit tested element and the element with the default touch behavior)."
+
+    bool hasDefaultTouchBehavior = isScrollableOverflow(style.overflowX()) || isScrollableOverflow(style.overflowY());
+    if (hasDefaultTouchBehavior)
+        effectiveTouchActions = RenderStyle::initialTouchActions();
+
+    auto touchActions = style.touchActions();
+    if (touchActions == RenderStyle::initialTouchActions())
+        return effectiveTouchActions;
+
+    if (effectiveTouchActions.contains(TouchAction::None))
+        return { TouchAction::None };
+
+    if (effectiveTouchActions.contains(TouchAction::Auto) || effectiveTouchActions.contains(TouchAction::Manipulation))
+        return touchActions;
+
+    auto sharedTouchActions = effectiveTouchActions & touchActions;
+    if (sharedTouchActions.isEmpty())
+        return { TouchAction::None };
+
+    return sharedTouchActions;
+}
+#endif
+
 void StyleResolver::adjustRenderStyle(RenderStyle& style, const RenderStyle& parentStyle, const RenderStyle* parentBoxStyle, const Element* element)
 {
     // If the composed tree parent has display:contents, the parent box style will be different from the parent style.
@@ -1087,6 +1117,10 @@ void StyleResolver::adjustRenderStyle(RenderStyle& style, const RenderStyle& par
     // 'center'), 'legacy' computes to the the inherited value. Otherwise, 'auto' computes to 'normal'.
     if (parentBoxStyle->justifyItems().positionType() == ItemPositionType::Legacy && style.justifyItems().position() == ItemPosition::Legacy)
         style.setJustifyItems(parentBoxStyle->justifyItems());
+
+#if ENABLE(POINTER_EVENTS)
+    style.setEffectiveTouchActions(computeEffectiveTouchActions(style, parentStyle.effectiveTouchActions()));
+#endif
 }
 
 static void checkForOrientationChange(RenderStyle* style)
index 1930432..79f086c 100644 (file)
@@ -4219,44 +4219,10 @@ void Element::setAttributeStyleMap(Ref<StylePropertyMap>&& map)
 #if ENABLE(POINTER_EVENTS)
 OptionSet<TouchAction> Element::computedTouchActions() const
 {
-    OptionSet<TouchAction> computedTouchActions = TouchAction::Auto;
-    for (auto* element = this; element; element = parentCrossingFrameBoundaries(element)) {
-        auto* renderer = element->renderer();
-        if (!renderer)
-            continue;
-
-        auto touchActions = renderer->style().touchActions();
-
-        // Once we've encountered touch-action: none, we know that this will be the computed value.
-        if (touchActions == TouchAction::None)
-            return touchActions;
-
-        // If the computed touch-action so far was "auto", we can just use the current element's touch-action.
-        if (computedTouchActions == TouchAction::Auto) {
-            computedTouchActions = touchActions;
-            continue;
-        }
-
-        // If the current element has touch-action: auto or the same touch-action as the computed touch-action,
-        // we need to keep going up the ancestry chain.
-        if (touchActions == TouchAction::Auto || touchActions == computedTouchActions)
-            continue;
-
-        // Now, the element's touch-action and the computed touch-action are different and are neither "auto" nor "none".
-        if (computedTouchActions == TouchAction::Manipulation) {
-            // If the computed touch-action is "manipulation", we can take the current element's touch-action as the newly
-            // computed touch-action.
-            computedTouchActions = touchActions;
-        } else if (touchActions == TouchAction::Manipulation) {
-            // Otherwise, we have a restricted computed touch-action so far. If the current element's touch-action is "manipulation"
-            // then we can just keep going and leave the computed touch-action untouched.
-            continue;
-        }
+    if (auto* style = renderOrDisplayContentsStyle())
+        return style->effectiveTouchActions();
 
-        // In any other case, we have competing restrictive touch-action values that can only yield "none".
-        return TouchAction::None;
-    }
-    return computedTouchActions;
+    return TouchAction::Auto;
 }
 
 #if ENABLE(OVERFLOW_SCROLLING_TOUCH)
index 6d0db53..2545478 100644 (file)
@@ -27,6 +27,8 @@
 
 #if ENABLE(POINTER_EVENTS)
 
+#include <wtf/text/TextStream.h>
+
 namespace WebCore {
 
 enum class TouchAction : uint8_t {
@@ -38,6 +40,8 @@ enum class TouchAction : uint8_t {
     PinchZoom    = 1 << 5,
 };
 
+TextStream& operator<<(TextStream&, TouchAction);
+
 }
 
 #endif // ENABLE(POINTER_EVENTS)
index 602d54d..1504ea3 100644 (file)
@@ -413,9 +413,16 @@ void GraphicsLayer::setShapeLayerWindRule(WindRule windRule)
 
 void GraphicsLayer::setEventRegion(Region&& eventRegion)
 {
-    m_eventRegion = eventRegion;
+    m_eventRegion = WTFMove(eventRegion);
 }
 
+#if ENABLE(POINTER_EVENTS)
+void GraphicsLayer::setTouchActionRegion(TouchActionRegion&& touchActionRegion)
+{
+    m_touchActionRegion = WTFMove(touchActionRegion);
+}
+#endif
+
 void GraphicsLayer::noteDeviceOrPageScaleFactorChangedIncludingDescendants()
 {
     deviceOrPageScaleFactorChanged();
@@ -926,8 +933,14 @@ void GraphicsLayer::dumpProperties(TextStream& ts, LayerTreeAsTextBehavior behav
         ts << indent << ")\n";
     }
 
-    if (behavior & LayerTreeAsTextIncludeEventRegion && !m_eventRegion.isEmpty())
-        ts << indent << "(event region" << m_eventRegion << ")\n";
+    if (behavior & LayerTreeAsTextIncludeEventRegion) {
+        if (!m_eventRegion.isEmpty())
+            ts << indent << "(event region" << m_eventRegion << ")\n";
+#if ENABLE(POINTER_EVENTS)
+        if (!m_touchActionRegion.isEmpty())
+            ts << indent << "(touch-action region" << m_touchActionRegion << ")\n";
+#endif
+    }
 
     if (behavior & LayerTreeAsTextIncludePaintingPhases && paintingPhase()) {
         ts << indent << "(paintingPhases\n";
index da9ac33..ba6c7a0 100644 (file)
@@ -37,6 +37,7 @@
 #include "PlatformLayer.h"
 #include "Region.h"
 #include "ScrollableArea.h"
+#include "TouchActionRegion.h"
 #include "TransformOperations.h"
 #include "WindRule.h"
 #include <wtf/Function.h>
@@ -455,7 +456,10 @@ public:
 
     const Region& eventRegion() const { return m_eventRegion; }
     virtual void setEventRegion(Region&&);
-
+#if ENABLE(POINTER_EVENTS)
+    const TouchActionRegion& touchActionRegion() const { return m_touchActionRegion; }
+    virtual void setTouchActionRegion(TouchActionRegion&&);
+#endif
     // Transitions are identified by a special animation name that cannot clash with a keyframe identifier.
     static String animationNameForTransition(AnimatedPropertyID);
 
@@ -731,7 +735,9 @@ protected:
     Optional<FloatRect> m_animationExtent;
 
     Region m_eventRegion;
-
+#if ENABLE(POINTER_EVENTS)
+    TouchActionRegion m_touchActionRegion;
+#endif
 #if USE(CA)
     WindRule m_shapeLayerWindRule { WindRule::NonZero };
     Path m_shapeLayerPath;
index 5f6744e..670e81e 100644 (file)
@@ -993,6 +993,17 @@ void GraphicsLayerCA::setEventRegion(Region&& eventRegion)
     noteLayerPropertyChanged(EventRegionChanged, m_isCommittingChanges ? DontScheduleFlush : ScheduleFlush);
 }
 
+#if ENABLE(POINTER_EVENTS)
+void GraphicsLayerCA::setTouchActionRegion(TouchActionRegion&& touchActionRegion)
+{
+    if (touchActionRegion == m_touchActionRegion)
+        return;
+
+    GraphicsLayer::setTouchActionRegion(WTFMove(touchActionRegion));
+    // FIXME: Invalidate and pass to platform layer.
+}
+#endif
+
 bool GraphicsLayerCA::shouldRepaintOnSizeChange() const
 {
     return drawsContent() && !tiledBacking();
index dff55c2..3fe5e7e 100644 (file)
@@ -125,7 +125,9 @@ public:
     WEBCORE_EXPORT void setShapeLayerWindRule(WindRule) override;
 
     WEBCORE_EXPORT void setEventRegion(Region&&) override;
-
+#if ENABLE(POINTER_EVENTS)
+    WEBCORE_EXPORT void setTouchActionRegion(TouchActionRegion&&) override;
+#endif
     WEBCORE_EXPORT void suspendAnimations(MonotonicTime) override;
     WEBCORE_EXPORT void resumeAnimations() override;
 
index 52f4165..81e3868 100644 (file)
@@ -44,6 +44,10 @@ class RenderLayer;
 class RenderLayerModelObject;
 class RenderObject;
 
+#if ENABLE(POINTER_EVENTS)
+class TouchActionRegion;
+#endif
+    
 typedef HashMap<OverlapTestRequestClient*, IntRect> OverlapTestRequestMap;
 
 /*
@@ -131,7 +135,9 @@ struct PaintInfo {
     bool requireSecurityOriginAccessForWidgets { false };
     const RenderLayer* m_enclosingSelfPaintingLayer { nullptr };
     Region* eventRegion { nullptr }; // For PaintPhase::EventRegion.
-
+#if ENABLE(POINTER_EVENTS)
+    TouchActionRegion* touchActionRegion { nullptr };
+#endif
 private:
     GraphicsContext* m_context;
 };
index 96f85f5..ca3048f 100644 (file)
@@ -70,6 +70,7 @@
 #include "Settings.h"
 #include "ShadowRoot.h"
 #include "ShapeOutsideInfo.h"
+#include "TouchActionRegion.h"
 #include "TransformState.h"
 #include <wtf/IsoMallocInlines.h>
 #include <wtf/NeverDestroyed.h>
@@ -1246,10 +1247,18 @@ void RenderBlock::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffs
         if (visibleToHitTesting()) {
             auto borderRegion = approximateAsRegion(style().getRoundedBorderFor(borderRect));
             paintInfo.eventRegion->unite(borderRegion);
+#if ENABLE(POINTER_EVENTS)
+            if (paintInfo.touchActionRegion)
+                paintInfo.touchActionRegion->unite(borderRegion, style().effectiveTouchActions());
+#endif
         }
 
         // No need to check descendants if we don't have overflow and the area is already covered.
-        if (!hasVisualOverflow() && paintInfo.eventRegion->contains(enclosingIntRect(borderRect)))
+        bool needsTraverseDescendants = hasVisualOverflow() || !paintInfo.eventRegion->contains(enclosingIntRect(borderRect));
+#if ENABLE(POINTER_EVENTS)
+        needsTraverseDescendants = needsTraverseDescendants || paintInfo.touchActionRegion;
+#endif
+        if (!needsTraverseDescendants)
             return;
     }
 
index e0107d8..30dc249 100644 (file)
@@ -4870,6 +4870,9 @@ void RenderLayer::collectEventRegionForFragments(const LayerFragments& layerFrag
     for (const auto& fragment : layerFragments) {
         PaintInfo paintInfo(context, fragment.foregroundRect.rect(), PaintPhase::EventRegion, { });
         paintInfo.eventRegion = localPaintingInfo.eventRegion;
+#if ENABLE(POINTER_EVENTS)
+        paintInfo.touchActionRegion = localPaintingInfo.touchActionRegion;
+#endif
         renderer().paint(paintInfo, toLayoutPoint(fragment.layerBounds.location() - renderBoxLocation() + localPaintingInfo.subpixelOffset));
     }
 }
index 7069c83..a469dc8 100644 (file)
@@ -80,6 +80,10 @@ class RenderView;
 class Scrollbar;
 class TransformationMatrix;
 
+#if ENABLE(POINTER_EVENTS)
+class TouchActionRegion;
+#endif
+
 enum BorderRadiusClippingRule { IncludeSelfForBorderRadius, DoNotIncludeSelfForBorderRadius };
 enum IncludeSelfOrNot { IncludeSelf, ExcludeSelf };
 
@@ -914,6 +918,9 @@ private:
         bool requireSecurityOriginAccessForWidgets;
         bool clipToDirtyRect { true };
         Region* eventRegion { nullptr };
+#if ENABLE(POINTER_EVENTS)
+        TouchActionRegion* touchActionRegion { nullptr };
+#endif
     };
 
     // Compute, cache and return clip rects computed with the given layer as the root.
index a90abdd..5e2f1f8 100644 (file)
@@ -765,10 +765,10 @@ bool RenderLayerBacking::updateConfiguration()
     if (!m_owningLayer.isRenderViewLayer()) {
         bool didUpdateContentsRect = false;
         updateDirectlyCompositedBoxDecorations(contentsInfo, didUpdateContentsRect);
-
-        updateEventRegion();
     } else
         updateRootLayerConfiguration();
+
+    updateEventRegion();
     
     // Requires layout.
     if (contentsInfo.isDirectlyCompositedImage())
@@ -1439,18 +1439,36 @@ void RenderLayerBacking::updateEventRegion()
     if (paintsIntoCompositedAncestor())
         return;
 
+    bool hasTouchActionElements = false;
+#if ENABLE(POINTER_EVENTS)
+    hasTouchActionElements = !!renderer().document().touchActionElements();
+#endif
+    if (m_owningLayer.isRenderViewLayer() && !hasTouchActionElements)
+        return;
+
     GraphicsContext nullContext(nullptr);
     RenderLayer::LayerPaintingInfo paintingInfo(&m_owningLayer, compositedBounds(), { }, LayoutSize());
 
     Region eventRegion;
     paintingInfo.eventRegion = &eventRegion;
 
+#if ENABLE(POINTER_EVENTS)
+    TouchActionRegion touchActionRegion;
+    if (hasTouchActionElements)
+        paintingInfo.touchActionRegion = &touchActionRegion;
+#endif
+
     auto paintFlags = RenderLayer::paintLayerPaintingCompositingAllPhasesFlags() | RenderLayer::PaintLayerCollectingEventRegion;
     m_owningLayer.paintLayerContents(nullContext, paintingInfo, paintFlags);
 
-    eventRegion.translate(roundedIntSize(contentOffsetInCompositingLayer()));
-
+    auto contentOffset = roundedIntSize(contentOffsetInCompositingLayer());
+    eventRegion.translate(contentOffset);
     m_graphicsLayer->setEventRegion(WTFMove(eventRegion));
+
+#if ENABLE(POINTER_EVENTS)
+    touchActionRegion.translate(contentOffset);
+    m_graphicsLayer->setTouchActionRegion(WTFMove(touchActionRegion));
+#endif
 #endif
 }
 
diff --git a/Source/WebCore/rendering/TouchActionRegion.cpp b/Source/WebCore/rendering/TouchActionRegion.cpp
new file mode 100644 (file)
index 0000000..c185b58
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "TouchActionRegion.h"
+
+#if ENABLE(POINTER_EVENTS)
+
+namespace WebCore {
+
+constexpr unsigned toIndex(TouchAction touchAction)
+{
+    switch (touchAction) {
+    case TouchAction::None:
+        return 0;
+    case TouchAction::Manipulation:
+        return 1;
+    case TouchAction::PanX:
+        return 2;
+    case TouchAction::PanY:
+        return 3;
+    case TouchAction::PinchZoom:
+        return 4;
+    case TouchAction::Auto:
+        break;
+    }
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
+constexpr TouchAction toTouchAction(unsigned index)
+{
+    switch (index) {
+    case 0:
+        return TouchAction::None;
+    case 1:
+        return TouchAction::Manipulation;
+    case 2:
+        return TouchAction::PanX;
+    case 3:
+        return TouchAction::PanY;
+    case 4:
+        return TouchAction::PinchZoom;
+    default:
+        break;
+    }
+    ASSERT_NOT_REACHED();
+    return TouchAction::Auto;
+}
+
+TouchActionRegion::TouchActionRegion() = default;
+
+void TouchActionRegion::unite(const Region& touchRegion, OptionSet<TouchAction> touchActions)
+{
+    for (auto touchAction : touchActions) {
+        if (touchAction == TouchAction::Auto)
+            break;
+        auto index = toIndex(touchAction);
+        if (m_regions.size() < index + 1)
+            m_regions.grow(index + 1);
+    }
+
+    for (unsigned i = 0; i < m_regions.size(); ++i) {
+        auto regionTouchAction = toTouchAction(i);
+        if (touchActions.contains(regionTouchAction))
+            m_regions[i].unite(touchRegion);
+        else
+            m_regions[i].subtract(touchRegion);
+    }
+}
+
+OptionSet<TouchAction> TouchActionRegion::actionsForPoint(const IntPoint& point) const
+{
+    OptionSet<TouchAction> actions;
+
+    for (unsigned i = 0; i < m_regions.size(); ++i) {
+        if (m_regions[i].contains(point)) {
+            auto action = toTouchAction(i);
+            actions.add(action);
+            if (action == TouchAction::None || action == TouchAction::Manipulation)
+                break;
+        }
+    }
+
+    return actions;
+}
+
+void TouchActionRegion::translate(const IntSize& offset)
+{
+    for (auto& region : m_regions)
+        region.translate(offset);
+}
+
+TextStream& operator<<(TextStream& ts, TouchAction touchAction)
+{
+    switch (touchAction) {
+    case TouchAction::None:
+        return ts << "none";
+    case TouchAction::Manipulation:
+        return ts << "manipulation";
+    case TouchAction::PanX:
+        return ts << "pan-x";
+    case TouchAction::PanY:
+        return ts << "pan-y";
+    case TouchAction::PinchZoom:
+        return ts << "pinch-zoom";
+    case TouchAction::Auto:
+        return ts << "auto";
+    }
+    ASSERT_NOT_REACHED();
+    return ts;
+}
+
+TextStream& operator<<(TextStream& ts, const TouchActionRegion& touchActionRegion)
+{
+    ts << "\n";
+    {
+        for (unsigned i = 0; i < touchActionRegion.m_regions.size(); ++i) {
+            if (touchActionRegion.m_regions[i].isEmpty())
+                continue;
+            TextStream::IndentScope indentScope(ts);
+            ts << indent << "(" << toTouchAction(i);
+            ts << indent << touchActionRegion.m_regions[i] << ")\n";
+        }
+    }
+    ts << indent;
+
+    return ts;
+}
+
+}
+
+#endif
diff --git a/Source/WebCore/rendering/TouchActionRegion.h b/Source/WebCore/rendering/TouchActionRegion.h
new file mode 100644 (file)
index 0000000..537e981
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(POINTER_EVENTS)
+
+#include "Region.h"
+#include "TouchAction.h"
+#include <wtf/OptionSet.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class TouchActionRegion {
+public:
+    WEBCORE_EXPORT TouchActionRegion();
+
+    bool isEmpty() const { return m_regions.isEmpty(); }
+
+    bool operator==(const TouchActionRegion& other) const { return m_regions == other.m_regions; }
+
+    WEBCORE_EXPORT void unite(const Region&, OptionSet<TouchAction>);
+    WEBCORE_EXPORT OptionSet<TouchAction> actionsForPoint(const IntPoint&) const;
+    WEBCORE_EXPORT void translate(const IntSize&);
+
+private:
+    friend TextStream& operator<<(TextStream&, const TouchActionRegion&);
+
+    Vector<Region> m_regions;
+};
+
+TextStream& operator<<(TextStream&, const TouchActionRegion&);
+
+}
+
+#endif
index f125c73..d493ece 100644 (file)
@@ -706,6 +706,8 @@ public:
 
 #if ENABLE(POINTER_EVENTS)
     OptionSet<TouchAction> touchActions() const { return OptionSet<TouchAction>::fromRaw(m_rareNonInheritedData->touchActions); }
+    // 'touch-action' behavior depends on values in ancestors. We use an additional inherited property to implement that.
+    OptionSet<TouchAction> effectiveTouchActions() const { return OptionSet<TouchAction>::fromRaw(m_rareInheritedData->effectiveTouchActions); }
 #endif
 
 #if ENABLE(CSS_SCROLL_SNAP)
@@ -1225,6 +1227,7 @@ public:
     
 #if ENABLE(POINTER_EVENTS)
     void setTouchActions(OptionSet<TouchAction> touchActions) { SET_VAR(m_rareNonInheritedData, touchActions, touchActions.toRaw()); }
+    void setEffectiveTouchActions(OptionSet<TouchAction> touchActions) { SET_VAR(m_rareInheritedData, effectiveTouchActions, touchActions.toRaw()); }
 #endif
 
 #if ENABLE(CSS_SCROLL_SNAP)
index 38a3db1..e9b0cb8 100644 (file)
@@ -137,6 +137,9 @@ StyleRareInheritedData::StyleRareInheritedData()
     , joinStyle(RenderStyle::initialJoinStyle())
     , hasSetStrokeWidth(false)
     , hasSetStrokeColor(false)
+#if ENABLE(POINTER_EVENTS)
+    , effectiveTouchActions(static_cast<unsigned>(RenderStyle::initialTouchActions()))
+#endif
     , strokeWidth(RenderStyle::initialStrokeWidth())
     , strokeColor(RenderStyle::initialStrokeColor())
     , miterLimit(RenderStyle::initialStrokeMiterLimit())
@@ -232,6 +235,9 @@ inline StyleRareInheritedData::StyleRareInheritedData(const StyleRareInheritedDa
     , joinStyle(o.joinStyle)
     , hasSetStrokeWidth(o.hasSetStrokeWidth)
     , hasSetStrokeColor(o.hasSetStrokeColor)
+#if ENABLE(POINTER_EVENTS)
+    , effectiveTouchActions(o.effectiveTouchActions)
+#endif
     , strokeWidth(o.strokeWidth)
     , strokeColor(o.strokeColor)
     , visitedLinkStrokeColor(o.visitedLinkStrokeColor)
@@ -354,6 +360,9 @@ bool StyleRareInheritedData::operator==(const StyleRareInheritedData& o) const
         && joinStyle == o.joinStyle
         && hasSetStrokeWidth == o.hasSetStrokeWidth
         && hasSetStrokeColor == o.hasSetStrokeColor
+#if ENABLE(POINTER_EVENTS)
+        && effectiveTouchActions == o.effectiveTouchActions
+#endif
         && strokeWidth == o.strokeWidth
         && strokeColor == o.strokeColor
         && visitedLinkStrokeColor == o.visitedLinkStrokeColor
index b540c5b..b8a31ec 100644 (file)
@@ -152,6 +152,11 @@ public:
     unsigned joinStyle : 2; // LineJoin
     unsigned hasSetStrokeWidth : 1;
     unsigned hasSetStrokeColor : 1;
+
+#if ENABLE(POINTER_EVENTS)
+    unsigned effectiveTouchActions : 6; // OptionSet<TouchAction>
+#endif
+
     Length strokeWidth;
     Color strokeColor;
     Color visitedLinkStrokeColor;