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

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

Issue 1707373002: Do not use Node in FocusController, 3rd (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@focus-navigation-advance-document
Patch Set: update Created 4 years, 10 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 | « no previous file | 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 00331f92853074ae97f543955673ddafec30f748..4617e58fbc64fcb03ecdc1167f5bc3041d6d51b2 100644
--- a/third_party/WebKit/Source/core/page/FocusController.cpp
+++ b/third_party/WebKit/Source/core/page/FocusController.cpp
@@ -72,7 +72,8 @@ inline bool isShadowInsertionPointFocusScopeOwner(Element& element)
class FocusNavigationScope {
STACK_ALLOCATED();
public:
- Node* rootNode() const;
+ Element* firstElement() const;
+ Element* lastElement() const;
Element* owner() const;
static FocusNavigationScope focusNavigationScopeOf(const Element&);
static FocusNavigationScope ownedByNonFocusableFocusScopeOwner(Element&);
@@ -82,6 +83,7 @@ public:
private:
explicit FocusNavigationScope(TreeScope*);
+ ContainerNode& rootNode() const;
RawPtrWillBeMember<TreeScope> m_rootTreeScope;
};
@@ -91,20 +93,31 @@ FocusNavigationScope::FocusNavigationScope(TreeScope* treeScope)
ASSERT(treeScope);
}
-Node* FocusNavigationScope::rootNode() const
+ContainerNode& FocusNavigationScope::rootNode() const
{
- return &m_rootTreeScope->rootNode();
+ return m_rootTreeScope->rootNode();
+}
+
+Element* FocusNavigationScope::firstElement() const
+{
+ ContainerNode& root = rootNode();
+ return root.isElementNode() ? &toElement(root) : ElementTraversal::next(root);
+}
+
+Element* FocusNavigationScope::lastElement() const
+{
+ return ElementTraversal::lastWithin(rootNode());
}
Element* FocusNavigationScope::owner() const
{
- Node* root = rootNode();
- if (root->isShadowRoot()) {
- ShadowRoot* shadowRoot = toShadowRoot(root);
- return shadowRoot->isYoungest() ? shadowRoot->host() : shadowRoot->shadowInsertionPointOfYoungerShadowRoot();
+ ContainerNode& root = rootNode();
+ if (root.isShadowRoot()) {
+ ShadowRoot& shadowRoot = toShadowRoot(root);
+ 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 = root.document().frame())
return frame->deprecatedLocalOwner();
return nullptr;
}
@@ -203,11 +216,8 @@ inline bool isShadowHostWithoutCustomFocusLogic(const Element& element)
}
#if ENABLE(ASSERT)
-inline bool isNonFocusableShadowHost(const Node& node)
+inline bool isNonFocusableShadowHost(const Element& element)
{
- if (!node.isElementNode())
- return false;
- const Element& element = toElement(node);
return isShadowHostWithoutCustomFocusLogic(element) && !element.isFocusable();
}
#endif
@@ -232,162 +242,154 @@ inline bool isShadowHostDelegatesFocus(const Element& element)
return element.authorShadowRoot() && element.authorShadowRoot()->delegatesFocus();
}
-inline int adjustedTabIndex(Node& node)
+inline int adjustedTabIndex(Element& element)
{
- return node.isElementNode() && isNonFocusableFocusScopeOwner(toElement(node)) ? 0 : node.tabIndex();
+ return isNonFocusableFocusScopeOwner(element) ? 0 : element.tabIndex();
}
-inline bool shouldVisit(Node& node)
+inline bool shouldVisit(Element& element)
{
- if (!node.isElementNode())
- return false;
- Element& element = toElement(node);
return element.isKeyboardFocusable() || isNonFocusableFocusScopeOwner(element);
}
-Element* findElementWithExactTabIndex(Node* start, int tabIndex, WebFocusType type)
+Element* findElementWithExactTabIndex(Element* start, int tabIndex, WebFocusType type)
{
// Search is inclusive of start
- for (Node* node = start; node; node = type == WebFocusTypeForward ? ElementTraversal::next(*node) : ElementTraversal::previous(*node)) {
- if (shouldVisit(*node) && adjustedTabIndex(*node) == tabIndex)
- return toElement(node);
+ for (Element* element = start; element; element = type == WebFocusTypeForward ? ElementTraversal::next(*element) : ElementTraversal::previous(*element)) {
+ if (shouldVisit(*element) && adjustedTabIndex(*element) == tabIndex)
+ return element;
}
return nullptr;
}
-Element* nextElementWithGreaterTabIndex(Node* start, int tabIndex)
+Element* nextElementWithGreaterTabIndex(Element* start, int tabIndex)
{
// Search is inclusive of start
int winningTabIndex = std::numeric_limits<short>::max() + 1;
- Node* winner = nullptr;
- for (Node& node : NodeTraversal::startsAt(start)) {
- int currentTabIndex = adjustedTabIndex(node);
- if (shouldVisit(node) && currentTabIndex > tabIndex && currentTabIndex < winningTabIndex) {
- winner = &node;
+ Element* winner = nullptr;
+ for (Element& element : ElementTraversal::startsAt(start)) {
+ int currentTabIndex = adjustedTabIndex(element);
+ if (shouldVisit(element) && currentTabIndex > tabIndex && currentTabIndex < winningTabIndex) {
+ winner = &element;
winningTabIndex = currentTabIndex;
}
}
- ASSERT(!winner || winner->isElementNode());
- return toElement(winner);
+ return winner;
}
-Element* previousElementWithLowerTabIndex(Node* start, int tabIndex)
+Element* previousElementWithLowerTabIndex(Element* start, int tabIndex)
{
// Search is inclusive of start
int winningTabIndex = 0;
- Node* winner = nullptr;
- for (Node* node = start; node; node = ElementTraversal::previous(*node)) {
- int currentTabIndex = adjustedTabIndex(*node);
- if (shouldVisit(*node) && currentTabIndex < tabIndex && currentTabIndex > winningTabIndex) {
- winner = node;
+ 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;
winningTabIndex = currentTabIndex;
}
}
- ASSERT(!winner || winner->isElementNode());
- return toElement(winner);
+ return winner;
}
-Element* nextFocusableElement(const FocusNavigationScope& scope, Node* start)
+Element* nextFocusableElement(const FocusNavigationScope& scope, Element* start)
{
if (start) {
int tabIndex = adjustedTabIndex(*start);
- // If a node is excluded from the normal tabbing cycle, the next focusable node is determined by tree order
+ // If an element is excluded from the normal tabbing cycle, the next focusable element is determined by tree order
if (tabIndex < 0) {
- for (Node& node : NodeTraversal::startsAfter(*start)) {
- if (shouldVisit(node) && adjustedTabIndex(node) >= 0)
- return &toElement(node);
+ for (Element& element : ElementTraversal::startsAfter(*start)) {
+ if (shouldVisit(element) && adjustedTabIndex(element) >= 0)
+ return &element;
}
} else {
- // First try to find a node with the same tabindex as start that comes after start in the scope.
+ // 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))
return winner;
}
if (!tabIndex) {
- // We've reached the last node in the document with a tabindex of 0. This is the end of the tabbing order.
+ // We've reached the last element in the document with a tabindex of 0. This is the end of the tabbing order.
return nullptr;
}
}
- // Look for the first node in the scope that:
+ // 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.rootNode(), start ? adjustedTabIndex(*start) : 0))
+ if (Element* winner = nextElementWithGreaterTabIndex(scope.firstElement(), start ? adjustedTabIndex(*start) : 0))
return winner;
- // There are no nodes with a tabindex greater than start's tabindex,
- // so find the first node with a tabindex of 0.
- return findElementWithExactTabIndex(scope.rootNode(), 0, WebFocusTypeForward);
+ // 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);
}
-Element* previousFocusableElement(const FocusNavigationScope& scope, Node* start)
+Element* previousFocusableElement(const FocusNavigationScope& scope, Element* start)
{
- Node* last = nullptr;
- for (Node* node = scope.rootNode(); node; node = node->lastChild())
- last = node;
- ASSERT(last);
-
- // First try to find the last node in the scope that comes before start and has the same tabindex as start.
- // If start is null, find the last node in the scope with a tabindex of 0.
- Node* startingNode;
- int startingTabIndex;
+ 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) {
- startingNode = ElementTraversal::previous(*start);
- startingTabIndex = adjustedTabIndex(*start);
+ startElement = ElementTraversal::previous(*start);
+ startTabIndex = adjustedTabIndex(*start);
} else {
- startingNode = last;
- startingTabIndex = 0;
+ startElement = lastElement;
+ startTabIndex = 0;
}
- // However, if a node is excluded from the normal tabbing cycle, the previous focusable node is determined by tree order
- if (startingTabIndex < 0) {
- for (Node* node = startingNode; node; node = ElementTraversal::previous(*node)) {
- if (shouldVisit(*node) && adjustedTabIndex(*node) >= 0)
- return toElement(node);
+ // 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;
}
} else {
- if (Element* winner = findElementWithExactTabIndex(startingNode, startingTabIndex, WebFocusTypeBackward))
+ if (Element* winner = findElementWithExactTabIndex(startElement, startTabIndex, WebFocusTypeBackward))
return winner;
}
- // There are no nodes before start with the same tabindex as start, so look for a node that:
+ // 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.
- startingTabIndex = (start && startingTabIndex) ? startingTabIndex : std::numeric_limits<short>::max();
- return previousElementWithLowerTabIndex(last, startingTabIndex);
+ startTabIndex = (start && startTabIndex) ? startTabIndex : std::numeric_limits<short>::max();
+ return previousElementWithLowerTabIndex(lastElement, startTabIndex);
}
-// Searches through the given tree scope, starting from start node, for the next/previous
-// selectable element that comes after/before start node.
+// Searches through the given tree scope, starting from start element, for the next/previous
+// selectable element that comes after/before start element.
// The order followed is as specified in the HTML spec[1], which is elements with tab indexes
// first (from lowest to highest), and then elements without tab indexes (in document order).
// The search algorithm also conforms the Shadow DOM spec[2], which inserts sequence in a shadow
// tree into its host.
//
-// @param start The node from which to start searching. The node after this will be focused.
+// @param start The element from which to start searching. The element after this will be focused.
// May be null.
-// @return The focus element that comes after/before start node.
+// @return The focus element that comes after/before start element.
//
// [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, Node* node)
+inline Element* findFocusableElementInternal(WebFocusType type, const FocusNavigationScope& scope, Element* element)
{
- Element* found = (type == WebFocusTypeForward) ? nextFocusableElement(scope, node) : previousFocusableElement(scope, node);
+ Element* found = (type == WebFocusTypeForward) ? nextFocusableElement(scope, element) : previousFocusableElement(scope, element);
return found;
}
-Element* findFocusableElementRecursivelyForward(const FocusNavigationScope& scope, Node* start)
+Element* findFocusableElementRecursivelyForward(const FocusNavigationScope& scope, Element* start)
{
- // Starting node is exclusive.
+ // Starting element is exclusive.
Element* found = findFocusableElementInternal(WebFocusTypeForward, scope, start);
while (found) {
if (isShadowHostDelegatesFocus(*found)) {
- // If tabindex is positive, find focusable node inside its shadow tree.
+ // 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))
return foundInInnerFocusScope;
}
- // Skip to the next node in the same scope.
+ // Skip to the next element in the same scope.
found = findFocusableElementInternal(WebFocusTypeForward, scope, found);
continue;
}
@@ -406,9 +408,9 @@ Element* findFocusableElementRecursivelyForward(const FocusNavigationScope& scop
return nullptr;
}
-Element* findFocusableElementRecursivelyBackward(const FocusNavigationScope& scope, Node* start)
+Element* findFocusableElementRecursivelyBackward(const FocusNavigationScope& scope, Element* start)
{
- // Starting node is exclusive.
+ // Starting element is exclusive.
Element* found = findFocusableElementInternal(WebFocusTypeBackward, scope, start);
while (found) {
// Now |found| is on a focusable shadow host.
@@ -434,7 +436,7 @@ Element* findFocusableElementRecursivelyBackward(const FocusNavigationScope& sco
}
// Now |found| is on a non focusable scope owner (either shadow host or <shadow>).
- // Find focusable node in descendant scope. If not found, find next focusable node within the
+ // 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);
@@ -451,7 +453,7 @@ Element* findFocusableElementRecursivelyBackward(const FocusNavigationScope& sco
return nullptr;
}
-Element* findFocusableElementRecursively(WebFocusType type, const FocusNavigationScope& scope, Node* start)
+Element* findFocusableElementRecursively(WebFocusType type, const FocusNavigationScope& scope, Element* start)
{
return (type == WebFocusTypeForward) ?
findFocusableElementRecursivelyForward(scope, start) :
@@ -477,19 +479,19 @@ Element* findFocusableElementDescendingDownIntoFrameDocument(WebFocusType type,
return element;
}
-Element* findFocusableElementAcrossFocusScopesForward(const FocusNavigationScope& scope, Node* currentNode)
+Element* findFocusableElementAcrossFocusScopesForward(const FocusNavigationScope& scope, Element* current)
{
- ASSERT(!currentNode || !isNonFocusableShadowHost(*currentNode));
+ ASSERT(!current || !isNonFocusableShadowHost(*current));
Element* found;
- if (currentNode && currentNode->isElementNode() && isShadowHostWithoutCustomFocusLogic(*toElement(currentNode))) {
- FocusNavigationScope innerScope = FocusNavigationScope::ownedByShadowHost(*toElement(currentNode));
+ if (current && isShadowHostWithoutCustomFocusLogic(*current)) {
+ FocusNavigationScope innerScope = FocusNavigationScope::ownedByShadowHost(*current);
Element* foundInInnerFocusScope = findFocusableElementRecursivelyForward(innerScope, nullptr);
- found = foundInInnerFocusScope ? foundInInnerFocusScope : findFocusableElementRecursivelyForward(scope, currentNode);
+ found = foundInInnerFocusScope ? foundInInnerFocusScope : findFocusableElementRecursivelyForward(scope, current);
} else {
- found = findFocusableElementRecursivelyForward(scope, currentNode);
+ found = findFocusableElementRecursivelyForward(scope, current);
}
- // If there's no focusable node to advance to, move up the focus scopes until we find one.
+ // If there's no focusable element to advance to, move up the focus scopes until we find one.
FocusNavigationScope currentScope = scope;
while (!found) {
Element* owner = currentScope.owner();
@@ -501,12 +503,12 @@ Element* findFocusableElementAcrossFocusScopesForward(const FocusNavigationScope
return findFocusableElementDescendingDownIntoFrameDocument(WebFocusTypeForward, found);
}
-Element* findFocusableElementAcrossFocusScopesBackward(const FocusNavigationScope& scope, Node* currentNode)
+Element* findFocusableElementAcrossFocusScopesBackward(const FocusNavigationScope& scope, Element* current)
{
- ASSERT(!currentNode || !isNonFocusableShadowHost(*currentNode));
- Element* found = findFocusableElementRecursivelyBackward(scope, currentNode);
+ ASSERT(!current || !isNonFocusableShadowHost(*current));
+ Element* found = findFocusableElementRecursivelyBackward(scope, current);
- // If there's no focusable node to advance to, move up the focus scopes until we find one.
+ // If there's no focusable element to advance to, move up the focus scopes until we find one.
FocusNavigationScope currentScope = scope;
while (!found) {
Element* owner = currentScope.owner();
@@ -522,11 +524,11 @@ Element* findFocusableElementAcrossFocusScopesBackward(const FocusNavigationScop
return findFocusableElementDescendingDownIntoFrameDocument(WebFocusTypeBackward, found);
}
-Element* findFocusableElementAcrossFocusScopes(WebFocusType type, const FocusNavigationScope& scope, Node* currentNode)
+Element* findFocusableElementAcrossFocusScopes(WebFocusType type, const FocusNavigationScope& scope, Element* current)
{
return (type == WebFocusTypeForward) ?
- findFocusableElementAcrossFocusScopesForward(scope, currentNode) :
- findFocusableElementAcrossFocusScopesBackward(scope, currentNode);
+ findFocusableElementAcrossFocusScopesForward(scope, current) :
+ findFocusableElementAcrossFocusScopesBackward(scope, current);
}
inline Element* adjustToElement(Node* node, WebFocusType type)
@@ -781,7 +783,7 @@ bool FocusController::advanceFocusInDocumentOrder(LocalFrame* frame, Element* st
ASSERT(element);
if (element == document->focusedElement()) {
- // Focus wrapped around to the same node.
+ // Focus wrapped around to the same element.
return true;
}
@@ -805,13 +807,13 @@ bool FocusController::advanceFocusInDocumentOrder(LocalFrame* frame, Element* st
return true;
}
- // FIXME: It would be nice to just be able to call setFocusedElement(node)
+ // FIXME: It would be nice to just be able to call setFocusedElement(element)
// here, but we can't do that because some elements (e.g. HTMLInputElement
// and HTMLTextAreaElement) do extra work in their focus() methods.
Document& newDocument = element->document();
if (&newDocument != document) {
- // Focus is going away from this document, so clear the focused node.
+ // Focus is going away from this document, so clear the focused element.
document->clearFocusedElement();
}
@@ -916,7 +918,7 @@ bool FocusController::setFocusedElement(Element* element, PassRefPtrWillBeRawPtr
}
setFocusedFrame(newFocusedFrame);
- // Setting the focused node can result in losing our last reft to node when JS event handlers fire.
+ // Setting the focused element can result in losing our last reft to element when JS event handlers fire.
RefPtrWillBeRawPtr<Element> protect = element;
ALLOW_UNUSED_LOCAL(protect);
if (newDocument) {
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698