Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(67)

Side by Side Diff: third_party/WebKit/Source/core/dom/Document.cpp

Issue 2965603002: Update hover states when dragging the mouse into an element (Closed)
Patch Set: hover drag Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 2612 matching lines...) Expand 10 before | Expand all | Expand 10 after
2623 2623
2624 if (layout_view_) 2624 if (layout_view_)
2625 layout_view_->SetIsInWindow(false); 2625 layout_view_->SetIsInWindow(false);
2626 2626
2627 if (RegistrationContext()) 2627 if (RegistrationContext())
2628 RegistrationContext()->DocumentWasDetached(); 2628 RegistrationContext()->DocumentWasDetached();
2629 2629
2630 MutationObserver::CleanSlotChangeList(*this); 2630 MutationObserver::CleanSlotChangeList(*this);
2631 2631
2632 hover_element_ = nullptr; 2632 hover_element_ = nullptr;
2633 active_hover_element_ = nullptr; 2633 active_element_ = nullptr;
2634 autofocus_element_ = nullptr; 2634 autofocus_element_ = nullptr;
2635 2635
2636 if (focused_element_.Get()) { 2636 if (focused_element_.Get()) {
2637 Element* old_focused_element = focused_element_; 2637 Element* old_focused_element = focused_element_;
2638 focused_element_ = nullptr; 2638 focused_element_ = nullptr;
2639 if (GetPage()) 2639 if (GetPage())
2640 GetPage()->GetChromeClient().FocusedNodeChanged(old_focused_element, 2640 GetPage()->GetChromeClient().FocusedNodeChanged(old_focused_element,
2641 nullptr); 2641 nullptr);
2642 } 2642 }
2643 sequential_focus_navigation_starting_point_ = nullptr; 2643 sequential_focus_navigation_starting_point_ = nullptr;
(...skipping 1536 matching lines...) Expand 10 before | Expand all | Expand 10 after
4180 DCHECK(!GetLayoutViewItem().IsNull() || ImportsController()); 4180 DCHECK(!GetLayoutViewItem().IsNull() || ImportsController());
4181 if (!GetLayoutViewItem().IsNull()) 4181 if (!GetLayoutViewItem().IsNull())
4182 GetLayoutViewItem().InvalidatePaintForViewAndCompositedLayers(); 4182 GetLayoutViewItem().InvalidatePaintForViewAndCompositedLayers();
4183 } 4183 }
4184 } 4184 }
4185 4185
4186 void Document::SetHoverElement(Element* new_hover_element) { 4186 void Document::SetHoverElement(Element* new_hover_element) {
4187 hover_element_ = new_hover_element; 4187 hover_element_ = new_hover_element;
4188 } 4188 }
4189 4189
4190 void Document::SetActiveHoverElement(Element* new_active_element) { 4190 void Document::SetActiveElement(Element* new_active_element) {
4191 if (!new_active_element) { 4191 if (!new_active_element) {
4192 active_hover_element_.Clear(); 4192 active_element_.Clear();
4193 return; 4193 return;
4194 } 4194 }
4195 4195
4196 active_hover_element_ = new_active_element; 4196 active_element_ = new_active_element;
4197 } 4197 }
4198 4198
4199 void Document::RemoveFocusedElementOfSubtree(Node* node, 4199 void Document::RemoveFocusedElementOfSubtree(Node* node,
4200 bool among_children_only) { 4200 bool among_children_only) {
4201 if (!focused_element_) 4201 if (!focused_element_)
4202 return; 4202 return;
4203 4203
4204 // We can't be focused if we're not in the document. 4204 // We can't be focused if we're not in the document.
4205 if (!node->isConnected()) 4205 if (!node->isConnected())
4206 return; 4206 return;
(...skipping 24 matching lines...) Expand all
4231 // hover effects on the ancestors of |element| and do not invoke 4231 // hover effects on the ancestors of |element| and do not invoke
4232 // new hover effects on any other element. 4232 // new hover effects on any other element.
4233 if (!GetPage()->IsCursorVisible()) 4233 if (!GetPage()->IsCursorVisible())
4234 return; 4234 return;
4235 4235
4236 if (GetFrame()) 4236 if (GetFrame())
4237 GetFrame()->GetEventHandler().ScheduleHoverStateUpdate(); 4237 GetFrame()->GetEventHandler().ScheduleHoverStateUpdate();
4238 } 4238 }
4239 4239
4240 void Document::ActiveChainNodeDetached(Element& element) { 4240 void Document::ActiveChainNodeDetached(Element& element) {
4241 if (element == active_hover_element_) 4241 if (element == active_element_)
4242 active_hover_element_ = SkipDisplayNoneAncestors(&element); 4242 active_element_ = SkipDisplayNoneAncestors(&element);
4243 } 4243 }
4244 4244
4245 const Vector<AnnotatedRegionValue>& Document::AnnotatedRegions() const { 4245 const Vector<AnnotatedRegionValue>& Document::AnnotatedRegions() const {
4246 return annotated_regions_; 4246 return annotated_regions_;
4247 } 4247 }
4248 4248
4249 void Document::SetAnnotatedRegions( 4249 void Document::SetAnnotatedRegions(
4250 const Vector<AnnotatedRegionValue>& regions) { 4250 const Vector<AnnotatedRegionValue>& regions) {
4251 annotated_regions_ = regions; 4251 annotated_regions_ = regions;
4252 SetAnnotatedRegionsDirty(false); 4252 SetAnnotatedRegionsDirty(false);
(...skipping 2211 matching lines...) Expand 10 before | Expand all | Expand 10 after
6464 6464
6465 while (inner_element_in_document && 6465 while (inner_element_in_document &&
6466 inner_element_in_document->GetDocument() != this) { 6466 inner_element_in_document->GetDocument() != this) {
6467 inner_element_in_document->GetDocument().UpdateHoverActiveState( 6467 inner_element_in_document->GetDocument().UpdateHoverActiveState(
6468 request, inner_element_in_document); 6468 request, inner_element_in_document);
6469 inner_element_in_document = 6469 inner_element_in_document =
6470 inner_element_in_document->GetDocument().LocalOwner(); 6470 inner_element_in_document->GetDocument().LocalOwner();
6471 } 6471 }
6472 6472
6473 UpdateDistribution(); 6473 UpdateDistribution();
6474 Element* old_active_element = ActiveHoverElement(); 6474
6475 UpdateActiveState(request, inner_element_in_document);
6476 UpdateHoverState(request, inner_element_in_document);
6477 }
6478
6479 void Document::UpdateActiveState(const HitTestRequest& request,
6480 Element* inner_element_in_document) {
6481 Element* old_active_element = GetActiveElement();
6475 if (old_active_element && !request.Active()) { 6482 if (old_active_element && !request.Active()) {
6476 // The oldActiveElement layoutObject is null, dropped on :active by setting 6483 // The oldActiveElement layoutObject is null, dropped on :active by setting
6477 // display: none, for instance. We still need to clear the ActiveChain as 6484 // display: none, for instance. We still need to clear the ActiveChain as
6478 // the mouse is released. 6485 // the mouse is released.
6479 for (Element* element = old_active_element; element; 6486 for (Element* element = old_active_element; element;
6480 element = FlatTreeTraversal::ParentElement(*element)) { 6487 element = FlatTreeTraversal::ParentElement(*element)) {
6481 element->SetActive(false); 6488 element->SetActive(false);
6482 user_action_elements_.SetInActiveChain(element, false); 6489 user_action_elements_.SetInActiveChain(element, false);
6483 } 6490 }
6484 SetActiveHoverElement(nullptr); 6491 SetActiveElement(nullptr);
6485 } else { 6492 } else {
6486 Element* new_active_element = inner_element_in_document; 6493 Element* new_active_element = inner_element_in_document;
6487 if (!old_active_element && new_active_element && 6494 if (!old_active_element && new_active_element &&
6488 !new_active_element->IsDisabledFormControl() && request.Active() && 6495 !new_active_element->IsDisabledFormControl() && request.Active() &&
6489 !request.TouchMove()) { 6496 !request.TouchMove()) {
6490 // We are setting the :active chain and freezing it. If future moves 6497 // We are setting the :active chain and freezing it. If future moves
6491 // happen, they will need to reference this chain. 6498 // happen, they will need to reference this chain.
6492 for (Element* element = new_active_element; element; 6499 for (Element* element = new_active_element; element;
6493 element = FlatTreeTraversal::ParentElement(*element)) { 6500 element = FlatTreeTraversal::ParentElement(*element)) {
6494 user_action_elements_.SetInActiveChain(element, true); 6501 user_action_elements_.SetInActiveChain(element, true);
6495 } 6502 }
6496 SetActiveHoverElement(new_active_element); 6503 SetActiveElement(new_active_element);
6497 } 6504 }
6498 } 6505 }
6499 6506
6507 // If the mouse has just been pressed, set :active on the chain. Those (and
6508 // only those) nodes should remain :active until the mouse is released.
6509 bool allow_active_changes = !old_active_element && GetActiveElement();
6510 if (!allow_active_changes)
6511 return;
6512
6513 // If the mouse is down and if this is a mouse move event, we want to restrict
6514 // changes in :active to only apply to elements that are in the :active
6515 // chain that we froze at the time the mouse went down.
6516 bool must_be_in_active_chain = request.Active() && request.Move();
6517
6518 Element* new_element =
6519 SkipDisplayNoneAncestors(inner_element_in_document);
6520
6521 // Now set the active state for our new object up to the root.
6522 for (Element* curr = new_element; curr;
6523 curr = FlatTreeTraversal::ParentElement(*curr)) {
6524 if (!must_be_in_active_chain || curr->InActiveChain())
6525 curr->SetActive(true);
6526 }
6527 }
6528
6529 void Document::UpdateHoverState(const HitTestRequest& request,
6530 Element* inner_element_in_document) {
6500 // Do not set hover state if event is from touch and on mobile. 6531 // Do not set hover state if event is from touch and on mobile.
6501 bool allow_hover_changes = 6532 bool allow_hover_changes =
6502 !(request.TouchEvent() && GetPage() && 6533 !(request.TouchEvent() && GetPage() &&
6503 GetPage()->GetVisualViewport().ShouldDisableDesktopWorkarounds()); 6534 GetPage()->GetVisualViewport().ShouldDisableDesktopWorkarounds());
6504 6535
6505 // If the mouse has just been pressed, set :active on the chain. Those (and
6506 // only those) nodes should remain :active until the mouse is released.
6507 bool allow_active_changes = !old_active_element && ActiveHoverElement();
6508
6509 // If the mouse is down and if this is a mouse move event, we want to restrict
6510 // changes in :hover/:active to only apply to elements that are in the :active
6511 // chain that we froze at the time the mouse went down.
6512 bool must_be_in_active_chain = request.Active() && request.Move();
6513
6514 Element* old_hover_element = HoverElement(); 6536 Element* old_hover_element = HoverElement();
6515 6537
6516 // The passed in innerElement may not be a result of a hit test for the 6538 // The passed in innerElement may not be a result of a hit test for the
6517 // current up-to-date flat/layout tree. That means the element may be 6539 // current up-to-date flat/layout tree. That means the element may be
6518 // display:none at this point. Skip up the ancestor chain until we reach an 6540 // display:none at this point. Skip up the ancestor chain until we reach an
6519 // element with a layoutObject or a display:contents element. 6541 // element with a layoutObject or a display:contents element.
6520 Element* new_hover_element = 6542 Element* new_hover_element =
6521 SkipDisplayNoneAncestors(inner_element_in_document); 6543 SkipDisplayNoneAncestors(inner_element_in_document);
6522 6544
6523 // Update our current hover element. 6545 // Update our current hover element.
6524 if (allow_hover_changes) 6546 if (allow_hover_changes)
6525 SetHoverElement(new_hover_element); 6547 SetHoverElement(new_hover_element);
6526 6548
6549 if (old_hover_element == new_hover_element || !allow_hover_changes)
6550 return;
6551
6527 Node* ancestor_element = nullptr; 6552 Node* ancestor_element = nullptr;
6528 if (old_hover_element && old_hover_element->isConnected() && 6553 if (old_hover_element && old_hover_element->isConnected() &&
6529 new_hover_element) { 6554 new_hover_element) {
6530 Node* ancestor = FlatTreeTraversal::CommonAncestor(*old_hover_element, 6555 Node* ancestor = FlatTreeTraversal::CommonAncestor(*old_hover_element,
6531 *new_hover_element); 6556 *new_hover_element);
6532 if (ancestor && ancestor->IsElementNode()) 6557 if (ancestor && ancestor->IsElementNode())
6533 ancestor_element = ToElement(ancestor); 6558 ancestor_element = ToElement(ancestor);
6534 } 6559 }
6535 6560
6536 HeapVector<Member<Element>, 32> elements_to_remove_from_chain; 6561 HeapVector<Member<Element>, 32> elements_to_remove_from_chain;
6537 HeapVector<Member<Element>, 32> elements_to_add_to_chain; 6562 HeapVector<Member<Element>, 32> elements_to_add_to_hover_chain;
6538 6563
6539 if (old_hover_element != new_hover_element) { 6564 // The old hover path only needs to be cleared up to (and not including) the
6540 // The old hover path only needs to be cleared up to (and not including) the 6565 // common ancestor;
6541 // common ancestor; 6566 //
6542 // 6567 // FIXME(ecobos@igalia.com): oldHoverElement may be disconnected from the
6543 // FIXME(ecobos@igalia.com): oldHoverElement may be disconnected from the 6568 // tree already.
6544 // tree already. This is due to our handling of m_hoverElement in 6569 if (old_hover_element && old_hover_element->isConnected()) {
6545 // hoveredElementDetached (which assumes all the parents are hovered) and 6570 for (Element* curr = old_hover_element; curr && curr != ancestor_element;
6546 // mustBeInActiveChain (which makes this not hold). 6571 curr = FlatTreeTraversal::ParentElement(*curr)) {
6547 // 6572 elements_to_remove_from_chain.push_back(curr);
6548 // In that case, none of the nodes in the chain have the flags, so there's
6549 // no problem in skipping this step.
6550 if (old_hover_element && old_hover_element->isConnected()) {
6551 for (Element* curr = old_hover_element; curr && curr != ancestor_element;
6552 curr = FlatTreeTraversal::ParentElement(*curr)) {
6553 if (!must_be_in_active_chain || curr->InActiveChain())
6554 elements_to_remove_from_chain.push_back(curr);
6555 }
6556 } 6573 }
6557 } 6574 }
6558 6575
6559 // Now set the hover state for our new object up to the root. 6576 // Now set the hover state for our new object up to the root.
6560 for (Element* curr = new_hover_element; curr; 6577 for (Element* curr = new_hover_element; curr;
6561 curr = FlatTreeTraversal::ParentElement(*curr)) { 6578 curr = FlatTreeTraversal::ParentElement(*curr)) {
6562 if (!must_be_in_active_chain || curr->InActiveChain()) 6579 elements_to_add_to_hover_chain.push_back(curr);
6563 elements_to_add_to_chain.push_back(curr);
6564 } 6580 }
6565 6581
6566 if (allow_hover_changes) { 6582 for (Element* element : elements_to_remove_from_chain)
6567 for (Element* element : elements_to_remove_from_chain) 6583 element->SetHovered(false);
6568 element->SetHovered(false);
6569 }
6570 6584
6571 bool saw_common_ancestor = false; 6585 bool saw_common_ancestor = false;
6572 for (Element* element : elements_to_add_to_chain) { 6586 for (Element* element : elements_to_add_to_hover_chain) {
6573 // Elements past the common ancestor do not change hover state, but might
6574 // change active state.
6575 if (element == ancestor_element) 6587 if (element == ancestor_element)
6576 saw_common_ancestor = true; 6588 saw_common_ancestor = true;
6577 if (allow_active_changes) 6589 if (!saw_common_ancestor || element == hover_element_)
6578 element->SetActive(true);
6579 if (allow_hover_changes &&
6580 (!saw_common_ancestor || element == hover_element_))
6581 element->SetHovered(true); 6590 element->SetHovered(true);
6582 } 6591 }
6583 } 6592 }
6584 6593
6585 bool Document::HaveScriptBlockingStylesheetsLoaded() const { 6594 bool Document::HaveScriptBlockingStylesheetsLoaded() const {
6586 return style_engine_->HaveScriptBlockingStylesheetsLoaded(); 6595 return style_engine_->HaveScriptBlockingStylesheetsLoaded();
6587 } 6596 }
6588 6597
6589 bool Document::HaveRenderBlockingStylesheetsLoaded() const { 6598 bool Document::HaveRenderBlockingStylesheetsLoaded() const {
6590 if (RuntimeEnabledFeatures::CSSInBodyDoesNotBlockPaintEnabled()) 6599 if (RuntimeEnabledFeatures::CSSInBodyDoesNotBlockPaintEnabled())
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after
6832 } 6841 }
6833 6842
6834 DEFINE_TRACE(Document) { 6843 DEFINE_TRACE(Document) {
6835 visitor->Trace(imports_controller_); 6844 visitor->Trace(imports_controller_);
6836 visitor->Trace(doc_type_); 6845 visitor->Trace(doc_type_);
6837 visitor->Trace(implementation_); 6846 visitor->Trace(implementation_);
6838 visitor->Trace(autofocus_element_); 6847 visitor->Trace(autofocus_element_);
6839 visitor->Trace(focused_element_); 6848 visitor->Trace(focused_element_);
6840 visitor->Trace(sequential_focus_navigation_starting_point_); 6849 visitor->Trace(sequential_focus_navigation_starting_point_);
6841 visitor->Trace(hover_element_); 6850 visitor->Trace(hover_element_);
6842 visitor->Trace(active_hover_element_); 6851 visitor->Trace(active_element_);
6843 visitor->Trace(document_element_); 6852 visitor->Trace(document_element_);
6844 visitor->Trace(root_scroller_controller_); 6853 visitor->Trace(root_scroller_controller_);
6845 visitor->Trace(title_element_); 6854 visitor->Trace(title_element_);
6846 visitor->Trace(ax_object_cache_); 6855 visitor->Trace(ax_object_cache_);
6847 visitor->Trace(markers_); 6856 visitor->Trace(markers_);
6848 visitor->Trace(css_target_); 6857 visitor->Trace(css_target_);
6849 visitor->Trace(current_script_stack_); 6858 visitor->Trace(current_script_stack_);
6850 visitor->Trace(script_runner_); 6859 visitor->Trace(script_runner_);
6851 visitor->Trace(lists_invalidated_at_document_); 6860 visitor->Trace(lists_invalidated_at_document_);
6852 for (int i = 0; i < kNumNodeListInvalidationTypes; ++i) 6861 for (int i = 0; i < kNumNodeListInvalidationTypes; ++i)
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
6939 } 6948 }
6940 6949
6941 void showLiveDocumentInstances() { 6950 void showLiveDocumentInstances() {
6942 WeakDocumentSet& set = liveDocumentSet(); 6951 WeakDocumentSet& set = liveDocumentSet();
6943 fprintf(stderr, "There are %u documents currently alive:\n", set.size()); 6952 fprintf(stderr, "There are %u documents currently alive:\n", set.size());
6944 for (blink::Document* document : set) 6953 for (blink::Document* document : set)
6945 fprintf(stderr, "- Document %p URL: %s\n", document, 6954 fprintf(stderr, "- Document %p URL: %s\n", document,
6946 document->Url().GetString().Utf8().data()); 6955 document->Url().GetString().Utf8().data());
6947 } 6956 }
6948 #endif 6957 #endif
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/dom/Document.h ('k') | third_party/WebKit/Source/core/input/GestureManager.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698