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 13 matching lines...) Expand all Loading... |
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
25 */ | 25 */ |
26 | 26 |
27 #include "config.h" | 27 #include "config.h" |
28 #include "core/events/EventPath.h" | 28 #include "core/events/EventPath.h" |
29 | 29 |
30 #include "EventNames.h" | 30 #include "EventNames.h" |
31 #include "RuntimeEnabledFeatures.h" | 31 #include "RuntimeEnabledFeatures.h" |
32 #include "SVGNames.h" | 32 #include "SVGNames.h" |
33 #include "core/dom/FullscreenElementStack.h" | 33 #include "core/dom/FullscreenElementStack.h" |
34 #include "core/dom/shadow/ElementShadow.h" | 34 #include "core/dom/Touch.h" |
| 35 #include "core/dom/TouchList.h" |
35 #include "core/dom/shadow/InsertionPoint.h" | 36 #include "core/dom/shadow/InsertionPoint.h" |
36 #include "core/dom/shadow/ShadowRoot.h" | 37 #include "core/dom/shadow/ShadowRoot.h" |
37 #include "core/html/shadow/HTMLShadowElement.h" | 38 #include "core/events/FocusEvent.h" |
| 39 #include "core/events/MouseEvent.h" |
| 40 #include "core/events/TouchEvent.h" |
38 #include "core/svg/SVGElementInstance.h" | 41 #include "core/svg/SVGElementInstance.h" |
39 #include "core/svg/SVGUseElement.h" | 42 #include "core/svg/SVGUseElement.h" |
40 | 43 |
41 namespace WebCore { | 44 namespace WebCore { |
42 | 45 |
43 Node* EventPath::parent(Node* node) | 46 Node* EventPath::parent(Node* node) |
44 { | 47 { |
45 EventPath eventPath(node); | 48 EventPath eventPath(node); |
46 return eventPath.size() > 1 ? eventPath[1].node() : 0; | 49 return eventPath.size() > 1 ? eventPath[1].node() : 0; |
47 } | 50 } |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
116 , m_event(0) | 119 , m_event(0) |
117 { | 120 { |
118 resetWith(node); | 121 resetWith(node); |
119 } | 122 } |
120 | 123 |
121 void EventPath::resetWith(Node* node) | 124 void EventPath::resetWith(Node* node) |
122 { | 125 { |
123 ASSERT(node); | 126 ASSERT(node); |
124 m_node = node; | 127 m_node = node; |
125 m_eventContexts.clear(); | 128 m_eventContexts.clear(); |
| 129 m_sharedEventContexts.clear(); |
126 calculatePath(); | 130 calculatePath(); |
127 calculateAdjustedTargets(); | 131 calculateAdjustedTargets(); |
128 calculateAdjustedEventPathForEachNode(); | 132 calculateAdjustedEventPath(); |
129 } | 133 } |
130 | 134 |
131 void EventPath::addEventContext(Node* node) | 135 void EventPath::addEventContext(Node* node) |
132 { | 136 { |
133 m_eventContexts.append(EventContext(node, eventTargetRespectingTargetRules(n
ode))); | 137 m_eventContexts.append(EventContext(node, eventTargetRespectingTargetRules(n
ode))); |
134 } | 138 } |
135 | 139 |
136 void EventPath::calculatePath() | 140 void EventPath::calculatePath() |
137 { | 141 { |
138 ASSERT(m_node); | 142 ASSERT(m_node); |
(...skipping 27 matching lines...) Expand all Loading... |
166 current = current->shadowHost(); | 170 current = current->shadowHost(); |
167 addEventContext(current); | 171 addEventContext(current); |
168 } else { | 172 } else { |
169 current = current->parentNode(); | 173 current = current->parentNode(); |
170 if (current) | 174 if (current) |
171 addEventContext(current); | 175 addEventContext(current); |
172 } | 176 } |
173 } | 177 } |
174 } | 178 } |
175 | 179 |
176 void EventPath::calculateAdjustedEventPathForEachNode() | 180 void EventPath::calculateAdjustedEventPath() |
177 { | 181 { |
178 if (!RuntimeEnabledFeatures::shadowDOMEnabled()) | 182 if (!RuntimeEnabledFeatures::shadowDOMEnabled()) |
179 return; | 183 return; |
180 TreeScope* lastScope = 0; | 184 for (size_t i = 0; i < m_sharedEventContexts.size(); ++i) { |
181 for (size_t i = 0; i < size(); ++i) { | 185 TreeScopeEventContext* sharedEventContext = m_sharedEventContexts[i].get
(); |
182 TreeScope* currentScope = &at(i).node()->treeScope(); | |
183 if (currentScope == lastScope) { | |
184 // Fast path. | |
185 at(i).setEventPath(at(i - 1).eventPath()); | |
186 continue; | |
187 } | |
188 lastScope = currentScope; | |
189 Vector<RefPtr<Node> > nodes; | 186 Vector<RefPtr<Node> > nodes; |
190 nodes.reserveInitialCapacity(size()); | 187 nodes.reserveInitialCapacity(size()); |
191 for (size_t j = 0; j < size(); ++j) { | 188 for (size_t i = 0; i < size(); ++i) { |
192 if (at(j).node()->treeScope().isInclusiveAncestorOf(*currentScope)) | 189 if (at(i).node()->treeScope().isInclusiveAncestorOf(sharedEventConte
xt->treeScope())) |
193 nodes.append(at(j).node()); | 190 nodes.append(at(i).node()); |
194 } | 191 } |
195 at(i).adoptEventPath(nodes); | 192 sharedEventContext->adoptEventPath(nodes); |
196 } | 193 } |
197 } | 194 } |
198 | 195 |
199 #ifndef NDEBUG | 196 #ifndef NDEBUG |
200 static inline bool movedFromOlderToYounger(const TreeScope& lastTreeScope, const
TreeScope& currentTreeScope) | 197 static inline bool movedFromOlderToYounger(const TreeScope& lastTreeScope, const
TreeScope& currentTreeScope) |
201 { | 198 { |
202 Node* rootNode = lastTreeScope.rootNode(); | 199 Node* rootNode = lastTreeScope.rootNode(); |
203 return rootNode->isShadowRoot() && toShadowRoot(rootNode)->youngerShadowRoot
() == currentTreeScope.rootNode(); | 200 return rootNode->isShadowRoot() && toShadowRoot(rootNode)->youngerShadowRoot
() == currentTreeScope.rootNode(); |
204 } | 201 } |
205 | 202 |
(...skipping 13 matching lines...) Expand all Loading... |
219 { | 216 { |
220 return currentTreeScope.parentTreeScope() == &lastTreeScope; | 217 return currentTreeScope.parentTreeScope() == &lastTreeScope; |
221 } | 218 } |
222 | 219 |
223 void EventPath::calculateAdjustedTargets() | 220 void EventPath::calculateAdjustedTargets() |
224 { | 221 { |
225 Vector<Node*, 32> targetStack; | 222 Vector<Node*, 32> targetStack; |
226 const TreeScope* lastTreeScope = 0; | 223 const TreeScope* lastTreeScope = 0; |
227 bool isSVGElement = at(0).node()->isSVGElement(); | 224 bool isSVGElement = at(0).node()->isSVGElement(); |
228 | 225 |
| 226 typedef HashMap<const TreeScope*, RefPtr<TreeScopeEventContext> > SharedEven
tContextMap; |
| 227 SharedEventContextMap sharedEventContextMap; |
| 228 TreeScopeEventContext* lastSharedEventContext = 0; |
| 229 |
229 for (size_t i = 0; i < size(); ++i) { | 230 for (size_t i = 0; i < size(); ++i) { |
230 Node* current = at(i).node(); | 231 Node* current = at(i).node(); |
231 const TreeScope& currentTreeScope = current->treeScope(); | 232 TreeScope& currentTreeScope = current->treeScope(); |
232 if (targetStack.isEmpty()) { | 233 if (targetStack.isEmpty()) { |
233 targetStack.append(current); | 234 targetStack.append(current); |
234 } else if (*lastTreeScope != currentTreeScope && !isSVGElement) { | 235 } else if (lastTreeScope != ¤tTreeScope && !isSVGElement) { |
235 if (movedFromParentToChild(*lastTreeScope, currentTreeScope)) { | 236 if (movedFromParentToChild(*lastTreeScope, currentTreeScope)) { |
236 targetStack.append(targetStack.last()); | 237 targetStack.append(targetStack.last()); |
237 } else if (movedFromChildToParent(*lastTreeScope, currentTreeScope))
{ | 238 } else if (movedFromChildToParent(*lastTreeScope, currentTreeScope))
{ |
238 ASSERT(!targetStack.isEmpty()); | 239 ASSERT(!targetStack.isEmpty()); |
239 targetStack.removeLast(); | 240 targetStack.removeLast(); |
240 if (targetStack.isEmpty()) | 241 if (targetStack.isEmpty()) |
241 targetStack.append(current); | 242 targetStack.append(current); |
242 } else { | 243 } else { |
243 ASSERT(movedFromYoungerToOlder(*lastTreeScope, currentTreeScope)
|| movedFromOlderToYounger(*lastTreeScope, currentTreeScope)); | 244 ASSERT(movedFromYoungerToOlder(*lastTreeScope, currentTreeScope)
|| movedFromOlderToYounger(*lastTreeScope, currentTreeScope)); |
244 ASSERT(!targetStack.isEmpty()); | 245 ASSERT(!targetStack.isEmpty()); |
245 targetStack.removeLast(); | 246 targetStack.removeLast(); |
246 if (targetStack.isEmpty()) | 247 if (targetStack.isEmpty()) |
247 targetStack.append(current); | 248 targetStack.append(current); |
248 else | 249 else |
249 targetStack.append(targetStack.last()); | 250 targetStack.append(targetStack.last()); |
250 } | 251 } |
251 } | 252 } |
252 at(i).setTarget(eventTargetRespectingTargetRules(targetStack.last())); | 253 if (lastTreeScope != ¤tTreeScope) { |
| 254 SharedEventContextMap::AddResult addResult = sharedEventContextMap.a
dd(¤tTreeScope, TreeScopeEventContext::create(currentTreeScope)); |
| 255 lastSharedEventContext = addResult.iterator->value.get(); |
| 256 if (addResult.isNewEntry) |
| 257 lastSharedEventContext->setTarget(eventTargetRespectingTargetRul
es(targetStack.last())); |
| 258 } |
| 259 at(i).setSharedEventContext(lastSharedEventContext); |
253 lastTreeScope = ¤tTreeScope; | 260 lastTreeScope = ¤tTreeScope; |
254 } | 261 } |
| 262 m_sharedEventContexts.appendRange(sharedEventContextMap.values().begin(), sh
aredEventContextMap.values().end()); |
| 263 } |
| 264 |
| 265 void EventPath::buildRelatedNodeMap(const Node* relatedNode, RelatedTargetMap& r
elatedTargetMap) |
| 266 { |
| 267 TreeScope* lastTreeScope = 0; |
| 268 EventPath eventPath(const_cast<Node*>(relatedNode)); |
| 269 for (size_t i = 0; i < eventPath.size(); ++i) { |
| 270 TreeScope* treeScope = &eventPath[i].node()->treeScope(); |
| 271 if (treeScope != lastTreeScope) |
| 272 relatedTargetMap.add(treeScope, eventPath[i].target()); |
| 273 lastTreeScope = treeScope; |
| 274 } |
255 } | 275 } |
256 | 276 |
| 277 EventTarget* EventPath::findRelatedNode(TreeScope* scope, RelatedTargetMap& rela
tedTargetMap) |
| 278 { |
| 279 Vector<TreeScope*, 32> parentTreeScopes; |
| 280 EventTarget* relatedNode = 0; |
| 281 while (scope) { |
| 282 parentTreeScopes.append(scope); |
| 283 RelatedTargetMap::const_iterator found = relatedTargetMap.find(scope); |
| 284 if (found != relatedTargetMap.end()) { |
| 285 relatedNode = found->value; |
| 286 break; |
| 287 } |
| 288 scope = scope->parentTreeScope(); |
| 289 } |
| 290 for (Vector<TreeScope*, 32>::iterator iter = parentTreeScopes.begin(); iter
< parentTreeScopes.end(); ++iter) |
| 291 relatedTargetMap.add(*iter, relatedNode); |
| 292 return relatedNode; |
| 293 } |
| 294 |
| 295 void EventPath::adjustForRelatedTarget(Node* target, EventTarget* relatedTarget) |
| 296 { |
| 297 if (!target) |
| 298 return; |
| 299 if (!relatedTarget) |
| 300 return; |
| 301 Node* relatedNode = relatedTarget->toNode(); |
| 302 if (!relatedNode) |
| 303 return; |
| 304 RelatedTargetMap relatedNodeMap; |
| 305 buildRelatedNodeMap(relatedNode, relatedNodeMap); |
| 306 |
| 307 for (size_t i = 0; i < m_sharedEventContexts.size(); ++i) { |
| 308 TreeScopeEventContext* sharedEventContext = m_sharedEventContexts[i].get
(); |
| 309 sharedEventContext->setRelatedTarget(findRelatedNode(&sharedEventContext
->treeScope(), relatedNodeMap)); |
| 310 } |
| 311 |
| 312 shrinkIfNeeded(target, relatedTarget); |
| 313 } |
| 314 |
| 315 void EventPath::shrinkIfNeeded(const Node* target, const EventTarget* relatedTar
get) |
| 316 { |
| 317 // Synthetic mouse events can have a relatedTarget which is identical to the
target. |
| 318 bool targetIsIdenticalToToRelatedTarget = (target == relatedTarget); |
| 319 |
| 320 for (size_t i = 0; i < size(); ++i) { |
| 321 if (targetIsIdenticalToToRelatedTarget) { |
| 322 if (target->treeScope().rootNode() == at(i).node()) { |
| 323 shrink(i + 1); |
| 324 break; |
| 325 } |
| 326 } else if (at(i).target() == at(i).relatedTarget()) { |
| 327 // Event dispatching should be stopped here. |
| 328 shrink(i); |
| 329 break; |
| 330 } |
| 331 } |
| 332 } |
| 333 |
| 334 void EventPath::adjustForTouchEvent(Node* node, TouchEvent& touchEvent) |
| 335 { |
| 336 Vector<TouchList*> adjustedTouches; |
| 337 Vector<TouchList*> adjustedTargetTouches; |
| 338 Vector<TouchList*> adjustedChangedTouches; |
| 339 Vector<TreeScope*> treeScopes; |
| 340 |
| 341 for (size_t i = 0; i < m_sharedEventContexts.size(); ++i) { |
| 342 TouchEventContext* touchEventContext = m_sharedEventContexts[i]->ensureT
ouchEventContext(); |
| 343 adjustedTouches.append(&touchEventContext->touches()); |
| 344 adjustedTargetTouches.append(&touchEventContext->targetTouches()); |
| 345 adjustedChangedTouches.append(&touchEventContext->changedTouches()); |
| 346 treeScopes.append(&m_sharedEventContexts[i]->treeScope()); |
| 347 } |
| 348 |
| 349 adjustTouchList(node, touchEvent.touches(), adjustedTouches, treeScopes); |
| 350 adjustTouchList(node, touchEvent.targetTouches(), adjustedTargetTouches, tre
eScopes); |
| 351 adjustTouchList(node, touchEvent.changedTouches(), adjustedChangedTouches, t
reeScopes); |
| 352 |
| 353 #ifndef NDEBUG |
| 354 for (size_t i = 0; i < m_sharedEventContexts.size(); ++i) { |
| 355 TreeScope& treeScope = m_sharedEventContexts[i]->treeScope(); |
| 356 TouchEventContext* touchEventContext = m_sharedEventContexts[i]->touchEv
entContext(); |
| 357 checkReachability(treeScope, touchEventContext->touches()); |
| 358 checkReachability(treeScope, touchEventContext->targetTouches()); |
| 359 checkReachability(treeScope, touchEventContext->changedTouches()); |
| 360 } |
| 361 #endif |
| 362 } |
| 363 |
| 364 void EventPath::adjustTouchList(const Node* node, const TouchList* touchList, Ve
ctor<TouchList*> adjustedTouchList, const Vector<TreeScope*>& treeScopes) |
| 365 { |
| 366 if (!touchList) |
| 367 return; |
| 368 for (size_t i = 0; i < touchList->length(); ++i) { |
| 369 const Touch& touch = *touchList->item(i); |
| 370 RelatedTargetMap relatedNodeMap; |
| 371 buildRelatedNodeMap(touch.target()->toNode(), relatedNodeMap); |
| 372 for (size_t j = 0; j < treeScopes.size(); ++j) { |
| 373 adjustedTouchList[j]->append(touch.cloneWithNewTarget(findRelatedNod
e(treeScopes[j], relatedNodeMap))); |
| 374 } |
| 375 } |
| 376 } |
| 377 |
| 378 #ifndef NDEBUG |
| 379 void EventPath::checkReachability(TreeScope& treeScope, TouchList& touchList) |
| 380 { |
| 381 for (size_t i = 0; i < touchList.length(); ++i) |
| 382 ASSERT(touchList.item(i)->target()->toNode()->treeScope().isInclusiveAnc
estorOf(treeScope)); |
| 383 } |
| 384 #endif |
| 385 |
257 } // namespace | 386 } // namespace |
OLD | NEW |