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 | 6 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2011, 2012 Apple Inc. All |
7 * rights reserved. | 7 * rights reserved. |
8 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. | 8 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. |
9 * (http://www.torchmobile.com/) | 9 * (http://www.torchmobile.com/) |
10 * Copyright (C) 2008, 2009, 2011, 2012 Google Inc. All rights reserved. | 10 * Copyright (C) 2008, 2009, 2011, 2012 Google Inc. All rights reserved. |
(...skipping 2011 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2022 // SecurityOrigin. | 2022 // SecurityOrigin. |
2023 | 2023 |
2024 updateStyle(); | 2024 updateStyle(); |
2025 | 2025 |
2026 notifyLayoutTreeOfSubtreeChanges(); | 2026 notifyLayoutTreeOfSubtreeChanges(); |
2027 | 2027 |
2028 // As a result of the style recalculation, the currently hovered element might | 2028 // As a result of the style recalculation, the currently hovered element might |
2029 // have been detached (for example, by setting display:none in the :hover | 2029 // have been detached (for example, by setting display:none in the :hover |
2030 // style), schedule another mouseMove event to check if any other elements | 2030 // style), schedule another mouseMove event to check if any other elements |
2031 // ended up under the mouse pointer due to re-layout. | 2031 // ended up under the mouse pointer due to re-layout. |
2032 if (hoverNode() && !hoverNode()->layoutObject() && frame()) | 2032 if (hoverElement() && hoverElement()->layoutObject() && frame()) |
2033 frame()->eventHandler().dispatchFakeMouseMoveEventSoon(); | 2033 frame()->eventHandler().dispatchFakeMouseMoveEventSoon(); |
2034 | 2034 |
2035 if (m_focusedElement && !m_focusedElement->isFocusable()) | 2035 if (m_focusedElement && !m_focusedElement->isFocusable()) |
2036 clearFocusedElementSoon(); | 2036 clearFocusedElementSoon(); |
2037 layoutViewItem().clearHitTestCache(); | 2037 layoutViewItem().clearHitTestCache(); |
2038 | 2038 |
2039 DCHECK(!DocumentAnimations::needsAnimationTimingUpdate(*this)); | 2039 DCHECK(!DocumentAnimations::needsAnimationTimingUpdate(*this)); |
2040 | 2040 |
2041 unsigned elementCount = | 2041 unsigned elementCount = |
2042 styleEngine().styleForElementCount() - startElementCount; | 2042 styleEngine().styleForElementCount() - startElementCount; |
(...skipping 466 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2509 m_domWindow->clearEventQueue(); | 2509 m_domWindow->clearEventQueue(); |
2510 | 2510 |
2511 if (m_layoutView) | 2511 if (m_layoutView) |
2512 m_layoutView->setIsInWindow(false); | 2512 m_layoutView->setIsInWindow(false); |
2513 | 2513 |
2514 if (registrationContext()) | 2514 if (registrationContext()) |
2515 registrationContext()->documentWasDetached(); | 2515 registrationContext()->documentWasDetached(); |
2516 | 2516 |
2517 MutationObserver::cleanSlotChangeList(*this); | 2517 MutationObserver::cleanSlotChangeList(*this); |
2518 | 2518 |
2519 m_hoverNode = nullptr; | 2519 m_hoverElement = nullptr; |
2520 m_activeHoverElement = nullptr; | 2520 m_activeHoverElement = nullptr; |
2521 m_autofocusElement = nullptr; | 2521 m_autofocusElement = nullptr; |
2522 | 2522 |
2523 if (m_focusedElement.get()) { | 2523 if (m_focusedElement.get()) { |
2524 Element* oldFocusedElement = m_focusedElement; | 2524 Element* oldFocusedElement = m_focusedElement; |
2525 m_focusedElement = nullptr; | 2525 m_focusedElement = nullptr; |
2526 if (page()) | 2526 if (page()) |
2527 page()->chromeClient().focusedNodeChanged(oldFocusedElement, nullptr); | 2527 page()->chromeClient().focusedNodeChanged(oldFocusedElement, nullptr); |
2528 } | 2528 } |
2529 m_sequentialFocusNavigationStartingPoint = nullptr; | 2529 m_sequentialFocusNavigationStartingPoint = nullptr; |
(...skipping 1380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3910 // We need to manually repaint because we avoid doing all repaints in layout | 3910 // We need to manually repaint because we avoid doing all repaints in layout |
3911 // or style recalc while sheets are still loading to avoid FOUC. | 3911 // or style recalc while sheets are still loading to avoid FOUC. |
3912 m_pendingSheetLayout = IgnoreLayoutWithPendingSheets; | 3912 m_pendingSheetLayout = IgnoreLayoutWithPendingSheets; |
3913 | 3913 |
3914 DCHECK(!layoutViewItem().isNull() || importsController()); | 3914 DCHECK(!layoutViewItem().isNull() || importsController()); |
3915 if (!layoutViewItem().isNull()) | 3915 if (!layoutViewItem().isNull()) |
3916 layoutViewItem().invalidatePaintForViewAndCompositedLayers(); | 3916 layoutViewItem().invalidatePaintForViewAndCompositedLayers(); |
3917 } | 3917 } |
3918 } | 3918 } |
3919 | 3919 |
3920 void Document::setHoverNode(Node* newHoverNode) { | 3920 void Document::setHoverElement(Element* newHoverElement) { |
3921 m_hoverNode = newHoverNode; | 3921 m_hoverElement = newHoverElement; |
3922 } | 3922 } |
3923 | 3923 |
3924 void Document::setActiveHoverElement(Element* newActiveElement) { | 3924 void Document::setActiveHoverElement(Element* newActiveElement) { |
3925 if (!newActiveElement) { | 3925 if (!newActiveElement) { |
3926 m_activeHoverElement.clear(); | 3926 m_activeHoverElement.clear(); |
3927 return; | 3927 return; |
3928 } | 3928 } |
3929 | 3929 |
3930 m_activeHoverElement = newActiveElement; | 3930 m_activeHoverElement = newActiveElement; |
3931 } | 3931 } |
3932 | 3932 |
3933 void Document::removeFocusedElementOfSubtree(Node* node, | 3933 void Document::removeFocusedElementOfSubtree(Node* node, |
3934 bool amongChildrenOnly) { | 3934 bool amongChildrenOnly) { |
3935 if (!m_focusedElement) | 3935 if (!m_focusedElement) |
3936 return; | 3936 return; |
3937 | 3937 |
3938 // We can't be focused if we're not in the document. | 3938 // We can't be focused if we're not in the document. |
3939 if (!node->isConnected()) | 3939 if (!node->isConnected()) |
3940 return; | 3940 return; |
3941 bool contains = | 3941 bool contains = |
3942 node->isShadowIncludingInclusiveAncestorOf(m_focusedElement.get()); | 3942 node->isShadowIncludingInclusiveAncestorOf(m_focusedElement.get()); |
3943 if (contains && (m_focusedElement != node || !amongChildrenOnly)) | 3943 if (contains && (m_focusedElement != node || !amongChildrenOnly)) |
3944 clearFocusedElement(); | 3944 clearFocusedElement(); |
3945 } | 3945 } |
3946 | 3946 |
3947 void Document::hoveredNodeDetached(Element& element) { | 3947 void Document::hoveredNodeDetached(Element& element) { |
3948 if (!m_hoverNode) | 3948 if (!m_hoverElement) |
3949 return; | 3949 return; |
3950 | 3950 |
3951 m_hoverNode->updateDistribution(); | 3951 m_hoverElement->updateDistribution(); |
3952 if (element != m_hoverNode && | 3952 if (element != m_hoverElement) |
3953 (!m_hoverNode->isTextNode() || | |
3954 element != FlatTreeTraversal::parent(*m_hoverNode))) | |
3955 return; | 3953 return; |
3956 | 3954 |
3957 m_hoverNode = FlatTreeTraversal::parent(element); | 3955 m_hoverElement = FlatTreeTraversal::parentElement(element); |
3958 while (m_hoverNode && !m_hoverNode->layoutObject()) | 3956 while (m_hoverElement && |
3959 m_hoverNode = FlatTreeTraversal::parent(*m_hoverNode); | 3957 !(m_hoverElement->layoutObject() && m_hoverElement->isHovered())) |
| 3958 m_hoverElement = FlatTreeTraversal::parentElement(*m_hoverElement); |
3960 | 3959 |
3961 // If the mouse cursor is not visible, do not clear existing | 3960 // If the mouse cursor is not visible, do not clear existing |
3962 // hover effects on the ancestors of |element| and do not invoke | 3961 // hover effects on the ancestors of |element| and do not invoke |
3963 // new hover effects on any other element. | 3962 // new hover effects on any other element. |
3964 if (!page()->isCursorVisible()) | 3963 if (!page()->isCursorVisible()) |
3965 return; | 3964 return; |
3966 | 3965 |
3967 if (frame()) | 3966 if (frame()) |
3968 frame()->eventHandler().scheduleHoverStateUpdate(); | 3967 frame()->eventHandler().scheduleHoverStateUpdate(); |
3969 } | 3968 } |
(...skipping 2168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6138 !m_snapCoordinator) | 6137 !m_snapCoordinator) |
6139 m_snapCoordinator = SnapCoordinator::create(); | 6138 m_snapCoordinator = SnapCoordinator::create(); |
6140 | 6139 |
6141 return m_snapCoordinator.get(); | 6140 return m_snapCoordinator.get(); |
6142 } | 6141 } |
6143 | 6142 |
6144 void Document::setContextFeatures(ContextFeatures& features) { | 6143 void Document::setContextFeatures(ContextFeatures& features) { |
6145 m_contextFeatures = &features; | 6144 m_contextFeatures = &features; |
6146 } | 6145 } |
6147 | 6146 |
6148 static LayoutObject* nearestCommonHoverAncestor(LayoutObject* obj1, | |
6149 LayoutObject* obj2) { | |
6150 if (!obj1 || !obj2) | |
6151 return 0; | |
6152 | |
6153 for (LayoutObject* currObj1 = obj1; currObj1; | |
6154 currObj1 = currObj1->hoverAncestor()) { | |
6155 for (LayoutObject* currObj2 = obj2; currObj2; | |
6156 currObj2 = currObj2->hoverAncestor()) { | |
6157 if (currObj1 == currObj2) | |
6158 return currObj1; | |
6159 } | |
6160 } | |
6161 | |
6162 return 0; | |
6163 } | |
6164 | |
6165 // TODO(mustaq) |request| parameter maybe a misuse of HitTestRequest in | 6147 // TODO(mustaq) |request| parameter maybe a misuse of HitTestRequest in |
6166 // updateHoverActiveState() since the function doesn't bother with hit-testing. | 6148 // updateHoverActiveState() since the function doesn't bother with hit-testing. |
6167 void Document::updateHoverActiveState(const HitTestRequest& request, | 6149 void Document::updateHoverActiveState(const HitTestRequest& request, |
6168 Element* innerElement, | 6150 Element* innerElement, |
6169 Scrollbar* hitScrollbar) { | 6151 Scrollbar* hitScrollbar) { |
6170 DCHECK(!request.readOnly()); | 6152 DCHECK(!request.readOnly()); |
6171 | 6153 |
6172 if (request.active() && m_frame) | 6154 if (request.active() && m_frame) |
6173 m_frame->eventHandler().notifyElementActivated(); | 6155 m_frame->eventHandler().notifyElementActivated(); |
6174 | 6156 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6217 m_userActionElements.setInActiveChain(node, true); | 6199 m_userActionElements.setInActiveChain(node, true); |
6218 } | 6200 } |
6219 setActiveHoverElement(newActiveElement); | 6201 setActiveHoverElement(newActiveElement); |
6220 } | 6202 } |
6221 } | 6203 } |
6222 // If the mouse has just been pressed, set :active on the chain. Those (and | 6204 // If the mouse has just been pressed, set :active on the chain. Those (and |
6223 // only those) nodes should remain :active until the mouse is released. | 6205 // only those) nodes should remain :active until the mouse is released. |
6224 bool allowActiveChanges = !oldActiveElement && activeHoverElement(); | 6206 bool allowActiveChanges = !oldActiveElement && activeHoverElement(); |
6225 | 6207 |
6226 // If the mouse is down and if this is a mouse move event, we want to restrict | 6208 // If the mouse is down and if this is a mouse move event, we want to restrict |
6227 // changes in :hover/:active to only apply to elements that are in the :active | 6209 // changes in :active to only apply to elements that are in the :active chain |
6228 // chain that we froze at the time the mouse went down. | 6210 // that we froze at the time the mouse went down. |
6229 bool mustBeInActiveChain = request.active() && request.move(); | 6211 bool mustBeInActiveChain = request.active() && request.move(); |
6230 | 6212 |
6231 Node* oldHoverNode = hoverNode(); | 6213 Element* oldHoverElement = hoverElement(); |
6232 | 6214 |
6233 // Check to see if the hovered node has changed. | 6215 // Check to see if the hovered node has changed. |
6234 // If it hasn't, we do not need to do anything. | 6216 // If it hasn't, we do not need to do anything. |
6235 Node* newHoverNode = innerElementInDocument; | 6217 Element* newHoverElement = innerElementInDocument; |
6236 while (newHoverNode && !newHoverNode->layoutObject()) | 6218 while (newHoverElement && !newHoverElement->layoutObject()) { |
6237 newHoverNode = newHoverNode->parentOrShadowHostNode(); | 6219 newHoverElement = |
| 6220 LayoutTreeBuilderTraversal::parentElement(*newHoverElement); |
| 6221 } |
| 6222 |
| 6223 DCHECK(!oldHoverElement || oldHoverElement->isConnected()); |
| 6224 DCHECK(!oldHoverElement || oldHoverElement->isHovered()); |
6238 | 6225 |
6239 // Update our current hover node. | 6226 // Update our current hover node. |
6240 setHoverNode(newHoverNode); | 6227 setHoverElement(newHoverElement); |
6241 | 6228 |
6242 // We have two different objects. Fetch their layoutObjects. | 6229 Node* ancestor = (oldHoverElement && newHoverElement) |
6243 LayoutObject* oldHoverObj = | 6230 ? FlatTreeTraversal::commonAncestor(*oldHoverElement, |
6244 oldHoverNode ? oldHoverNode->layoutObject() : nullptr; | 6231 *newHoverElement) |
6245 LayoutObject* newHoverObj = | 6232 : nullptr; |
6246 newHoverNode ? newHoverNode->layoutObject() : nullptr; | |
6247 | 6233 |
6248 // Locate the common ancestor layout object for the two layoutObjects. | 6234 HeapVector<Member<Element>, 32> elementsToRemoveFromChain; |
6249 LayoutObject* ancestor = nearestCommonHoverAncestor(oldHoverObj, newHoverObj); | 6235 HeapVector<Member<Element>, 32> elementsToAddToChain; |
6250 Node* ancestorNode(ancestor ? ancestor->node() : nullptr); | |
6251 | 6236 |
6252 HeapVector<Member<Node>, 32> nodesToRemoveFromChain; | 6237 if (oldHoverElement != newHoverElement) { |
6253 HeapVector<Member<Node>, 32> nodesToAddToChain; | |
6254 | |
6255 if (oldHoverObj != newHoverObj) { | |
6256 // If the old hovered node is not nil but it's layoutObject is, it was | |
6257 // probably detached as part of the :hover style (for instance by setting | |
6258 // display:none in the :hover pseudo-class). In this case, the old hovered | |
6259 // element (and its ancestors) must be updated, to ensure it's normal style | |
6260 // is re-applied. | |
6261 if (oldHoverNode && !oldHoverObj) { | |
6262 for (Node& node : NodeTraversal::inclusiveAncestorsOf(*oldHoverNode)) { | |
6263 if (!mustBeInActiveChain || | |
6264 (node.isElementNode() && toElement(node).inActiveChain())) | |
6265 nodesToRemoveFromChain.push_back(node); | |
6266 } | |
6267 } | |
6268 | |
6269 // The old hover path only needs to be cleared up to (and not including) the | 6238 // The old hover path only needs to be cleared up to (and not including) the |
6270 // common ancestor; | 6239 // common ancestor; |
6271 for (LayoutObject* curr = oldHoverObj; curr && curr != ancestor; | 6240 for (Element* curr = oldHoverElement; curr && curr != ancestor; |
6272 curr = curr->hoverAncestor()) { | 6241 curr = FlatTreeTraversal::parentElement(*curr)) |
6273 if (curr->node() && !curr->isText() && | 6242 elementsToRemoveFromChain.push_back(curr); |
6274 (!mustBeInActiveChain || curr->node()->inActiveChain())) | |
6275 nodesToRemoveFromChain.push_back(curr->node()); | |
6276 } | |
6277 | |
6278 // TODO(mustaq): The two loops above may push a single node twice into | |
6279 // nodesToRemoveFromChain. There must be a better way. | |
6280 } | 6243 } |
6281 | 6244 |
6282 // Now set the hover state for our new object up to the root. | 6245 // Now set the hover state for our new object up to the root. |
6283 for (LayoutObject* curr = newHoverObj; curr; curr = curr->hoverAncestor()) { | 6246 for (Element* curr = newHoverElement; curr; |
6284 if (curr->node() && !curr->isText() && | 6247 curr = FlatTreeTraversal::parentElement(*curr)) |
6285 (!mustBeInActiveChain || curr->node()->inActiveChain())) | 6248 elementsToAddToChain.push_back(curr); |
6286 nodesToAddToChain.push_back(curr->node()); | |
6287 } | |
6288 | 6249 |
6289 size_t removeCount = nodesToRemoveFromChain.size(); | 6250 for (Element* element : elementsToRemoveFromChain) |
6290 for (size_t i = 0; i < removeCount; ++i) { | 6251 element->setHovered(false); |
6291 nodesToRemoveFromChain[i]->setHovered(false); | |
6292 } | |
6293 | 6252 |
6294 bool sawCommonAncestor = false; | 6253 bool sawCommonAncestor = false; |
6295 size_t addCount = nodesToAddToChain.size(); | 6254 for (Element* element : elementsToAddToChain) { |
6296 for (size_t i = 0; i < addCount; ++i) { | |
6297 // Elements past the common ancestor do not change hover state, but might | 6255 // Elements past the common ancestor do not change hover state, but might |
6298 // change active state. | 6256 // change active state. |
6299 if (ancestorNode && nodesToAddToChain[i] == ancestorNode) | 6257 if (element == ancestor) |
6300 sawCommonAncestor = true; | 6258 sawCommonAncestor = true; |
6301 if (allowActiveChanges) | 6259 if (allowActiveChanges && |
6302 nodesToAddToChain[i]->setActive(true); | 6260 (!mustBeInActiveChain || element->inActiveChain())) |
6303 if (!sawCommonAncestor || nodesToAddToChain[i] == m_hoverNode) { | 6261 element->setActive(true); |
6304 nodesToAddToChain[i]->setHovered(true); | 6262 if (!sawCommonAncestor || element == m_hoverElement) |
6305 } | 6263 element->setHovered(true); |
6306 } | 6264 } |
6307 } | 6265 } |
6308 | 6266 |
6309 bool Document::haveScriptBlockingStylesheetsLoaded() const { | 6267 bool Document::haveScriptBlockingStylesheetsLoaded() const { |
6310 return m_styleEngine->haveScriptBlockingStylesheetsLoaded(); | 6268 return m_styleEngine->haveScriptBlockingStylesheetsLoaded(); |
6311 } | 6269 } |
6312 | 6270 |
6313 bool Document::haveRenderBlockingStylesheetsLoaded() const { | 6271 bool Document::haveRenderBlockingStylesheetsLoaded() const { |
6314 if (RuntimeEnabledFeatures::cssInBodyDoesNotBlockPaintEnabled()) | 6272 if (RuntimeEnabledFeatures::cssInBodyDoesNotBlockPaintEnabled()) |
6315 return m_styleEngine->haveRenderBlockingStylesheetsLoaded(); | 6273 return m_styleEngine->haveRenderBlockingStylesheetsLoaded(); |
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6550 sendSensitiveInputVisibility(); | 6508 sendSensitiveInputVisibility(); |
6551 } | 6509 } |
6552 | 6510 |
6553 DEFINE_TRACE(Document) { | 6511 DEFINE_TRACE(Document) { |
6554 visitor->trace(m_importsController); | 6512 visitor->trace(m_importsController); |
6555 visitor->trace(m_docType); | 6513 visitor->trace(m_docType); |
6556 visitor->trace(m_implementation); | 6514 visitor->trace(m_implementation); |
6557 visitor->trace(m_autofocusElement); | 6515 visitor->trace(m_autofocusElement); |
6558 visitor->trace(m_focusedElement); | 6516 visitor->trace(m_focusedElement); |
6559 visitor->trace(m_sequentialFocusNavigationStartingPoint); | 6517 visitor->trace(m_sequentialFocusNavigationStartingPoint); |
6560 visitor->trace(m_hoverNode); | 6518 visitor->trace(m_hoverElement); |
6561 visitor->trace(m_activeHoverElement); | 6519 visitor->trace(m_activeHoverElement); |
6562 visitor->trace(m_documentElement); | 6520 visitor->trace(m_documentElement); |
6563 visitor->trace(m_rootScrollerController); | 6521 visitor->trace(m_rootScrollerController); |
6564 visitor->trace(m_titleElement); | 6522 visitor->trace(m_titleElement); |
6565 visitor->trace(m_axObjectCache); | 6523 visitor->trace(m_axObjectCache); |
6566 visitor->trace(m_markers); | 6524 visitor->trace(m_markers); |
6567 visitor->trace(m_cssTarget); | 6525 visitor->trace(m_cssTarget); |
6568 visitor->trace(m_currentScriptStack); | 6526 visitor->trace(m_currentScriptStack); |
6569 visitor->trace(m_scriptRunner); | 6527 visitor->trace(m_scriptRunner); |
6570 visitor->trace(m_listsInvalidatedAtDocument); | 6528 visitor->trace(m_listsInvalidatedAtDocument); |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6663 } | 6621 } |
6664 | 6622 |
6665 void showLiveDocumentInstances() { | 6623 void showLiveDocumentInstances() { |
6666 WeakDocumentSet& set = liveDocumentSet(); | 6624 WeakDocumentSet& set = liveDocumentSet(); |
6667 fprintf(stderr, "There are %u documents currently alive:\n", set.size()); | 6625 fprintf(stderr, "There are %u documents currently alive:\n", set.size()); |
6668 for (blink::Document* document : set) | 6626 for (blink::Document* document : set) |
6669 fprintf(stderr, "- Document %p URL: %s\n", document, | 6627 fprintf(stderr, "- Document %p URL: %s\n", document, |
6670 document->url().getString().utf8().data()); | 6628 document->url().getString().utf8().data()); |
6671 } | 6629 } |
6672 #endif | 6630 #endif |
OLD | NEW |