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

Unified Diff: third_party/WebKit/Source/core/input/BoundaryEventDispatcher.cpp

Issue 2255323004: Create MouseEventManager and EventHandlingUtil (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebasing Created 4 years, 3 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 side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/core/input/BoundaryEventDispatcher.cpp
diff --git a/third_party/WebKit/Source/core/input/BoundaryEventDispatcher.cpp b/third_party/WebKit/Source/core/input/BoundaryEventDispatcher.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ee36458c433ce87e166dc4753c44fa63de4e5d89
--- /dev/null
+++ b/third_party/WebKit/Source/core/input/BoundaryEventDispatcher.cpp
@@ -0,0 +1,134 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "core/input/BoundaryEventDispatcher.h"
+
+#include "core/dom/Node.h"
+#include "core/dom/shadow/FlatTreeTraversal.h"
+
+namespace blink {
+
+namespace {
+
+bool isInDocument(EventTarget* target)
+{
+ return target && target->toNode() && target->toNode()->isConnected();
+}
+
+void buildAncestorChain(
+ EventTarget* target,
+ HeapVector<Member<Node>, 20>* ancestors)
+{
+ if (!isInDocument(target))
+ return;
+ Node* targetNode = target->toNode();
+ DCHECK(targetNode);
+ targetNode->updateDistribution();
+ // Index 0 element in the ancestors arrays will be the corresponding
+ // target. So the root of their document will be their last element.
+ for (Node* node = targetNode; node; node = FlatTreeTraversal::parent(*node))
+ ancestors->append(node);
+}
+
+void buildAncestorChainsAndFindCommonAncestors(
+ EventTarget* exitedTarget, EventTarget* enteredTarget,
+ HeapVector<Member<Node>, 20>* exitedAncestorsOut,
+ HeapVector<Member<Node>, 20>* enteredAncestorsOut,
+ size_t* exitedAncestorsCommonParentIndexOut,
+ size_t* enteredAncestorsCommonParentIndexOut)
+{
+ DCHECK(exitedAncestorsOut);
+ DCHECK(enteredAncestorsOut);
+ DCHECK(exitedAncestorsCommonParentIndexOut);
+ DCHECK(enteredAncestorsCommonParentIndexOut);
+
+ buildAncestorChain(exitedTarget, exitedAncestorsOut);
+ buildAncestorChain(enteredTarget, enteredAncestorsOut);
+
+ *exitedAncestorsCommonParentIndexOut = exitedAncestorsOut->size();
+ *enteredAncestorsCommonParentIndexOut = enteredAncestorsOut->size();
+ while (*exitedAncestorsCommonParentIndexOut > 0
+ && *enteredAncestorsCommonParentIndexOut > 0) {
+ if ((*exitedAncestorsOut)[(*exitedAncestorsCommonParentIndexOut) - 1]
+ != (*enteredAncestorsOut)[(*enteredAncestorsCommonParentIndexOut) - 1])
+ break;
+ (*exitedAncestorsCommonParentIndexOut)--;
+ (*enteredAncestorsCommonParentIndexOut)--;
+ }
+}
+
+} // namespace
+
+void BoundaryEventDispatcher::sendBoundaryEvents(
+ EventTarget* exitedTarget,
+ EventTarget* enteredTarget)
+{
+ if (exitedTarget == enteredTarget)
+ return;
+
+ // Dispatch out event
+ if (isInDocument(exitedTarget))
+ dispatchOut(exitedTarget, enteredTarget);
+
+ // Create lists of all exited/entered ancestors, locate the common ancestor
+ // Based on httparchive, in more than 97% cases the depth of DOM is less
+ // than 20.
+ HeapVector<Member<Node>, 20> exitedAncestors;
+ HeapVector<Member<Node>, 20> enteredAncestors;
+ size_t exitedAncestorsCommonParentIndex = 0;
+ size_t enteredAncestorsCommonParentIndex = 0;
+
+ // A note on mouseenter and mouseleave: These are non-bubbling events, and they are dispatched if there
+ // is a capturing event handler on an ancestor or a normal event handler on the element itself. This special
+ // handling is necessary to avoid O(n^2) capturing event handler checks.
+ //
+ // Note, however, that this optimization can possibly cause some unanswered/missing/redundant mouseenter or
+ // mouseleave events in certain contrived eventhandling scenarios, e.g., when:
+ // - the mouseleave handler for a node sets the only capturing-mouseleave-listener in its ancestor, or
+ // - DOM mods in any mouseenter/mouseleave handler changes the common ancestor of exited & entered nodes, etc.
+ // We think the spec specifies a "frozen" state to avoid such corner cases (check the discussion on "candidate event
+ // listeners" at http://www.w3.org/TR/uievents), but our code below preserves one such behavior from past only to
+ // match Firefox and IE behavior.
+ //
+ // TODO(mustaq): Confirm spec conformance, double-check with other browsers.
+
+ buildAncestorChainsAndFindCommonAncestors(
+ exitedTarget, enteredTarget,
+ &exitedAncestors, &enteredAncestors,
+ &exitedAncestorsCommonParentIndex, &enteredAncestorsCommonParentIndex);
+
+ bool exitedNodeHasCapturingAncestor = false;
+ const AtomicString &leaveEvent = getLeaveEvent();
+ for (size_t j = 0; j < exitedAncestors.size(); j++) {
+ if (exitedAncestors[j]->hasCapturingEventListeners(leaveEvent)) {
+ exitedNodeHasCapturingAncestor = true;
+ break;
+ }
+ }
+
+ // Dispatch leave events, in child-to-parent order.
+ for (size_t j = 0; j < exitedAncestorsCommonParentIndex; j++)
+ dispatchLeave(exitedAncestors[j], enteredTarget, !exitedNodeHasCapturingAncestor);
+
+ // Dispatch over event
+ if (isInDocument(enteredTarget))
+ dispatchOver(enteredTarget, exitedTarget);
+
+ // Defer locating capturing enter listener until /after/ dispatching the leave events because
+ // the leave handlers might set a capturing enter handler.
+ bool enteredNodeHasCapturingAncestor = false;
+ const AtomicString &enterEvent = getEnterEvent();
+ for (size_t i = 0; i < enteredAncestors.size(); i++) {
+ if (enteredAncestors[i]->hasCapturingEventListeners(enterEvent)) {
+ enteredNodeHasCapturingAncestor = true;
+ break;
+ }
+ }
+
+ // Dispatch enter events, in parent-to-child order.
+ for (size_t i = enteredAncestorsCommonParentIndex; i > 0; i--)
+ dispatchEnter(enteredAncestors[i - 1], exitedTarget, !enteredNodeHasCapturingAncestor);
+}
+
+} // namespace blink
« no previous file with comments | « third_party/WebKit/Source/core/input/BoundaryEventDispatcher.h ('k') | third_party/WebKit/Source/core/input/EventHandler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698