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

Unified Diff: third_party/WebKit/Source/core/page/FocusController.cpp

Issue 1707443003: Consider slots as a focus scope (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Adding initializations of member variables Created 4 years, 9 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/WebKit/Source/core/dom/shadow/SlotScopedTraversal.cpp ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/WebKit/Source/core/page/FocusController.cpp
diff --git a/third_party/WebKit/Source/core/page/FocusController.cpp b/third_party/WebKit/Source/core/page/FocusController.cpp
index bfc62ce382a91ed1872ca6d0d38ba2e2481aa9ff..279dc5146873c26d7c2ae56db09355da53d92c0e 100644
--- a/third_party/WebKit/Source/core/page/FocusController.cpp
+++ b/third_party/WebKit/Source/core/page/FocusController.cpp
@@ -28,13 +28,14 @@
#include "core/HTMLNames.h"
#include "core/dom/AXObjectCache.h"
+#include "core/dom/ContainerNode.h"
#include "core/dom/Document.h"
#include "core/dom/Element.h"
#include "core/dom/ElementTraversal.h"
-#include "core/dom/NodeTraversal.h"
#include "core/dom/Range.h"
#include "core/dom/shadow/ElementShadow.h"
#include "core/dom/shadow/ShadowRoot.h"
+#include "core/dom/shadow/SlotScopedTraversal.h"
#include "core/editing/EditingUtilities.h" // For firstPositionInOrBeforeNode
#include "core/editing/Editor.h"
#include "core/editing/FrameSelection.h"
@@ -49,6 +50,7 @@
#include "core/html/HTMLImageElement.h"
#include "core/html/HTMLPlugInElement.h"
#include "core/html/HTMLShadowElement.h"
+#include "core/html/HTMLSlotElement.h"
#include "core/html/HTMLTextFormControlElement.h"
#include "core/input/EventHandler.h"
#include "core/page/ChromeClient.h"
@@ -69,89 +71,181 @@ inline bool isShadowInsertionPointFocusScopeOwner(Element& element)
return isActiveShadowInsertionPoint(element) && toHTMLShadowElement(element).olderShadowRoot();
}
-class FocusNavigationScope {
+class ScopedFocusNavigation {
STACK_ALLOCATED();
public:
- Element* firstElement() const;
- Element* lastElement() const;
+ Element* currentElement() const;
+ void setCurrentElement(Element*);
+ void moveToNext();
+ void moveToPrevious();
+ void moveToFirst();
+ void moveToLast();
Element* owner() const;
- static FocusNavigationScope focusNavigationScopeOf(const Element&);
- static FocusNavigationScope ownedByNonFocusableFocusScopeOwner(Element&);
- static FocusNavigationScope ownedByShadowHost(const Element&);
- static FocusNavigationScope ownedByShadowInsertionPoint(HTMLShadowElement&);
- static FocusNavigationScope ownedByIFrame(const HTMLFrameOwnerElement&);
+ static ScopedFocusNavigation createScopedFocusNavigation(const Element& root, const Element* current);
+ static ScopedFocusNavigation ownedByNonFocusableFocusScopeOwner(Element&);
+ static ScopedFocusNavigation ownedByShadowHost(const Element&);
+ static ScopedFocusNavigation ownedByShadowInsertionPoint(HTMLShadowElement&);
+ static ScopedFocusNavigation ownedByHTMLSlotElement(const HTMLSlotElement&);
+ static ScopedFocusNavigation ownedByIFrame(const HTMLFrameOwnerElement&);
private:
- explicit FocusNavigationScope(TreeScope*);
- ContainerNode& rootNode() const;
- RawPtrWillBeMember<TreeScope> m_rootTreeScope;
+ ScopedFocusNavigation(TreeScope&, const Element*);
+ ScopedFocusNavigation(HTMLSlotElement&, const Element*);
+ RawPtrWillBeMember<ContainerNode> m_rootNode;
+ RawPtrWillBeMember<HTMLSlotElement> m_rootSlot;
+ RawPtrWillBeMember<Element> m_current;
};
-FocusNavigationScope::FocusNavigationScope(TreeScope* treeScope)
- : m_rootTreeScope(treeScope)
+ScopedFocusNavigation::ScopedFocusNavigation(TreeScope& treeScope, const Element* current)
+ : m_rootNode(treeScope.rootNode())
+ , m_rootSlot(nullptr)
+ , m_current(const_cast<Element*>(current))
{
- ASSERT(treeScope);
}
-ContainerNode& FocusNavigationScope::rootNode() const
+ScopedFocusNavigation::ScopedFocusNavigation(HTMLSlotElement& slot, const Element* current)
+ : m_rootNode(nullptr)
+ , m_rootSlot(&slot)
+ , m_current(const_cast<Element*>(current))
{
- return m_rootTreeScope->rootNode();
}
-Element* FocusNavigationScope::firstElement() const
+Element* ScopedFocusNavigation::currentElement() const
{
- ContainerNode& root = rootNode();
- return root.isElementNode() ? &toElement(root) : ElementTraversal::next(root);
+ return m_current;
}
-Element* FocusNavigationScope::lastElement() const
+void ScopedFocusNavigation::setCurrentElement(Element* element)
{
- return ElementTraversal::lastWithin(rootNode());
+ m_current = element;
}
-Element* FocusNavigationScope::owner() const
+void ScopedFocusNavigation::moveToNext()
{
- ContainerNode& root = rootNode();
- if (root.isShadowRoot()) {
- ShadowRoot& shadowRoot = toShadowRoot(root);
+ ASSERT(m_current);
+ if (m_rootSlot) {
+ m_current = SlotScopedTraversal::next(*m_current);
+ } else {
+ m_current = ElementTraversal::next(*m_current);
+ while (m_current && SlotScopedTraversal::isSlotScoped(*m_current))
+ m_current = ElementTraversal::next(*m_current);
+ }
+}
+
+void ScopedFocusNavigation::moveToPrevious()
+{
+ ASSERT(m_current);
+ if (m_rootSlot) {
+ m_current = SlotScopedTraversal::previous(*m_current);
+ } else {
+ m_current = ElementTraversal::previous(*m_current);
+ while (m_current && SlotScopedTraversal::isSlotScoped(*m_current))
+ m_current = ElementTraversal::previous(*m_current);
+ }
+}
+
+void ScopedFocusNavigation::moveToFirst()
+{
+ if (m_rootSlot) {
+ if (!m_rootSlot->getAssignedNodes().isEmpty()) {
+ WillBeHeapVector<RefPtrWillBeMember<Node>> assignedNodes = m_rootSlot->getAssignedNodes();
+ for (auto assignedNode : assignedNodes) {
+ if (assignedNode->isElementNode()) {
+ m_current = toElement(assignedNode);
+ break;
+ }
+ }
+ } else {
+ m_current = nullptr;
+ }
+ } else {
+ Element* first = m_rootNode->isElementNode() ? &toElement(*m_rootNode) : ElementTraversal::next(*m_rootNode);
+ while (first && SlotScopedTraversal::isSlotScoped(*first))
+ first = ElementTraversal::next(*first, m_rootNode);
+ m_current = first;
+ }
+}
+
+void ScopedFocusNavigation::moveToLast()
+{
+ if (m_rootSlot) {
+ if (!m_rootSlot->getAssignedNodes().isEmpty()) {
+ WillBeHeapVector<RefPtrWillBeMember<Node>> assignedNodes = m_rootSlot->getAssignedNodes();
+ for (auto assignedNode = assignedNodes.rbegin(); assignedNode != assignedNodes.rend(); ++assignedNode) {
+ if ((*assignedNode)->isElementNode()) {
+ Element* lastWithin = ElementTraversal::lastWithin(*toElement(*assignedNode));
+ if (lastWithin)
+ m_current = lastWithin;
+ else
+ m_current = toElement(*assignedNode);
+ break;
+ }
+ }
+ } else {
+ m_current = nullptr;
+ }
+ } else {
+ Element* last = ElementTraversal::lastWithin(*m_rootNode);
+ while (last && SlotScopedTraversal::isSlotScoped(*last))
+ last = ElementTraversal::previous(*last, m_rootNode);
+ m_current = last;
+ }
+}
+
+Element* ScopedFocusNavigation::owner() const
+{
+ if (m_rootSlot)
+ return m_rootSlot;
+ if (m_rootNode->isShadowRoot()) {
+ ShadowRoot& shadowRoot = toShadowRoot(*m_rootNode);
return shadowRoot.isYoungest() ? shadowRoot.host() : shadowRoot.shadowInsertionPointOfYoungerShadowRoot();
}
// FIXME: Figure out the right thing for OOPI here.
- if (Frame* frame = root.document().frame())
+ if (Frame* frame = m_rootNode->document().frame())
return frame->deprecatedLocalOwner();
return nullptr;
}
-FocusNavigationScope FocusNavigationScope::focusNavigationScopeOf(const Element& element)
+ScopedFocusNavigation ScopedFocusNavigation::createScopedFocusNavigation(const Element& root, const Element* current)
{
- return FocusNavigationScope(&element.treeScope());
+ if (SlotScopedTraversal::isSlotScoped(root))
+ return ScopedFocusNavigation(*SlotScopedTraversal::findScopeOwnerSlot(root), current);
+ return ScopedFocusNavigation(*&root.treeScope(), current);
}
-FocusNavigationScope FocusNavigationScope::ownedByNonFocusableFocusScopeOwner(Element& element)
+ScopedFocusNavigation ScopedFocusNavigation::ownedByNonFocusableFocusScopeOwner(Element& element)
{
if (isShadowHost(element))
- return FocusNavigationScope::ownedByShadowHost(element);
- ASSERT(isShadowInsertionPointFocusScopeOwner(element));
- return FocusNavigationScope::ownedByShadowInsertionPoint(toHTMLShadowElement(element));
+ return ScopedFocusNavigation::ownedByShadowHost(element);
+ if (isShadowInsertionPointFocusScopeOwner(element))
+ return ScopedFocusNavigation::ownedByShadowInsertionPoint(toHTMLShadowElement(element));
+ ASSERT(isHTMLSlotElement(element));
+ return ScopedFocusNavigation::ownedByHTMLSlotElement(toHTMLSlotElement(element));
}
-FocusNavigationScope FocusNavigationScope::ownedByShadowHost(const Element& element)
+ScopedFocusNavigation ScopedFocusNavigation::ownedByShadowHost(const Element& element)
{
ASSERT(isShadowHost(element));
- return FocusNavigationScope(&element.shadow()->youngestShadowRoot());
+ return ScopedFocusNavigation(*&element.shadow()->youngestShadowRoot(), nullptr);
}
-FocusNavigationScope FocusNavigationScope::ownedByIFrame(const HTMLFrameOwnerElement& frame)
+ScopedFocusNavigation ScopedFocusNavigation::ownedByIFrame(const HTMLFrameOwnerElement& frame)
{
ASSERT(frame.contentFrame());
ASSERT(frame.contentFrame()->isLocalFrame());
- return FocusNavigationScope(toLocalFrame(frame.contentFrame())->document());
+ toLocalFrame(frame.contentFrame())->document()->updateDistribution();
+ return ScopedFocusNavigation(*toLocalFrame(frame.contentFrame())->document(), nullptr);
}
-FocusNavigationScope FocusNavigationScope::ownedByShadowInsertionPoint(HTMLShadowElement& shadowInsertionPoint)
+ScopedFocusNavigation ScopedFocusNavigation::ownedByShadowInsertionPoint(HTMLShadowElement& shadowInsertionPoint)
{
ASSERT(isShadowInsertionPointFocusScopeOwner(shadowInsertionPoint));
- return FocusNavigationScope(shadowInsertionPoint.olderShadowRoot());
+ return ScopedFocusNavigation(*shadowInsertionPoint.olderShadowRoot(), nullptr);
+}
+
+ScopedFocusNavigation ScopedFocusNavigation::ownedByHTMLSlotElement(const HTMLSlotElement& element)
+{
+ return ScopedFocusNavigation(const_cast<HTMLSlotElement&>(element), nullptr);
}
inline void dispatchBlurEvent(const Document& document, Element& focusedElement)
@@ -234,7 +328,7 @@ inline bool isKeyboardFocusableShadowHost(const Element& element)
inline bool isNonFocusableFocusScopeOwner(Element& element)
{
- return isNonKeyboardFocusableShadowHost(element) || isShadowInsertionPointFocusScopeOwner(element);
+ return isNonKeyboardFocusableShadowHost(element) || isShadowInsertionPointFocusScopeOwner(element) || isHTMLSlotElement(element);
}
inline bool isShadowHostDelegatesFocus(const Element& element)
@@ -252,59 +346,65 @@ inline bool shouldVisit(Element& element)
return element.isKeyboardFocusable() || isNonFocusableFocusScopeOwner(element);
}
-Element* findElementWithExactTabIndex(Element* start, int tabIndex, WebFocusType type)
+Element* findElementWithExactTabIndex(ScopedFocusNavigation& scope, int tabIndex, WebFocusType type)
{
// Search is inclusive of start
- for (Element* element = start; element; element = type == WebFocusTypeForward ? ElementTraversal::next(*element) : ElementTraversal::previous(*element)) {
- if (shouldVisit(*element) && adjustedTabIndex(*element) == tabIndex)
- return element;
+ for (; scope.currentElement(); type == WebFocusTypeForward ? scope.moveToNext() : scope.moveToPrevious()) {
+ Element* current = scope.currentElement();
+ if (shouldVisit(*current) && adjustedTabIndex(*current) == tabIndex)
+ return current;
}
return nullptr;
}
-Element* nextElementWithGreaterTabIndex(Element* start, int tabIndex)
+Element* nextElementWithGreaterTabIndex(ScopedFocusNavigation& scope, int tabIndex)
{
// Search is inclusive of start
int winningTabIndex = std::numeric_limits<short>::max() + 1;
Element* winner = nullptr;
- for (Element& element : ElementTraversal::startsAt(start)) {
- int currentTabIndex = adjustedTabIndex(element);
- if (shouldVisit(element) && currentTabIndex > tabIndex && currentTabIndex < winningTabIndex) {
- winner = &element;
+ for (; scope.currentElement(); scope.moveToNext()) {
+ Element* current = scope.currentElement();
+ int currentTabIndex = adjustedTabIndex(*current);
+ if (shouldVisit(*current) && currentTabIndex > tabIndex && currentTabIndex < winningTabIndex) {
+ winner = current;
winningTabIndex = currentTabIndex;
}
}
return winner;
}
-Element* previousElementWithLowerTabIndex(Element* start, int tabIndex)
+Element* previousElementWithLowerTabIndex(ScopedFocusNavigation& scope, int tabIndex)
{
// Search is inclusive of start
int winningTabIndex = 0;
Element* winner = nullptr;
- for (Element* element = start; element; element = ElementTraversal::previous(*element)) {
- int currentTabIndex = adjustedTabIndex(*element);
- if (shouldVisit(*element) && currentTabIndex < tabIndex && currentTabIndex > winningTabIndex) {
- winner = element;
+ for (; scope.currentElement(); scope.moveToPrevious()) {
+ Element* current = scope.currentElement();
+ int currentTabIndex = adjustedTabIndex(*current);
+ if (shouldVisit(*current) && currentTabIndex < tabIndex && currentTabIndex > winningTabIndex) {
+ winner = current;
winningTabIndex = currentTabIndex;
}
}
return winner;
}
-Element* nextFocusableElement(const FocusNavigationScope& scope, Element* start)
+Element* nextFocusableElement(ScopedFocusNavigation& scope)
{
- if (start) {
- int tabIndex = adjustedTabIndex(*start);
+ Element* current = scope.currentElement();
+ if (current) {
+ int tabIndex = adjustedTabIndex(*current);
// If an element is excluded from the normal tabbing cycle, the next focusable element is determined by tree order
if (tabIndex < 0) {
- for (Element& element : ElementTraversal::startsAfter(*start)) {
- if (shouldVisit(element) && adjustedTabIndex(element) >= 0)
- return &element;
+ for (scope.moveToNext(); scope.currentElement(); scope.moveToNext()) {
+ current = scope.currentElement();
+ if (shouldVisit(*current) && adjustedTabIndex(*current) >= 0)
+ return current;
}
} else {
// First try to find an element with the same tabindex as start that comes after start in the scope.
- if (Element* winner = findElementWithExactTabIndex(ElementTraversal::next(*start), tabIndex, WebFocusTypeForward))
+ scope.moveToNext();
+ if (Element* winner = findElementWithExactTabIndex(scope, tabIndex, WebFocusTypeForward))
return winner;
}
if (!tabIndex) {
@@ -316,46 +416,49 @@ Element* nextFocusableElement(const FocusNavigationScope& scope, Element* start)
// Look for the first element in the scope that:
// 1) has the lowest tabindex that is higher than start's tabindex (or 0, if start is null), and
// 2) comes first in the scope, if there's a tie.
- if (Element* winner = nextElementWithGreaterTabIndex(scope.firstElement(), start ? adjustedTabIndex(*start) : 0))
+ scope.moveToFirst();
+ if (Element* winner = nextElementWithGreaterTabIndex(scope, current ? adjustedTabIndex(*current) : 0)) {
return winner;
+ }
// There are no elements with a tabindex greater than start's tabindex,
// so find the first element with a tabindex of 0.
- return findElementWithExactTabIndex(scope.firstElement(), 0, WebFocusTypeForward);
+ scope.moveToFirst();
+ return findElementWithExactTabIndex(scope, 0, WebFocusTypeForward);
}
-Element* previousFocusableElement(const FocusNavigationScope& scope, Element* start)
+Element* previousFocusableElement(ScopedFocusNavigation& scope)
{
- Element* lastElement = scope.lastElement();
-
// First try to find the last element in the scope that comes before start and has the same tabindex as start.
// If start is null, find the last element in the scope with a tabindex of 0.
- Element* startElement;
- int startTabIndex;
- if (start) {
- startElement = ElementTraversal::previous(*start);
- startTabIndex = adjustedTabIndex(*start);
+ int tabIndex;
+ Element* current = scope.currentElement();
+ if (current) {
+ scope.moveToPrevious();
+ tabIndex = adjustedTabIndex(*current);
} else {
- startElement = lastElement;
- startTabIndex = 0;
+ scope.moveToLast();
+ tabIndex = 0;
}
// However, if an element is excluded from the normal tabbing cycle, the previous focusable element is determined by tree order
- if (startTabIndex < 0) {
- for (Element* element = startElement; element; element = ElementTraversal::previous(*element)) {
- if (shouldVisit(*element) && adjustedTabIndex(*element) >= 0)
- return element;
+ if (tabIndex < 0) {
+ for (; scope.currentElement(); scope.moveToPrevious()) {
+ current = scope.currentElement();
+ if (shouldVisit(*current) && adjustedTabIndex(*current) >= 0)
+ return current;
}
} else {
- if (Element* winner = findElementWithExactTabIndex(startElement, startTabIndex, WebFocusTypeBackward))
+ if (Element* winner = findElementWithExactTabIndex(scope, tabIndex, WebFocusTypeBackward))
return winner;
}
// There are no elements before start with the same tabindex as start, so look for an element that:
// 1) has the highest non-zero tabindex (that is less than start's tabindex), and
// 2) comes last in the scope, if there's a tie.
- startTabIndex = (start && startTabIndex) ? startTabIndex : std::numeric_limits<short>::max();
- return previousElementWithLowerTabIndex(lastElement, startTabIndex);
+ tabIndex = (current && tabIndex) ? tabIndex : std::numeric_limits<short>::max();
+ scope.moveToLast();
+ return previousElementWithLowerTabIndex(scope, tabIndex);
}
// Searches through the given tree scope, starting from start element, for the next/previous
@@ -371,58 +474,60 @@ Element* previousFocusableElement(const FocusNavigationScope& scope, Element* st
//
// [1] https://html.spec.whatwg.org/multipage/interaction.html#sequential-focus-navigation
// [2] https://w3c.github.io/webcomponents/spec/shadow/#focus-navigation
-inline Element* findFocusableElementInternal(WebFocusType type, const FocusNavigationScope& scope, Element* element)
+inline Element* findFocusableElementInternal(WebFocusType type, ScopedFocusNavigation& scope)
{
- Element* found = (type == WebFocusTypeForward) ? nextFocusableElement(scope, element) : previousFocusableElement(scope, element);
+ Element* found = (type == WebFocusTypeForward) ? nextFocusableElement(scope) : previousFocusableElement(scope);
return found;
}
-Element* findFocusableElementRecursivelyForward(const FocusNavigationScope& scope, Element* start)
+Element* findFocusableElementRecursivelyForward(ScopedFocusNavigation& scope)
{
// Starting element is exclusive.
- Element* found = findFocusableElementInternal(WebFocusTypeForward, scope, start);
+ Element* found = findFocusableElementInternal(WebFocusTypeForward, scope);
while (found) {
if (isShadowHostDelegatesFocus(*found)) {
// If tabindex is positive, find focusable element inside its shadow tree.
if (found->tabIndex() >= 0 && isShadowHostWithoutCustomFocusLogic(*found)) {
- FocusNavigationScope innerScope = FocusNavigationScope::ownedByShadowHost(*found);
- if (Element* foundInInnerFocusScope = findFocusableElementRecursivelyForward(innerScope, nullptr))
+ ScopedFocusNavigation innerScope = ScopedFocusNavigation::ownedByShadowHost(*found);
+ if (Element* foundInInnerFocusScope = findFocusableElementRecursivelyForward(innerScope))
return foundInInnerFocusScope;
}
// Skip to the next element in the same scope.
- found = findFocusableElementInternal(WebFocusTypeForward, scope, found);
+ found = findFocusableElementInternal(WebFocusTypeForward, scope);
continue;
}
if (!isNonFocusableFocusScopeOwner(*found))
return found;
- // Now |found| is on a non focusable scope owner (either shadow host or <shadow>)
+ // Now |found| is on a non focusable scope owner (either shadow host or <shadow> or slot)
// Find inside the inward scope and return it if found. Otherwise continue searching in the same
// scope.
- FocusNavigationScope innerScope = FocusNavigationScope::ownedByNonFocusableFocusScopeOwner(*found);
- if (Element* foundInInnerFocusScope = findFocusableElementRecursivelyForward(innerScope, nullptr))
+ ScopedFocusNavigation innerScope = ScopedFocusNavigation::ownedByNonFocusableFocusScopeOwner(*found);
+ if (Element* foundInInnerFocusScope = findFocusableElementRecursivelyForward(innerScope))
return foundInInnerFocusScope;
- found = findFocusableElementInternal(WebFocusTypeForward, scope, found);
+ scope.setCurrentElement(found);
+ found = findFocusableElementInternal(WebFocusTypeForward, scope);
}
return nullptr;
}
-Element* findFocusableElementRecursivelyBackward(const FocusNavigationScope& scope, Element* start)
+Element* findFocusableElementRecursivelyBackward(ScopedFocusNavigation& scope)
{
// Starting element is exclusive.
- Element* found = findFocusableElementInternal(WebFocusTypeBackward, scope, start);
+ Element* found = findFocusableElementInternal(WebFocusTypeBackward, scope);
+
while (found) {
// Now |found| is on a focusable shadow host.
// Find inside shadow backwards. If any focusable element is found, return it, otherwise return
// the host itself.
if (isKeyboardFocusableShadowHost(*found)) {
- FocusNavigationScope innerScope = FocusNavigationScope::ownedByShadowHost(*found);
- Element* foundInInnerFocusScope = findFocusableElementRecursivelyBackward(innerScope, nullptr);
+ ScopedFocusNavigation innerScope = ScopedFocusNavigation::ownedByShadowHost(*found);
+ Element* foundInInnerFocusScope = findFocusableElementRecursivelyBackward(innerScope);
if (foundInInnerFocusScope)
return foundInInnerFocusScope;
if (isShadowHostDelegatesFocus(*found)) {
- found = findFocusableElementInternal(WebFocusTypeBackward, scope, found);
+ found = findFocusableElementInternal(WebFocusTypeBackward, scope);
continue;
}
return found;
@@ -431,33 +536,36 @@ Element* findFocusableElementRecursivelyBackward(const FocusNavigationScope& sco
// If delegatesFocus is true and tabindex is negative, skip the whole shadow tree under the
// shadow host.
if (isShadowHostDelegatesFocus(*found) && found->tabIndex() < 0) {
- found = findFocusableElementInternal(WebFocusTypeBackward, scope, found);
+ found = findFocusableElementInternal(WebFocusTypeBackward, scope);
continue;
}
- // Now |found| is on a non focusable scope owner (either shadow host or <shadow>).
+ // Now |found| is on a non focusable scope owner (either shadow host or <shadow> or slot).
// Find focusable element in descendant scope. If not found, find next focusable element within the
// current scope.
if (isNonFocusableFocusScopeOwner(*found)) {
- FocusNavigationScope innerScope = FocusNavigationScope::ownedByNonFocusableFocusScopeOwner(*found);
- Element* foundInInnerFocusScope = findFocusableElementRecursivelyBackward(innerScope, nullptr);
+ ScopedFocusNavigation innerScope = ScopedFocusNavigation::ownedByNonFocusableFocusScopeOwner(*found);
+ Element* foundInInnerFocusScope = findFocusableElementRecursivelyBackward(innerScope);
+
if (foundInInnerFocusScope)
return foundInInnerFocusScope;
- found = findFocusableElementInternal(WebFocusTypeBackward, scope, found);
+ found = findFocusableElementInternal(WebFocusTypeBackward, scope);
continue;
}
if (!isShadowHostDelegatesFocus(*found))
return found;
- found = findFocusableElementInternal(WebFocusTypeBackward, scope, found);
+
+ scope.setCurrentElement(found);
+ found = findFocusableElementInternal(WebFocusTypeBackward, scope);
}
return nullptr;
}
-Element* findFocusableElementRecursively(WebFocusType type, const FocusNavigationScope& scope, Element* start)
+Element* findFocusableElementRecursively(WebFocusType type, ScopedFocusNavigation& scope)
{
return (type == WebFocusTypeForward) ?
- findFocusableElementRecursivelyForward(scope, start) :
- findFocusableElementRecursivelyBackward(scope, start);
+ findFocusableElementRecursivelyForward(scope) :
+ findFocusableElementRecursivelyBackward(scope);
}
Element* findFocusableElementDescendingDownIntoFrameDocument(WebFocusType type, Element* element)
@@ -470,7 +578,8 @@ Element* findFocusableElementDescendingDownIntoFrameDocument(WebFocusType type,
if (!owner.contentFrame() || !owner.contentFrame()->isLocalFrame())
break;
toLocalFrame(owner.contentFrame())->document()->updateLayoutIgnorePendingStylesheets();
- Element* foundElement = findFocusableElementRecursively(type, FocusNavigationScope::ownedByIFrame(owner), nullptr);
+ ScopedFocusNavigation scope = ScopedFocusNavigation::ownedByIFrame(owner);
+ Element* foundElement = findFocusableElementRecursively(type, scope);
if (!foundElement)
break;
ASSERT(element != foundElement);
@@ -479,56 +588,57 @@ Element* findFocusableElementDescendingDownIntoFrameDocument(WebFocusType type,
return element;
}
-Element* findFocusableElementAcrossFocusScopesForward(const FocusNavigationScope& scope, Element* current)
+Element* findFocusableElementAcrossFocusScopesForward(ScopedFocusNavigation& scope)
{
+ Element* current = scope.currentElement();
ASSERT(!current || !isNonFocusableShadowHost(*current));
Element* found;
if (current && isShadowHostWithoutCustomFocusLogic(*current)) {
- FocusNavigationScope innerScope = FocusNavigationScope::ownedByShadowHost(*current);
- Element* foundInInnerFocusScope = findFocusableElementRecursivelyForward(innerScope, nullptr);
- found = foundInInnerFocusScope ? foundInInnerFocusScope : findFocusableElementRecursivelyForward(scope, current);
+ ScopedFocusNavigation innerScope = ScopedFocusNavigation::ownedByShadowHost(*current);
+ Element* foundInInnerFocusScope = findFocusableElementRecursivelyForward(innerScope);
+ found = foundInInnerFocusScope ? foundInInnerFocusScope : findFocusableElementRecursivelyForward(scope);
} else {
- found = findFocusableElementRecursivelyForward(scope, current);
+ found = findFocusableElementRecursivelyForward(scope);
}
// If there's no focusable element to advance to, move up the focus scopes until we find one.
- FocusNavigationScope currentScope = scope;
+ ScopedFocusNavigation currentScope = scope;
while (!found) {
Element* owner = currentScope.owner();
if (!owner)
break;
- currentScope = FocusNavigationScope::focusNavigationScopeOf(*owner);
- found = findFocusableElementRecursivelyForward(currentScope, owner);
+ currentScope = ScopedFocusNavigation::createScopedFocusNavigation(*owner, owner);
+ found = findFocusableElementRecursivelyForward(currentScope);
}
return findFocusableElementDescendingDownIntoFrameDocument(WebFocusTypeForward, found);
}
-Element* findFocusableElementAcrossFocusScopesBackward(const FocusNavigationScope& scope, Element* current)
+Element* findFocusableElementAcrossFocusScopesBackward(ScopedFocusNavigation& scope)
{
- ASSERT(!current || !isNonFocusableShadowHost(*current));
- Element* found = findFocusableElementRecursivelyBackward(scope, current);
+ ASSERT(!scope.currentElement() || !isNonFocusableShadowHost(*scope.currentElement()));
+ Element* found = findFocusableElementRecursivelyBackward(scope);
// If there's no focusable element to advance to, move up the focus scopes until we find one.
- FocusNavigationScope currentScope = scope;
+ ScopedFocusNavigation currentScope = scope;
while (!found) {
Element* owner = currentScope.owner();
if (!owner)
break;
- currentScope = FocusNavigationScope::focusNavigationScopeOf(*owner);
+ currentScope = ScopedFocusNavigation::createScopedFocusNavigation(*owner, owner);
if (isKeyboardFocusableShadowHost(*owner) && !isShadowHostDelegatesFocus(*owner)) {
found = owner;
break;
}
- found = findFocusableElementRecursivelyBackward(currentScope, owner);
+ found = findFocusableElementRecursivelyBackward(currentScope);
}
return findFocusableElementDescendingDownIntoFrameDocument(WebFocusTypeBackward, found);
}
-Element* findFocusableElementAcrossFocusScopes(WebFocusType type, const FocusNavigationScope& scope, Element* current)
+Element* findFocusableElementAcrossFocusScopes(WebFocusType type, ScopedFocusNavigation& scope)
{
return (type == WebFocusTypeForward) ?
- findFocusableElementAcrossFocusScopesForward(scope, current) :
- findFocusableElementAcrossFocusScopesBackward(scope, current);
+ findFocusableElementAcrossFocusScopesForward(scope) :
+ findFocusableElementAcrossFocusScopesBackward(scope);
}
inline Element* adjustToElement(Node* node, WebFocusType type)
@@ -541,6 +651,8 @@ inline Element* adjustToElement(Node* node, WebFocusType type)
// The returned element is used as an *exclusive* start element. Thus, we should return the result of ElementTraversal::previous(*node),
// instead of ElementTraversal::next(*node), if type == WebFocusTypeForward, and vice-versa.
// The caller will call ElementTraversal::{next/previous} for the returned value and get the {next|previous} element of the |node|.
+
+ // TODO(yuzus) Use ScopedFocusNavigation traversal here.
return (type == WebFocusTypeForward) ? ElementTraversal::previous(*node) : ElementTraversal::next(*node);
}
@@ -743,6 +855,7 @@ bool FocusController::advanceFocusInDocumentOrder(LocalFrame* frame, Element* st
ASSERT(frame);
Document* document = frame->document();
ASSERT(document->documentElement());
+ document->updateDistribution();
Element* current = start;
if (!current && !initialFocus)
@@ -755,8 +868,8 @@ bool FocusController::advanceFocusInDocumentOrder(LocalFrame* frame, Element* st
current = adjustToElement(frame->selection().start().anchorNode(), type);
document->updateLayoutIgnorePendingStylesheets();
-
- RefPtrWillBeRawPtr<Element> element = findFocusableElementAcrossFocusScopes(type, FocusNavigationScope::focusNavigationScopeOf(current ? *current : *document->documentElement()), current);
+ ScopedFocusNavigation scope = ScopedFocusNavigation::createScopedFocusNavigation(current ? *current : *document->documentElement(), current);
+ RefPtrWillBeRawPtr<Element> element = findFocusableElementAcrossFocusScopes(type, scope);
if (!element) {
// If there's a RemoteFrame on the ancestor chain, we need to continue
@@ -778,7 +891,8 @@ bool FocusController::advanceFocusInDocumentOrder(LocalFrame* frame, Element* st
}
// Chrome doesn't want focus, so we should wrap focus.
- element = findFocusableElementRecursively(type, FocusNavigationScope::focusNavigationScopeOf(*toLocalFrame(m_page->mainFrame())->document()->documentElement()), nullptr);
+ ScopedFocusNavigation scope = ScopedFocusNavigation::createScopedFocusNavigation(*toLocalFrame(m_page->mainFrame())->document()->documentElement(), nullptr);
+ element = findFocusableElementRecursively(type, scope);
element = findFocusableElementDescendingDownIntoFrameDocument(type, element.get());
if (!element)
@@ -838,13 +952,15 @@ Element* FocusController::findFocusableElement(WebFocusType type, Element& eleme
{
// FIXME: No spacial navigation code yet.
ASSERT(type == WebFocusTypeForward || type == WebFocusTypeBackward);
- return findFocusableElementAcrossFocusScopes(type, FocusNavigationScope::focusNavigationScopeOf(element), &element);
+ ScopedFocusNavigation scope = ScopedFocusNavigation::createScopedFocusNavigation(element, &element);
+ return findFocusableElementAcrossFocusScopes(type, scope);
}
Element* FocusController::findFocusableElementInShadowHost(const Element& shadowHost)
{
ASSERT(shadowHost.authorShadowRoot());
- return findFocusableElementAcrossFocusScopes(WebFocusTypeForward, FocusNavigationScope::ownedByShadowHost(shadowHost), nullptr);
+ ScopedFocusNavigation scope = ScopedFocusNavigation::ownedByShadowHost(shadowHost);
+ return findFocusableElementAcrossFocusScopes(WebFocusTypeForward, scope);
}
static bool relinquishesEditingFocus(const Element& element)
« no previous file with comments | « third_party/WebKit/Source/core/dom/shadow/SlotScopedTraversal.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698