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 1237ded036ba45e531b0417259a5a5afc84cd3b8..c253779291417e1207eeb3039ee07792a1f8b932 100644 |
--- a/third_party/WebKit/Source/core/dom/Document.cpp |
+++ b/third_party/WebKit/Source/core/dom/Document.cpp |
@@ -2630,7 +2630,7 @@ void Document::Shutdown() { |
MutationObserver::CleanSlotChangeList(*this); |
hover_element_ = nullptr; |
- active_hover_element_ = nullptr; |
+ active_element_ = nullptr; |
autofocus_element_ = nullptr; |
if (focused_element_.Get()) { |
@@ -4187,13 +4187,13 @@ void Document::SetHoverElement(Element* new_hover_element) { |
hover_element_ = new_hover_element; |
} |
-void Document::SetActiveHoverElement(Element* new_active_element) { |
+void Document::SetActiveElement(Element* new_active_element) { |
if (!new_active_element) { |
- active_hover_element_.Clear(); |
+ active_element_.Clear(); |
return; |
} |
- active_hover_element_ = new_active_element; |
+ active_element_ = new_active_element; |
} |
void Document::RemoveFocusedElementOfSubtree(Node* node, |
@@ -4238,8 +4238,8 @@ void Document::HoveredElementDetached(Element& element) { |
} |
void Document::ActiveChainNodeDetached(Element& element) { |
- if (element == active_hover_element_) |
- active_hover_element_ = SkipDisplayNoneAncestors(&element); |
+ if (element == active_element_) |
+ active_element_ = SkipDisplayNoneAncestors(&element); |
} |
const Vector<AnnotatedRegionValue>& Document::AnnotatedRegions() const { |
@@ -6471,7 +6471,14 @@ void Document::UpdateHoverActiveState(const HitTestRequest& request, |
} |
UpdateDistribution(); |
- Element* old_active_element = ActiveHoverElement(); |
+ |
+ UpdateActiveState(request, inner_element_in_document); |
+ UpdateHoverState(request, inner_element_in_document); |
+} |
+ |
+void Document::UpdateActiveState(const HitTestRequest& request, |
+ Element* inner_element_in_document) { |
+ Element* old_active_element = GetActiveElement(); |
if (old_active_element && !request.Active()) { |
// The oldActiveElement layoutObject is null, dropped on :active by setting |
// display: none, for instance. We still need to clear the ActiveChain as |
@@ -6481,7 +6488,7 @@ void Document::UpdateHoverActiveState(const HitTestRequest& request, |
element->SetActive(false); |
user_action_elements_.SetInActiveChain(element, false); |
} |
- SetActiveHoverElement(nullptr); |
+ SetActiveElement(nullptr); |
} else { |
Element* new_active_element = inner_element_in_document; |
if (!old_active_element && new_active_element && |
@@ -6493,24 +6500,39 @@ void Document::UpdateHoverActiveState(const HitTestRequest& request, |
element = FlatTreeTraversal::ParentElement(*element)) { |
user_action_elements_.SetInActiveChain(element, true); |
} |
- SetActiveHoverElement(new_active_element); |
+ SetActiveElement(new_active_element); |
} |
} |
- // Do not set hover state if event is from touch and on mobile. |
- bool allow_hover_changes = |
- !(request.TouchEvent() && GetPage() && |
- GetPage()->GetVisualViewport().ShouldDisableDesktopWorkarounds()); |
- |
// If the mouse has just been pressed, set :active on the chain. Those (and |
// only those) nodes should remain :active until the mouse is released. |
- bool allow_active_changes = !old_active_element && ActiveHoverElement(); |
+ bool allow_active_changes = !old_active_element && GetActiveElement(); |
+ if (!allow_active_changes) |
+ return; |
// If the mouse is down and if this is a mouse move event, we want to restrict |
- // changes in :hover/:active to only apply to elements that are in the :active |
+ // changes in :active to only apply to elements that are in the :active |
// chain that we froze at the time the mouse went down. |
bool must_be_in_active_chain = request.Active() && request.Move(); |
+ Element* new_element = |
+ SkipDisplayNoneAncestors(inner_element_in_document); |
+ |
+ // Now set the active state for our new object up to the root. |
+ for (Element* curr = new_element; curr; |
+ curr = FlatTreeTraversal::ParentElement(*curr)) { |
+ if (!must_be_in_active_chain || curr->InActiveChain()) |
+ curr->SetActive(true); |
+ } |
+} |
+ |
+void Document::UpdateHoverState(const HitTestRequest& request, |
+ Element* inner_element_in_document) { |
+ // Do not set hover state if event is from touch and on mobile. |
+ bool allow_hover_changes = |
+ !(request.TouchEvent() && GetPage() && |
+ GetPage()->GetVisualViewport().ShouldDisableDesktopWorkarounds()); |
+ |
Element* old_hover_element = HoverElement(); |
// The passed in innerElement may not be a result of a hit test for the |
@@ -6524,6 +6546,9 @@ void Document::UpdateHoverActiveState(const HitTestRequest& request, |
if (allow_hover_changes) |
SetHoverElement(new_hover_element); |
+ if (old_hover_element == new_hover_element || !allow_hover_changes) |
+ return; |
+ |
Node* ancestor_element = nullptr; |
if (old_hover_element && old_hover_element->isConnected() && |
new_hover_element) { |
@@ -6534,50 +6559,34 @@ void Document::UpdateHoverActiveState(const HitTestRequest& request, |
} |
HeapVector<Member<Element>, 32> elements_to_remove_from_chain; |
- HeapVector<Member<Element>, 32> elements_to_add_to_chain; |
+ HeapVector<Member<Element>, 32> elements_to_add_to_hover_chain; |
- if (old_hover_element != new_hover_element) { |
- // The old hover path only needs to be cleared up to (and not including) the |
- // common ancestor; |
- // |
- // 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 (old_hover_element && old_hover_element->isConnected()) { |
- for (Element* curr = old_hover_element; curr && curr != ancestor_element; |
- curr = FlatTreeTraversal::ParentElement(*curr)) { |
- if (!must_be_in_active_chain || curr->InActiveChain()) |
- elements_to_remove_from_chain.push_back(curr); |
- } |
+ // The old hover path only needs to be cleared up to (and not including) the |
+ // common ancestor; |
+ // |
+ // FIXME(ecobos@igalia.com): oldHoverElement may be disconnected from the |
+ // tree already. |
+ if (old_hover_element && old_hover_element->isConnected()) { |
+ for (Element* curr = old_hover_element; curr && curr != ancestor_element; |
+ curr = FlatTreeTraversal::ParentElement(*curr)) { |
+ elements_to_remove_from_chain.push_back(curr); |
} |
} |
// Now set the hover state for our new object up to the root. |
for (Element* curr = new_hover_element; curr; |
curr = FlatTreeTraversal::ParentElement(*curr)) { |
- if (!must_be_in_active_chain || curr->InActiveChain()) |
- elements_to_add_to_chain.push_back(curr); |
+ elements_to_add_to_hover_chain.push_back(curr); |
} |
- if (allow_hover_changes) { |
- for (Element* element : elements_to_remove_from_chain) |
- element->SetHovered(false); |
- } |
+ for (Element* element : elements_to_remove_from_chain) |
+ element->SetHovered(false); |
bool saw_common_ancestor = false; |
- for (Element* element : elements_to_add_to_chain) { |
- // Elements past the common ancestor do not change hover state, but might |
- // change active state. |
+ for (Element* element : elements_to_add_to_hover_chain) { |
if (element == ancestor_element) |
saw_common_ancestor = true; |
- if (allow_active_changes) |
- element->SetActive(true); |
- if (allow_hover_changes && |
- (!saw_common_ancestor || element == hover_element_)) |
+ if (!saw_common_ancestor || element == hover_element_) |
element->SetHovered(true); |
} |
} |
@@ -6839,7 +6848,7 @@ DEFINE_TRACE(Document) { |
visitor->Trace(focused_element_); |
visitor->Trace(sequential_focus_navigation_starting_point_); |
visitor->Trace(hover_element_); |
- visitor->Trace(active_hover_element_); |
+ visitor->Trace(active_element_); |
visitor->Trace(document_element_); |
visitor->Trace(root_scroller_controller_); |
visitor->Trace(title_element_); |