Implement touch-action: manipulation; for iOS
authorwenson_hsieh@apple.com <wenson_hsieh@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 22 Oct 2015 13:54:55 +0000 (13:54 +0000)
committerwenson_hsieh@apple.com <wenson_hsieh@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 22 Oct 2015 13:54:55 +0000 (13:54 +0000)
https://bugs.webkit.org/show_bug.cgi?id=149854
<rdar://problem/23017145>

Reviewed by Benjamin Poulain.

Source/WebCore:

Implements the manipulation value for the CSS property touch-action. Adds support for
parsing the touch-action property and two of its values: auto and manipulation.

Tests: css3/touch-action/touch-action-computed-style.html
       css3/touch-action/touch-action-manipulation-fast-clicks.html
       css3/touch-action/touch-action-parsing.html

* css/CSSComputedStyleDeclaration.cpp:
(WebCore::ComputedStyleExtractor::propertyValue):
* css/CSSParser.cpp:
(WebCore::isValidKeywordPropertyAndValue):
(WebCore::isKeywordPropertyID):
(WebCore::CSSParser::parseValue):
* css/CSSPrimitiveValueMappings.h:
(WebCore::CSSPrimitiveValue::CSSPrimitiveValue):
(WebCore::CSSPrimitiveValue::operator TouchAction):
* css/CSSPropertyNames.in:
* css/CSSValueKeywords.in:
* dom/Element.cpp:
(WebCore::Element::allowsDoubleTapGesture): Here, we determine whether an element that resulted from
    hit-testing a touch should allow double-tap gestures. To do this, we walk up the element's parents,
    stopping when we detect an element that disallows double tap gestures by having a touch-action other
    than auto or by hitting the root node.
* dom/Element.h:
* dom/Node.h:
(WebCore::Node::allowsDoubleTapGesture):
* rendering/style/RenderStyle.h:
* rendering/style/RenderStyleConstants.h:
* rendering/style/StyleRareNonInheritedData.cpp:
(WebCore::StyleRareNonInheritedData::StyleRareNonInheritedData):
(WebCore::StyleRareNonInheritedData::operator==):
* rendering/style/StyleRareNonInheritedData.h:

Source/WebKit2:

Implements the manipulation value for the CSS property touch-action. Performs hit-testing upon receiving a potential
tap to determine whether to disable double-tap gesture recognition over the duration of the tap. If so, sends a message
from the web process to the UI process indicating that double-tapping should be disabled, allowing single taps to
avoid the delay.

* WebProcess/WebPage/ios/WebPageIOS.mm:
(WebKit::WebPage::potentialTapAtPosition):

LayoutTests:

Add tests to check that the manipulation and auto values of the touch-action property can be
properly parsed and can be obtained through computed style. Also tests that putting touch-action:
manipulation on an element and tapping repeatedly on it will fire clicks instead of recognizing
double taps and causing the viewport to zoom.

* TestExpectations:
* css3/touch-action/touch-action-computed-style-expected.txt: Added.
* css3/touch-action/touch-action-computed-style.html: Added.
* css3/touch-action/touch-action-manipulation-fast-clicks-expected.txt: Added.
* css3/touch-action/touch-action-manipulation-fast-clicks.html: Added.
* css3/touch-action/touch-action-parsing-expected.txt: Added.
* css3/touch-action/touch-action-parsing.html: Added.
* platform/ios-simulator-wk2/TestExpectations:

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

24 files changed:
LayoutTests/ChangeLog
LayoutTests/TestExpectations
LayoutTests/css3/touch-action/touch-action-computed-style-expected.txt [new file with mode: 0644]
LayoutTests/css3/touch-action/touch-action-computed-style.html [new file with mode: 0644]
LayoutTests/css3/touch-action/touch-action-manipulation-fast-clicks-expected.txt [new file with mode: 0644]
LayoutTests/css3/touch-action/touch-action-manipulation-fast-clicks.html [new file with mode: 0644]
LayoutTests/css3/touch-action/touch-action-parsing-expected.txt [new file with mode: 0644]
LayoutTests/css3/touch-action/touch-action-parsing.html [new file with mode: 0644]
LayoutTests/platform/ios-simulator-wk2/TestExpectations
Source/WebCore/ChangeLog
Source/WebCore/css/CSSComputedStyleDeclaration.cpp
Source/WebCore/css/CSSParser.cpp
Source/WebCore/css/CSSPrimitiveValueMappings.h
Source/WebCore/css/CSSPropertyNames.in
Source/WebCore/css/CSSValueKeywords.in
Source/WebCore/dom/Element.cpp
Source/WebCore/dom/Element.h
Source/WebCore/dom/Node.h
Source/WebCore/rendering/style/RenderStyle.h
Source/WebCore/rendering/style/RenderStyleConstants.h
Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp
Source/WebCore/rendering/style/StyleRareNonInheritedData.h
Source/WebKit2/ChangeLog
Source/WebKit2/WebProcess/WebPage/ios/WebPageIOS.mm

index 0cca020..e9f77c7 100644 (file)
@@ -1,3 +1,25 @@
+2015-10-22  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        Implement touch-action: manipulation; for iOS
+        https://bugs.webkit.org/show_bug.cgi?id=149854
+        <rdar://problem/23017145>
+
+        Reviewed by Benjamin Poulain.
+
+        Add tests to check that the manipulation and auto values of the touch-action property can be
+        properly parsed and can be obtained through computed style. Also tests that putting touch-action:
+        manipulation on an element and tapping repeatedly on it will fire clicks instead of recognizing
+        double taps and causing the viewport to zoom.
+
+        * TestExpectations:
+        * css3/touch-action/touch-action-computed-style-expected.txt: Added.
+        * css3/touch-action/touch-action-computed-style.html: Added.
+        * css3/touch-action/touch-action-manipulation-fast-clicks-expected.txt: Added.
+        * css3/touch-action/touch-action-manipulation-fast-clicks.html: Added.
+        * css3/touch-action/touch-action-parsing-expected.txt: Added.
+        * css3/touch-action/touch-action-parsing.html: Added.
+        * platform/ios-simulator-wk2/TestExpectations:
+
 2015-10-22  Xabier Rodriguez Calvar  <calvaris@igalia.com>
 
         [Streams API] Add writable stream attributes
index 21854ed..60de520 100644 (file)
@@ -6,6 +6,7 @@
 # Platform-specific tests. Skipped here, then re-enabled on the appropriate platform.
 #//////////////////////////////////////////////////////////////////////////////////////////
 
+css3/touch-action [ Skip ]
 accessibility/ios-simulator [ Skip ]
 accessibility/gtk [ Skip ]
 accessibility/mac [ Skip ]
diff --git a/LayoutTests/css3/touch-action/touch-action-computed-style-expected.txt b/LayoutTests/css3/touch-action/touch-action-computed-style-expected.txt
new file mode 100644 (file)
index 0000000..af1aea5
--- /dev/null
@@ -0,0 +1,22 @@
+Testing touch-action: manipulation;
+PASS window.getComputedStyle(document.body).getPropertyValue('touch-action') is 'manipulation'
+Testing touch-action: auto;
+PASS window.getComputedStyle(document.body).getPropertyValue('touch-action') is 'auto'
+Testing a bogus value
+PASS window.getComputedStyle(document.body).getPropertyValue('touch-action') is 'auto'
+Testing all caps
+PASS window.getComputedStyle(document.body).getPropertyValue('touch-action') is 'manipulation'
+Testing weird casing
+PASS window.getComputedStyle(document.body).getPropertyValue('touch-action') is 'auto'
+Testing !important (auto)
+PASS window.getComputedStyle(document.body).getPropertyValue('touch-action') is 'auto'
+Testing !important (manipulation)
+PASS window.getComputedStyle(document.body).getPropertyValue('touch-action') is 'manipulation'
+Testing non-inheritance
+PASS window.getComputedStyle(document.getElementById('child')).getPropertyValue('touch-action') is 'auto'
+PASS successfullyParsed is true
+
+TEST COMPLETE
+Testing the computed style of touch-action:
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
diff --git a/LayoutTests/css3/touch-action/touch-action-computed-style.html b/LayoutTests/css3/touch-action/touch-action-computed-style.html
new file mode 100644 (file)
index 0000000..609b488
--- /dev/null
@@ -0,0 +1,61 @@
+<html>
+    <head>
+        <script src="../../resources/js-test-pre.js"></script>
+    </head>
+
+    <body id="body-elem">
+        <div id="child"></div>
+        <p id="description"></p>
+        <script>
+            description("Testing the computed style of touch-action:");
+            let styleElement = document.createElement("style");
+            document.head.appendChild(styleElement);
+            let stylesheet = styleElement.sheet;
+
+            debug("Testing touch-action: manipulation;");
+            stylesheet.insertRule("body { touch-action: manipulation; }", 0);
+            shouldBe("window.getComputedStyle(document.body).getPropertyValue('touch-action')", "'manipulation'");
+            stylesheet.deleteRule(0);
+
+            debug("Testing touch-action: auto;");
+            stylesheet.insertRule("body { touch-action: auto; }", 0);
+            shouldBe("window.getComputedStyle(document.body).getPropertyValue('touch-action')", "'auto'");
+            stylesheet.deleteRule(0);
+
+            debug("Testing a bogus value");
+            stylesheet.insertRule("body { touch-action: typo; }", 0);
+            shouldBe("window.getComputedStyle(document.body).getPropertyValue('touch-action')", "'auto'");
+            stylesheet.deleteRule(0);
+
+            debug("Testing all caps");
+            stylesheet.insertRule("body { touch-action: MANIPULATION; }", 0);
+            shouldBe("window.getComputedStyle(document.body).getPropertyValue('touch-action')", "'manipulation'");
+            stylesheet.deleteRule(0);
+
+            debug("Testing weird casing");
+            stylesheet.insertRule("body { touch-action: aUtO; }", 0);
+            shouldBe("window.getComputedStyle(document.body).getPropertyValue('touch-action')", "'auto'");
+            stylesheet.deleteRule(0);
+
+            debug("Testing !important (auto)");
+            stylesheet.insertRule("body { touch-action: auto !important; }", 0);
+            stylesheet.insertRule("#body-elem { touch-action: manipulation; }", 1);
+            shouldBe("window.getComputedStyle(document.body).getPropertyValue('touch-action')", "'auto'");
+            stylesheet.deleteRule(1);
+            stylesheet.deleteRule(0);
+
+            debug("Testing !important (manipulation)");
+            stylesheet.insertRule("body { touch-action: manipulation !important; }", 0);
+            stylesheet.insertRule("#body-elem { touch-action: auto; }", 1);
+            shouldBe("window.getComputedStyle(document.body).getPropertyValue('touch-action')", "'manipulation'");
+            stylesheet.deleteRule(1);
+            stylesheet.deleteRule(0);
+
+            debug("Testing non-inheritance");
+            stylesheet.insertRule("body { touch-action: manipulation; }", 0);
+            shouldBe("window.getComputedStyle(document.getElementById('child')).getPropertyValue('touch-action')", "'auto'");
+            stylesheet.deleteRule(0);
+        </script>
+        <script src="../../resources/js-test-post.js"></script>
+    </body>
+</html>
diff --git a/LayoutTests/css3/touch-action/touch-action-manipulation-fast-clicks-expected.txt b/LayoutTests/css3/touch-action/touch-action-manipulation-fast-clicks-expected.txt
new file mode 100644 (file)
index 0000000..512374b
--- /dev/null
@@ -0,0 +1,12 @@
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
+Repeatedly tapping on the button should fire click events.
+
+This test is best run in WebKitTestRunner. If you are running this test manually, verify that tapping the button causes a "Click!" message to appear below, and that click occurred without the regular 350ms delay for double tapping.
+
+Click!
+Click!
+Click!
+
diff --git a/LayoutTests/css3/touch-action/touch-action-manipulation-fast-clicks.html b/LayoutTests/css3/touch-action/touch-action-manipulation-fast-clicks.html
new file mode 100644 (file)
index 0000000..b6519e7
--- /dev/null
@@ -0,0 +1,59 @@
+<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true ] -->
+
+<html>
+<meta name="viewport" content="initial-scale=1.0">
+
+<head>
+    <script src="../../resources/js-test-pre.js"></script>
+    <script id="ui-script" type="text/plain">
+        (function() {
+            function performTap() {
+                uiController.singleTapAtPoint(200, 200, performTap);
+            }
+            performTap();
+        })();
+    </script>
+
+    <script>
+    var clickCount = 0;
+    if (window.testRunner)
+        testRunner.waitUntilDone();
+
+    function getUIScript() {
+        return document.getElementById("ui-script").text;
+    }
+
+    function runTest() {
+        if (testRunner.runUIScript)
+            testRunner.runUIScript(getUIScript(), function(result) { });
+    }
+    function handleClicked() {
+        clickCount++;
+        document.body.appendChild(document.createTextNode("Click!"));
+        document.body.appendChild(document.createElement("br"));
+        if (clickCount == 3)
+            testRunner.notifyDone();
+    }
+    </script>
+
+    <style>
+    body {
+        margin: 0;
+    }
+
+    #target {
+        touch-action: manipulation;
+        width: 400px;
+        height: 400px;
+    }
+    </style>
+</head>
+
+<body onload="runTest()">
+    <button id="target" onclick="handleClicked()"></button>
+    <p>Repeatedly tapping on the button should fire click events.</p>
+    <p>This test is best run in WebKitTestRunner. If you are running this test manually, verify that tapping the button causes a "Click!" message to appear below, and that click occurred without the regular 350ms delay for double tapping.</p>
+    <script src="../../resources/js-test-post.js"></script>
+</body>
+
+</html>
diff --git a/LayoutTests/css3/touch-action/touch-action-parsing-expected.txt b/LayoutTests/css3/touch-action/touch-action-parsing-expected.txt
new file mode 100644 (file)
index 0000000..a7c983b
--- /dev/null
@@ -0,0 +1,12 @@
+PASS cssRule.type is 1
+PASS declaration.length is 1
+PASS declaration.getPropertyValue('touch-action') is 'manipulation'
+PASS cssRule.type is 1
+PASS declaration.length is 1
+PASS declaration.getPropertyValue('touch-action') is 'auto'
+PASS successfullyParsed is true
+
+TEST COMPLETE
+Test the parsing of touch-action.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
diff --git a/LayoutTests/css3/touch-action/touch-action-parsing.html b/LayoutTests/css3/touch-action/touch-action-parsing.html
new file mode 100644 (file)
index 0000000..ee17557
--- /dev/null
@@ -0,0 +1,31 @@
+<html>
+    <head>
+        <script src="../../resources/js-test-pre.js"></script>
+    </head>
+    <body>
+        <p id="description"></p>
+        <script>
+            description("Test the parsing of touch-action.");
+
+            var cssRule, declaration;
+            var styleElement = document.createElement("style");
+            document.head.appendChild(styleElement);
+            let stylesheet = styleElement.sheet;
+
+            stylesheet.insertRule("body { touch-action: manipulation; }", 0);
+            cssRule = stylesheet.cssRules.item(0);
+            shouldBe("cssRule.type", "1");
+            declaration = cssRule.style;
+            shouldBe("declaration.length", "1");
+            shouldBe("declaration.getPropertyValue('touch-action')", "'manipulation'");
+
+            stylesheet.insertRule("body { touch-action: auto; }", 0);
+            cssRule = stylesheet.cssRules.item(0);
+            shouldBe("cssRule.type", "1");
+            declaration = cssRule.style;
+            shouldBe("declaration.length", "1");
+            shouldBe("declaration.getPropertyValue('touch-action')", "'auto'");
+        </script>
+        <script src="../../resources/js-test-post.js"></script>
+    </body>
+</html>
index 3110284..e0ecca9 100644 (file)
@@ -6,6 +6,7 @@
 # Platform-specific directories. Skipped globally, then re-enabled here.
 #//////////////////////////////////////////////////////////////////////////////////////////
 
+css3/touch-action [ Pass ]
 fast/harness/ui-side-scripts.html [ Pass ]
 fast/harness/concurrent-ui-side-scripts.html [ Pass ]
 fast/zooming/ios [ Pass ]
index 8791925..8c78c52 100644 (file)
@@ -1,3 +1,44 @@
+2015-10-22  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        Implement touch-action: manipulation; for iOS
+        https://bugs.webkit.org/show_bug.cgi?id=149854
+        <rdar://problem/23017145>
+
+        Reviewed by Benjamin Poulain.
+
+        Implements the manipulation value for the CSS property touch-action. Adds support for
+        parsing the touch-action property and two of its values: auto and manipulation.
+
+        Tests: css3/touch-action/touch-action-computed-style.html
+               css3/touch-action/touch-action-manipulation-fast-clicks.html
+               css3/touch-action/touch-action-parsing.html
+
+        * css/CSSComputedStyleDeclaration.cpp:
+        (WebCore::ComputedStyleExtractor::propertyValue):
+        * css/CSSParser.cpp:
+        (WebCore::isValidKeywordPropertyAndValue):
+        (WebCore::isKeywordPropertyID):
+        (WebCore::CSSParser::parseValue):
+        * css/CSSPrimitiveValueMappings.h:
+        (WebCore::CSSPrimitiveValue::CSSPrimitiveValue):
+        (WebCore::CSSPrimitiveValue::operator TouchAction):
+        * css/CSSPropertyNames.in:
+        * css/CSSValueKeywords.in:
+        * dom/Element.cpp:
+        (WebCore::Element::allowsDoubleTapGesture): Here, we determine whether an element that resulted from
+            hit-testing a touch should allow double-tap gestures. To do this, we walk up the element's parents,
+            stopping when we detect an element that disallows double tap gestures by having a touch-action other
+            than auto or by hitting the root node.
+        * dom/Element.h:
+        * dom/Node.h:
+        (WebCore::Node::allowsDoubleTapGesture):
+        * rendering/style/RenderStyle.h:
+        * rendering/style/RenderStyleConstants.h:
+        * rendering/style/StyleRareNonInheritedData.cpp:
+        (WebCore::StyleRareNonInheritedData::StyleRareNonInheritedData):
+        (WebCore::StyleRareNonInheritedData::operator==):
+        * rendering/style/StyleRareNonInheritedData.h:
+
 2015-10-22  Ryosuke Niwa  <rniwa@webkit.org>
 
         REGRESSION (r181972): Scroll position changes to top of youtube page when switching tabs
index 10e6e7a..1814c32 100644 (file)
@@ -3193,6 +3193,8 @@ RefPtr<CSSValue> ComputedStyleExtractor::propertyValue(CSSPropertyID propertyID,
 #if ENABLE(TOUCH_EVENTS)
         case CSSPropertyWebkitTapHighlightColor:
             return currentColorOrValidColor(style.get(), style->tapHighlightColor());
+        case CSSPropertyTouchAction:
+            return cssValuePool.createValue(style->touchAction());
 #endif
 #if PLATFORM(IOS)
         case CSSPropertyWebkitTouchCallout:
index d0fa961..7c11092 100644 (file)
@@ -754,6 +754,12 @@ static inline bool isValidKeywordPropertyAndValue(CSSPropertyID propertyId, int
         if (valueID == CSSValueNormal || valueID == CSSValueBreakWord)
             return true;
         break;
+#if ENABLE(TOUCH_EVENTS)
+    case CSSPropertyTouchAction: // auto | manipulation
+        if (valueID == CSSValueAuto || valueID == CSSValueManipulation)
+            return true;
+        break;
+#endif
 #if ENABLE(CSS_SCROLL_SNAP)
     case CSSPropertyWebkitScrollSnapType: // none | mandatory | proximity
         if (valueID == CSSValueNone || valueID == CSSValueMandatory || valueID == CSSValueProximity)
@@ -1176,6 +1182,9 @@ static inline bool isKeywordPropertyID(CSSPropertyID propertyId)
     case CSSPropertyWhiteSpace:
     case CSSPropertyWordBreak:
     case CSSPropertyWordWrap:
+#if ENABLE(TOUCH_EVENTS)
+    case CSSPropertyTouchAction:
+#endif
 #if ENABLE(CSS_SCROLL_SNAP)
     case CSSPropertyWebkitScrollSnapType:
 #endif
@@ -3267,6 +3276,9 @@ bool CSSParser::parseValue(CSSPropertyID propId, bool important)
     case CSSPropertyWhiteSpace:
     case CSSPropertyWordBreak:
     case CSSPropertyWordWrap:
+#if ENABLE(TOUCH_EVENTS)
+    case CSSPropertyTouchAction:
+#endif
 #if ENABLE(CSS_SCROLL_SNAP)
     case CSSPropertyWebkitScrollSnapType:
 #endif
index 14fb90d..6fdc5b4 100644 (file)
@@ -5252,6 +5252,37 @@ template<> inline CSSPrimitiveValue::CSSPrimitiveValue(TextZoom textZoom)
     m_value.valueID = CSSValueNormal;
 }
 
+#if ENABLE(TOUCH_EVENTS)
+template<> inline CSSPrimitiveValue::CSSPrimitiveValue(TouchAction touchAction)
+    : CSSValue(PrimitiveClass)
+{
+    m_primitiveUnitType = CSS_VALUE_ID;
+    switch (touchAction) {
+    case TouchAction::Auto:
+        m_value.valueID = CSSValueAuto;
+        break;
+    case TouchAction::Manipulation:
+        m_value.valueID = CSSValueManipulation;
+        break;
+    }
+}
+
+template<> inline CSSPrimitiveValue::operator TouchAction() const
+{
+    ASSERT(isValueID());
+    switch (m_value.valueID) {
+    case CSSValueAuto:
+        return TouchAction::Auto;
+    case CSSValueManipulation:
+        return TouchAction::Manipulation;
+    default:
+        break;
+    }
+    ASSERT_NOT_REACHED();
+    return TouchAction::Auto;
+}
+#endif
+
 #if ENABLE(CSS_SCROLL_SNAP)
 template<> inline CSSPrimitiveValue::CSSPrimitiveValue(ScrollSnapType e)
     : CSSValue(PrimitiveClass)
index 4092549..f2c205a 100644 (file)
@@ -666,6 +666,9 @@ user-zoom [SkipBuilder]
 #if defined(ENABLE_ACCELERATED_OVERFLOW_SCROLLING) && ENABLE_ACCELERATED_OVERFLOW_SCROLLING
 -webkit-overflow-scrolling [Inherited, NameForMethods=UseTouchOverflowScrolling, Converter=OverflowScrolling]
 #endif
+#if defined(ENABLE_TOUCH_EVENTS) && ENABLE_TOUCH_EVENTS
+touch-action
+#endif
 #if defined(WTF_PLATFORM_IOS) && WTF_PLATFORM_IOS
 -webkit-touch-callout [Inherited, NameForMethods=TouchCalloutEnabled, Converter=TouchCallout]
 #endif
index dd484fd..b4aa125 100644 (file)
@@ -1172,3 +1172,8 @@ style
 // will-change
 scroll-position
 contents
+
+#if defined(ENABLE_TOUCH_EVENTS) && ENABLE_TOUCH_EVENTS
+// touch-action
+manipulation
+#endif
index f874220..8893dff 100644 (file)
@@ -4,7 +4,7 @@
  *           (C) 2001 Peter Kelly (pmk@post.com)
  *           (C) 2001 Dirk Mueller (mueller@kde.org)
  *           (C) 2007 David Smith (catfish.man@gmail.com)
- * Copyright (C) 2004-2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2004-2015 Apple Inc. All rights reserved.
  *           (C) 2007 Eric Seidel (eric@webkit.org)
  *
  * This library is free software; you can redistribute it and/or
@@ -1381,6 +1381,17 @@ URL Element::absoluteLinkURL() const
     return document().completeURL(stripLeadingAndTrailingHTMLSpaces(linkAttribute));
 }
 
+#if ENABLE(TOUCH_EVENTS)
+bool Element::allowsDoubleTapGesture() const
+{
+    if (renderStyle() && renderStyle()->touchAction() != TouchAction::Auto)
+        return false;
+
+    Element* parent = parentElement();
+    return !parent || parent->allowsDoubleTapGesture();
+}
+#endif
+
 StyleResolver& Element::styleResolver()
 {
     if (auto* shadowRoot = containingShadowRoot())
index 12d1414..9a72407 100644 (file)
@@ -487,6 +487,10 @@ public:
 
     WEBCORE_EXPORT URL absoluteLinkURL() const;
 
+#if ENABLE(TOUCH_EVENTS)
+    virtual bool allowsDoubleTapGesture() const override;
+#endif
+
     StyleResolver& styleResolver();
     Ref<RenderStyle> resolveStyle(RenderStyle* parentStyle);
 
index 9e15467..cb1e7e6 100644 (file)
@@ -529,6 +529,10 @@ public:
     void dispatchSubtreeModifiedEvent();
     bool dispatchDOMActivateEvent(int detail, PassRefPtr<Event> underlyingEvent);
 
+#if ENABLE(TOUCH_EVENTS)
+    virtual bool allowsDoubleTapGesture() const { return true; }
+#endif
+
 #if ENABLE(TOUCH_EVENTS) && !PLATFORM(IOS)
     bool dispatchTouchEvent(PassRefPtr<TouchEvent>);
 #endif
index b3b25f1..565f8a4 100644 (file)
@@ -1119,6 +1119,10 @@ public:
     int initialLetterDrop() const { return initialLetter().width(); }
     int initialLetterHeight() const { return initialLetter().height(); }
 
+#if ENABLE(TOUCH_EVENTS)
+    TouchAction touchAction() const { return static_cast<TouchAction>(rareNonInheritedData->m_touchAction); }
+#endif
+
 #if ENABLE(CSS_SCROLL_SNAP)
     ScrollSnapType scrollSnapType() const { return static_cast<ScrollSnapType>(rareNonInheritedData->m_scrollSnapType); }
     const ScrollSnapPoints* scrollSnapPointsX() const;
@@ -1679,6 +1683,10 @@ public:
     
     void setInitialLetter(const IntSize& size) { SET_VAR(rareNonInheritedData, m_initialLetter, size); }
     
+#if ENABLE(TOUCH_EVENTS)
+    void setTouchAction(TouchAction touchAction) { SET_VAR(rareNonInheritedData, m_touchAction, static_cast<unsigned>(touchAction)); }
+#endif
+
 #if ENABLE(CSS_SCROLL_SNAP)
     void setScrollSnapType(ScrollSnapType type) { SET_VAR(rareNonInheritedData, m_scrollSnapType, static_cast<unsigned>(type)); }
     void setScrollSnapPointsX(std::unique_ptr<ScrollSnapPoints>);
@@ -2032,6 +2040,10 @@ public:
 
     static WillChangeData* initialWillChange() { return nullptr; }
 
+#if ENABLE(TOUCH_EVENTS)
+    static TouchAction initialTouchAction() { return TouchAction::Auto; }
+#endif
+
 #if ENABLE(CSS_SCROLL_SNAP)
     static ScrollSnapType initialScrollSnapType() { return ScrollSnapType::None; }
     static ScrollSnapPoints* initialScrollSnapPointsX() { return nullptr; }
index b72b3a7..3434280 100644 (file)
@@ -643,6 +643,13 @@ enum Isolation { IsolationAuto, IsolationIsolate };
 // Fill, Stroke, ViewBox are just used for SVG.
 enum CSSBoxType { BoxMissing = 0, MarginBox, BorderBox, PaddingBox, ContentBox, Fill, Stroke, ViewBox };
 
+#if ENABLE(TOUCH_EVENTS)
+enum class TouchAction {
+    Auto,
+    Manipulation
+};
+#endif
+
 #if ENABLE(CSS_SCROLL_SNAP)
 enum class ScrollSnapType {
     None,
index 09fc912..6ebbdba 100644 (file)
@@ -79,6 +79,9 @@ StyleRareNonInheritedData::StyleRareNonInheritedData()
     , m_justifyContent(RenderStyle::initialContentAlignment())
     , m_justifyItems(RenderStyle::initialSelfAlignment())
     , m_justifySelf(RenderStyle::initialSelfAlignment())
+#if ENABLE(TOUCH_EVENTS)
+    , m_touchAction(static_cast<unsigned>(RenderStyle::initialTouchAction()))
+#endif
 #if ENABLE(CSS_SCROLL_SNAP)
     , m_scrollSnapType(static_cast<unsigned>(RenderStyle::initialScrollSnapType()))
 #endif
@@ -168,6 +171,9 @@ inline StyleRareNonInheritedData::StyleRareNonInheritedData(const StyleRareNonIn
     , m_justifyContent(o.m_justifyContent)
     , m_justifyItems(o.m_justifyItems)
     , m_justifySelf(o.m_justifySelf)
+#if ENABLE(TOUCH_EVENTS)
+    , m_touchAction(o.m_touchAction)
+#endif
 #if ENABLE(CSS_SCROLL_SNAP)
     , m_scrollSnapType(o.m_scrollSnapType)
 #endif
@@ -282,6 +288,9 @@ bool StyleRareNonInheritedData::operator==(const StyleRareNonInheritedData& o) c
         && m_borderFit == o.m_borderFit
         && m_textCombine == o.m_textCombine
         && m_textDecorationStyle == o.m_textDecorationStyle
+#if ENABLE(TOUCH_EVENTS)
+        && m_touchAction == o.m_touchAction
+#endif
 #if ENABLE(CSS_SCROLL_SNAP)
         && m_scrollSnapType == o.m_scrollSnapType
 #endif
index 7ad9763..126aec6 100644 (file)
@@ -184,6 +184,10 @@ public:
     StyleSelfAlignmentData m_justifyItems;
     StyleSelfAlignmentData m_justifySelf;
 
+#if ENABLE(TOUCH_EVENTS)
+    unsigned m_touchAction : 1; // TouchAction
+#endif
+
 #if ENABLE(CSS_SCROLL_SNAP)
     unsigned m_scrollSnapType : 2; // ScrollSnapType
 #endif
index 67830f2..5b240a3 100644 (file)
@@ -1,3 +1,19 @@
+2015-10-22  Wenson Hsieh  <wenson_hsieh@apple.com>
+
+        Implement touch-action: manipulation; for iOS
+        https://bugs.webkit.org/show_bug.cgi?id=149854
+        <rdar://problem/23017145>
+
+        Reviewed by Benjamin Poulain.
+
+        Implements the manipulation value for the CSS property touch-action. Performs hit-testing upon receiving a potential
+        tap to determine whether to disable double-tap gesture recognition over the duration of the tap. If so, sends a message
+        from the web process to the UI process indicating that double-tapping should be disabled, allowing single taps to
+        avoid the delay.
+
+        * WebProcess/WebPage/ios/WebPageIOS.mm:
+        (WebKit::WebPage::potentialTapAtPosition):
+
 2015-10-22  Ryosuke Niwa  <rniwa@webkit.org>
 
         REGRESSION (r181972): Scroll position changes to top of youtube page when switching tabs
index 55daf94..ea42744 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012-2014 Apple Inc. All rights reserved.
+ * Copyright (C) 2012-2015 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -665,6 +665,12 @@ void WebPage::potentialTapAtPosition(uint64_t requestID, const WebCore::FloatPoi
     m_potentialTapNode = m_page->mainFrame().nodeRespondingToClickEvents(position, m_potentialTapLocation);
     sendTapHighlightForNodeIfNecessary(requestID, m_potentialTapNode.get());
     if (m_potentialTapNode) {
+#if ENABLE(TOUCH_EVENTS)
+        if (!m_potentialTapNode->allowsDoubleTapGesture()) {
+            send(Messages::WebPageProxy::DisableDoubleTapGesturesUntilTapIsFinishedIfNecessary(requestID, false, FloatRect(), false, 0, 0));
+            return;
+        }
+#endif
         FloatPoint origin = position;
         FloatRect renderRect;
         bool isReplaced;