Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(185)

Side by Side Diff: third_party/WebKit/Source/core/input/PointerEventManager.cpp

Issue 1904453003: Change finding common ancestor from O(n^2) to O(n) (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698