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

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: new tests + esprehn is smart. 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
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 2811 matching lines...) Expand 10 before | Expand all | Expand 10 after
2822 // mousemove events before the first layout should not lead to a premature l ayout() 2822 // mousemove events before the first layout should not lead to a premature l ayout()
2823 // happening, which could show a flash of white. 2823 // happening, which could show a flash of white.
2824 // See also the similar code in EventHandler::hitTestResultAtPoint. 2824 // See also the similar code in EventHandler::hitTestResultAtPoint.
2825 if (!renderer() || !view() || !view()->didFirstLayout()) 2825 if (!renderer() || !view() || !view()->didFirstLayout())
2826 return MouseEventWithHitTestResults(event, HitTestResult(LayoutPoint())) ; 2826 return MouseEventWithHitTestResults(event, HitTestResult(LayoutPoint())) ;
2827 2827
2828 HitTestResult result(documentPoint); 2828 HitTestResult result(documentPoint);
2829 renderView()->hitTest(request, result); 2829 renderView()->hitTest(request, result);
2830 2830
2831 if (!request.readOnly()) 2831 if (!request.readOnly())
2832 updateHoverActiveState(request, result.innerElement()); 2832 updateHoverActiveState(request, result.innerElement(), &event);
2833 2833
2834 return MouseEventWithHitTestResults(event, result); 2834 return MouseEventWithHitTestResults(event, result);
2835 } 2835 }
2836 2836
2837 // DOM Section 1.1.1 2837 // DOM Section 1.1.1
2838 bool Document::childTypeAllowed(NodeType type) const 2838 bool Document::childTypeAllowed(NodeType type) const
2839 { 2839 {
2840 switch (type) { 2840 switch (type) {
2841 case ATTRIBUTE_NODE: 2841 case ATTRIBUTE_NODE:
2842 case CDATA_SECTION_NODE: 2842 case CDATA_SECTION_NODE:
(...skipping 2064 matching lines...) Expand 10 before | Expand all | Expand 10 after
4907 for (RenderObject* currObj1 = obj1; currObj1; currObj1 = currObj1->hoverAnce stor()) { 4907 for (RenderObject* currObj1 = obj1; currObj1; currObj1 = currObj1->hoverAnce stor()) {
4908 for (RenderObject* currObj2 = obj2; currObj2; currObj2 = currObj2->hover Ancestor()) { 4908 for (RenderObject* currObj2 = obj2; currObj2; currObj2 = currObj2->hover Ancestor()) {
4909 if (currObj1 == currObj2) 4909 if (currObj1 == currObj2)
4910 return currObj1; 4910 return currObj1;
4911 } 4911 }
4912 } 4912 }
4913 4913
4914 return 0; 4914 return 0;
4915 } 4915 }
4916 4916
4917 void Document::updateHoverActiveState(const HitTestRequest& request, Element* in nerElement) 4917 void Document::updateHoverActiveState(const HitTestRequest& request, Element* in nerElement, const PlatformMouseEvent* event)
4918 { 4918 {
4919 ASSERT(!request.readOnly()); 4919 ASSERT(!request.readOnly());
4920 4920
4921 Element* innerElementInDocument = innerElement; 4921 Element* innerElementInDocument = innerElement;
4922 while (innerElementInDocument && innerElementInDocument->document() != this) { 4922 while (innerElementInDocument && innerElementInDocument->document() != this) {
4923 innerElementInDocument->document()->updateHoverActiveState(request, inne rElementInDocument); 4923 innerElementInDocument->document()->updateHoverActiveState(request, inne rElementInDocument, event);
4924 innerElementInDocument = innerElementInDocument->document()->ownerElemen t(); 4924 innerElementInDocument = innerElementInDocument->document()->ownerElemen t();
4925 } 4925 }
4926 4926
4927 Element* oldActiveElement = activeElement(); 4927 Element* oldActiveElement = activeElement();
4928 if (oldActiveElement && !request.active()) { 4928 if (oldActiveElement && !request.active()) {
4929 // We are clearing the :active chain because the mouse has been released . 4929 // We are clearing the :active chain because the mouse has been released .
4930 for (RenderObject* curr = oldActiveElement->renderer(); curr; curr = cur r->parent()) { 4930 for (RenderObject* curr = oldActiveElement->renderer(); curr; curr = cur r->parent()) {
4931 if (curr->node()) { 4931 if (curr->node()) {
4932 ASSERT(!curr->node()->isTextNode()); 4932 ASSERT(!curr->node()->isTextNode());
4933 curr->node()->setActive(false); 4933 curr->node()->setActive(false);
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
5001 nodesToRemoveFromChain.append(curr->node()); 5001 nodesToRemoveFromChain.append(curr->node());
5002 } 5002 }
5003 } 5003 }
5004 5004
5005 // Now set the hover state for our new object up to the root. 5005 // Now set the hover state for our new object up to the root.
5006 for (RenderObject* curr = newHoverObj; curr; curr = curr->hoverAncestor()) { 5006 for (RenderObject* curr = newHoverObj; curr; curr = curr->hoverAncestor()) {
5007 if (curr->node() && !curr->isText() && (!mustBeInActiveChain || curr->no de()->inActiveChain())) 5007 if (curr->node() && !curr->isText() && (!mustBeInActiveChain || curr->no de()->inActiveChain()))
5008 nodesToAddToChain.append(curr->node()); 5008 nodesToAddToChain.append(curr->node());
5009 } 5009 }
5010 5010
5011 // mouseenter and mouseleave events do not bubble, so they are dispatched if f there is a capturing
5012 // event handler on an ancestor or a normal event handler on the element its elf. This special
5013 // handling is necessary to avoid O(n^2) capturing event handler checks. We' ll check the previously
5014 // hovered node's ancestor tree for 'mouseleave' handlers here, then check t he newly hovered node's
5015 // ancestor tree for 'mouseenter' handlers after dispatching the 'mouseleave ' events (as the handler
5016 // for 'mouseleave' might set a capturing 'mouseenter' handler, odd as that might be).
5017 bool ancestorHasCapturingMouseleaveListener = false;
5018 if (event && newHoverNode != oldHoverNode.get()) {
5019 for (Node* node = oldHoverNode.get(); node; node = node->parentOrShadowH ostNode()) {
5020 if (node->hasCapturingEventListeners(eventNames().mouseleaveEvent)) {
5021 ancestorHasCapturingMouseleaveListener = true;
5022 break;
5023 }
5024 }
5025 }
5026
5011 size_t removeCount = nodesToRemoveFromChain.size(); 5027 size_t removeCount = nodesToRemoveFromChain.size();
5012 for (size_t i = 0; i < removeCount; ++i) 5028 for (size_t i = 0; i < removeCount; ++i) {
5013 nodesToRemoveFromChain[i]->setHovered(false); 5029 nodesToRemoveFromChain[i]->setHovered(false);
5030 if (event && (ancestorHasCapturingMouseleaveListener || nodesToRemoveFro mChain[i]->hasEventListeners(eventNames().mouseleaveEvent)))
5031 nodesToRemoveFromChain[i]->dispatchMouseEvent(*event, eventNames().m ouseleaveEvent, 0, newHoverNode);
5032 }
5033
5034 bool ancestorHasCapturingMouseenterListener = false;
5035 if (event && newHoverNode != oldHoverNode.get()) {
5036 for (Node* node = newHoverNode; node; node = node->parentOrShadowHostNod e()) {
5037 if (node->hasCapturingEventListeners(eventNames().mouseenterEvent)) {
5038 ancestorHasCapturingMouseenterListener = true;
5039 break;
5040 }
5041 }
5042 }
5014 5043
5015 bool sawCommonAncestor = false; 5044 bool sawCommonAncestor = false;
5016 size_t addCount = nodesToAddToChain.size(); 5045 size_t addCount = nodesToAddToChain.size();
5017 for (size_t i = 0; i < addCount; ++i) { 5046 for (size_t i = 0; i < addCount; ++i) {
5018 // Elements past the common ancestor do not change hover state, but migh t change active state. 5047 // Elements past the common ancestor do not change hover state, but migh t change active state.
5019 if (ancestor && nodesToAddToChain[i] == ancestor->node()) 5048 if (ancestor && nodesToAddToChain[i] == ancestor->node())
5020 sawCommonAncestor = true; 5049 sawCommonAncestor = true;
5021 if (allowActiveChanges) 5050 if (allowActiveChanges)
5022 nodesToAddToChain[i]->setActive(true); 5051 nodesToAddToChain[i]->setActive(true);
5023 if (!sawCommonAncestor) 5052 if (!sawCommonAncestor) {
5024 nodesToAddToChain[i]->setHovered(true); 5053 nodesToAddToChain[i]->setHovered(true);
5054 if (event && (ancestorHasCapturingMouseenterListener || nodesToAddTo Chain[i]->hasEventListeners(eventNames().mouseenterEvent)))
5055 nodesToAddToChain[i]->dispatchMouseEvent(*event, eventNames().mo useenterEvent, 0, oldHoverNode.get());
5056 }
5025 } 5057 }
5026 5058
5027 updateStyleIfNeeded(); 5059 updateStyleIfNeeded();
5028 } 5060 }
5029 5061
5030 void Document::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const 5062 void Document::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
5031 { 5063 {
5032 MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM); 5064 MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM);
5033 ContainerNode::reportMemoryUsage(memoryObjectInfo); 5065 ContainerNode::reportMemoryUsage(memoryObjectInfo);
5034 TreeScope::reportMemoryUsage(memoryObjectInfo); 5066 TreeScope::reportMemoryUsage(memoryObjectInfo);
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
5173 { 5205 {
5174 return DocumentLifecycleNotifier::create(this); 5206 return DocumentLifecycleNotifier::create(this);
5175 } 5207 }
5176 5208
5177 DocumentLifecycleNotifier* Document::lifecycleNotifier() 5209 DocumentLifecycleNotifier* Document::lifecycleNotifier()
5178 { 5210 {
5179 return static_cast<DocumentLifecycleNotifier*>(ScriptExecutionContext::lifec ycleNotifier()); 5211 return static_cast<DocumentLifecycleNotifier*>(ScriptExecutionContext::lifec ycleNotifier());
5180 } 5212 }
5181 5213
5182 } // namespace WebCore 5214 } // namespace WebCore
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698