| Index: third_party/WebKit/Source/core/dom/Document.cpp
|
| diff --git a/third_party/WebKit/Source/core/dom/Document.cpp b/third_party/WebKit/Source/core/dom/Document.cpp
|
| index a49395510b0afd78c07bd6f7cebd0d756787d773..b58f72725a46788a76d5b8f3b66fff5141b39ca3 100644
|
| --- a/third_party/WebKit/Source/core/dom/Document.cpp
|
| +++ b/third_party/WebKit/Source/core/dom/Document.cpp
|
| @@ -2027,7 +2027,7 @@ void Document::updateStyleAndLayoutTree() {
|
| // have been detached (for example, by setting display:none in the :hover
|
| // style), schedule another mouseMove event to check if any other elements
|
| // ended up under the mouse pointer due to re-layout.
|
| - if (hoverNode() && !hoverNode()->layoutObject() && frame())
|
| + if (hoverElement() && !hoverElement()->layoutObject() && frame())
|
| frame()->eventHandler().dispatchFakeMouseMoveEventSoon();
|
|
|
| if (m_focusedElement && !m_focusedElement->isFocusable())
|
| @@ -2517,7 +2517,7 @@ void Document::shutdown() {
|
|
|
| MutationObserver::cleanSlotChangeList(*this);
|
|
|
| - m_hoverNode = nullptr;
|
| + m_hoverElement = nullptr;
|
| m_activeHoverElement = nullptr;
|
| m_autofocusElement = nullptr;
|
|
|
| @@ -3920,8 +3920,8 @@ void Document::styleResolverMayHaveChanged() {
|
| }
|
| }
|
|
|
| -void Document::setHoverNode(Node* newHoverNode) {
|
| - m_hoverNode = newHoverNode;
|
| +void Document::setHoverElement(Element* newHoverElement) {
|
| + m_hoverElement = newHoverElement;
|
| }
|
|
|
| void Document::setActiveHoverElement(Element* newActiveElement) {
|
| @@ -3947,28 +3947,22 @@ void Document::removeFocusedElementOfSubtree(Node* node,
|
| clearFocusedElement();
|
| }
|
|
|
| -static Node* skipDisplayNoneAncestors(Node* node) {
|
| - while (node) {
|
| - if (node->layoutObject())
|
| - return node;
|
| - if (node->isElementNode() && toElement(node)->hasDisplayContentsStyle())
|
| - return node;
|
| - node = FlatTreeTraversal::parent(*node);
|
| +static Element* skipDisplayNoneAncestors(Element* element) {
|
| + for (; element; element = FlatTreeTraversal::parentElement(*element)) {
|
| + if (element->layoutObject() || element->hasDisplayContentsStyle())
|
| + return element;
|
| }
|
| return nullptr;
|
| }
|
|
|
| -void Document::hoveredNodeDetached(Element& element) {
|
| - if (!m_hoverNode)
|
| +void Document::hoveredElementDetached(Element& element) {
|
| + if (!m_hoverElement)
|
| return;
|
| -
|
| - m_hoverNode->updateDistribution();
|
| - if (element != m_hoverNode &&
|
| - (!m_hoverNode->isTextNode() ||
|
| - element != FlatTreeTraversal::parent(*m_hoverNode)))
|
| + if (element != m_hoverElement)
|
| return;
|
|
|
| - m_hoverNode = skipDisplayNoneAncestors(&element);
|
| + m_hoverElement->updateDistribution();
|
| + m_hoverElement = skipDisplayNoneAncestors(&element);
|
|
|
| // If the mouse cursor is not visible, do not clear existing
|
| // hover effects on the ancestors of |element| and do not invoke
|
| @@ -3981,16 +3975,8 @@ void Document::hoveredNodeDetached(Element& element) {
|
| }
|
|
|
| void Document::activeChainNodeDetached(Element& element) {
|
| - if (!m_activeHoverElement)
|
| - return;
|
| -
|
| - if (element != m_activeHoverElement)
|
| - return;
|
| -
|
| - Node* activeNode = skipDisplayNoneAncestors(&element);
|
| - m_activeHoverElement = activeNode && activeNode->isElementNode()
|
| - ? toElement(activeNode)
|
| - : nullptr;
|
| + if (element == m_activeHoverElement)
|
| + m_activeHoverElement = skipDisplayNoneAncestors(&element);
|
| }
|
|
|
| const Vector<AnnotatedRegionValue>& Document::annotatedRegions() const {
|
| @@ -6182,11 +6168,10 @@ void Document::updateHoverActiveState(const HitTestRequest& request,
|
| // The oldActiveElement layoutObject is null, dropped on :active by setting
|
| // display: none, for instance. We still need to clear the ActiveChain as
|
| // the mouse is released.
|
| - for (Node* node = oldActiveElement; node;
|
| - node = FlatTreeTraversal::parent(*node)) {
|
| - DCHECK(!node->isTextNode());
|
| - node->setActive(false);
|
| - m_userActionElements.setInActiveChain(node, false);
|
| + for (Element* element = oldActiveElement; element;
|
| + element = FlatTreeTraversal::parentElement(*element)) {
|
| + element->setActive(false);
|
| + m_userActionElements.setInActiveChain(element, false);
|
| }
|
| setActiveHoverElement(nullptr);
|
| } else {
|
| @@ -6196,10 +6181,9 @@ void Document::updateHoverActiveState(const HitTestRequest& request,
|
| !request.touchMove()) {
|
| // We are setting the :active chain and freezing it. If future moves
|
| // happen, they will need to reference this chain.
|
| - for (Node* node = newActiveElement; node;
|
| - node = FlatTreeTraversal::parent(*node)) {
|
| - DCHECK(!node->isTextNode());
|
| - m_userActionElements.setInActiveChain(node, true);
|
| + for (Element* element = newActiveElement; element;
|
| + element = FlatTreeTraversal::parentElement(*element)) {
|
| + m_userActionElements.setInActiveChain(element, true);
|
| }
|
| setActiveHoverElement(newActiveElement);
|
| }
|
| @@ -6213,66 +6197,68 @@ void Document::updateHoverActiveState(const HitTestRequest& request,
|
| // chain that we froze at the time the mouse went down.
|
| bool mustBeInActiveChain = request.active() && request.move();
|
|
|
| - Node* oldHoverNode = hoverNode();
|
| + Element* oldHoverElement = hoverElement();
|
|
|
| // The passed in innerElement may not be a result of a hit test for the
|
| // current up-to-date flat/layout tree. That means the element may be
|
| // display:none at this point. Skip up the ancestor chain until we reach an
|
| // element with a layoutObject or a display:contents element.
|
| - Node* newHoverNode = skipDisplayNoneAncestors(innerElementInDocument);
|
| + Element* newHoverElement = skipDisplayNoneAncestors(innerElementInDocument);
|
|
|
| - // Update our current hover node.
|
| - setHoverNode(newHoverNode);
|
| + // Update our current hover element.
|
| + setHoverElement(newHoverElement);
|
|
|
| - Node* ancestor =
|
| - (oldHoverNode && oldHoverNode->isConnected() && newHoverNode)
|
| - ? FlatTreeTraversal::commonAncestor(*oldHoverNode, *newHoverNode)
|
| - : nullptr;
|
| + Node* ancestorElement = nullptr;
|
| + if (oldHoverElement && oldHoverElement->isConnected() && newHoverElement) {
|
| + Node* ancestor =
|
| + FlatTreeTraversal::commonAncestor(*oldHoverElement, *newHoverElement);
|
| + if (ancestor && ancestor->isElementNode())
|
| + ancestorElement = toElement(ancestor);
|
| + }
|
|
|
| - HeapVector<Member<Node>, 32> nodesToRemoveFromChain;
|
| - HeapVector<Member<Node>, 32> nodesToAddToChain;
|
| + HeapVector<Member<Element>, 32> elementsToRemoveFromChain;
|
| + HeapVector<Member<Element>, 32> elementsToAddToChain;
|
|
|
| - if (oldHoverNode != newHoverNode) {
|
| + if (oldHoverElement != newHoverElement) {
|
| // The old hover path only needs to be cleared up to (and not including) the
|
| // common ancestor;
|
| //
|
| - // FIXME(ecobos@igalia.com): oldHoverNode may be disconnected from the tree
|
| - // already. This is due to our handling of m_hoverNode in
|
| - // hoveredNodeDetached (which assumes all the parents are hovered) and
|
| + // FIXME(ecobos@igalia.com): oldHoverElement may be disconnected from the
|
| + // tree already. This is due to our handling of m_hoverElement in
|
| + // hoveredElementDetached (which assumes all the parents are hovered) and
|
| // mustBeInActiveChain (which makes this not hold).
|
| //
|
| // In that case, none of the nodes in the chain have the flags, so there's
|
| // no problem in skipping this step.
|
| - if (oldHoverNode && oldHoverNode->isConnected()) {
|
| - for (Node* curr = oldHoverNode; curr && curr != ancestor;
|
| - curr = FlatTreeTraversal::parent(*curr)) {
|
| - if (!curr->isTextNode() &&
|
| - (!mustBeInActiveChain || curr->inActiveChain()))
|
| - nodesToRemoveFromChain.push_back(curr);
|
| + if (oldHoverElement && oldHoverElement->isConnected()) {
|
| + for (Element* curr = oldHoverElement; curr && curr != ancestorElement;
|
| + curr = FlatTreeTraversal::parentElement(*curr)) {
|
| + if (!mustBeInActiveChain || curr->inActiveChain())
|
| + elementsToRemoveFromChain.push_back(curr);
|
| }
|
| }
|
| }
|
|
|
| // Now set the hover state for our new object up to the root.
|
| - for (Node* curr = newHoverNode; curr;
|
| - curr = FlatTreeTraversal::parent(*curr)) {
|
| - if (!curr->isTextNode() && (!mustBeInActiveChain || curr->inActiveChain()))
|
| - nodesToAddToChain.push_back(curr);
|
| + for (Element* curr = newHoverElement; curr;
|
| + curr = FlatTreeTraversal::parentElement(*curr)) {
|
| + if (!mustBeInActiveChain || curr->inActiveChain())
|
| + elementsToAddToChain.push_back(curr);
|
| }
|
|
|
| - for (Node* node : nodesToRemoveFromChain)
|
| - node->setHovered(false);
|
| + for (Element* element : elementsToRemoveFromChain)
|
| + element->setHovered(false);
|
|
|
| bool sawCommonAncestor = false;
|
| - for (Node* node : nodesToAddToChain) {
|
| + for (Element* element : elementsToAddToChain) {
|
| // Elements past the common ancestor do not change hover state, but might
|
| // change active state.
|
| - if (node == ancestor)
|
| + if (element == ancestorElement)
|
| sawCommonAncestor = true;
|
| if (allowActiveChanges)
|
| - node->setActive(true);
|
| - if (!sawCommonAncestor || node == m_hoverNode)
|
| - node->setHovered(true);
|
| + element->setActive(true);
|
| + if (!sawCommonAncestor || element == m_hoverElement)
|
| + element->setHovered(true);
|
| }
|
| }
|
|
|
| @@ -6527,7 +6513,7 @@ DEFINE_TRACE(Document) {
|
| visitor->trace(m_autofocusElement);
|
| visitor->trace(m_focusedElement);
|
| visitor->trace(m_sequentialFocusNavigationStartingPoint);
|
| - visitor->trace(m_hoverNode);
|
| + visitor->trace(m_hoverElement);
|
| visitor->trace(m_activeHoverElement);
|
| visitor->trace(m_documentElement);
|
| visitor->trace(m_rootScrollerController);
|
|
|