[iOS] Correctly handle overlapping regions for elements with a touch-action property
https://bugs.webkit.org/show_bug.cgi?id=194813
<rdar://problem/48194708>
Reviewed by Antti Koivisto.
Source/WebKit:
We now use WebKit::touchActionsForPoint() to determine the touch actions for a given touch using its location in -[WKContentViewInteraction
_handleTouchActionsForTouchEvent:]. We then record these touch actions for the touch's identifier on the RemoteScrollingCoordinatorProxy.
Then, as we interact with a UIScrollView, we get its gesture recognizer and get its active touch identifier through the new
-[WKContentViewInteraction activeTouchIdentifierForGestureRecognizer:] method, and query the RemoteScrollingCoordinatorProxy for the touch
actions matching that touch identifier.
Tests: pointerevents/ios/touch-action-none-overlap.html
pointerevents/ios/touch-action-pan-x-overlap.html
pointerevents/ios/touch-action-pan-y-overlap.html
pointerevents/ios/touch-action-pinch-zoom-overlap.html
* UIProcess/PageClient.h:
(WebKit::PageClient::activeTouchIdentifierForGestureRecognizer):
* UIProcess/RemoteLayerTree/RemoteScrollingCoordinatorProxy.cpp: Maintain a touch identifier to touch actions map.
(WebKit::RemoteScrollingCoordinatorProxy::activeTouchActionsForTouchIdentifier const):
(WebKit::RemoteScrollingCoordinatorProxy::setTouchActionsForTouchIdentifier):
(WebKit::RemoteScrollingCoordinatorProxy::clearTouchActionsForTouchIdentifier):
(WebKit::RemoteScrollingCoordinatorProxy::touchActionDataAtPoint const): Deleted.
(WebKit::RemoteScrollingCoordinatorProxy::touchActionDataForScrollNodeID const): Deleted.
(WebKit::RemoteScrollingCoordinatorProxy::setTouchDataForTouchIdentifier): Deleted.
(WebKit::RemoteScrollingCoordinatorProxy::clearTouchDataForTouchIdentifier): Deleted.
* UIProcess/RemoteLayerTree/RemoteScrollingCoordinatorProxy.h:
* UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.h:
* UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.mm:
(-[WKScrollingNodeScrollViewDelegate scrollViewWillEndDragging:withVelocity:targetContentOffset:]):
(-[WKScrollingNodeScrollViewDelegate _scrollView:adjustedOffsetForOffset:translation:startPoint:locationInView:horizontalVelocity:verticalVelocity:]):
(WebKit::ScrollingTreeScrollingNodeDelegateIOS::activeTouchActionsForGestureRecognizer const):
(WebKit::ScrollingTreeScrollingNodeDelegateIOS::touchActionData const): Deleted.
* UIProcess/ios/PageClientImplIOS.h:
* UIProcess/ios/PageClientImplIOS.mm:
(WebKit::PageClientImpl::activeTouchIdentifierForGestureRecognizer):
* UIProcess/ios/WKContentViewInteraction.h:
* UIProcess/ios/WKContentViewInteraction.mm:
(-[WKContentView activeTouchIdentifierForGestureRecognizer:]):
(-[WKContentView _handleTouchActionsForTouchEvent:]):
LayoutTests:
Add new tests that check that an element overlapping another element with a "touch-action" property is not affected
by the property set on that underlying element.
* pointerevents/ios/touch-action-none-overlap-expected.txt: Added.
* pointerevents/ios/touch-action-none-overlap.html: Added.
* pointerevents/ios/touch-action-pan-x-overlap-expected.txt: Added.
* pointerevents/ios/touch-action-pan-x-overlap.html: Added.
* pointerevents/ios/touch-action-pan-y-overlap-expected.txt: Added.
* pointerevents/ios/touch-action-pan-y-overlap.html: Added.
* pointerevents/ios/touch-action-pinch-zoom-overlap-expected.txt: Added.
* pointerevents/ios/touch-action-pinch-zoom-overlap.html: Added.
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@245112 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index e875ba8..98e9a49 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,23 @@
+2019-05-08 Antoine Quint <graouts@apple.com>
+
+ [iOS] Correctly handle overlapping regions for elements with a touch-action property
+ https://bugs.webkit.org/show_bug.cgi?id=194813
+ <rdar://problem/48194708>
+
+ Reviewed by Antti Koivisto.
+
+ Add new tests that check that an element overlapping another element with a "touch-action" property is not affected
+ by the property set on that underlying element.
+
+ * pointerevents/ios/touch-action-none-overlap-expected.txt: Added.
+ * pointerevents/ios/touch-action-none-overlap.html: Added.
+ * pointerevents/ios/touch-action-pan-x-overlap-expected.txt: Added.
+ * pointerevents/ios/touch-action-pan-x-overlap.html: Added.
+ * pointerevents/ios/touch-action-pan-y-overlap-expected.txt: Added.
+ * pointerevents/ios/touch-action-pan-y-overlap.html: Added.
+ * pointerevents/ios/touch-action-pinch-zoom-overlap-expected.txt: Added.
+ * pointerevents/ios/touch-action-pinch-zoom-overlap.html: Added.
+
2019-05-08 Chris Dumez <cdumez@apple.com>
[iOS Debug] ASSERTION FAILED: !m_originalNode in WebCore::JSLazyEventListener::checkValidityForEventTarget(WebCore::EventTarget &)
diff --git a/LayoutTests/pointerevents/ios/touch-action-none-overlap-expected.txt b/LayoutTests/pointerevents/ios/touch-action-none-overlap-expected.txt
new file mode 100644
index 0000000..dc42c15
--- /dev/null
+++ b/LayoutTests/pointerevents/ios/touch-action-none-overlap-expected.txt
@@ -0,0 +1,3 @@
+
+PASS Testing that an element overlapping an element with touch-action: none allows for scrolling while the touch-action: none element correctly prevents scrolling.
+
diff --git a/LayoutTests/pointerevents/ios/touch-action-none-overlap.html b/LayoutTests/pointerevents/ios/touch-action-none-overlap.html
new file mode 100644
index 0000000..f3b43f0
--- /dev/null
+++ b/LayoutTests/pointerevents/ios/touch-action-none-overlap.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<meta name="viewport" content="width=device-width, initial-scale=1">
+</head>
+<body>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../utils.js"></script>
+<script>
+
+'use strict';
+
+function assertNoScroll()
+{
+ assert_equals(window.pageXOffset, 0, "The page was not scrolled in the x-axis.");
+ assert_equals(window.pageYOffset, 0, "The page was not scrolled in the y-axis.");
+}
+
+target_test({ width: "200px", height: "200px" }, (target, test) => {
+ document.body.style.width = "2000px";
+ document.body.style.height = "2000px";
+
+ target.style.touchAction = "none";
+
+ const overlap = document.body.insertBefore(document.createElement("div"), target.nextElementSibling);
+ overlap.setAttribute("style", "position: absolute; left: 50px; top: 50px; width: 100px; height: 100px;");
+
+ // Swipe over the "touch-action: none" element and around the overlapping element.
+ ui.swipe({ x: 25, y: 175 }, { x: 25, y: 25 }).then(assertNoScroll)
+ .then(() => ui.swipe({ x: 175, y: 175 }, { x: 175, y: 25 })).then(assertNoScroll)
+ .then(() => ui.swipe({ x: 175, y: 25 }, { x: 25, y: 25 })).then(assertNoScroll)
+ .then(() => ui.swipe({ x: 175, y: 175 }, { x: 25, y: 175 })).then(assertNoScroll)
+ // Now swipe over the overlapping element, this should scroll.
+ .then(() => ui.swipe({ x: 125, y: 125 }, { x: 75, y: 75 })).then(() => {
+ assert_not_equals(window.pageXOffset, 0, "The page was scrolled in the x-axis.");
+ assert_not_equals(window.pageYOffset, 0, "The page was scrolled in the y-axis.");
+ test.done();
+ });
+}, "Testing that an element overlapping an element with touch-action: none allows for scrolling while the touch-action: none element correctly prevents scrolling.");
+
+</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/LayoutTests/pointerevents/ios/touch-action-pan-x-overlap-expected.txt b/LayoutTests/pointerevents/ios/touch-action-pan-x-overlap-expected.txt
new file mode 100644
index 0000000..3c0de1d
--- /dev/null
+++ b/LayoutTests/pointerevents/ios/touch-action-pan-x-overlap-expected.txt
@@ -0,0 +1,3 @@
+
+PASS Testing that an element overlapping an element with touch-action: pan-x allows for scrolling while the touch-action: pan-x element correctly prevents scrolling in the y-axis.
+
diff --git a/LayoutTests/pointerevents/ios/touch-action-pan-x-overlap.html b/LayoutTests/pointerevents/ios/touch-action-pan-x-overlap.html
new file mode 100644
index 0000000..16d5a35
--- /dev/null
+++ b/LayoutTests/pointerevents/ios/touch-action-pan-x-overlap.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<meta name="viewport" content="width=device-width, initial-scale=1">
+</head>
+<body>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../utils.js"></script>
+<script>
+
+'use strict';
+
+function assertNoScroll()
+{
+ assert_equals(window.pageXOffset, 0, "The page was not scrolled in the x-axis.");
+ assert_equals(window.pageYOffset, 0, "The page was not scrolled in the y-axis.");
+}
+
+target_test({ width: "200px", height: "200px" }, (target, test) => {
+ document.body.style.width = "2000px";
+ document.body.style.height = "2000px";
+
+ target.style.touchAction = "pan-x";
+
+ const overlap = document.body.insertBefore(document.createElement("div"), target.nextElementSibling);
+ overlap.setAttribute("style", "position: absolute; left: 50px; top: 50px; width: 100px; height: 100px;");
+
+ // Swipe in the y-axis over the "touch-action: pan-x" element and around the overlapping element.
+ ui.swipe({ x: 25, y: 175 }, { x: 25, y: 25 }).then(assertNoScroll)
+ .then(() => ui.swipe({ x: 175, y: 175 }, { x: 175, y: 25 })).then(assertNoScroll)
+ // Now swipe over the overlapping element, this should scroll in both directions.
+ .then(() => ui.swipe({ x: 125, y: 125 }, { x: 75, y: 75 })).then(() => {
+ assert_not_equals(window.pageXOffset, 0, "The page was scrolled in the x-axis.");
+ assert_not_equals(window.pageYOffset, 0, "The page was scrolled in the y-axis.");
+ test.done();
+ });
+}, "Testing that an element overlapping an element with touch-action: pan-x allows for scrolling while the touch-action: pan-x element correctly prevents scrolling in the y-axis.");
+
+</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/LayoutTests/pointerevents/ios/touch-action-pan-y-overlap-expected.txt b/LayoutTests/pointerevents/ios/touch-action-pan-y-overlap-expected.txt
new file mode 100644
index 0000000..924183b
--- /dev/null
+++ b/LayoutTests/pointerevents/ios/touch-action-pan-y-overlap-expected.txt
@@ -0,0 +1,3 @@
+
+PASS Testing that an element overlapping an element with touch-action: pan-y allows for scrolling while the touch-action: pan-y element correctly prevents scrolling in the x-axis.
+
diff --git a/LayoutTests/pointerevents/ios/touch-action-pan-y-overlap.html b/LayoutTests/pointerevents/ios/touch-action-pan-y-overlap.html
new file mode 100644
index 0000000..e86f2d7
--- /dev/null
+++ b/LayoutTests/pointerevents/ios/touch-action-pan-y-overlap.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<meta name="viewport" content="width=device-width, initial-scale=1">
+</head>
+<body>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../utils.js"></script>
+<script>
+
+'use strict';
+
+function assertNoScroll()
+{
+ assert_equals(window.pageXOffset, 0, "The page was not scrolled in the x-axis.");
+ assert_equals(window.pageYOffset, 0, "The page was not scrolled in the y-axis.");
+}
+
+target_test({ width: "200px", height: "200px" }, (target, test) => {
+ document.body.style.width = "2000px";
+ document.body.style.height = "2000px";
+
+ target.style.touchAction = "pan-y";
+
+ const overlap = document.body.insertBefore(document.createElement("div"), target.nextElementSibling);
+ overlap.setAttribute("style", "position: absolute; left: 50px; top: 50px; width: 100px; height: 100px;");
+
+ // Swipe in the x-axis over the "touch-action: pan-y" element and around the overlapping element.
+ ui.swipe({ x: 175, y: 25 }, { x: 25, y: 25 }).then(assertNoScroll)
+ .then(() => ui.swipe({ x: 175, y: 175 }, { x: 25, y: 175 })).then(assertNoScroll)
+ // Now swipe over the overlapping element, this should scroll in both directions.
+ .then(() => ui.swipe({ x: 125, y: 125 }, { x: 75, y: 75 })).then(() => {
+ assert_not_equals(window.pageXOffset, 0, "The page was scrolled in the x-axis.");
+ assert_not_equals(window.pageYOffset, 0, "The page was scrolled in the y-axis.");
+ test.done();
+ });
+}, "Testing that an element overlapping an element with touch-action: pan-y allows for scrolling while the touch-action: pan-y element correctly prevents scrolling in the x-axis.");
+
+</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/LayoutTests/pointerevents/ios/touch-action-pinch-zoom-overlap-expected.txt b/LayoutTests/pointerevents/ios/touch-action-pinch-zoom-overlap-expected.txt
new file mode 100644
index 0000000..36ff36c
--- /dev/null
+++ b/LayoutTests/pointerevents/ios/touch-action-pinch-zoom-overlap-expected.txt
@@ -0,0 +1,3 @@
+
+PASS Testing that an element overlapping an element with touch-action: pinch-zoom allows for scrolling while the touch-action: pinch-zoom element correctly prevents scrolling.
+
diff --git a/LayoutTests/pointerevents/ios/touch-action-pinch-zoom-overlap.html b/LayoutTests/pointerevents/ios/touch-action-pinch-zoom-overlap.html
new file mode 100644
index 0000000..75427e4
--- /dev/null
+++ b/LayoutTests/pointerevents/ios/touch-action-pinch-zoom-overlap.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset=utf-8>
+<meta name="viewport" content="width=device-width, initial-scale=1">
+</head>
+<body>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../utils.js"></script>
+<script>
+
+'use strict';
+
+function assertNoScroll()
+{
+ assert_equals(window.pageXOffset, 0, "The page was not scrolled in the x-axis.");
+ assert_equals(window.pageYOffset, 0, "The page was not scrolled in the y-axis.");
+}
+
+target_test({ width: "200px", height: "200px" }, (target, test) => {
+ document.body.style.width = "2000px";
+ document.body.style.height = "2000px";
+
+ target.style.touchAction = "pinch-zoom";
+
+ const overlap = document.body.insertBefore(document.createElement("div"), target.nextElementSibling);
+ overlap.setAttribute("style", "position: absolute; left: 50px; top: 50px; width: 100px; height: 100px;");
+
+ // Swipe over the "touch-action: pinch-zoom" element and around the overlapping element.
+ ui.swipe({ x: 25, y: 175 }, { x: 25, y: 25 }).then(assertNoScroll)
+ .then(() => ui.swipe({ x: 175, y: 175 }, { x: 175, y: 25 })).then(assertNoScroll)
+ .then(() => ui.swipe({ x: 175, y: 25 }, { x: 25, y: 25 })).then(assertNoScroll)
+ .then(() => ui.swipe({ x: 175, y: 175 }, { x: 25, y: 175 })).then(assertNoScroll)
+ // Now swipe over the overlapping element, this should scroll.
+ .then(() => ui.swipe({ x: 125, y: 125 }, { x: 75, y: 75 })).then(() => {
+ assert_not_equals(window.pageXOffset, 0, "The page was scrolled in the x-axis.");
+ assert_not_equals(window.pageYOffset, 0, "The page was scrolled in the y-axis.");
+ test.done();
+ });
+}, "Testing that an element overlapping an element with touch-action: pinch-zoom allows for scrolling while the touch-action: pinch-zoom element correctly prevents scrolling.");
+
+</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/Source/WebKit/ChangeLog b/Source/WebKit/ChangeLog
index 5c62974..b808218 100644
--- a/Source/WebKit/ChangeLog
+++ b/Source/WebKit/ChangeLog
@@ -1,3 +1,48 @@
+2019-05-08 Antoine Quint <graouts@apple.com>
+
+ [iOS] Correctly handle overlapping regions for elements with a touch-action property
+ https://bugs.webkit.org/show_bug.cgi?id=194813
+ <rdar://problem/48194708>
+
+ Reviewed by Antti Koivisto.
+
+ We now use WebKit::touchActionsForPoint() to determine the touch actions for a given touch using its location in -[WKContentViewInteraction
+ _handleTouchActionsForTouchEvent:]. We then record these touch actions for the touch's identifier on the RemoteScrollingCoordinatorProxy.
+
+ Then, as we interact with a UIScrollView, we get its gesture recognizer and get its active touch identifier through the new
+ -[WKContentViewInteraction activeTouchIdentifierForGestureRecognizer:] method, and query the RemoteScrollingCoordinatorProxy for the touch
+ actions matching that touch identifier.
+
+ Tests: pointerevents/ios/touch-action-none-overlap.html
+ pointerevents/ios/touch-action-pan-x-overlap.html
+ pointerevents/ios/touch-action-pan-y-overlap.html
+ pointerevents/ios/touch-action-pinch-zoom-overlap.html
+
+ * UIProcess/PageClient.h:
+ (WebKit::PageClient::activeTouchIdentifierForGestureRecognizer):
+ * UIProcess/RemoteLayerTree/RemoteScrollingCoordinatorProxy.cpp: Maintain a touch identifier to touch actions map.
+ (WebKit::RemoteScrollingCoordinatorProxy::activeTouchActionsForTouchIdentifier const):
+ (WebKit::RemoteScrollingCoordinatorProxy::setTouchActionsForTouchIdentifier):
+ (WebKit::RemoteScrollingCoordinatorProxy::clearTouchActionsForTouchIdentifier):
+ (WebKit::RemoteScrollingCoordinatorProxy::touchActionDataAtPoint const): Deleted.
+ (WebKit::RemoteScrollingCoordinatorProxy::touchActionDataForScrollNodeID const): Deleted.
+ (WebKit::RemoteScrollingCoordinatorProxy::setTouchDataForTouchIdentifier): Deleted.
+ (WebKit::RemoteScrollingCoordinatorProxy::clearTouchDataForTouchIdentifier): Deleted.
+ * UIProcess/RemoteLayerTree/RemoteScrollingCoordinatorProxy.h:
+ * UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.h:
+ * UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.mm:
+ (-[WKScrollingNodeScrollViewDelegate scrollViewWillEndDragging:withVelocity:targetContentOffset:]):
+ (-[WKScrollingNodeScrollViewDelegate _scrollView:adjustedOffsetForOffset:translation:startPoint:locationInView:horizontalVelocity:verticalVelocity:]):
+ (WebKit::ScrollingTreeScrollingNodeDelegateIOS::activeTouchActionsForGestureRecognizer const):
+ (WebKit::ScrollingTreeScrollingNodeDelegateIOS::touchActionData const): Deleted.
+ * UIProcess/ios/PageClientImplIOS.h:
+ * UIProcess/ios/PageClientImplIOS.mm:
+ (WebKit::PageClientImpl::activeTouchIdentifierForGestureRecognizer):
+ * UIProcess/ios/WKContentViewInteraction.h:
+ * UIProcess/ios/WKContentViewInteraction.mm:
+ (-[WKContentView activeTouchIdentifierForGestureRecognizer:]):
+ (-[WKContentView _handleTouchActionsForTouchEvent:]):
+
2019-05-08 Megan Gardner <megan_gardner@apple.com>
Add quirks to emulate undo and redo in hidden editable areas on some websites
diff --git a/Source/WebKit/UIProcess/PageClient.h b/Source/WebKit/UIProcess/PageClient.h
index e767f5e..afc94ce 100644
--- a/Source/WebKit/UIProcess/PageClient.h
+++ b/Source/WebKit/UIProcess/PageClient.h
@@ -501,6 +501,7 @@
#if ENABLE(POINTER_EVENTS)
virtual void cancelPointersForGestureRecognizer(UIGestureRecognizer*) { }
+ virtual WTF::Optional<unsigned> activeTouchIdentifierForGestureRecognizer(UIGestureRecognizer*) { return WTF::nullopt; }
#endif
#if PLATFORM(WPE)
diff --git a/Source/WebKit/UIProcess/RemoteLayerTree/RemoteScrollingCoordinatorProxy.cpp b/Source/WebKit/UIProcess/RemoteLayerTree/RemoteScrollingCoordinatorProxy.cpp
index 774792c..3b838ea 100644
--- a/Source/WebKit/UIProcess/RemoteLayerTree/RemoteScrollingCoordinatorProxy.cpp
+++ b/Source/WebKit/UIProcess/RemoteLayerTree/RemoteScrollingCoordinatorProxy.cpp
@@ -247,28 +247,22 @@
}
#if ENABLE(POINTER_EVENTS)
-Optional<TouchActionData> RemoteScrollingCoordinatorProxy::touchActionDataAtPoint(const IntPoint p) const
+OptionSet<TouchAction> RemoteScrollingCoordinatorProxy::activeTouchActionsForTouchIdentifier(unsigned touchIdentifier) const
{
- return m_scrollingTree->touchActionDataAtPoint(p);
+ auto iterator = m_touchActionsByTouchIdentifier.find(touchIdentifier);
+ if (iterator == m_touchActionsByTouchIdentifier.end())
+ return { };
+ return iterator->value;
}
-Optional<TouchActionData> RemoteScrollingCoordinatorProxy::touchActionDataForScrollNodeID(ScrollingNodeID scrollingNodeID) const
+void RemoteScrollingCoordinatorProxy::setTouchActionsForTouchIdentifier(OptionSet<TouchAction> touchActions, unsigned touchIdentifier)
{
- for (auto& touchActionData : m_touchActionDataByTouchIdentifier.values()) {
- if (touchActionData.scrollingNodeID == scrollingNodeID)
- return touchActionData;
- }
- return WTF::nullopt;
+ m_touchActionsByTouchIdentifier.set(touchIdentifier, touchActions);
}
-void RemoteScrollingCoordinatorProxy::setTouchDataForTouchIdentifier(TouchActionData touchActionData, unsigned touchIdentifier)
+void RemoteScrollingCoordinatorProxy::clearTouchActionsForTouchIdentifier(unsigned touchIdentifier)
{
- m_touchActionDataByTouchIdentifier.set(touchIdentifier, touchActionData);
-}
-
-void RemoteScrollingCoordinatorProxy::clearTouchDataForTouchIdentifier(unsigned touchIdentifier)
-{
- m_touchActionDataByTouchIdentifier.remove(touchIdentifier);
+ m_touchActionsByTouchIdentifier.remove(touchIdentifier);
}
#endif
diff --git a/Source/WebKit/UIProcess/RemoteLayerTree/RemoteScrollingCoordinatorProxy.h b/Source/WebKit/UIProcess/RemoteLayerTree/RemoteScrollingCoordinatorProxy.h
index 2cc1024..dc19989 100644
--- a/Source/WebKit/UIProcess/RemoteLayerTree/RemoteScrollingCoordinatorProxy.h
+++ b/Source/WebKit/UIProcess/RemoteLayerTree/RemoteScrollingCoordinatorProxy.h
@@ -102,10 +102,9 @@
String scrollingTreeAsText() const;
#if ENABLE(POINTER_EVENTS)
- Optional<WebCore::TouchActionData> touchActionDataAtPoint(const WebCore::IntPoint) const;
- Optional<WebCore::TouchActionData> touchActionDataForScrollNodeID(WebCore::ScrollingNodeID) const;
- void setTouchDataForTouchIdentifier(WebCore::TouchActionData, unsigned);
- void clearTouchDataForTouchIdentifier(unsigned);
+ OptionSet<WebCore::TouchAction> activeTouchActionsForTouchIdentifier(unsigned touchIdentifier) const;
+ void setTouchActionsForTouchIdentifier(OptionSet<WebCore::TouchAction>, unsigned);
+ void clearTouchActionsForTouchIdentifier(unsigned);
#endif
private:
@@ -120,7 +119,7 @@
WebPageProxy& m_webPageProxy;
RefPtr<RemoteScrollingTree> m_scrollingTree;
#if ENABLE(POINTER_EVENTS)
- HashMap<unsigned, WebCore::TouchActionData> m_touchActionDataByTouchIdentifier;
+ HashMap<unsigned, OptionSet<WebCore::TouchAction>> m_touchActionsByTouchIdentifier;
#endif
RequestedScrollInfo* m_requestedScrollInfo;
#if ENABLE(CSS_SCROLL_SNAP)
diff --git a/Source/WebKit/UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.h b/Source/WebKit/UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.h
index f508f16..0656656 100644
--- a/Source/WebKit/UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.h
+++ b/Source/WebKit/UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.h
@@ -66,7 +66,7 @@
void repositionScrollingLayers();
#if ENABLE(POINTER_EVENTS)
- Optional<WebCore::TouchActionData> touchActionData() const;
+ OptionSet<TouchAction> activeTouchActionsForGestureRecognizer(UIGestureRecognizer*) const;
void cancelPointersForGestureRecognizer(UIGestureRecognizer*);
#endif
diff --git a/Source/WebKit/UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.mm b/Source/WebKit/UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.mm
index 39e475c..ac685f2 100644
--- a/Source/WebKit/UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.mm
+++ b/Source/WebKit/UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.mm
@@ -79,19 +79,17 @@
{
#if ENABLE(POINTER_EVENTS)
if (![scrollView isZooming]) {
- if (auto touchActionData = _scrollingTreeNodeDelegate->touchActionData()) {
- auto touchActions = touchActionData->touchActions;
- if (touchActions != WebCore::TouchAction::Auto && touchActions != WebCore::TouchAction::Manipulation) {
- bool canPanX = true;
- bool canPanY = true;
- if (!touchActions.contains(WebCore::TouchAction::PanX)) {
- canPanX = false;
- targetContentOffset->x = scrollView.contentOffset.x;
- }
- if (!touchActions.contains(WebCore::TouchAction::PanY)) {
- canPanY = false;
- targetContentOffset->y = scrollView.contentOffset.y;
- }
+ auto touchActions = _scrollingTreeNodeDelegate->activeTouchActionsForGestureRecognizer(scrollView.panGestureRecognizer);
+ if (touchActions && !touchActions.containsAny({ WebCore::TouchAction::Auto, WebCore::TouchAction::Manipulation })) {
+ bool canPanX = true;
+ bool canPanY = true;
+ if (!touchActions.contains(WebCore::TouchAction::PanX)) {
+ canPanX = false;
+ targetContentOffset->x = scrollView.contentOffset.x;
+ }
+ if (!touchActions.contains(WebCore::TouchAction::PanY)) {
+ canPanY = false;
+ targetContentOffset->y = scrollView.contentOffset.y;
}
}
}
@@ -148,14 +146,14 @@
#if ENABLE(POINTER_EVENTS)
- (CGPoint)_scrollView:(UIScrollView *)scrollView adjustedOffsetForOffset:(CGPoint)offset translation:(CGPoint)translation startPoint:(CGPoint)start locationInView:(CGPoint)locationInView horizontalVelocity:(inout double *)hv verticalVelocity:(inout double *)vv
{
- auto touchActionData = _scrollingTreeNodeDelegate->touchActionData();
- if (!touchActionData) {
- [self cancelPointersForGestureRecognizer:scrollView.panGestureRecognizer];
+ auto* panGestureRecognizer = scrollView.panGestureRecognizer;
+ auto touchActions = _scrollingTreeNodeDelegate->activeTouchActionsForGestureRecognizer(panGestureRecognizer);
+ if (!touchActions) {
+ [self cancelPointersForGestureRecognizer:panGestureRecognizer];
return offset;
}
- auto touchActions = touchActionData->touchActions;
- if (touchActions == WebCore::TouchAction::Auto || touchActions == WebCore::TouchAction::Manipulation)
+ if (touchActions.containsAny({ WebCore::TouchAction::Auto, WebCore::TouchAction::Manipulation }))
return offset;
CGPoint adjustedContentOffset = CGPointMake(offset.x, offset.y);
@@ -338,9 +336,12 @@
}
#if ENABLE(POINTER_EVENTS)
-Optional<TouchActionData> ScrollingTreeScrollingNodeDelegateIOS::touchActionData() const
+OptionSet<TouchAction> ScrollingTreeScrollingNodeDelegateIOS::activeTouchActionsForGestureRecognizer(UIGestureRecognizer* gestureRecognizer) const
{
- return downcast<RemoteScrollingTree>(scrollingTree()).scrollingCoordinatorProxy().touchActionDataForScrollNodeID(scrollingNode().scrollingNodeID());
+ auto& scrollingCoordinatorProxy = downcast<RemoteScrollingTree>(scrollingTree()).scrollingCoordinatorProxy();
+ if (auto touchIdentifier = scrollingCoordinatorProxy.webPageProxy().pageClient().activeTouchIdentifierForGestureRecognizer(gestureRecognizer))
+ return scrollingCoordinatorProxy.activeTouchActionsForTouchIdentifier(*touchIdentifier);
+ return { };
}
void ScrollingTreeScrollingNodeDelegateIOS::cancelPointersForGestureRecognizer(UIGestureRecognizer* gestureRecognizer)
diff --git a/Source/WebKit/UIProcess/ios/PageClientImplIOS.h b/Source/WebKit/UIProcess/ios/PageClientImplIOS.h
index 3872fbd..876ac91 100644
--- a/Source/WebKit/UIProcess/ios/PageClientImplIOS.h
+++ b/Source/WebKit/UIProcess/ios/PageClientImplIOS.h
@@ -251,6 +251,7 @@
#if ENABLE(POINTER_EVENTS)
void cancelPointersForGestureRecognizer(UIGestureRecognizer*) override;
+ WTF::Optional<unsigned> activeTouchIdentifierForGestureRecognizer(UIGestureRecognizer*) override;
#endif
WKContentView *m_contentView;
diff --git a/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm b/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm
index 9d27bc4..67fb2e3 100644
--- a/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm
+++ b/Source/WebKit/UIProcess/ios/PageClientImplIOS.mm
@@ -866,6 +866,11 @@
{
[m_contentView cancelPointersForGestureRecognizer:gestureRecognizer];
}
+
+WTF::Optional<unsigned> PageClientImpl::activeTouchIdentifierForGestureRecognizer(UIGestureRecognizer* gestureRecognizer)
+{
+ return [m_contentView activeTouchIdentifierForGestureRecognizer:gestureRecognizer];
+}
#endif
void PageClientImpl::handleAutocorrectionContext(const WebAutocorrectionContext& context)
diff --git a/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h b/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h
index a223ba11..9736c2b 100644
--- a/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h
+++ b/Source/WebKit/UIProcess/ios/WKContentViewInteraction.h
@@ -409,6 +409,7 @@
#if ENABLE(POINTER_EVENTS)
- (void)cancelPointersForGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer;
+- (WTF::Optional<unsigned>)activeTouchIdentifierForGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer;
#endif
#define DECLARE_WKCONTENTVIEW_ACTION_FOR_WEB_VIEW(_action) \
diff --git a/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm b/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm
index d9c674a..953ebf9 100644
--- a/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm
+++ b/Source/WebKit/UIProcess/ios/WKContentViewInteraction.mm
@@ -37,6 +37,7 @@
#import "NativeWebKeyboardEvent.h"
#import "NativeWebTouchEvent.h"
#import "RemoteLayerTreeDrawingAreaProxy.h"
+#import "RemoteLayerTreeViews.h"
#import "SmartMagnificationController.h"
#import "TextInputSPI.h"
#import "UIKitSPI.h"
@@ -1257,6 +1258,20 @@
}
#endif
}
+
+- (WTF::Optional<unsigned>)activeTouchIdentifierForGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
+{
+#if HAVE(UI_WEB_TOUCH_EVENTS_GESTURE_RECOGNIZER_WITH_ACTIVE_TOUCHES_BY_ID)
+ // FIXME: <rdar://problem/48035706>
+ NSMapTable<NSNumber *, UITouch *> *activeTouches = [_touchEventGestureRecognizer activeTouchesByIdentifier];
+ for (NSNumber *touchIdentifier in activeTouches) {
+ UITouch *touch = [activeTouches objectForKey:touchIdentifier];
+ if ([touch.gestureRecognizers containsObject:gestureRecognizer])
+ return [touchIdentifier unsignedIntValue];
+ }
+#endif
+ return WTF::nullopt;
+}
#endif
inline static UIKeyModifierFlags gestureRecognizerModifierFlags(UIGestureRecognizer *recognizer)
@@ -1318,19 +1333,18 @@
for (const auto& touchPoint : touchEvent.touchPoints()) {
auto phase = touchPoint.phase();
if (phase == WebKit::WebPlatformTouchPoint::TouchPressed) {
- auto touchActionData = scrollingCoordinator->touchActionDataAtPoint(touchPoint.location());
- if (!touchActionData || touchActionData->touchActions.contains(WebCore::TouchAction::Manipulation))
+ auto touchActions = WebKit::touchActionsForPoint(self, touchPoint.location());
+ if (!touchActions || touchActions.containsAny({ WebCore::TouchAction::Auto, WebCore::TouchAction::Manipulation }))
continue;
- if (auto scrollingNodeID = touchActionData->scrollingNodeID)
- scrollingCoordinator->setTouchDataForTouchIdentifier(*touchActionData, touchPoint.identifier());
- else {
- if (!touchActionData->touchActions.contains(WebCore::TouchAction::PinchZoom))
- _webView.scrollView.pinchGestureRecognizer.enabled = NO;
- _preventsPanningInXAxis = !touchActionData->touchActions.contains(WebCore::TouchAction::PanX);
- _preventsPanningInYAxis = !touchActionData->touchActions.contains(WebCore::TouchAction::PanY);
- }
+ scrollingCoordinator->setTouchActionsForTouchIdentifier(touchActions, touchPoint.identifier());
+
+ if (!touchActions.contains(WebCore::TouchAction::PinchZoom))
+ _webView.scrollView.pinchGestureRecognizer.enabled = NO;
+ _preventsPanningInXAxis = !touchActions.contains(WebCore::TouchAction::PanX);
+ _preventsPanningInYAxis = !touchActions.contains(WebCore::TouchAction::PanY);
+
} else if (phase == WebKit::WebPlatformTouchPoint::TouchReleased || phase == WebKit::WebPlatformTouchPoint::TouchCancelled)
- scrollingCoordinator->clearTouchDataForTouchIdentifier(touchPoint.identifier());
+ scrollingCoordinator->clearTouchActionsForTouchIdentifier(touchPoint.identifier());
}
}
#endif