| Index: Source/core/events/EventPath.cpp
|
| diff --git a/Source/core/events/EventPath.cpp b/Source/core/events/EventPath.cpp
|
| index ca9a57dcdfac8f53816988b3479cfcec779d74ac..c641fe0ea53abb1a11cc28728fccc6ad4461edde 100644
|
| --- a/Source/core/events/EventPath.cpp
|
| +++ b/Source/core/events/EventPath.cpp
|
| @@ -31,10 +31,13 @@
|
| #include "RuntimeEnabledFeatures.h"
|
| #include "SVGNames.h"
|
| #include "core/dom/FullscreenElementStack.h"
|
| -#include "core/dom/shadow/ElementShadow.h"
|
| +#include "core/dom/Touch.h"
|
| +#include "core/dom/TouchList.h"
|
| #include "core/dom/shadow/InsertionPoint.h"
|
| #include "core/dom/shadow/ShadowRoot.h"
|
| -#include "core/html/shadow/HTMLShadowElement.h"
|
| +#include "core/events/FocusEvent.h"
|
| +#include "core/events/MouseEvent.h"
|
| +#include "core/events/TouchEvent.h"
|
| #include "core/svg/SVGElementInstance.h"
|
| #include "core/svg/SVGUseElement.h"
|
|
|
| @@ -123,9 +126,10 @@ void EventPath::resetWith(Node* node)
|
| ASSERT(node);
|
| m_node = node;
|
| m_eventContexts.clear();
|
| + m_sharedEventContexts.clear();
|
| calculatePath();
|
| calculateAdjustedTargets();
|
| - calculateAdjustedEventPathForEachNode();
|
| + calculateAdjustedEventPath();
|
| }
|
|
|
| void EventPath::addEventContext(Node* node)
|
| @@ -173,26 +177,19 @@ void EventPath::calculatePath()
|
| }
|
| }
|
|
|
| -void EventPath::calculateAdjustedEventPathForEachNode()
|
| +void EventPath::calculateAdjustedEventPath()
|
| {
|
| if (!RuntimeEnabledFeatures::shadowDOMEnabled())
|
| return;
|
| - TreeScope* lastScope = 0;
|
| - for (size_t i = 0; i < size(); ++i) {
|
| - TreeScope* currentScope = &at(i).node()->treeScope();
|
| - if (currentScope == lastScope) {
|
| - // Fast path.
|
| - at(i).setEventPath(at(i - 1).eventPath());
|
| - continue;
|
| - }
|
| - lastScope = currentScope;
|
| + for (size_t i = 0; i < m_sharedEventContexts.size(); ++i) {
|
| + TreeScopeEventContext* sharedEventContext = m_sharedEventContexts[i].get();
|
| Vector<RefPtr<Node> > nodes;
|
| nodes.reserveInitialCapacity(size());
|
| - for (size_t j = 0; j < size(); ++j) {
|
| - if (at(j).node()->treeScope().isInclusiveAncestorOf(*currentScope))
|
| - nodes.append(at(j).node());
|
| + for (size_t i = 0; i < size(); ++i) {
|
| + if (at(i).node()->treeScope().isInclusiveAncestorOf(sharedEventContext->treeScope()))
|
| + nodes.append(at(i).node());
|
| }
|
| - at(i).adoptEventPath(nodes);
|
| + sharedEventContext->adoptEventPath(nodes);
|
| }
|
| }
|
|
|
| @@ -226,12 +223,16 @@ void EventPath::calculateAdjustedTargets()
|
| const TreeScope* lastTreeScope = 0;
|
| bool isSVGElement = at(0).node()->isSVGElement();
|
|
|
| + typedef HashMap<const TreeScope*, RefPtr<TreeScopeEventContext> > SharedEventContextMap;
|
| + SharedEventContextMap sharedEventContextMap;
|
| + TreeScopeEventContext* lastSharedEventContext = 0;
|
| +
|
| for (size_t i = 0; i < size(); ++i) {
|
| Node* current = at(i).node();
|
| - const TreeScope& currentTreeScope = current->treeScope();
|
| + TreeScope& currentTreeScope = current->treeScope();
|
| if (targetStack.isEmpty()) {
|
| targetStack.append(current);
|
| - } else if (*lastTreeScope != currentTreeScope && !isSVGElement) {
|
| + } else if (lastTreeScope != ¤tTreeScope && !isSVGElement) {
|
| if (movedFromParentToChild(*lastTreeScope, currentTreeScope)) {
|
| targetStack.append(targetStack.last());
|
| } else if (movedFromChildToParent(*lastTreeScope, currentTreeScope)) {
|
| @@ -249,9 +250,137 @@ void EventPath::calculateAdjustedTargets()
|
| targetStack.append(targetStack.last());
|
| }
|
| }
|
| - at(i).setTarget(eventTargetRespectingTargetRules(targetStack.last()));
|
| + if (lastTreeScope != ¤tTreeScope) {
|
| + SharedEventContextMap::AddResult addResult = sharedEventContextMap.add(¤tTreeScope, TreeScopeEventContext::create(currentTreeScope));
|
| + lastSharedEventContext = addResult.iterator->value.get();
|
| + if (addResult.isNewEntry)
|
| + lastSharedEventContext->setTarget(eventTargetRespectingTargetRules(targetStack.last()));
|
| + }
|
| + at(i).setSharedEventContext(lastSharedEventContext);
|
| lastTreeScope = ¤tTreeScope;
|
| }
|
| + m_sharedEventContexts.appendRange(sharedEventContextMap.values().begin(), sharedEventContextMap.values().end());
|
| +}
|
| +
|
| +void EventPath::buildRelatedNodeMap(const Node* relatedNode, RelatedTargetMap& relatedTargetMap)
|
| +{
|
| + TreeScope* lastTreeScope = 0;
|
| + EventPath eventPath(const_cast<Node*>(relatedNode));
|
| + for (size_t i = 0; i < eventPath.size(); ++i) {
|
| + TreeScope* treeScope = &eventPath[i].node()->treeScope();
|
| + if (treeScope != lastTreeScope)
|
| + relatedTargetMap.add(treeScope, eventPath[i].target());
|
| + lastTreeScope = treeScope;
|
| + }
|
| +}
|
| +
|
| +EventTarget* EventPath::findRelatedNode(TreeScope* scope, RelatedTargetMap& relatedTargetMap)
|
| +{
|
| + Vector<TreeScope*, 32> parentTreeScopes;
|
| + EventTarget* relatedNode = 0;
|
| + while (scope) {
|
| + parentTreeScopes.append(scope);
|
| + RelatedTargetMap::const_iterator found = relatedTargetMap.find(scope);
|
| + if (found != relatedTargetMap.end()) {
|
| + relatedNode = found->value;
|
| + break;
|
| + }
|
| + scope = scope->parentTreeScope();
|
| + }
|
| + for (Vector<TreeScope*, 32>::iterator iter = parentTreeScopes.begin(); iter < parentTreeScopes.end(); ++iter)
|
| + relatedTargetMap.add(*iter, relatedNode);
|
| + return relatedNode;
|
| +}
|
| +
|
| +void EventPath::adjustForRelatedTarget(Node* target, EventTarget* relatedTarget)
|
| +{
|
| + if (!target)
|
| + return;
|
| + if (!relatedTarget)
|
| + return;
|
| + Node* relatedNode = relatedTarget->toNode();
|
| + if (!relatedNode)
|
| + return;
|
| + RelatedTargetMap relatedNodeMap;
|
| + buildRelatedNodeMap(relatedNode, relatedNodeMap);
|
| +
|
| + for (size_t i = 0; i < m_sharedEventContexts.size(); ++i) {
|
| + TreeScopeEventContext* sharedEventContext = m_sharedEventContexts[i].get();
|
| + sharedEventContext->setRelatedTarget(findRelatedNode(&sharedEventContext->treeScope(), relatedNodeMap));
|
| + }
|
| +
|
| + shrinkIfNeeded(target, relatedTarget);
|
| +}
|
| +
|
| +void EventPath::shrinkIfNeeded(const Node* target, const EventTarget* relatedTarget)
|
| +{
|
| + // Synthetic mouse events can have a relatedTarget which is identical to the target.
|
| + bool targetIsIdenticalToToRelatedTarget = (target == relatedTarget);
|
| +
|
| + for (size_t i = 0; i < size(); ++i) {
|
| + if (targetIsIdenticalToToRelatedTarget) {
|
| + if (target->treeScope().rootNode() == at(i).node()) {
|
| + shrink(i + 1);
|
| + break;
|
| + }
|
| + } else if (at(i).target() == at(i).relatedTarget()) {
|
| + // Event dispatching should be stopped here.
|
| + shrink(i);
|
| + break;
|
| + }
|
| + }
|
| }
|
|
|
| +void EventPath::adjustForTouchEvent(Node* node, TouchEvent& touchEvent)
|
| +{
|
| + Vector<TouchList*> adjustedTouches;
|
| + Vector<TouchList*> adjustedTargetTouches;
|
| + Vector<TouchList*> adjustedChangedTouches;
|
| + Vector<TreeScope*> treeScopes;
|
| +
|
| + for (size_t i = 0; i < m_sharedEventContexts.size(); ++i) {
|
| + TouchEventContext* touchEventContext = m_sharedEventContexts[i]->ensureTouchEventContext();
|
| + adjustedTouches.append(&touchEventContext->touches());
|
| + adjustedTargetTouches.append(&touchEventContext->targetTouches());
|
| + adjustedChangedTouches.append(&touchEventContext->changedTouches());
|
| + treeScopes.append(&m_sharedEventContexts[i]->treeScope());
|
| + }
|
| +
|
| + adjustTouchList(node, touchEvent.touches(), adjustedTouches, treeScopes);
|
| + adjustTouchList(node, touchEvent.targetTouches(), adjustedTargetTouches, treeScopes);
|
| + adjustTouchList(node, touchEvent.changedTouches(), adjustedChangedTouches, treeScopes);
|
| +
|
| +#ifndef NDEBUG
|
| + for (size_t i = 0; i < m_sharedEventContexts.size(); ++i) {
|
| + TreeScope& treeScope = m_sharedEventContexts[i]->treeScope();
|
| + TouchEventContext* touchEventContext = m_sharedEventContexts[i]->touchEventContext();
|
| + checkReachability(treeScope, touchEventContext->touches());
|
| + checkReachability(treeScope, touchEventContext->targetTouches());
|
| + checkReachability(treeScope, touchEventContext->changedTouches());
|
| + }
|
| +#endif
|
| +}
|
| +
|
| +void EventPath::adjustTouchList(const Node* node, const TouchList* touchList, Vector<TouchList*> adjustedTouchList, const Vector<TreeScope*>& treeScopes)
|
| +{
|
| + if (!touchList)
|
| + return;
|
| + for (size_t i = 0; i < touchList->length(); ++i) {
|
| + const Touch& touch = *touchList->item(i);
|
| + RelatedTargetMap relatedNodeMap;
|
| + buildRelatedNodeMap(touch.target()->toNode(), relatedNodeMap);
|
| + for (size_t j = 0; j < treeScopes.size(); ++j) {
|
| + adjustedTouchList[j]->append(touch.cloneWithNewTarget(findRelatedNode(treeScopes[j], relatedNodeMap)));
|
| + }
|
| + }
|
| +}
|
| +
|
| +#ifndef NDEBUG
|
| +void EventPath::checkReachability(TreeScope& treeScope, TouchList& touchList)
|
| +{
|
| + for (size_t i = 0; i < touchList.length(); ++i)
|
| + ASSERT(touchList.item(i)->target()->toNode()->treeScope().isInclusiveAncestorOf(treeScope));
|
| +}
|
| +#endif
|
| +
|
| } // namespace
|
|
|