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 fa4278952a6736afb10589c37e53c10c84e43678..534e58bf0cadefa62be63e1671807b2978ec35ed 100644 |
--- a/third_party/WebKit/Source/core/dom/Document.cpp |
+++ b/third_party/WebKit/Source/core/dom/Document.cpp |
@@ -577,6 +577,7 @@ void Document::dispose() |
// these extra pointers or we will create a reference cycle. |
m_docType = nullptr; |
m_focusedElement = nullptr; |
+ m_sequentialFocusNavigationStartingPoint = nullptr; |
m_hoverNode = nullptr; |
m_activeHoverElement = nullptr; |
m_titleElement = nullptr; |
@@ -2244,6 +2245,7 @@ void Document::detach(const AttachContext& context) |
if (frameHost()) |
frameHost()->chromeClient().focusedNodeChanged(oldFocusedElement.get(), nullptr); |
} |
+ m_sequentialFocusNavigationStartingPoint = nullptr; |
if (this == &axObjectCacheOwner()) |
clearAXObjectCache(); |
@@ -3632,6 +3634,7 @@ bool Document::setFocusedElement(PassRefPtrWillBeRawPtr<Element> prpNewFocusedEl |
} |
// Set focus on the new node |
m_focusedElement = newFocusedElement; |
+ setSequentialFocusNavigationStartingPoint(m_focusedElement.get()); |
m_focusedElement->setFocus(true); |
// Element::setFocus for frames can dispatch events. |
@@ -3715,6 +3718,49 @@ void Document::clearFocusedElement() |
setFocusedElement(nullptr, FocusParams(SelectionBehaviorOnFocus::None, WebFocusTypeNone, nullptr)); |
} |
+void Document::setSequentialFocusNavigationStartingPoint(Node* node) |
+{ |
+ if (!node) { |
+ m_sequentialFocusNavigationStartingPoint = nullptr; |
+ return; |
+ } |
+ ASSERT(node->document() == this); |
+ if (!m_sequentialFocusNavigationStartingPoint) |
+ m_sequentialFocusNavigationStartingPoint = Range::create(*this); |
+ m_sequentialFocusNavigationStartingPoint->selectNodeContents(node->isElementNode() ? node : node->parentOrShadowHostElement(), ASSERT_NO_EXCEPTION); |
+} |
+ |
+Element* Document::sequentialFocusNavigationStartingPoint(WebFocusType type) const |
+{ |
+ if (m_focusedElement) |
+ return m_focusedElement.get(); |
+ if (!m_sequentialFocusNavigationStartingPoint) |
+ return nullptr; |
+ if (!m_sequentialFocusNavigationStartingPoint->collapsed()) { |
+ Node* node = m_sequentialFocusNavigationStartingPoint->startContainer(); |
+ ASSERT(node == m_sequentialFocusNavigationStartingPoint->endContainer()); |
+ return node->isElementNode() ? toElement(node) : node->parentOrShadowHostElement(); |
+ } |
+ |
+ // Range::selectNodeContents didn't select contents because the element had |
+ // no children. |
+ if (m_sequentialFocusNavigationStartingPoint->startContainer()->isElementNode() |
+ && !m_sequentialFocusNavigationStartingPoint->startContainer()->hasChildren() |
+ && m_sequentialFocusNavigationStartingPoint->startOffset() == 0) |
+ return toElement(m_sequentialFocusNavigationStartingPoint->startContainer()); |
+ |
+ // A node selected by Range::selectNodeContents was removed from the |
+ // document tree. |
+ if (Node* nextNode = m_sequentialFocusNavigationStartingPoint->firstNode()) { |
+ if (type == WebFocusTypeForward) |
+ return ElementTraversal::previous(*nextNode); |
+ if (nextNode->isElementNode()) |
+ return toElement(nextNode); |
+ return ElementTraversal::next(*nextNode); |
+ } |
+ return nullptr; |
+} |
+ |
void Document::setCSSTarget(Element* newTarget) |
{ |
if (m_cssTarget) |
@@ -5880,6 +5926,7 @@ DEFINE_TRACE(Document) |
visitor->trace(m_implementation); |
visitor->trace(m_autofocusElement); |
visitor->trace(m_focusedElement); |
+ visitor->trace(m_sequentialFocusNavigationStartingPoint); |
visitor->trace(m_hoverNode); |
visitor->trace(m_activeHoverElement); |
visitor->trace(m_documentElement); |