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

Side by Side Diff: Source/core/dom/Document.cpp

Issue 18836002: Implement 'mouseenter' and 'mouseleave' from DOM Level 3 Events. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Attribute tests. Created 7 years, 5 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 | Annotate | Revision Log
« no previous file with comments | « Source/core/dom/Document.h ('k') | Source/core/dom/Document.idl » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2001 Dirk Mueller (mueller@kde.org) 4 * (C) 2001 Dirk Mueller (mueller@kde.org)
5 * (C) 2006 Alexey Proskuryakov (ap@webkit.org) 5 * (C) 2006 Alexey Proskuryakov (ap@webkit.org)
6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2011, 2012 Apple Inc. All r ights reserved. 6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2011, 2012 Apple Inc. All r ights reserved.
7 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.t orchmobile.com/) 7 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.t orchmobile.com/)
8 * Copyright (C) 2008, 2009, 2011, 2012 Google Inc. All rights reserved. 8 * Copyright (C) 2008, 2009, 2011, 2012 Google Inc. All rights reserved.
9 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) 9 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
10 * Copyright (C) Research In Motion Limited 2010-2011. All rights reserved. 10 * Copyright (C) Research In Motion Limited 2010-2011. All rights reserved.
(...skipping 2772 matching lines...) Expand 10 before | Expand all | Expand 10 after
2783 // mousemove events before the first layout should not lead to a premature l ayout() 2783 // mousemove events before the first layout should not lead to a premature l ayout()
2784 // happening, which could show a flash of white. 2784 // happening, which could show a flash of white.
2785 // See also the similar code in EventHandler::hitTestResultAtPoint. 2785 // See also the similar code in EventHandler::hitTestResultAtPoint.
2786 if (!renderer() || !view() || !view()->didFirstLayout()) 2786 if (!renderer() || !view() || !view()->didFirstLayout())
2787 return MouseEventWithHitTestResults(event, HitTestResult(LayoutPoint())) ; 2787 return MouseEventWithHitTestResults(event, HitTestResult(LayoutPoint())) ;
2788 2788
2789 HitTestResult result(documentPoint); 2789 HitTestResult result(documentPoint);
2790 renderView()->hitTest(request, result); 2790 renderView()->hitTest(request, result);
2791 2791
2792 if (!request.readOnly()) 2792 if (!request.readOnly())
2793 updateHoverActiveState(request, result.innerElement()); 2793 updateHoverActiveState(request, result.innerElement(), &event);
2794 2794
2795 return MouseEventWithHitTestResults(event, result); 2795 return MouseEventWithHitTestResults(event, result);
2796 } 2796 }
2797 2797
2798 // DOM Section 1.1.1 2798 // DOM Section 1.1.1
2799 bool Document::childTypeAllowed(NodeType type) const 2799 bool Document::childTypeAllowed(NodeType type) const
2800 { 2800 {
2801 switch (type) { 2801 switch (type) {
2802 case ATTRIBUTE_NODE: 2802 case ATTRIBUTE_NODE:
2803 case CDATA_SECTION_NODE: 2803 case CDATA_SECTION_NODE:
(...skipping 2036 matching lines...) Expand 10 before | Expand all | Expand 10 after
4840 for (RenderObject* currObj1 = obj1; currObj1; currObj1 = currObj1->hoverAnce stor()) { 4840 for (RenderObject* currObj1 = obj1; currObj1; currObj1 = currObj1->hoverAnce stor()) {
4841 for (RenderObject* currObj2 = obj2; currObj2; currObj2 = currObj2->hover Ancestor()) { 4841 for (RenderObject* currObj2 = obj2; currObj2; currObj2 = currObj2->hover Ancestor()) {
4842 if (currObj1 == currObj2) 4842 if (currObj1 == currObj2)
4843 return currObj1; 4843 return currObj1;
4844 } 4844 }
4845 } 4845 }
4846 4846
4847 return 0; 4847 return 0;
4848 } 4848 }
4849 4849
4850 void Document::updateHoverActiveState(const HitTestRequest& request, Element* in nerElement) 4850 void Document::updateHoverActiveState(const HitTestRequest& request, Element* in nerElement, const PlatformMouseEvent* event)
4851 { 4851 {
4852 ASSERT(!request.readOnly()); 4852 ASSERT(!request.readOnly());
4853 4853
4854 Element* innerElementInDocument = innerElement; 4854 Element* innerElementInDocument = innerElement;
4855 while (innerElementInDocument && innerElementInDocument->document() != this) { 4855 while (innerElementInDocument && innerElementInDocument->document() != this) {
4856 innerElementInDocument->document()->updateHoverActiveState(request, inne rElementInDocument); 4856 innerElementInDocument->document()->updateHoverActiveState(request, inne rElementInDocument, event);
4857 innerElementInDocument = innerElementInDocument->document()->ownerElemen t(); 4857 innerElementInDocument = innerElementInDocument->document()->ownerElemen t();
4858 } 4858 }
4859 4859
4860 Element* oldActiveElement = activeElement(); 4860 Element* oldActiveElement = activeElement();
4861 if (oldActiveElement && !request.active()) { 4861 if (oldActiveElement && !request.active()) {
4862 // We are clearing the :active chain because the mouse has been released . 4862 // We are clearing the :active chain because the mouse has been released .
4863 for (RenderObject* curr = oldActiveElement->renderer(); curr; curr = cur r->parent()) { 4863 for (RenderObject* curr = oldActiveElement->renderer(); curr; curr = cur r->parent()) {
4864 if (curr->node()) { 4864 if (curr->node()) {
4865 ASSERT(!curr->node()->isTextNode()); 4865 ASSERT(!curr->node()->isTextNode());
4866 curr->node()->setActive(false); 4866 curr->node()->setActive(false);
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
4934 nodesToRemoveFromChain.append(curr->node()); 4934 nodesToRemoveFromChain.append(curr->node());
4935 } 4935 }
4936 } 4936 }
4937 4937
4938 // Now set the hover state for our new object up to the root. 4938 // Now set the hover state for our new object up to the root.
4939 for (RenderObject* curr = newHoverObj; curr; curr = curr->hoverAncestor()) { 4939 for (RenderObject* curr = newHoverObj; curr; curr = curr->hoverAncestor()) {
4940 if (curr->node() && !curr->isText() && (!mustBeInActiveChain || curr->no de()->inActiveChain())) 4940 if (curr->node() && !curr->isText() && (!mustBeInActiveChain || curr->no de()->inActiveChain()))
4941 nodesToAddToChain.append(curr->node()); 4941 nodesToAddToChain.append(curr->node());
4942 } 4942 }
4943 4943
4944 // mouseenter and mouseleave events do not bubble, so they are dispatched if f there is a capturing
4945 // event handler on an ancestor or a normal event handler on the element its elf. This special
4946 // handling is necessary to avoid O(n^2) capturing event handler checks. We' ll check the previously
4947 // hovered node's ancestor tree for 'mouseleave' handlers here, then check t he newly hovered node's
4948 // ancestor tree for 'mouseenter' handlers after dispatching the 'mouseleave ' events (as the handler
4949 // for 'mouseleave' might set a capturing 'mouseenter' handler, odd as that might be).
4950 bool ancestorHasCapturingMouseleaveListener = false;
4951 if (event && newHoverNode != oldHoverNode.get()) {
4952 for (Node* node = oldHoverNode.get(); node; node = node->parentOrShadowH ostNode()) {
4953 if (node->hasCapturingEventListeners(eventNames().mouseleaveEvent)) {
4954 ancestorHasCapturingMouseleaveListener = true;
4955 break;
4956 }
4957 }
4958 }
4959
4944 size_t removeCount = nodesToRemoveFromChain.size(); 4960 size_t removeCount = nodesToRemoveFromChain.size();
4945 for (size_t i = 0; i < removeCount; ++i) 4961 for (size_t i = 0; i < removeCount; ++i) {
4946 nodesToRemoveFromChain[i]->setHovered(false); 4962 nodesToRemoveFromChain[i]->setHovered(false);
4963 if (event && (ancestorHasCapturingMouseleaveListener || nodesToRemoveFro mChain[i]->hasEventListeners(eventNames().mouseleaveEvent)))
4964 nodesToRemoveFromChain[i]->dispatchMouseEvent(*event, eventNames().m ouseleaveEvent, 0, newHoverNode);
4965 }
4966
4967 bool ancestorHasCapturingMouseenterListener = false;
4968 if (event && newHoverNode != oldHoverNode.get()) {
4969 for (Node* node = newHoverNode; node; node = node->parentOrShadowHostNod e()) {
4970 if (node->hasCapturingEventListeners(eventNames().mouseenterEvent)) {
4971 ancestorHasCapturingMouseenterListener = true;
4972 break;
4973 }
4974 }
4975 }
4947 4976
4948 bool sawCommonAncestor = false; 4977 bool sawCommonAncestor = false;
4949 size_t addCount = nodesToAddToChain.size(); 4978 size_t addCount = nodesToAddToChain.size();
4950 for (size_t i = 0; i < addCount; ++i) { 4979 for (size_t i = 0; i < addCount; ++i) {
4951 // Elements past the common ancestor do not change hover state, but migh t change active state. 4980 // Elements past the common ancestor do not change hover state, but migh t change active state.
4952 if (ancestor && nodesToAddToChain[i] == ancestor->node()) 4981 if (ancestor && nodesToAddToChain[i] == ancestor->node())
4953 sawCommonAncestor = true; 4982 sawCommonAncestor = true;
4954 if (allowActiveChanges) 4983 if (allowActiveChanges)
4955 nodesToAddToChain[i]->setActive(true); 4984 nodesToAddToChain[i]->setActive(true);
4956 if (!sawCommonAncestor) 4985 if (!sawCommonAncestor) {
4957 nodesToAddToChain[i]->setHovered(true); 4986 nodesToAddToChain[i]->setHovered(true);
4987 if (event && (ancestorHasCapturingMouseenterListener || nodesToAddTo Chain[i]->hasEventListeners(eventNames().mouseenterEvent)))
4988 nodesToAddToChain[i]->dispatchMouseEvent(*event, eventNames().mo useenterEvent, 0, oldHoverNode.get());
4989 }
4958 } 4990 }
4959 4991
4960 updateStyleIfNeeded(); 4992 updateStyleIfNeeded();
4961 } 4993 }
4962 4994
4963 void Document::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const 4995 void Document::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
4964 { 4996 {
4965 MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM); 4997 MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM);
4966 ContainerNode::reportMemoryUsage(memoryObjectInfo); 4998 ContainerNode::reportMemoryUsage(memoryObjectInfo);
4967 TreeScope::reportMemoryUsage(memoryObjectInfo); 4999 TreeScope::reportMemoryUsage(memoryObjectInfo);
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
5104 { 5136 {
5105 return DocumentLifecycleNotifier::create(this); 5137 return DocumentLifecycleNotifier::create(this);
5106 } 5138 }
5107 5139
5108 DocumentLifecycleNotifier* Document::lifecycleNotifier() 5140 DocumentLifecycleNotifier* Document::lifecycleNotifier()
5109 { 5141 {
5110 return static_cast<DocumentLifecycleNotifier*>(ScriptExecutionContext::lifec ycleNotifier()); 5142 return static_cast<DocumentLifecycleNotifier*>(ScriptExecutionContext::lifec ycleNotifier());
5111 } 5143 }
5112 5144
5113 } // namespace WebCore 5145 } // namespace WebCore
OLDNEW
« no previous file with comments | « Source/core/dom/Document.h ('k') | Source/core/dom/Document.idl » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698