Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "core/input/PointerEventManager.h" | 5 #include "core/input/PointerEventManager.h" |
| 6 | 6 |
| 7 #include "core/dom/ElementTraversal.h" | 7 #include "core/dom/ElementTraversal.h" |
| 8 #include "core/dom/shadow/FlatTreeTraversal.h" | 8 #include "core/dom/shadow/FlatTreeTraversal.h" |
| 9 #include "core/events/MouseEvent.h" | 9 #include "core/events/MouseEvent.h" |
| 10 #include "core/html/HTMLCanvasElement.h" | 10 #include "core/html/HTMLCanvasElement.h" |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 72 HTMLCanvasElement* canvas = Traversal<HTMLCanvasElement>::firstAncestorOrSel f(*element); | 72 HTMLCanvasElement* canvas = Traversal<HTMLCanvasElement>::firstAncestorOrSel f(*element); |
| 73 // In this case, the event target is canvas and mouse rerouting doesn't happ en. | 73 // In this case, the event target is canvas and mouse rerouting doesn't happ en. |
| 74 if (canvas == element) | 74 if (canvas == element) |
| 75 return mouseEvent; | 75 return mouseEvent; |
| 76 String region = canvas->getIdFromControl(element); | 76 String region = canvas->getIdFromControl(element); |
| 77 PlatformMouseEvent newMouseEvent = mouseEvent; | 77 PlatformMouseEvent newMouseEvent = mouseEvent; |
| 78 newMouseEvent.setRegion(region); | 78 newMouseEvent.setRegion(region); |
| 79 return newMouseEvent; | 79 return newMouseEvent; |
| 80 } | 80 } |
| 81 | 81 |
| 82 void findCommonAncestor( | |
|
mustaq
2016/04/20 16:09:05
s/findCommonAncestor/buildAncestorChainsAndFindCom
dtapuska
2016/04/20 19:42:28
Can we add some comments around this in terms of t
Navid Zolghadr
2016/04/21 14:46:41
Done.
| |
| 83 EventTarget* exitedTarget, EventTarget* enteredTarget, | |
| 84 HeapVector<Member<Node>, 32> &exitedAncestors, | |
| 85 HeapVector<Member<Node>, 32> &enteredAncestors, | |
| 86 size_t& exitedAncestorsCommonParentIndex, | |
| 87 size_t& enteredAncestorsCommonParentIndex) | |
| 88 { | |
| 89 if (isInDocument(exitedTarget)) { | |
| 90 Node* exitedNode = exitedTarget->toNode(); | |
| 91 exitedNode->updateDistribution(); | |
| 92 for (Node* node = exitedNode; node; node = FlatTreeTraversal::parent(*no de)) | |
| 93 exitedAncestors.append(node); | |
| 94 } | |
| 95 | |
| 96 if (isInDocument(enteredTarget)) { | |
| 97 Node* enteredNode = enteredTarget->toNode(); | |
| 98 enteredNode->updateDistribution(); | |
| 99 for (Node* node = enteredNode; node; node = FlatTreeTraversal::parent(*n ode)) | |
| 100 enteredAncestors.append(node); | |
| 101 } | |
| 102 | |
| 103 exitedAncestorsCommonParentIndex = exitedAncestors.size(); | |
|
mustaq
2016/04/20 16:09:05
Add DCHECKs to emphasize that we are not subtracti
Navid Zolghadr
2016/04/21 14:46:41
Why is that needed though? The for/while condition
| |
| 104 enteredAncestorsCommonParentIndex = enteredAncestors.size(); | |
| 105 for (size_t i = exitedAncestors.size(), j = enteredAncestors.size(); | |
|
mustaq
2016/04/20 16:09:06
Nit: I think a |while| loop modifying the |*Index|
Navid Zolghadr
2016/04/21 14:46:41
Done.
| |
| 106 i > 0 && j > 0; --i, --j) { | |
| 107 if (exitedAncestors[i-1] != enteredAncestors[j-1]) | |
| 108 break; | |
| 109 exitedAncestorsCommonParentIndex = i-1; | |
| 110 enteredAncestorsCommonParentIndex = j-1; | |
| 111 } | |
| 112 } | |
| 113 | |
| 82 } // namespace | 114 } // namespace |
| 83 | 115 |
| 84 WebInputEventResult PointerEventManager::dispatchPointerEvent( | 116 WebInputEventResult PointerEventManager::dispatchPointerEvent( |
| 85 EventTarget* target, | 117 EventTarget* target, |
| 86 PointerEvent* pointerEvent, | 118 PointerEvent* pointerEvent, |
| 87 bool checkForListener) | 119 bool checkForListener) |
| 88 { | 120 { |
| 89 if (!target) | 121 if (!target) |
| 90 return WebInputEventResult::NotHandled; | 122 return WebInputEventResult::NotHandled; |
| 91 | 123 |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 173 pointerEvent, EventTypeNames::pointerout, enteredTarget)); | 205 pointerEvent, EventTypeNames::pointerout, enteredTarget)); |
| 174 } else { | 206 } else { |
| 175 dispatchMouseEvent(exitedTarget, | 207 dispatchMouseEvent(exitedTarget, |
| 176 EventTypeNames::mouseout, | 208 EventTypeNames::mouseout, |
| 177 mouseEventWithRegion(exitedTarget->toNode(), mouseEvent), | 209 mouseEventWithRegion(exitedTarget->toNode(), mouseEvent), |
| 178 enteredTarget); | 210 enteredTarget); |
| 179 } | 211 } |
| 180 } | 212 } |
| 181 | 213 |
| 182 // Create lists of all exited/entered ancestors, locate the common ancestor | 214 // Create lists of all exited/entered ancestors, locate the common ancestor |
| 183 HeapVector<Member<Node>, 32> exitedAncestors; | 215 HeapVector<Member<Node>, 32> exitedAncestors; |
|
mustaq
2016/04/20 16:09:05
Please add a comment that httparchive=>97% cases h
Navid Zolghadr
2016/04/21 14:46:41
Done.
| |
| 184 HeapVector<Member<Node>, 32> enteredAncestors; | 216 HeapVector<Member<Node>, 32> enteredAncestors; |
| 185 if (isInDocument(exitedTarget)) { | 217 size_t exitedAncestorsCommonParentIndex = 0; |
| 186 Node* exitedNode = exitedTarget->toNode(); | 218 size_t enteredAncestorsCommonParentIndex = 0; |
| 187 exitedNode->updateDistribution(); | |
| 188 for (Node* node = exitedNode; node; node = FlatTreeTraversal::parent(*no de)) | |
| 189 exitedAncestors.append(node); | |
| 190 } | |
| 191 | |
| 192 if (isInDocument(enteredTarget)) { | |
| 193 Node* enteredNode = enteredTarget->toNode(); | |
| 194 enteredNode->updateDistribution(); | |
| 195 for (Node* node = enteredNode; node; node = FlatTreeTraversal::parent(*n ode)) | |
| 196 enteredAncestors.append(node); | |
| 197 } | |
| 198 | 219 |
| 199 // A note on mouseenter and mouseleave: These are non-bubbling events, and t hey are dispatched if there | 220 // A note on mouseenter and mouseleave: These are non-bubbling events, and t hey are dispatched if there |
| 200 // is a capturing event handler on an ancestor or a normal event handler on the element itself. This special | 221 // is a capturing event handler on an ancestor or a normal event handler on the element itself. This special |
| 201 // handling is necessary to avoid O(n^2) capturing event handler checks. | 222 // handling is necessary to avoid O(n^2) capturing event handler checks. |
| 202 // | 223 // |
| 203 // Note, however, that this optimization can possibly cause some unanswere d/missing/redundant mouseenter or | 224 // Note, however, that this optimization can possibly cause some unanswere d/missing/redundant mouseenter or |
| 204 // mouseleave events in certain contrived eventhandling scenarios, e.g., whe n: | 225 // mouseleave events in certain contrived eventhandling scenarios, e.g., whe n: |
| 205 // - the mouseleave handler for a node sets the only capturing-mouseleave-li stener in its ancestor, or | 226 // - the mouseleave handler for a node sets the only capturing-mouseleave-li stener in its ancestor, or |
| 206 // - DOM mods in any mouseenter/mouseleave handler changes the common ancest or of exited & entered nodes, etc. | 227 // - DOM mods in any mouseenter/mouseleave handler changes the common ancest or of exited & entered nodes, etc. |
| 207 // We think the spec specifies a "frozen" state to avoid such corner cases ( check the discussion on "candidate event | 228 // We think the spec specifies a "frozen" state to avoid such corner cases ( check the discussion on "candidate event |
| 208 // listeners" at http://www.w3.org/TR/uievents), but our code below preserve s one such behavior from past only to | 229 // listeners" at http://www.w3.org/TR/uievents), but our code below preserve s one such behavior from past only to |
| 209 // match Firefox and IE behavior. | 230 // match Firefox and IE behavior. |
| 210 // | 231 // |
| 211 // TODO(mustaq): Confirm spec conformance, double-check with other browsers. | 232 // TODO(mustaq): Confirm spec conformance, double-check with other browsers. |
| 212 | 233 |
| 213 size_t numExitedAncestors = exitedAncestors.size(); | 234 findCommonAncestor( |
| 214 size_t numEnteredAncestors = enteredAncestors.size(); | 235 exitedTarget, enteredTarget, |
| 215 | 236 exitedAncestors, enteredAncestors, |
| 216 size_t exitedAncestorIndex = numExitedAncestors; | 237 exitedAncestorsCommonParentIndex, enteredAncestorsCommonParentIndex); |
| 217 size_t enteredAncestorIndex = numEnteredAncestors; | |
| 218 for (size_t i = 0; i < numExitedAncestors; i++) { | |
| 219 for (size_t j = 0; j < numEnteredAncestors; j++) { | |
| 220 if (exitedAncestors[i] == enteredAncestors[j]) { | |
| 221 exitedAncestorIndex = i; | |
| 222 enteredAncestorIndex = j; | |
| 223 break; | |
| 224 } | |
| 225 } | |
| 226 if (exitedAncestorIndex < exitedAncestors.size()) | |
| 227 break; | |
| 228 } | |
| 229 | 238 |
| 230 bool exitedNodeHasCapturingAncestor = false; | 239 bool exitedNodeHasCapturingAncestor = false; |
| 231 for (size_t j = 0; j < exitedAncestors.size(); j++) { | 240 for (size_t j = 0; j < exitedAncestors.size(); j++) { |
| 232 if (exitedAncestors[j]->hasCapturingEventListeners(EventTypeNames::mouse leave) | 241 if (exitedAncestors[j]->hasCapturingEventListeners(EventTypeNames::mouse leave) |
| 233 || (RuntimeEnabledFeatures::pointerEventEnabled() | 242 || (RuntimeEnabledFeatures::pointerEventEnabled() |
| 234 && exitedAncestors[j]->hasCapturingEventListeners(EventTypeNames::po interleave))) | 243 && exitedAncestors[j]->hasCapturingEventListeners(EventTypeNames::po interleave))) |
| 235 exitedNodeHasCapturingAncestor = true; | 244 exitedNodeHasCapturingAncestor = true; |
| 236 } | 245 } |
| 237 | 246 |
| 238 // Dispatch pointerleave/mouseleave events, in child-to-parent order. | 247 // Dispatch pointerleave/mouseleave events, in child-to-parent order. |
| 239 for (size_t j = 0; j < exitedAncestorIndex; j++) { | 248 for (size_t j = 0; j < exitedAncestorsCommonParentIndex; j++) { |
| 240 if (!sendMouseEvent) { | 249 if (!sendMouseEvent) { |
| 241 dispatchPointerEvent(exitedAncestors[j].get(), | 250 dispatchPointerEvent(exitedAncestors[j].get(), |
| 242 m_pointerEventFactory.createPointerTransitionEvent( | 251 m_pointerEventFactory.createPointerTransitionEvent( |
| 243 pointerEvent, EventTypeNames::pointerleave, enteredTarget), | 252 pointerEvent, EventTypeNames::pointerleave, enteredTarget), |
| 244 !exitedNodeHasCapturingAncestor); | 253 !exitedNodeHasCapturingAncestor); |
| 245 } else { | 254 } else { |
| 246 dispatchMouseEvent(exitedAncestors[j].get(), | 255 dispatchMouseEvent(exitedAncestors[j].get(), |
| 247 EventTypeNames::mouseleave, | 256 EventTypeNames::mouseleave, |
| 248 mouseEventWithRegion(exitedTarget->toNode(), mouseEvent), | 257 mouseEventWithRegion(exitedTarget->toNode(), mouseEvent), |
| 249 enteredTarget, 0, !exitedNodeHasCapturingAncestor); | 258 enteredTarget, 0, !exitedNodeHasCapturingAncestor); |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 265 // the leave handlers might set a capturing enter handler. | 274 // the leave handlers might set a capturing enter handler. |
| 266 bool enteredNodeHasCapturingAncestor = false; | 275 bool enteredNodeHasCapturingAncestor = false; |
| 267 for (size_t i = 0; i < enteredAncestors.size(); i++) { | 276 for (size_t i = 0; i < enteredAncestors.size(); i++) { |
| 268 if (enteredAncestors[i]->hasCapturingEventListeners(EventTypeNames::mous eenter) | 277 if (enteredAncestors[i]->hasCapturingEventListeners(EventTypeNames::mous eenter) |
| 269 || (RuntimeEnabledFeatures::pointerEventEnabled() | 278 || (RuntimeEnabledFeatures::pointerEventEnabled() |
| 270 && enteredAncestors[i]->hasCapturingEventListeners(EventTypeNames::p ointerenter))) | 279 && enteredAncestors[i]->hasCapturingEventListeners(EventTypeNames::p ointerenter))) |
| 271 enteredNodeHasCapturingAncestor = true; | 280 enteredNodeHasCapturingAncestor = true; |
| 272 } | 281 } |
| 273 | 282 |
| 274 // Dispatch pointerenter/mouseenter events, in parent-to-child order. | 283 // Dispatch pointerenter/mouseenter events, in parent-to-child order. |
| 275 for (size_t i = enteredAncestorIndex; i > 0; i--) { | 284 for (size_t i = enteredAncestorsCommonParentIndex; i > 0; i--) { |
| 276 if (!sendMouseEvent) { | 285 if (!sendMouseEvent) { |
| 277 dispatchPointerEvent(enteredAncestors[i-1].get(), | 286 dispatchPointerEvent(enteredAncestors[i-1].get(), |
| 278 m_pointerEventFactory.createPointerTransitionEvent( | 287 m_pointerEventFactory.createPointerTransitionEvent( |
| 279 pointerEvent, EventTypeNames::pointerenter, exitedTarget), | 288 pointerEvent, EventTypeNames::pointerenter, exitedTarget), |
| 280 !enteredNodeHasCapturingAncestor); | 289 !enteredNodeHasCapturingAncestor); |
| 281 } else { | 290 } else { |
| 282 dispatchMouseEvent(enteredAncestors[i-1].get(), | 291 dispatchMouseEvent(enteredAncestors[i-1].get(), |
| 283 EventTypeNames::mouseenter, mouseEvent, exitedTarget, | 292 EventTypeNames::mouseenter, mouseEvent, exitedTarget, |
| 284 0, !enteredNodeHasCapturingAncestor); | 293 0, !enteredNodeHasCapturingAncestor); |
| 285 } | 294 } |
| (...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 632 | 641 |
| 633 DEFINE_TRACE(PointerEventManager) | 642 DEFINE_TRACE(PointerEventManager) |
| 634 { | 643 { |
| 635 visitor->trace(m_nodeUnderPointer); | 644 visitor->trace(m_nodeUnderPointer); |
| 636 visitor->trace(m_pointerCaptureTarget); | 645 visitor->trace(m_pointerCaptureTarget); |
| 637 visitor->trace(m_pendingPointerCaptureTarget); | 646 visitor->trace(m_pendingPointerCaptureTarget); |
| 638 } | 647 } |
| 639 | 648 |
| 640 | 649 |
| 641 } // namespace blink | 650 } // namespace blink |
| OLD | NEW |