Diff
Modified: trunk/LayoutTests/ChangeLog (195898 => 195899)
--- trunk/LayoutTests/ChangeLog 2016-01-30 18:09:44 UTC (rev 195898)
+++ trunk/LayoutTests/ChangeLog 2016-01-30 18:38:20 UTC (rev 195899)
@@ -1,3 +1,16 @@
+2016-01-30 Ryosuke Niwa <[email protected]>
+
+ TouchList should be retargeted
+ https://bugs.webkit.org/show_bug.cgi?id=149592
+
+ Reviewed by Antti Koivisto.
+
+ Added a regression test for retargeting touch targets on iOS.
+
+ * fast/shadow-dom/touch-event-ios-expected.txt: Added.
+ * fast/shadow-dom/touch-event-ios.html: Added.
+ * platform/mac/TestExpectations: Added the failing expectation on Mac since touch support is not enabled.
+
2016-01-30 Michael Catanzaro <[email protected]>
[GTK] Two disk cache tests are failing
Added: trunk/LayoutTests/fast/shadow-dom/touch-event-ios-expected.txt (0 => 195899)
--- trunk/LayoutTests/fast/shadow-dom/touch-event-ios-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/shadow-dom/touch-event-ios-expected.txt 2016-01-30 18:38:20 UTC (rev 195899)
@@ -0,0 +1,117 @@
+Tests for retargeting touch targets. This test requires touch events support and runUIScript.
+
+touchstart at left-shadow with
+ target: left-shadow-target
+ touches: [0: left-shadow-target]
+ targetTouches: [0: left-shadow-target]
+ changedTouches: [0: left-shadow-target]
+
+touchstart at document with
+ target: left-host
+ touches: [0: left-host]
+ targetTouches: [0: left-host]
+ changedTouches: [0: left-host]
+
+touchstart at right-lower-shadow with
+ target: slot
+ touches: [0: left-host, 1: right-target]
+ targetTouches: [0: right-target]
+ changedTouches: [0: right-target]
+
+touchstart at right-upper-shadow with
+ target: slot
+ touches: [0: left-host, 1: right-target]
+ targetTouches: [0: right-target]
+ changedTouches: [0: right-target]
+
+touchstart at document with
+ target: right-target
+ touches: [0: left-host, 1: right-target]
+ targetTouches: [0: right-target]
+ changedTouches: [0: right-target]
+
+touchmove at left-shadow with
+ target: left-shadow-target
+ touches: [0: left-shadow-target, 1: right-target]
+ targetTouches: [0: left-shadow-target]
+ changedTouches: [0: left-shadow-target]
+
+touchmove at document with
+ target: left-host
+ touches: [0: left-host, 1: right-target]
+ targetTouches: [0: left-host]
+ changedTouches: [0: left-host]
+
+touchstart at document with
+ target: bottom-target
+ touches: [0: left-host, 1: right-target, 2: bottom-target]
+ targetTouches: [0: bottom-target]
+ changedTouches: [0: bottom-target]
+
+touchmove at left-shadow with
+ target: left-shadow-target
+ touches: [0: left-shadow-target, 1: right-target, 2: bottom-target]
+ targetTouches: [0: left-shadow-target]
+ changedTouches: [0: left-shadow-target]
+
+touchmove at document with
+ target: left-host
+ touches: [0: left-host, 1: right-target, 2: bottom-target]
+ targetTouches: [0: left-host]
+ changedTouches: [0: left-host]
+
+touchmove at right-lower-shadow with
+ target: slot
+ touches: [0: left-host, 1: right-target, 2: bottom-target]
+ targetTouches: [0: right-target]
+ changedTouches: [0: right-target]
+
+touchmove at right-upper-shadow with
+ target: slot
+ touches: [0: left-host, 1: right-target, 2: bottom-target]
+ targetTouches: [0: right-target]
+ changedTouches: [0: right-target]
+
+touchmove at document with
+ target: right-target
+ touches: [0: left-host, 1: right-target, 2: bottom-target]
+ targetTouches: [0: right-target]
+ changedTouches: [0: right-target]
+
+touchend at document with
+ target: bottom-target
+ touches: []
+ targetTouches: []
+ changedTouches: [0: bottom-target]
+
+touchend at left-shadow with
+ target: left-shadow-target
+ touches: []
+ targetTouches: []
+ changedTouches: [0: left-shadow-target]
+
+touchend at document with
+ target: left-host
+ touches: []
+ targetTouches: []
+ changedTouches: [0: left-host]
+
+touchend at right-lower-shadow with
+ target: slot
+ touches: []
+ targetTouches: []
+ changedTouches: [0: right-target]
+
+touchend at right-upper-shadow with
+ target: slot
+ touches: []
+ targetTouches: []
+ changedTouches: [0: right-target]
+
+touchend at document with
+ target: right-target
+ touches: []
+ targetTouches: []
+ changedTouches: [0: right-target]
+
+
Added: trunk/LayoutTests/fast/shadow-dom/touch-event-ios.html (0 => 195899)
--- trunk/LayoutTests/fast/shadow-dom/touch-event-ios.html (rev 0)
+++ trunk/LayoutTests/fast/shadow-dom/touch-event-ios.html 2016-01-30 18:38:20 UTC (rev 195899)
@@ -0,0 +1,154 @@
+<!DOCTYPE html>
+<html>
+<body>
+<p>Tests for retargeting touch targets. This test requires touch events support and runUIScript.</p>
+<script>
+
+function block(width, height, color) {
+ return {display: 'block', width: width + 'px', height: height + 'px', backgroundColor: color};
+}
+
+function inlineBlock(width, height, color) {
+ return {display: 'inline-block', width: width + 'px', height: height + 'px', backgroundColor: color};
+}
+
+function addChildren(parent, children) {
+ for (var child of children) {
+ if (typeof(child) == 'string')
+ child = document.createTextNode(child);
+ parent.appendChild(child);
+ }
+}
+
+function element(name, children) {
+ var element = document.createElement(name);
+ element.treeName = name;
+ if (children)
+ addChildren(element, children);
+ return element;
+}
+
+function elementWithStyle(name, style, children) {
+ var newElement = element(name, children);
+ for (var name in style)
+ newElement.style[name] = style[name];
+ return newElement;
+}
+
+function attachShadow(name, element, shadowChildren) {
+ var shadowRoot = element.attachShadow({mode: 'closed'});
+ shadowRoot.treeName = name;
+ element.shadowTree = shadowRoot;
+ addChildren(shadowRoot, shadowChildren);
+ return shadowRoot;
+}
+
+/*
+parent
+ + left-host -- (left-shadow)
+ | + left-shadow-target
+ + right-upper-host --------------------------------- (right-upper-shadow)
+ | + right-lower-host -- (right-lower-shadow) + right-shadow-child
+ | + right-target + right-lower-shadow-child + slot
+ | + slot
+ + bottomTarget
+*/
+
+var leftHost = elementWithStyle('left-host', block(200, 150, 'yellow'));
+var leftTarget = elementWithStyle('left-shadow-target', block(100, 100, 'red'));
+var leftShadowRoot = attachShadow('left-shadow', leftHost, [leftTarget]);
+
+var rightTarget = elementWithStyle('right-target', block(50, 50, 'blue'));
+var rightLowerHost = elementWithStyle('right-lower-host', block(100, 100, 'purple'), [rightTarget]);
+var rightLowerShadowRoot = attachShadow('right-lower-shadow', rightLowerHost, [
+ elementWithStyle('right-lower-shadow-child', block(100, 100, 'pink'), [
+ element('slot')
+ ])]);
+
+var rightUpperHost = elementWithStyle('right-upper-host', block(250, 250, 'green'), [rightLowerHost]);
+var rightUpperShadowRoot = attachShadow('right-upper-shadow', rightUpperHost, [
+ elementWithStyle('right-shadow-child', block(200, 200, 'purple'), [
+ element('slot')
+ ])]);
+
+var bottomTarget = elementWithStyle('bottom-target', block(100, 100, '#666'));
+
+document.body.appendChild(elementWithStyle('host-parent', block(500, 500, '#eee'), [leftHost, rightUpperHost, bottomTarget]));
+
+function getUIScript()
+{
+ function xCenter(element) { return element.offsetLeft + element.offsetWidth / 2; }
+ function yCenter(element) { return element.offsetTop + element.offsetHeight / 2; }
+
+ return `
+ (function() {
+ uiController.touchDownAtPoint(${xCenter(leftTarget)}, ${yCenter(leftTarget)}, 1, function() {
+ uiController.touchDownAtPoint(${xCenter(rightTarget)}, ${yCenter(rightTarget)}, 2, function() {
+ uiController.touchDownAtPoint(${xCenter(bottomTarget)}, ${yCenter(bottomTarget)}, 3, function() {
+ uiController.liftUpAtPoint(${xCenter(leftTarget)}, ${yCenter(leftTarget)}, 2, function () {
+ uiController.liftUpAtPoint(${xCenter(rightTarget)}, ${yCenter(rightTarget)}, 1, function () {
+ uiController.liftUpAtPoint(${xCenter(bottomTarget)}, ${yCenter(bottomTarget)}, 0, function () {
+ uiController.uiScriptComplete("Done");
+ });
+ });
+ });
+ });
+ });
+ });
+ })();`
+}
+
+window._onload_ = function runTest()
+{
+ if (window.testRunner)
+ testRunner.dumpAsText();
+
+ function formatTouchList(list) {
+ var text = '';
+ for (var i = 0; i < list.length; i++) {
+ if (text)
+ text += ', ';
+ text += `${i}: ${list[i].target.treeName}`;
+ }
+ return `[${text}]`;
+ }
+
+ var output = '';
+
+ function logger(event) {
+ output += `${event.type} at ${this.treeName} with
+ target: ${event.target.treeName}
+ touches: ${formatTouchList(event.touches)}
+ targetTouches: ${formatTouchList(event.targetTouches)}
+ changedTouches: ${formatTouchList(event.changedTouches)}
+
+`;
+ }
+
+ function attachLoggers(node) {
+ node.addEventListener('touchstart', logger);
+ node.addEventListener('touchmove', logger);
+ node.addEventListener('touchend', logger);
+ }
+
+ document.body.treeName = 'body';
+ document.treeName = 'document';
+ attachLoggers(document);
+ attachLoggers(leftShadowRoot);
+ attachLoggers(rightUpperShadowRoot);
+ attachLoggers(rightLowerShadowRoot);
+
+ if (window.testRunner && testRunner.runUIScript) {
+ testRunner.waitUntilDone();
+ testRunner.runUIScript(getUIScript(), function(result) {
+ var pre = document.createElement('pre');
+ pre.textContent = output;
+ document.body.appendChild(pre);
+ testRunner.notifyDone();
+ });
+ }
+}
+
+</script>
+</body>
+</html>
Modified: trunk/LayoutTests/platform/mac/TestExpectations (195898 => 195899)
--- trunk/LayoutTests/platform/mac/TestExpectations 2016-01-30 18:09:44 UTC (rev 195898)
+++ trunk/LayoutTests/platform/mac/TestExpectations 2016-01-30 18:38:20 UTC (rev 195899)
@@ -1257,6 +1257,9 @@
webkit.org/b/149441 fast/shadow-dom/css-scoping-shadow-slotted-rule.html [ ImageOnlyFailure ]
webkit.org/b/149441 fast/shadow-dom/css-scoping-shadow-slot-display-override.html [ ImageOnlyFailure ]
+# Touch events is not enabled on Mac
+webkit.org/b/149592 fast/shadow-dom/touch-event-ios.html [ Failure ]
+
webkit.org/b/150225 fast/custom-elements [ Pass ]
# Times out in debug.
Modified: trunk/Source/WebCore/ChangeLog (195898 => 195899)
--- trunk/Source/WebCore/ChangeLog 2016-01-30 18:09:44 UTC (rev 195898)
+++ trunk/Source/WebCore/ChangeLog 2016-01-30 18:38:20 UTC (rev 195899)
@@ -1,3 +1,37 @@
+2016-01-30 Ryosuke Niwa <[email protected]>
+
+ TouchList should be retargeted
+ https://bugs.webkit.org/show_bug.cgi?id=149592
+
+ Reviewed by Antti Koivisto.
+
+ Retarget touch target's using the same algorithm as the one used for related targets instead of
+ EventRelatedNodeResolver which is removed in this patch.
+
+ Also enable the retargeting on iOS.
+
+ Test: fast/shadow-dom/touch-event-ios.html
+
+ * dom/EventContext.cpp:
+ (WebCore::TouchEventContext::TouchEventContext):
+ (WebCore::TouchEventContext::handleLocalEvents):
+ (WebCore::TouchEventContext::checkReachability):
+ * dom/EventContext.h:
+ (WebCore::toTouchEventContext):
+ (WebCore::EventContext::isUnreachableNode):
+ * dom/EventDispatcher.cpp:
+ (WebCore::EventRelatedNodeResolver): Deleted.
+ (WebCore::EventPath::EventPath):
+ (WebCore::EventDispatcher::dispatchEvent):
+ (WebCore::addRelatedNodeResolversForTouchList): Deleted.
+ (WebCore::EventPath::updateTouchLists): Deleted.
+ (WebCore::EventPath::setRelatedTarget): Removed superfluous UNUSED_PARAM since the argument is always used.
+ (WebCore::EventPath::retargetTouch): Extracted from updateTouchLists/setRelatedTarget. Clones Touch object
+ with the new target for each event context just like related targets.
+ (WebCore::EventPath::retargetTouchLists): Renamed from updateTouchLists. Calls retargetTouch on each Touch
+ object in each TouchList.
+ * dom/TouchEvent.h:
+
2016-01-30 Dave Hyatt <[email protected]>
Support break-after, break-before and break-inside.
Modified: trunk/Source/WebCore/dom/EventContext.cpp (195898 => 195899)
--- trunk/Source/WebCore/dom/EventContext.cpp 2016-01-30 18:09:44 UTC (rev 195898)
+++ trunk/Source/WebCore/dom/EventContext.cpp 2016-01-30 18:38:20 UTC (rev 195899)
@@ -90,7 +90,7 @@
return true;
}
-#if ENABLE(TOUCH_EVENTS) && !PLATFORM(IOS)
+#if ENABLE(TOUCH_EVENTS)
TouchEventContext::TouchEventContext(PassRefPtr<Node> node, PassRefPtr<EventTarget> currentTarget, PassRefPtr<EventTarget> target)
: EventContext(node, currentTarget, target)
, m_touches(TouchList::create())
@@ -105,16 +105,16 @@
void TouchEventContext::handleLocalEvents(Event& event) const
{
-#ifndef NDEBUG
+#if !ASSERT_DISABLED
checkReachability(m_touches.get());
checkReachability(m_targetTouches.get());
checkReachability(m_changedTouches.get());
#endif
ASSERT(is<TouchEvent>(event));
TouchEvent& touchEvent = downcast<TouchEvent>(event);
- touchEvent.setTouches(m_touches);
- touchEvent.setTargetTouches(m_targetTouches);
- touchEvent.setChangedTouches(m_changedTouches);
+ touchEvent.setTouches(m_touches.get());
+ touchEvent.setTargetTouches(m_targetTouches.get());
+ touchEvent.setChangedTouches(m_changedTouches.get());
EventContext::handleLocalEvents(event);
}
@@ -123,7 +123,7 @@
return true;
}
-#ifndef NDEBUG
+#if !ASSERT_DISABLED
void TouchEventContext::checkReachability(TouchList* touchList) const
{
size_t length = touchList->length();
Modified: trunk/Source/WebCore/dom/EventContext.h (195898 => 195899)
--- trunk/Source/WebCore/dom/EventContext.h 2016-01-30 18:09:44 UTC (rev 195898)
+++ trunk/Source/WebCore/dom/EventContext.h 2016-01-30 18:38:20 UTC (rev 195899)
@@ -35,7 +35,7 @@
namespace WebCore {
class Event;
-#if ENABLE(TOUCH_EVENTS) && !PLATFORM(IOS)
+#if ENABLE(TOUCH_EVENTS)
class TouchList;
#endif
@@ -54,7 +54,7 @@
virtual bool isTouchEventContext() const;
protected:
-#ifndef NDEBUG
+#if !ASSERT_DISABLED
bool isUnreachableNode(EventTarget*);
bool isReachable(Node*) const;
#endif
@@ -77,7 +77,7 @@
};
-#if ENABLE(TOUCH_EVENTS) && !PLATFORM(IOS)
+#if ENABLE(TOUCH_EVENTS)
class TouchEventContext final : public EventContext {
public:
TouchEventContext(PassRefPtr<Node>, PassRefPtr<EventTarget> currentTarget, PassRefPtr<EventTarget> target);
@@ -111,7 +111,7 @@
RefPtr<TouchList> m_touches;
RefPtr<TouchList> m_targetTouches;
RefPtr<TouchList> m_changedTouches;
-#ifndef NDEBUG
+#if !ASSERT_DISABLED
void checkReachability(TouchList*) const;
#endif
};
@@ -129,7 +129,7 @@
}
#endif // ENABLE(TOUCH_EVENTS) && !PLATFORM(IOS)
-#ifndef NDEBUG
+#if !ASSERT_DISABLED
inline bool EventContext::isUnreachableNode(EventTarget* target)
{
// FIXME: Checks also for SVG elements.
Modified: trunk/Source/WebCore/dom/EventDispatcher.cpp (195898 => 195899)
--- trunk/Source/WebCore/dom/EventDispatcher.cpp 2016-01-30 18:09:44 UTC (rev 195898)
+++ trunk/Source/WebCore/dom/EventDispatcher.cpp 2016-01-30 18:38:20 UTC (rev 195899)
@@ -87,7 +87,7 @@
EventContext& contextAt(size_t i) { return *m_path[i]; }
#if ENABLE(TOUCH_EVENTS)
- bool updateTouchLists(const TouchEvent&);
+ void retargetTouchLists(const TouchEvent&);
#endif
void setRelatedTarget(Node& origin, EventTarget&);
@@ -96,98 +96,14 @@
EventContext* lastContextIfExists() { return m_path.isEmpty() ? nullptr : m_path.last().get(); }
private:
-#if ENABLE(TOUCH_EVENTS) && !PLATFORM(IOS)
- void updateTouchListsInEventPath(const TouchList*, TouchEventContext::TouchListType);
+#if ENABLE(TOUCH_EVENTS)
+ void retargetTouch(TouchEventContext::TouchListType, const Touch&);
#endif
Event& m_event;
Vector<std::unique_ptr<EventContext>, 32> m_path;
};
-#if ENABLE(TOUCH_EVENTS) && !PLATFORM(IOS)
-// FIXME: Use RelatedNodeRetargeter instead.
-class EventRelatedNodeResolver {
-public:
- EventRelatedNodeResolver(Touch& touch, TouchEventContext::TouchListType touchListType)
- : m_relatedNode(*touch.target()->toNode())
- , m_relatedNodeTreeScope(m_relatedNode.treeScope())
- , m_relatedNodeInCurrentTreeScope(nullptr)
- , m_currentTreeScope(nullptr)
- , m_touch(&touch)
- , m_touchListType(touchListType)
- {
- ASSERT(touch.target()->toNode());
- }
-
- Touch* touch() const { return m_touch; }
- TouchEventContext::TouchListType touchListType() const { return m_touchListType; }
-
- Node* moveToParentOrShadowHost(Node& newTarget)
- {
- TreeScope& newTreeScope = newTarget.treeScope();
- if (&newTreeScope == m_currentTreeScope)
- return m_relatedNodeInCurrentTreeScope;
-
- if (m_currentTreeScope) {
- ASSERT(is<ShadowRoot>(m_currentTreeScope->rootNode()));
- ASSERT(&newTarget == downcast<ShadowRoot>(m_currentTreeScope->rootNode()).host());
- ASSERT(m_currentTreeScope->parentTreeScope() == &newTreeScope);
- }
-
- if (&newTreeScope == &m_relatedNodeTreeScope)
- m_relatedNodeInCurrentTreeScope = &m_relatedNode;
- else if (m_relatedNodeInCurrentTreeScope) {
- ASSERT(m_currentTreeScope);
- m_relatedNodeInCurrentTreeScope = &newTarget;
- } else {
- if (!m_currentTreeScope) {
- TreeScope* newTreeScopeAncestor = &newTreeScope;
- do {
- m_relatedNodeInCurrentTreeScope = findHostOfTreeScopeInTargetTreeScope(m_relatedNodeTreeScope, *newTreeScopeAncestor);
- newTreeScopeAncestor = newTreeScopeAncestor->parentTreeScope();
- if (newTreeScopeAncestor == &m_relatedNodeTreeScope) {
- m_relatedNodeInCurrentTreeScope = &m_relatedNode;
- break;
- }
- } while (newTreeScopeAncestor && !m_relatedNodeInCurrentTreeScope);
- }
- ASSERT(m_relatedNodeInCurrentTreeScope || findHostOfTreeScopeInTargetTreeScope(newTreeScope, m_relatedNodeTreeScope)
- || &newTreeScope.documentScope() != &m_relatedNodeTreeScope.documentScope());
- }
-
- m_currentTreeScope = &newTreeScope;
-
- return m_relatedNodeInCurrentTreeScope;
- }
-
- static Node* findHostOfTreeScopeInTargetTreeScope(const TreeScope& startingTreeScope, const TreeScope& targetScope)
- {
- ASSERT(&targetScope != &startingTreeScope);
- Node* previousHost = nullptr;
- for (const TreeScope* scope = &startingTreeScope; scope; scope = scope->parentTreeScope()) {
- if (scope == &targetScope) {
- ASSERT(previousHost);
- ASSERT_WITH_SECURITY_IMPLICATION(&previousHost->treeScope() == &targetScope);
- return previousHost;
- }
- if (is<ShadowRoot>(scope->rootNode()))
- previousHost = downcast<ShadowRoot>(scope->rootNode()).host();
- else
- ASSERT_WITH_SECURITY_IMPLICATION(!scope->parentTreeScope());
- }
- return nullptr;
- }
-
-private:
- Node& m_relatedNode;
- const TreeScope& m_relatedNodeTreeScope;
- Node* m_relatedNodeInCurrentTreeScope;
- TreeScope* m_currentTreeScope;
- Touch* m_touch;
- TouchEventContext::TouchListType m_touchListType;
-};
-#endif
-
inline EventTarget* eventTargetRespectingTargetRules(Node& referenceNode)
{
if (is<PseudoElement>(referenceNode))
@@ -311,11 +227,9 @@
if (EventTarget* relatedTarget = event.relatedTarget())
eventPath.setRelatedTarget(*node, *relatedTarget);
-#if ENABLE(TOUCH_EVENTS) && !PLATFORM(IOS)
- if (is<TouchEvent>(event)) {
- if (!eventPath.updateTouchLists(downcast<TouchEvent>(event)))
- return true;
- }
+#if ENABLE(TOUCH_EVENTS)
+ if (is<TouchEvent>(event))
+ eventPath.retargetTouchLists(downcast<TouchEvent>(event));
#endif
ChildNodesLazySnapshot::takeChildNodesLazySnapshot();
@@ -403,7 +317,7 @@
#endif
bool isMouseOrFocusEvent = event.isMouseEvent() || event.isFocusEvent();
-#if ENABLE(TOUCH_EVENTS) && !PLATFORM(IOS)
+#if ENABLE(TOUCH_EVENTS)
bool isTouchEvent = event.isTouchEvent();
#endif
EventTarget* target = nullptr;
@@ -417,7 +331,7 @@
EventTarget* currentTarget = eventTargetRespectingTargetRules(*node);
if (isMouseOrFocusEvent)
m_path.append(std::make_unique<MouseOrFocusEventContext>(node, currentTarget, target));
-#if ENABLE(TOUCH_EVENTS) && !PLATFORM(IOS)
+#if ENABLE(TOUCH_EVENTS)
else if (isTouchEvent)
m_path.append(std::make_unique<TouchEventContext>(node, currentTarget, target));
#endif
@@ -459,42 +373,6 @@
}
}
-#if ENABLE(TOUCH_EVENTS) && !PLATFORM(IOS)
-static void addRelatedNodeResolversForTouchList(Vector<EventRelatedNodeResolver, 16>& touchTargetResolvers, TouchList* touchList, TouchEventContext::TouchListType type)
-{
- const size_t touchListSize = touchList->length();
- for (size_t i = 0; i < touchListSize; ++i)
- touchTargetResolvers.append(EventRelatedNodeResolver(*touchList->item(i), type));
-}
-
-bool EventPath::updateTouchLists(const TouchEvent& touchEvent)
-{
- if (!touchEvent.touches() || !touchEvent.targetTouches() || !touchEvent.changedTouches())
- return false;
-
- Vector<EventRelatedNodeResolver, 16> touchTargetResolvers;
- const size_t touchNodeCount = touchEvent.touches()->length() + touchEvent.targetTouches()->length() + touchEvent.changedTouches()->length();
- touchTargetResolvers.reserveInitialCapacity(touchNodeCount);
-
- addRelatedNodeResolversForTouchList(touchTargetResolvers, touchEvent.touches(), TouchEventContext::Touches);
- addRelatedNodeResolversForTouchList(touchTargetResolvers, touchEvent.targetTouches(), TouchEventContext::TargetTouches);
- addRelatedNodeResolversForTouchList(touchTargetResolvers, touchEvent.changedTouches(), TouchEventContext::ChangedTouches);
-
- ASSERT(touchTargetResolvers.size() == touchNodeCount);
- for (auto& eventPath : m_path) {
- TouchEventContext& context = toTouchEventContext(*eventPath);
- Node& nodeToMoveTo = *context.node();
- for (size_t resolverIndex = 0; resolverIndex < touchNodeCount; ++resolverIndex) {
- EventRelatedNodeResolver& currentResolver = touchTargetResolvers[resolverIndex];
- Node* nodeInCurrentTreeScope = currentResolver.moveToParentOrShadowHost(nodeToMoveTo);
- ASSERT(currentResolver.touch());
- context.touchList(currentResolver.touchListType())->append(currentResolver.touch()->cloneWithNewTarget(nodeInCurrentTreeScope));
- }
- }
- return true;
-}
-#endif
-
class RelatedNodeRetargeter {
public:
RelatedNodeRetargeter(Node& relatedNode, TreeScope& targetTreeScope)
@@ -622,7 +500,6 @@
void EventPath::setRelatedTarget(Node& origin, EventTarget& relatedTarget)
{
- UNUSED_PARAM(origin);
Node* relatedNode = relatedTarget.toNode();
if (!relatedNode || m_path.isEmpty())
return;
@@ -661,6 +538,50 @@
}
}
+#if ENABLE(TOUCH_EVENTS)
+void EventPath::retargetTouch(TouchEventContext::TouchListType touchListType, const Touch& touch)
+{
+ EventTarget* eventTarget = touch.target();
+ if (!eventTarget)
+ return;
+
+ Node* targetNode = eventTarget->toNode();
+ if (!targetNode)
+ return;
+
+ RelatedNodeRetargeter retargeter(*targetNode, downcast<MouseOrFocusEventContext>(*m_path[0]).node()->treeScope());
+ TreeScope* previousTreeScope = nullptr;
+ for (auto& context : m_path) {
+ TreeScope& currentTreeScope = context->node()->treeScope();
+ if (UNLIKELY(previousTreeScope && ¤tTreeScope != previousTreeScope))
+ retargeter.moveToNewTreeScope(previousTreeScope, currentTreeScope);
+
+ Node* currentRelatedNode = retargeter.currentNode(currentTreeScope);
+ downcast<TouchEventContext>(*context).touchList(touchListType)->append(touch.cloneWithNewTarget(currentRelatedNode));
+
+ previousTreeScope = ¤tTreeScope;
+ }
+}
+
+void EventPath::retargetTouchLists(const TouchEvent& touchEvent)
+{
+ if (touchEvent.touches()) {
+ for (size_t i = 0; i < touchEvent.touches()->length(); ++i)
+ retargetTouch(TouchEventContext::Touches, *touchEvent.touches()->item(i));
+ }
+
+ if (touchEvent.targetTouches()) {
+ for (size_t i = 0; i < touchEvent.targetTouches()->length(); ++i)
+ retargetTouch(TouchEventContext::TargetTouches, *touchEvent.targetTouches()->item(i));
+ }
+
+ if (touchEvent.changedTouches()) {
+ for (size_t i = 0; i < touchEvent.changedTouches()->length(); ++i)
+ retargetTouch(TouchEventContext::ChangedTouches, *touchEvent.changedTouches()->item(i));
+ }
+}
+#endif
+
bool EventPath::hasEventListeners(const AtomicString& eventType) const
{
for (auto& eventPath : m_path) {
Modified: trunk/Source/WebCore/dom/TouchEvent.h (195898 => 195899)
--- trunk/Source/WebCore/dom/TouchEvent.h 2016-01-30 18:09:44 UTC (rev 195898)
+++ trunk/Source/WebCore/dom/TouchEvent.h 2016-01-30 18:38:20 UTC (rev 195899)
@@ -65,9 +65,9 @@
TouchList* targetTouches() const { return m_targetTouches.get(); }
TouchList* changedTouches() const { return m_changedTouches.get(); }
- void setTouches(PassRefPtr<TouchList> touches) { m_touches = touches; }
- void setTargetTouches(PassRefPtr<TouchList> targetTouches) { m_targetTouches = targetTouches; }
- void setChangedTouches(PassRefPtr<TouchList> changedTouches) { m_changedTouches = changedTouches; }
+ void setTouches(RefPtr<TouchList>&& touches) { m_touches = touches; }
+ void setTargetTouches(RefPtr<TouchList>&& targetTouches) { m_targetTouches = targetTouches; }
+ void setChangedTouches(RefPtr<TouchList>&& changedTouches) { m_changedTouches = changedTouches; }
virtual bool isTouchEvent() const override;
Modified: trunk/Tools/ChangeLog (195898 => 195899)
--- trunk/Tools/ChangeLog 2016-01-30 18:09:44 UTC (rev 195898)
+++ trunk/Tools/ChangeLog 2016-01-30 18:38:20 UTC (rev 195899)
@@ -1,3 +1,26 @@
+2016-01-30 Ryosuke Niwa <[email protected]>
+
+ TouchList should be retargeted
+ https://bugs.webkit.org/show_bug.cgi?id=149592
+
+ Reviewed by Antti Koivisto.
+
+ Added touchDownAtPoint and liftUpAtPoint to UIScriptController so that we can test touch events with
+ multiple touch targets on iOS. fast/shadow-dom/touch-event-ios.html uses this new testing feature.
+
+ * WebKitTestRunner/UIScriptContext/Bindings/UIScriptController.idl:
+ * WebKitTestRunner/UIScriptContext/UIScriptController.cpp:
+ (WTR::UIScriptController::touchDownAtPoint): Added.
+ (WTR::UIScriptController::liftUpAtPoint): Added.
+ * WebKitTestRunner/UIScriptContext/UIScriptController.h:
+ * WebKitTestRunner/ios/HIDEventGenerator.h:
+ * WebKitTestRunner/ios/HIDEventGenerator.mm:
+ (-[HIDEventGenerator touchDown:touchCount:completionBlock:]): Added. Sends touch down and waits.
+ (-[HIDEventGenerator liftUp:touchCount:completionBlock:]): Ditto for lift up.
+ * WebKitTestRunner/ios/UIScriptControllerIOS.mm:
+ (WTR::UIScriptController::touchDownAtPoint): Added.
+ (WTR::UIScriptController::liftUpAtPoint): Added.
+
2016-01-30 Yusuke Suzuki <[email protected]>
Enable SamplingProfiler on POSIX environment
Modified: trunk/Tools/WebKitTestRunner/UIScriptContext/Bindings/UIScriptController.idl (195898 => 195899)
--- trunk/Tools/WebKitTestRunner/UIScriptContext/Bindings/UIScriptController.idl 2016-01-30 18:09:44 UTC (rev 195898)
+++ trunk/Tools/WebKitTestRunner/UIScriptContext/Bindings/UIScriptController.idl 2016-01-30 18:38:20 UTC (rev 195899)
@@ -30,8 +30,10 @@
void zoomToScale(double scale, object callback);
// Interaction.
- // These functions post events asynchronously. The callback is fired when the events have been disptached, but any
+ // These functions post events asynchronously. The callback is fired when the events have been dispatched, but any
// resulting behavior may also be asynchronous.
+ void touchDownAtPoint(long x, long y, long touchCount, object callback);
+ void liftUpAtPoint(long x, long y, long touchCount, object callback);
void singleTapAtPoint(long x, long y, object callback);
void doubleTapAtPoint(long x, long y, object callback);
Modified: trunk/Tools/WebKitTestRunner/UIScriptContext/UIScriptController.cpp (195898 => 195899)
--- trunk/Tools/WebKitTestRunner/UIScriptContext/UIScriptController.cpp 2016-01-30 18:09:44 UTC (rev 195898)
+++ trunk/Tools/WebKitTestRunner/UIScriptContext/UIScriptController.cpp 2016-01-30 18:38:20 UTC (rev 195899)
@@ -118,6 +118,14 @@
{
}
+void UIScriptController::touchDownAtPoint(long x, long y, long touchCount, JSValueRef)
+{
+}
+
+void UIScriptController::liftUpAtPoint(long x, long y, long touchCount, JSValueRef)
+{
+}
+
void UIScriptController::singleTapAtPoint(long x, long y, JSValueRef)
{
}
Modified: trunk/Tools/WebKitTestRunner/UIScriptContext/UIScriptController.h (195898 => 195899)
--- trunk/Tools/WebKitTestRunner/UIScriptContext/UIScriptController.h 2016-01-30 18:09:44 UTC (rev 195898)
+++ trunk/Tools/WebKitTestRunner/UIScriptContext/UIScriptController.h 2016-01-30 18:38:20 UTC (rev 195899)
@@ -47,6 +47,8 @@
void doAsyncTask(JSValueRef callback);
void zoomToScale(double scale, JSValueRef callback);
+ void touchDownAtPoint(long x, long y, long touchCount, JSValueRef callback);
+ void liftUpAtPoint(long x, long y, long touchCount, JSValueRef callback);
void singleTapAtPoint(long x, long y, JSValueRef callback);
void doubleTapAtPoint(long x, long y, JSValueRef callback);
Modified: trunk/Tools/WebKitTestRunner/ios/HIDEventGenerator.h (195898 => 195899)
--- trunk/Tools/WebKitTestRunner/ios/HIDEventGenerator.h 2016-01-30 18:09:44 UTC (rev 195898)
+++ trunk/Tools/WebKitTestRunner/ios/HIDEventGenerator.h 2016-01-30 18:38:20 UTC (rev 195899)
@@ -35,6 +35,8 @@
- (void)touchDown:(CGPoint)location;
- (void)liftUp:(CGPoint)location;
- (void)moveToPoints:(CGPoint*)locations touchCount:(NSUInteger)count duration:(NSTimeInterval)seconds;
+- (void)touchDown:(CGPoint)location touchCount:(NSUInteger)count completionBlock:(void (^)(void))completionBlock;
+- (void)liftUp:(CGPoint)location touchCount:(NSUInteger)count completionBlock:(void (^)(void))completionBlock;
// Taps
- (void)tap:(CGPoint)location completionBlock:(void (^)(void))completionBlock;
Modified: trunk/Tools/WebKitTestRunner/ios/HIDEventGenerator.mm (195898 => 195899)
--- trunk/Tools/WebKitTestRunner/ios/HIDEventGenerator.mm 2016-01-30 18:09:44 UTC (rev 195898)
+++ trunk/Tools/WebKitTestRunner/ios/HIDEventGenerator.mm 2016-01-30 18:38:20 UTC (rev 195899)
@@ -370,6 +370,18 @@
[self _updateTouchPoints:newLocations count:touchCount];
}
+- (void)touchDown:(CGPoint)location touchCount:(NSUInteger)count completionBlock:(void (^)(void))completionBlock
+{
+ [self touchDown:location touchCount:count];
+ [self _sendMarkerHIDEventWithCompletionBlock:completionBlock];
+}
+
+- (void)liftUp:(CGPoint)location touchCount:(NSUInteger)count completionBlock:(void (^)(void))completionBlock
+{
+ [self liftUp:location touchCount:count];
+ [self _sendMarkerHIDEventWithCompletionBlock:completionBlock];
+}
+
- (void)sendTaps:(int)tapCount location:(CGPoint)location withNumberOfTouches:(int)touchCount completionBlock:(void (^)(void))completionBlock
{
struct timespec doubleDelay = { 0, static_cast<long>(multiTapInterval) };
Modified: trunk/Tools/WebKitTestRunner/ios/UIScriptControllerIOS.mm (195898 => 195899)
--- trunk/Tools/WebKitTestRunner/ios/UIScriptControllerIOS.mm 2016-01-30 18:09:44 UTC (rev 195898)
+++ trunk/Tools/WebKitTestRunner/ios/UIScriptControllerIOS.mm 2016-01-30 18:38:20 UTC (rev 195899)
@@ -79,6 +79,30 @@
return point;
}
+void UIScriptController::touchDownAtPoint(long x, long y, long touchCount, JSValueRef callback)
+{
+ unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);
+
+ auto location = globalToContentCoordinates(TestController::singleton().mainWebView()->platformView(), x, y);
+ [[HIDEventGenerator sharedHIDEventGenerator] touchDown:location touchCount:touchCount completionBlock:^{
+ if (!m_context)
+ return;
+ m_context->asyncTaskComplete(callbackID);
+ }];
+}
+
+void UIScriptController::liftUpAtPoint(long x, long y, long touchCount, JSValueRef callback)
+{
+ unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);
+
+ auto location = globalToContentCoordinates(TestController::singleton().mainWebView()->platformView(), x, y);
+ [[HIDEventGenerator sharedHIDEventGenerator] liftUp:location touchCount:touchCount completionBlock:^{
+ if (!m_context)
+ return;
+ m_context->asyncTaskComplete(callbackID);
+ }];
+}
+
void UIScriptController::singleTapAtPoint(long x, long y, JSValueRef callback)
{
unsigned callbackID = m_context->prepareForAsyncTask(callback, CallbackTypeNonPersistent);