| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Neither the name of Google Inc. nor the names of its | 10 * * Neither the name of Google Inc. nor the names of its |
| (...skipping 24 matching lines...) Expand all Loading... |
| 35 #include "core/events/TouchEvent.h" | 35 #include "core/events/TouchEvent.h" |
| 36 #include "core/events/TouchEventContext.h" | 36 #include "core/events/TouchEventContext.h" |
| 37 #include "core/html/HTMLSlotElement.h" | 37 #include "core/html/HTMLSlotElement.h" |
| 38 #include "core/svg/SVGUseElement.h" | 38 #include "core/svg/SVGUseElement.h" |
| 39 | 39 |
| 40 namespace blink { | 40 namespace blink { |
| 41 | 41 |
| 42 EventTarget* EventPath::eventTargetRespectingTargetRules(Node& referenceNode) | 42 EventTarget* EventPath::eventTargetRespectingTargetRules(Node& referenceNode) |
| 43 { | 43 { |
| 44 if (referenceNode.isPseudoElement()) { | 44 if (referenceNode.isPseudoElement()) { |
| 45 ASSERT(referenceNode.parentNode()); | 45 DCHECK(referenceNode.parentNode()); |
| 46 return referenceNode.parentNode(); | 46 return referenceNode.parentNode(); |
| 47 } | 47 } |
| 48 | 48 |
| 49 return &referenceNode; | 49 return &referenceNode; |
| 50 } | 50 } |
| 51 | 51 |
| 52 static inline bool shouldStopAtShadowRoot(Event& event, ShadowRoot& shadowRoot,
EventTarget& target) | 52 static inline bool shouldStopAtShadowRoot(Event& event, ShadowRoot& shadowRoot,
EventTarget& target) |
| 53 { | 53 { |
| 54 if (shadowRoot.isV1()) { | 54 if (shadowRoot.isV1()) { |
| 55 // In v1, an event is scoped by default unless event.composed flag is se
t. | 55 // In v1, an event is scoped by default unless event.composed flag is se
t. |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 96 if (eventPathShouldBeEmptyFor(*m_node, m_event)) | 96 if (eventPathShouldBeEmptyFor(*m_node, m_event)) |
| 97 return; | 97 return; |
| 98 | 98 |
| 99 calculatePath(); | 99 calculatePath(); |
| 100 calculateAdjustedTargets(); | 100 calculateAdjustedTargets(); |
| 101 calculateTreeOrderAndSetNearestAncestorClosedTree(); | 101 calculateTreeOrderAndSetNearestAncestorClosedTree(); |
| 102 } | 102 } |
| 103 | 103 |
| 104 void EventPath::calculatePath() | 104 void EventPath::calculatePath() |
| 105 { | 105 { |
| 106 ASSERT(m_node); | 106 DCHECK(m_node); |
| 107 ASSERT(m_nodeEventContexts.isEmpty()); | 107 DCHECK(m_nodeEventContexts.isEmpty()); |
| 108 m_node->updateDistribution(); | 108 m_node->updateDistribution(); |
| 109 | 109 |
| 110 // For performance and memory usage reasons we want to store the | 110 // For performance and memory usage reasons we want to store the |
| 111 // path using as few bytes as possible and with as few allocations | 111 // path using as few bytes as possible and with as few allocations |
| 112 // as possible which is why we gather the data on the stack before | 112 // as possible which is why we gather the data on the stack before |
| 113 // storing it in a perfectly sized m_nodeEventContexts Vector. | 113 // storing it in a perfectly sized m_nodeEventContexts Vector. |
| 114 HeapVector<Member<Node>, 64> nodesInPath; | 114 HeapVector<Member<Node>, 64> nodesInPath; |
| 115 Node* current = m_node; | 115 Node* current = m_node; |
| 116 | 116 |
| 117 // Exclude nodes in SVG <use>'s shadow tree from event path. | 117 // Exclude nodes in SVG <use>'s shadow tree from event path. |
| 118 // See crbug.com/630870 | 118 // See crbug.com/630870 |
| 119 while (current->isSVGElement()) { | 119 while (current->isSVGElement()) { |
| 120 SVGUseElement* correspondingUseElement = toSVGElement(current)->correspo
ndingUseElement(); | 120 SVGUseElement* correspondingUseElement = toSVGElement(current)->correspo
ndingUseElement(); |
| 121 if (!correspondingUseElement) | 121 if (!correspondingUseElement) |
| 122 break; | 122 break; |
| 123 current = correspondingUseElement; | 123 current = correspondingUseElement; |
| 124 } | 124 } |
| 125 | 125 |
| 126 nodesInPath.append(current); | 126 nodesInPath.append(current); |
| 127 while (current) { | 127 while (current) { |
| 128 if (m_event && current->keepEventInNode(m_event)) | 128 if (m_event && current->keepEventInNode(m_event)) |
| 129 break; | 129 break; |
| 130 HeapVector<Member<InsertionPoint>, 8> insertionPoints; | 130 HeapVector<Member<InsertionPoint>, 8> insertionPoints; |
| 131 collectDestinationInsertionPoints(*current, insertionPoints); | 131 collectDestinationInsertionPoints(*current, insertionPoints); |
| 132 if (!insertionPoints.isEmpty()) { | 132 if (!insertionPoints.isEmpty()) { |
| 133 for (const auto& insertionPoint : insertionPoints) { | 133 for (const auto& insertionPoint : insertionPoints) { |
| 134 if (insertionPoint->isShadowInsertionPoint()) { | 134 if (insertionPoint->isShadowInsertionPoint()) { |
| 135 ShadowRoot* containingShadowRoot = insertionPoint->containin
gShadowRoot(); | 135 ShadowRoot* containingShadowRoot = insertionPoint->containin
gShadowRoot(); |
| 136 ASSERT(containingShadowRoot); | 136 DCHECK(containingShadowRoot); |
| 137 if (!containingShadowRoot->isOldest()) | 137 if (!containingShadowRoot->isOldest()) |
| 138 nodesInPath.append(containingShadowRoot->olderShadowRoot
()); | 138 nodesInPath.append(containingShadowRoot->olderShadowRoot
()); |
| 139 } | 139 } |
| 140 nodesInPath.append(insertionPoint); | 140 nodesInPath.append(insertionPoint); |
| 141 } | 141 } |
| 142 current = insertionPoints.last(); | 142 current = insertionPoints.last(); |
| 143 continue; | 143 continue; |
| 144 } | 144 } |
| 145 if (current->isChildOfV1ShadowHost()) { | 145 if (current->isChildOfV1ShadowHost()) { |
| 146 if (HTMLSlotElement* slot = current->assignedSlot()) { | 146 if (HTMLSlotElement* slot = current->assignedSlot()) { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 175 HeapHashMap<Member<const TreeScope>, Member<TreeScopeEventContext>> treeScop
eEventContextMap; | 175 HeapHashMap<Member<const TreeScope>, Member<TreeScopeEventContext>> treeScop
eEventContextMap; |
| 176 for (const auto& treeScopeEventContext : m_treeScopeEventContexts) | 176 for (const auto& treeScopeEventContext : m_treeScopeEventContexts) |
| 177 treeScopeEventContextMap.add(&treeScopeEventContext->treeScope(), treeSc
opeEventContext.get()); | 177 treeScopeEventContextMap.add(&treeScopeEventContext->treeScope(), treeSc
opeEventContext.get()); |
| 178 TreeScopeEventContext* rootTree = nullptr; | 178 TreeScopeEventContext* rootTree = nullptr; |
| 179 for (const auto& treeScopeEventContext : m_treeScopeEventContexts) { | 179 for (const auto& treeScopeEventContext : m_treeScopeEventContexts) { |
| 180 // Use olderShadowRootOrParentTreeScope here for parent-child relationsh
ips. | 180 // Use olderShadowRootOrParentTreeScope here for parent-child relationsh
ips. |
| 181 // See the definition of trees of trees in the Shadow DOM spec: | 181 // See the definition of trees of trees in the Shadow DOM spec: |
| 182 // http://w3c.github.io/webcomponents/spec/shadow/ | 182 // http://w3c.github.io/webcomponents/spec/shadow/ |
| 183 TreeScope* parent = treeScopeEventContext.get()->treeScope().olderShadow
RootOrParentTreeScope(); | 183 TreeScope* parent = treeScopeEventContext.get()->treeScope().olderShadow
RootOrParentTreeScope(); |
| 184 if (!parent) { | 184 if (!parent) { |
| 185 ASSERT(!rootTree); | 185 DCHECK(!rootTree); |
| 186 rootTree = treeScopeEventContext.get(); | 186 rootTree = treeScopeEventContext.get(); |
| 187 continue; | 187 continue; |
| 188 } | 188 } |
| 189 // TODO(tkent): Add a stream printer for HashMap::iterator. |
| 189 ASSERT(treeScopeEventContextMap.find(parent) != treeScopeEventContextMap
.end()); | 190 ASSERT(treeScopeEventContextMap.find(parent) != treeScopeEventContextMap
.end()); |
| 190 treeScopeEventContextMap.find(parent)->value->addChild(*treeScopeEventCo
ntext.get()); | 191 treeScopeEventContextMap.find(parent)->value->addChild(*treeScopeEventCo
ntext.get()); |
| 191 } | 192 } |
| 192 ASSERT(rootTree); | 193 DCHECK(rootTree); |
| 193 rootTree->calculateTreeOrderAndSetNearestAncestorClosedTree(0, nullptr); | 194 rootTree->calculateTreeOrderAndSetNearestAncestorClosedTree(0, nullptr); |
| 194 } | 195 } |
| 195 | 196 |
| 196 TreeScopeEventContext* EventPath::ensureTreeScopeEventContext(Node* currentTarge
t, TreeScope* treeScope, TreeScopeEventContextMap& treeScopeEventContextMap) | 197 TreeScopeEventContext* EventPath::ensureTreeScopeEventContext(Node* currentTarge
t, TreeScope* treeScope, TreeScopeEventContextMap& treeScopeEventContextMap) |
| 197 { | 198 { |
| 198 if (!treeScope) | 199 if (!treeScope) |
| 199 return nullptr; | 200 return nullptr; |
| 200 TreeScopeEventContext* treeScopeEventContext; | 201 TreeScopeEventContext* treeScopeEventContext; |
| 201 bool isNewEntry; | 202 bool isNewEntry; |
| 202 { | 203 { |
| (...skipping 22 matching lines...) Expand all Loading... |
| 225 | 226 |
| 226 TreeScopeEventContextMap treeScopeEventContextMap; | 227 TreeScopeEventContextMap treeScopeEventContextMap; |
| 227 TreeScopeEventContext* lastTreeScopeEventContext = nullptr; | 228 TreeScopeEventContext* lastTreeScopeEventContext = nullptr; |
| 228 | 229 |
| 229 for (size_t i = 0; i < size(); ++i) { | 230 for (size_t i = 0; i < size(); ++i) { |
| 230 Node* currentNode = at(i).node(); | 231 Node* currentNode = at(i).node(); |
| 231 TreeScope& currentTreeScope = currentNode->treeScope(); | 232 TreeScope& currentTreeScope = currentNode->treeScope(); |
| 232 if (lastTreeScope != ¤tTreeScope) { | 233 if (lastTreeScope != ¤tTreeScope) { |
| 233 lastTreeScopeEventContext = ensureTreeScopeEventContext(currentNode,
¤tTreeScope, treeScopeEventContextMap); | 234 lastTreeScopeEventContext = ensureTreeScopeEventContext(currentNode,
¤tTreeScope, treeScopeEventContextMap); |
| 234 } | 235 } |
| 235 ASSERT(lastTreeScopeEventContext); | 236 DCHECK(lastTreeScopeEventContext); |
| 236 at(i).setTreeScopeEventContext(lastTreeScopeEventContext); | 237 at(i).setTreeScopeEventContext(lastTreeScopeEventContext); |
| 237 lastTreeScope = ¤tTreeScope; | 238 lastTreeScope = ¤tTreeScope; |
| 238 } | 239 } |
| 239 m_treeScopeEventContexts.appendRange(treeScopeEventContextMap.values().begin
(), treeScopeEventContextMap.values().end()); | 240 m_treeScopeEventContexts.appendRange(treeScopeEventContextMap.values().begin
(), treeScopeEventContextMap.values().end()); |
| 240 } | 241 } |
| 241 | 242 |
| 242 void EventPath::buildRelatedNodeMap(const Node& relatedNode, RelatedTargetMap& r
elatedTargetMap) | 243 void EventPath::buildRelatedNodeMap(const Node& relatedNode, RelatedTargetMap& r
elatedTargetMap) |
| 243 { | 244 { |
| 244 EventPath* relatedTargetEventPath = new EventPath(const_cast<Node&>(relatedN
ode)); | 245 EventPath* relatedTargetEventPath = new EventPath(const_cast<Node&>(relatedN
ode)); |
| 245 for (size_t i = 0; i < relatedTargetEventPath->m_treeScopeEventContexts.size
(); ++i) { | 246 for (size_t i = 0; i < relatedTargetEventPath->m_treeScopeEventContexts.size
(); ++i) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 256 HeapVector<Member<TreeScope>, 32> parentTreeScopes; | 257 HeapVector<Member<TreeScope>, 32> parentTreeScopes; |
| 257 EventTarget* relatedNode = nullptr; | 258 EventTarget* relatedNode = nullptr; |
| 258 for (TreeScope* current = &scope; current; current = current->olderShadowRoo
tOrParentTreeScope()) { | 259 for (TreeScope* current = &scope; current; current = current->olderShadowRoo
tOrParentTreeScope()) { |
| 259 parentTreeScopes.append(current); | 260 parentTreeScopes.append(current); |
| 260 RelatedTargetMap::const_iterator iter = relatedTargetMap.find(current); | 261 RelatedTargetMap::const_iterator iter = relatedTargetMap.find(current); |
| 261 if (iter != relatedTargetMap.end() && iter->value) { | 262 if (iter != relatedTargetMap.end() && iter->value) { |
| 262 relatedNode = iter->value; | 263 relatedNode = iter->value; |
| 263 break; | 264 break; |
| 264 } | 265 } |
| 265 } | 266 } |
| 266 ASSERT(relatedNode); | 267 DCHECK(relatedNode); |
| 267 for (const auto& entry : parentTreeScopes) | 268 for (const auto& entry : parentTreeScopes) |
| 268 relatedTargetMap.add(entry, relatedNode); | 269 relatedTargetMap.add(entry, relatedNode); |
| 269 | 270 |
| 270 return relatedNode; | 271 return relatedNode; |
| 271 } | 272 } |
| 272 | 273 |
| 273 void EventPath::adjustForRelatedTarget(Node& target, EventTarget* relatedTarget) | 274 void EventPath::adjustForRelatedTarget(Node& target, EventTarget* relatedTarget) |
| 274 { | 275 { |
| 275 if (!relatedTarget) | 276 if (!relatedTarget) |
| 276 return; | 277 return; |
| 277 Node* relatedNode = relatedTarget->toNode(); | 278 Node* relatedNode = relatedTarget->toNode(); |
| 278 if (!relatedNode) | 279 if (!relatedNode) |
| 279 return; | 280 return; |
| 280 if (target.document() != relatedNode->document()) | 281 if (target.document() != relatedNode->document()) |
| 281 return; | 282 return; |
| 282 retargetRelatedTarget(*relatedNode); | 283 retargetRelatedTarget(*relatedNode); |
| 283 shrinkForRelatedTarget(target, *relatedNode); | 284 shrinkForRelatedTarget(target, *relatedNode); |
| 284 } | 285 } |
| 285 | 286 |
| 286 void EventPath::retargetRelatedTarget(const Node& relatedTargetNode) | 287 void EventPath::retargetRelatedTarget(const Node& relatedTargetNode) |
| 287 { | 288 { |
| 288 RelatedTargetMap relatedNodeMap; | 289 RelatedTargetMap relatedNodeMap; |
| 289 buildRelatedNodeMap(relatedTargetNode, relatedNodeMap); | 290 buildRelatedNodeMap(relatedTargetNode, relatedNodeMap); |
| 290 | 291 |
| 291 for (const auto& treeScopeEventContext : m_treeScopeEventContexts) { | 292 for (const auto& treeScopeEventContext : m_treeScopeEventContexts) { |
| 292 EventTarget* adjustedRelatedTarget = findRelatedNode(treeScopeEventConte
xt->treeScope(), relatedNodeMap); | 293 EventTarget* adjustedRelatedTarget = findRelatedNode(treeScopeEventConte
xt->treeScope(), relatedNodeMap); |
| 293 ASSERT(adjustedRelatedTarget); | 294 DCHECK(adjustedRelatedTarget); |
| 294 treeScopeEventContext.get()->setRelatedTarget(adjustedRelatedTarget); | 295 treeScopeEventContext.get()->setRelatedTarget(adjustedRelatedTarget); |
| 295 } | 296 } |
| 296 } | 297 } |
| 297 | 298 |
| 298 void EventPath::shrinkForRelatedTarget(const Node& target, const Node& relatedTa
rget) | 299 void EventPath::shrinkForRelatedTarget(const Node& target, const Node& relatedTa
rget) |
| 299 { | 300 { |
| 300 if (!target.isInShadowTree() && !relatedTarget.isInShadowTree()) | 301 if (!target.isInShadowTree() && !relatedTarget.isInShadowTree()) |
| 301 return; | 302 return; |
| 302 for (size_t i = 0; i < size(); ++i) { | 303 for (size_t i = 0; i < size(); ++i) { |
| 303 if (at(i).target() == at(i).relatedTarget()) { | 304 if (at(i).target() == at(i).relatedTarget()) { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 320 adjustedTouches.append(&touchEventContext->touches()); | 321 adjustedTouches.append(&touchEventContext->touches()); |
| 321 adjustedTargetTouches.append(&touchEventContext->targetTouches()); | 322 adjustedTargetTouches.append(&touchEventContext->targetTouches()); |
| 322 adjustedChangedTouches.append(&touchEventContext->changedTouches()); | 323 adjustedChangedTouches.append(&touchEventContext->changedTouches()); |
| 323 treeScopes.append(&treeScopeEventContext->treeScope()); | 324 treeScopes.append(&treeScopeEventContext->treeScope()); |
| 324 } | 325 } |
| 325 | 326 |
| 326 adjustTouchList(touchEvent.touches(), adjustedTouches, treeScopes); | 327 adjustTouchList(touchEvent.touches(), adjustedTouches, treeScopes); |
| 327 adjustTouchList(touchEvent.targetTouches(), adjustedTargetTouches, treeScope
s); | 328 adjustTouchList(touchEvent.targetTouches(), adjustedTargetTouches, treeScope
s); |
| 328 adjustTouchList(touchEvent.changedTouches(), adjustedChangedTouches, treeSco
pes); | 329 adjustTouchList(touchEvent.changedTouches(), adjustedChangedTouches, treeSco
pes); |
| 329 | 330 |
| 330 #if ENABLE(ASSERT) | 331 #if DCHECK_IS_ON() |
| 331 for (const auto& treeScopeEventContext : m_treeScopeEventContexts) { | 332 for (const auto& treeScopeEventContext : m_treeScopeEventContexts) { |
| 332 TreeScope& treeScope = treeScopeEventContext->treeScope(); | 333 TreeScope& treeScope = treeScopeEventContext->treeScope(); |
| 333 TouchEventContext* touchEventContext = treeScopeEventContext->touchEvent
Context(); | 334 TouchEventContext* touchEventContext = treeScopeEventContext->touchEvent
Context(); |
| 334 checkReachability(treeScope, touchEventContext->touches()); | 335 checkReachability(treeScope, touchEventContext->touches()); |
| 335 checkReachability(treeScope, touchEventContext->targetTouches()); | 336 checkReachability(treeScope, touchEventContext->targetTouches()); |
| 336 checkReachability(treeScope, touchEventContext->changedTouches()); | 337 checkReachability(treeScope, touchEventContext->changedTouches()); |
| 337 } | 338 } |
| 338 #endif | 339 #endif |
| 339 } | 340 } |
| 340 | 341 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 354 RelatedTargetMap relatedNodeMap; | 355 RelatedTargetMap relatedNodeMap; |
| 355 buildRelatedNodeMap(*targetNode, relatedNodeMap); | 356 buildRelatedNodeMap(*targetNode, relatedNodeMap); |
| 356 for (size_t j = 0; j < treeScopes.size(); ++j) { | 357 for (size_t j = 0; j < treeScopes.size(); ++j) { |
| 357 adjustedTouchList[j]->append(touch.cloneWithNewTarget(findRelatedNod
e(*treeScopes[j], relatedNodeMap))); | 358 adjustedTouchList[j]->append(touch.cloneWithNewTarget(findRelatedNod
e(*treeScopes[j], relatedNodeMap))); |
| 358 } | 359 } |
| 359 } | 360 } |
| 360 } | 361 } |
| 361 | 362 |
| 362 const NodeEventContext& EventPath::topNodeEventContext() | 363 const NodeEventContext& EventPath::topNodeEventContext() |
| 363 { | 364 { |
| 364 ASSERT(!isEmpty()); | 365 DCHECK(!isEmpty()); |
| 365 return last(); | 366 return last(); |
| 366 } | 367 } |
| 367 | 368 |
| 368 void EventPath::ensureWindowEventContext() | 369 void EventPath::ensureWindowEventContext() |
| 369 { | 370 { |
| 370 ASSERT(m_event); | 371 DCHECK(m_event); |
| 371 if (!m_windowEventContext) | 372 if (!m_windowEventContext) |
| 372 m_windowEventContext = new WindowEventContext(*m_event, topNodeEventCont
ext()); | 373 m_windowEventContext = new WindowEventContext(*m_event, topNodeEventCont
ext()); |
| 373 } | 374 } |
| 374 | 375 |
| 375 #if ENABLE(ASSERT) | 376 #if DCHECK_IS_ON() |
| 376 void EventPath::checkReachability(TreeScope& treeScope, TouchList& touchList) | 377 void EventPath::checkReachability(TreeScope& treeScope, TouchList& touchList) |
| 377 { | 378 { |
| 378 for (size_t i = 0; i < touchList.length(); ++i) | 379 for (size_t i = 0; i < touchList.length(); ++i) |
| 379 ASSERT(touchList.item(i)->target()->toNode()->treeScope().isInclusiveOld
erSiblingShadowRootOrAncestorTreeScopeOf(treeScope)); | 380 DCHECK(touchList.item(i)->target()->toNode()->treeScope().isInclusiveOld
erSiblingShadowRootOrAncestorTreeScopeOf(treeScope)); |
| 380 } | 381 } |
| 381 #endif | 382 #endif |
| 382 | 383 |
| 383 DEFINE_TRACE(EventPath) | 384 DEFINE_TRACE(EventPath) |
| 384 { | 385 { |
| 385 visitor->trace(m_nodeEventContexts); | 386 visitor->trace(m_nodeEventContexts); |
| 386 visitor->trace(m_node); | 387 visitor->trace(m_node); |
| 387 visitor->trace(m_event); | 388 visitor->trace(m_event); |
| 388 visitor->trace(m_treeScopeEventContexts); | 389 visitor->trace(m_treeScopeEventContexts); |
| 389 visitor->trace(m_windowEventContext); | 390 visitor->trace(m_windowEventContext); |
| 390 } | 391 } |
| 391 | 392 |
| 392 } // namespace blink | 393 } // namespace blink |
| OLD | NEW |