Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 2877 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2888 // mousemove events before the first layout should not lead to a premature l ayout() | 2888 // mousemove events before the first layout should not lead to a premature l ayout() |
| 2889 // happening, which could show a flash of white. | 2889 // happening, which could show a flash of white. |
| 2890 // See also the similar code in EventHandler::hitTestResultAtPoint. | 2890 // See also the similar code in EventHandler::hitTestResultAtPoint. |
| 2891 if (!renderer() || !view() || !view()->didFirstLayout()) | 2891 if (!renderer() || !view() || !view()->didFirstLayout()) |
| 2892 return MouseEventWithHitTestResults(event, HitTestResult(LayoutPoint())) ; | 2892 return MouseEventWithHitTestResults(event, HitTestResult(LayoutPoint())) ; |
| 2893 | 2893 |
| 2894 HitTestResult result(documentPoint); | 2894 HitTestResult result(documentPoint); |
| 2895 renderView()->hitTest(request, result); | 2895 renderView()->hitTest(request, result); |
| 2896 | 2896 |
| 2897 if (!request.readOnly()) | 2897 if (!request.readOnly()) |
| 2898 updateHoverActiveState(request, result.innerElement()); | 2898 updateHoverActiveState(request, result.innerElement(), &event); |
| 2899 | 2899 |
| 2900 return MouseEventWithHitTestResults(event, result); | 2900 return MouseEventWithHitTestResults(event, result); |
| 2901 } | 2901 } |
| 2902 | 2902 |
| 2903 // DOM Section 1.1.1 | 2903 // DOM Section 1.1.1 |
| 2904 bool Document::childTypeAllowed(NodeType type) const | 2904 bool Document::childTypeAllowed(NodeType type) const |
| 2905 { | 2905 { |
| 2906 switch (type) { | 2906 switch (type) { |
| 2907 case ATTRIBUTE_NODE: | 2907 case ATTRIBUTE_NODE: |
| 2908 case CDATA_SECTION_NODE: | 2908 case CDATA_SECTION_NODE: |
| (...skipping 2074 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4983 for (RenderObject* currObj1 = obj1; currObj1; currObj1 = currObj1->hoverAnce stor()) { | 4983 for (RenderObject* currObj1 = obj1; currObj1; currObj1 = currObj1->hoverAnce stor()) { |
| 4984 for (RenderObject* currObj2 = obj2; currObj2; currObj2 = currObj2->hover Ancestor()) { | 4984 for (RenderObject* currObj2 = obj2; currObj2; currObj2 = currObj2->hover Ancestor()) { |
| 4985 if (currObj1 == currObj2) | 4985 if (currObj1 == currObj2) |
| 4986 return currObj1; | 4986 return currObj1; |
| 4987 } | 4987 } |
| 4988 } | 4988 } |
| 4989 | 4989 |
| 4990 return 0; | 4990 return 0; |
| 4991 } | 4991 } |
| 4992 | 4992 |
| 4993 void Document::updateHoverActiveState(const HitTestRequest& request, Element* in nerElement) | 4993 void Document::updateHoverActiveState(const HitTestRequest& request, Element* in nerElement, const PlatformMouseEvent* event) |
| 4994 { | 4994 { |
| 4995 ASSERT(!request.readOnly()); | 4995 ASSERT(!request.readOnly()); |
| 4996 | 4996 |
| 4997 Element* innerElementInDocument = innerElement; | 4997 Element* innerElementInDocument = innerElement; |
| 4998 while (innerElementInDocument && innerElementInDocument->document() != this) { | 4998 while (innerElementInDocument && innerElementInDocument->document() != this) { |
| 4999 innerElementInDocument->document()->updateHoverActiveState(request, inne rElementInDocument); | 4999 innerElementInDocument->document()->updateHoverActiveState(request, inne rElementInDocument, event); |
| 5000 innerElementInDocument = innerElementInDocument->document()->ownerElemen t(); | 5000 innerElementInDocument = innerElementInDocument->document()->ownerElemen t(); |
| 5001 } | 5001 } |
| 5002 | 5002 |
| 5003 Element* oldActiveElement = activeElement(); | 5003 Element* oldActiveElement = activeElement(); |
| 5004 if (oldActiveElement && !request.active()) { | 5004 if (oldActiveElement && !request.active()) { |
| 5005 // We are clearing the :active chain because the mouse has been released . | 5005 // We are clearing the :active chain because the mouse has been released . |
| 5006 for (RenderObject* curr = oldActiveElement->renderer(); curr; curr = cur r->parent()) { | 5006 for (RenderObject* curr = oldActiveElement->renderer(); curr; curr = cur r->parent()) { |
| 5007 if (curr->node()) { | 5007 if (curr->node()) { |
| 5008 ASSERT(!curr->node()->isTextNode()); | 5008 ASSERT(!curr->node()->isTextNode()); |
| 5009 curr->node()->setActive(false); | 5009 curr->node()->setActive(false); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5052 // We have two different objects. Fetch their renderers. | 5052 // We have two different objects. Fetch their renderers. |
| 5053 RenderObject* oldHoverObj = oldHoverNode ? oldHoverNode->renderer() : 0; | 5053 RenderObject* oldHoverObj = oldHoverNode ? oldHoverNode->renderer() : 0; |
| 5054 RenderObject* newHoverObj = newHoverNode ? newHoverNode->renderer() : 0; | 5054 RenderObject* newHoverObj = newHoverNode ? newHoverNode->renderer() : 0; |
| 5055 | 5055 |
| 5056 // Locate the common ancestor render object for the two renderers. | 5056 // Locate the common ancestor render object for the two renderers. |
| 5057 RenderObject* ancestor = nearestCommonHoverAncestor(oldHoverObj, newHoverObj ); | 5057 RenderObject* ancestor = nearestCommonHoverAncestor(oldHoverObj, newHoverObj ); |
| 5058 | 5058 |
| 5059 Vector<RefPtr<Node>, 32> nodesToRemoveFromChain; | 5059 Vector<RefPtr<Node>, 32> nodesToRemoveFromChain; |
| 5060 Vector<RefPtr<Node>, 32> nodesToAddToChain; | 5060 Vector<RefPtr<Node>, 32> nodesToAddToChain; |
| 5061 | 5061 |
| 5062 // mouseenter and mouseleave events do not bubble, so they are dispatched if f there is a capturing | |
|
PhistucK
2013/07/08 17:57:26
s/iff/if
Mike West
2013/07/09 09:37:00
"iff" is short for "if and only if" (e.g. "necessa
| |
| 5063 // event handler on an ancestor or a normal event handler on the element its elf. This special | |
| 5064 // handling is necessary to avoid O(n^2) capturing event handler checks. | |
| 5065 bool hasCapturingMouseEnterListener = false; | |
| 5066 bool hasCapturingMouseLeaveListener = false; | |
| 5067 if (event && newHoverNode != oldHoverNode.get()) { | |
| 5068 // Walk up the newly hovered node's ancestor tree for 'mouseenter' event s, and the previously | |
| 5069 // hovered node's ancestor tree for 'mouseleave' events. | |
| 5070 for (Node* node = newHoverNode; node; node = node->parentOrShadowHostNod e()) { | |
| 5071 if (node->hasCapturingEventListeners(eventNames().mouseenterEvent)) { | |
| 5072 hasCapturingMouseEnterListener = true; | |
| 5073 break; | |
| 5074 } | |
| 5075 } | |
| 5076 for (Node* node = oldHoverNode.get(); node; node = node->parentOrShadowH ostNode()) { | |
| 5077 if (node->hasCapturingEventListeners(eventNames().mouseleaveEvent)) { | |
| 5078 hasCapturingMouseLeaveListener = true; | |
| 5079 break; | |
| 5080 } | |
| 5081 } | |
| 5082 } | |
| 5083 | |
| 5062 if (oldHoverObj != newHoverObj) { | 5084 if (oldHoverObj != newHoverObj) { |
| 5063 // If the old hovered node is not nil but it's renderer is, it was proba bly detached as part of the :hover style | 5085 // If the old hovered node is not nil but it's renderer is, it was proba bly detached as part of the :hover style |
| 5064 // (for instance by setting display:none in the :hover pseudo-class). In this case, the old hovered element (and its ancestors) | 5086 // (for instance by setting display:none in the :hover pseudo-class). In this case, the old hovered element (and its ancestors) |
| 5065 // must be updated, to ensure it's normal style is re-applied. | 5087 // must be updated, to ensure it's normal style is re-applied. |
| 5066 if (oldHoverNode && !oldHoverObj) { | 5088 if (oldHoverNode && !oldHoverObj) { |
| 5067 for (Node* node = oldHoverNode.get(); node; node = node->parentNode( )) { | 5089 for (Node* node = oldHoverNode.get(); node; node = node->parentNode( )) { |
| 5068 if (!mustBeInActiveChain || (node->isElementNode() && toElement( node)->inActiveChain())) | 5090 if (!mustBeInActiveChain || (node->isElementNode() && toElement( node)->inActiveChain())) |
| 5069 nodesToRemoveFromChain.append(node); | 5091 nodesToRemoveFromChain.append(node); |
| 5070 } | 5092 } |
| 5071 | 5093 |
| 5072 } | 5094 } |
| 5073 | 5095 |
| 5074 // The old hover path only needs to be cleared up to (and not including) the common ancestor; | 5096 // The old hover path only needs to be cleared up to (and not including) the common ancestor; |
| 5075 for (RenderObject* curr = oldHoverObj; curr && curr != ancestor; curr = curr->hoverAncestor()) { | 5097 for (RenderObject* curr = oldHoverObj; curr && curr != ancestor; curr = curr->hoverAncestor()) { |
| 5076 if (curr->node() && !curr->isText() && (!mustBeInActiveChain || curr ->node()->inActiveChain())) | 5098 if (curr->node() && !curr->isText() && (!mustBeInActiveChain || curr ->node()->inActiveChain())) |
| 5077 nodesToRemoveFromChain.append(curr->node()); | 5099 nodesToRemoveFromChain.append(curr->node()); |
| 5078 } | 5100 } |
| 5079 } | 5101 } |
| 5080 | 5102 |
| 5081 // Now set the hover state for our new object up to the root. | 5103 // Now set the hover state for our new object up to the root. |
| 5082 for (RenderObject* curr = newHoverObj; curr; curr = curr->hoverAncestor()) { | 5104 for (RenderObject* curr = newHoverObj; curr; curr = curr->hoverAncestor()) { |
| 5083 if (curr->node() && !curr->isText() && (!mustBeInActiveChain || curr->no de()->inActiveChain())) | 5105 if (curr->node() && !curr->isText() && (!mustBeInActiveChain || curr->no de()->inActiveChain())) |
| 5084 nodesToAddToChain.append(curr->node()); | 5106 nodesToAddToChain.append(curr->node()); |
| 5085 } | 5107 } |
| 5086 | 5108 |
| 5087 size_t removeCount = nodesToRemoveFromChain.size(); | 5109 size_t removeCount = nodesToRemoveFromChain.size(); |
| 5088 for (size_t i = 0; i < removeCount; ++i) | 5110 for (size_t i = 0; i < removeCount; ++i) { |
| 5089 nodesToRemoveFromChain[i]->setHovered(false); | 5111 nodesToRemoveFromChain[i]->setHovered(false); |
| 5112 if (event && (hasCapturingMouseLeaveListener || nodesToRemoveFromChain[i ]->hasEventListeners(eventNames().mouseleaveEvent))) | |
| 5113 nodesToRemoveFromChain[i]->dispatchMouseEvent(*event, eventNames().m ouseleaveEvent, 0, newHoverNode); | |
| 5114 } | |
| 5090 | 5115 |
| 5091 bool sawCommonAncestor = false; | 5116 bool sawCommonAncestor = false; |
| 5092 size_t addCount = nodesToAddToChain.size(); | 5117 size_t addCount = nodesToAddToChain.size(); |
| 5093 for (size_t i = 0; i < addCount; ++i) { | 5118 for (size_t i = 0; i < addCount; ++i) { |
| 5094 // Elements past the common ancestor do not change hover state, but migh t change active state. | 5119 // Elements past the common ancestor do not change hover state, but migh t change active state. |
| 5095 if (ancestor && nodesToAddToChain[i] == ancestor->node()) | 5120 if (ancestor && nodesToAddToChain[i] == ancestor->node()) |
| 5096 sawCommonAncestor = true; | 5121 sawCommonAncestor = true; |
| 5097 if (allowActiveChanges) | 5122 if (allowActiveChanges) |
| 5098 nodesToAddToChain[i]->setActive(true); | 5123 nodesToAddToChain[i]->setActive(true); |
| 5099 if (!sawCommonAncestor) | 5124 if (!sawCommonAncestor) { |
| 5100 nodesToAddToChain[i]->setHovered(true); | 5125 nodesToAddToChain[i]->setHovered(true); |
| 5126 if (event && (hasCapturingMouseEnterListener || nodesToAddToChain[i] ->hasEventListeners(eventNames().mouseenterEvent))) | |
|
esprehn
2013/07/08 18:13:02
This is not correct, I could add a listener inside
Mike West
2013/07/09 09:37:00
You're right; I didn't think of that case at all.
| |
| 5127 nodesToAddToChain[i]->dispatchMouseEvent(*event, eventNames().mo useenterEvent, 0, oldHoverNode.get()); | |
| 5128 } | |
| 5101 } | 5129 } |
| 5102 | 5130 |
| 5103 updateStyleIfNeeded(); | 5131 updateStyleIfNeeded(); |
| 5104 } | 5132 } |
| 5105 | 5133 |
| 5106 void Document::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const | 5134 void Document::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const |
| 5107 { | 5135 { |
| 5108 MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM); | 5136 MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM); |
| 5109 ContainerNode::reportMemoryUsage(memoryObjectInfo); | 5137 ContainerNode::reportMemoryUsage(memoryObjectInfo); |
| 5110 TreeScope::reportMemoryUsage(memoryObjectInfo); | 5138 TreeScope::reportMemoryUsage(memoryObjectInfo); |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5249 { | 5277 { |
| 5250 return DocumentLifecycleNotifier::create(this); | 5278 return DocumentLifecycleNotifier::create(this); |
| 5251 } | 5279 } |
| 5252 | 5280 |
| 5253 DocumentLifecycleNotifier* Document::lifecycleNotifier() | 5281 DocumentLifecycleNotifier* Document::lifecycleNotifier() |
| 5254 { | 5282 { |
| 5255 return static_cast<DocumentLifecycleNotifier*>(ScriptExecutionContext::lifec ycleNotifier()); | 5283 return static_cast<DocumentLifecycleNotifier*>(ScriptExecutionContext::lifec ycleNotifier()); |
| 5256 } | 5284 } |
| 5257 | 5285 |
| 5258 } // namespace WebCore | 5286 } // namespace WebCore |
| OLD | NEW |