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 |