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

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: Refactoring related to OILPAN 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
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 9f9b58368ff266604e36f62763ec9d01d125e4a6..fd67e5a0e0b7db5e3a13b0eef8d5a478bb729c0f 100644
--- a/third_party/WebKit/Source/core/page/FocusController.cpp
+++ b/third_party/WebKit/Source/core/page/FocusController.cpp
@@ -28,10 +28,12 @@
#include "core/HTMLNames.h"
#include "core/dom/AXObjectCache.h"
+#include "core/dom/AssignedNodeTraversal.h"
+#include "core/dom/CombinedNodeTraversal.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"
@@ -49,6 +51,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"
@@ -78,11 +81,14 @@ public:
static FocusNavigationScope ownedByNonFocusableFocusScopeOwner(Element&);
static FocusNavigationScope ownedByShadowHost(const Element&);
static FocusNavigationScope ownedByShadowInsertionPoint(HTMLShadowElement&);
+ static FocusNavigationScope ownedByHTMLSlotElement(HTMLSlotElement&);
static FocusNavigationScope ownedByIFrame(const HTMLFrameOwnerElement&);
private:
explicit FocusNavigationScope(TreeScope*);
+ explicit FocusNavigationScope(HTMLSlotElement*);
RawPtrWillBeMember<TreeScope> m_rootTreeScope;
+ RawPtrWillBeMember<HTMLSlotElement> m_rootSlot;
};
FocusNavigationScope::FocusNavigationScope(TreeScope* treeScope)
@@ -91,13 +97,23 @@ FocusNavigationScope::FocusNavigationScope(TreeScope* treeScope)
ASSERT(treeScope);
}
+FocusNavigationScope::FocusNavigationScope(HTMLSlotElement* slot)
+ : m_rootSlot(slot)
+{
+ ASSERT(slot);
+}
+
Node* FocusNavigationScope::rootNode() const
{
+ if (m_rootSlot)
+ return m_rootSlot;
return &m_rootTreeScope->rootNode();
}
Element* FocusNavigationScope::owner() const
{
+ if (m_rootSlot)
+ return m_rootSlot;
Node* root = rootNode();
if (root->isShadowRoot()) {
ShadowRoot* shadowRoot = toShadowRoot(root);
@@ -111,6 +127,8 @@ Element* FocusNavigationScope::owner() const
FocusNavigationScope FocusNavigationScope::focusNavigationScopeOf(const Node& node)
{
+ if (AssignedNodeTraversal::isInAssignedScope(node))
+ return FocusNavigationScope(AssignedNodeTraversal::slot(node));
return FocusNavigationScope(&node.treeScope());
}
@@ -118,8 +136,10 @@ FocusNavigationScope FocusNavigationScope::ownedByNonFocusableFocusScopeOwner(El
{
if (isShadowHost(element))
return FocusNavigationScope::ownedByShadowHost(element);
- ASSERT(isShadowInsertionPointFocusScopeOwner(element));
- return FocusNavigationScope::ownedByShadowInsertionPoint(toHTMLShadowElement(element));
+ if (isShadowInsertionPointFocusScopeOwner(element))
+ return FocusNavigationScope::ownedByShadowInsertionPoint(toHTMLShadowElement(element));
+ ASSERT(isHTMLSlotElement(element));
+ return FocusNavigationScope::ownedByHTMLSlotElement(toHTMLSlotElement(element));
}
FocusNavigationScope FocusNavigationScope::ownedByShadowHost(const Element& element)
@@ -141,6 +161,11 @@ FocusNavigationScope FocusNavigationScope::ownedByShadowInsertionPoint(HTMLShado
return FocusNavigationScope(shadowInsertionPoint.olderShadowRoot());
}
+FocusNavigationScope FocusNavigationScope::ownedByHTMLSlotElement(HTMLSlotElement& element)
+{
+ return FocusNavigationScope(&element);
+}
+
inline void dispatchBlurEvent(const Document& document, Element& focusedElement)
{
focusedElement.dispatchBlurEvent(nullptr, WebFocusTypePage);
@@ -224,7 +249,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)
@@ -248,7 +273,10 @@ inline bool shouldVisit(Node& node)
Element* findElementWithExactTabIndex(Node* 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 (!start)
+ return nullptr;
+ CombinedNodeTraversal* traversal = new CombinedNodeTraversal(*start);
+ for (Node* node = start; node; node = type == WebFocusTypeForward ? traversal->next() : traversal->previous()) {
if (shouldVisit(*node) && adjustedTabIndex(*node) == tabIndex)
return toElement(node);
}
@@ -260,10 +288,14 @@ Element* nextElementWithGreaterTabIndex(Node* 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;
+ if (!start)
+ return nullptr;
+
+ CombinedNodeTraversal* traversal = new CombinedNodeTraversal(*start);
+ for (Node* node = start; node; node = traversal->next()) {
+ int currentTabIndex = adjustedTabIndex(*node);
+ if (shouldVisit(*node) && currentTabIndex > tabIndex && currentTabIndex < winningTabIndex) {
+ winner = node;
winningTabIndex = currentTabIndex;
}
}
@@ -276,7 +308,8 @@ Element* previousElementWithLowerTabIndex(Node* start, int tabIndex)
// Search is inclusive of start
int winningTabIndex = 0;
Node* winner = nullptr;
- for (Node* node = start; node; node = ElementTraversal::previous(*node)) {
+ CombinedNodeTraversal* traversal = new CombinedNodeTraversal(*start);
+ for (Node* node = start; node; node = traversal->previous()) {
int currentTabIndex = adjustedTabIndex(*node);
if (shouldVisit(*node) && currentTabIndex < tabIndex && currentTabIndex > winningTabIndex) {
winner = node;
@@ -293,13 +326,15 @@ Element* nextFocusableElement(const FocusNavigationScope& scope, Node* 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 (tabIndex < 0) {
- for (Node& node : NodeTraversal::startsAfter(*start)) {
- if (shouldVisit(node) && adjustedTabIndex(node) >= 0)
- return &toElement(node);
+ CombinedNodeTraversal* traversal = new CombinedNodeTraversal(*start);
+ for (Node* node = traversal->next(); node; node = traversal->next()) {
+ if (shouldVisit(*node) && adjustedTabIndex(*node) >= 0)
+ return &toElement(*node);
}
} else {
// First try to find a node with the same tabindex as start that comes after start in the scope.
- if (Element* winner = findElementWithExactTabIndex(ElementTraversal::next(*start), tabIndex, WebFocusTypeForward))
+ CombinedNodeTraversal* traversal = new CombinedNodeTraversal(*start);
+ if (Element* winner = findElementWithExactTabIndex(traversal->next(), tabIndex, WebFocusTypeForward))
return winner;
}
if (!tabIndex) {
@@ -311,9 +346,15 @@ Element* nextFocusableElement(const FocusNavigationScope& scope, Node* start)
// Look for the first node 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))
- return winner;
+ if (isHTMLSlotElement(scope.rootNode())) {
+ if (Element* winner = nextElementWithGreaterTabIndex(toHTMLSlotElement(scope.rootNode())->getAssignedNodes()[0].get(), start ? adjustedTabIndex(*start) : 0))
+ return winner;
+ return findElementWithExactTabIndex(toHTMLSlotElement(scope.rootNode())->getAssignedNodes()[0].get(), 0, WebFocusTypeForward);
+ }
+ if (Element* winner = nextElementWithGreaterTabIndex(scope.rootNode(), 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);
@@ -322,8 +363,12 @@ Element* nextFocusableElement(const FocusNavigationScope& scope, Node* start)
Element* previousFocusableElement(const FocusNavigationScope& scope, Node* start)
{
Node* last = nullptr;
- for (Node* node = scope.rootNode(); node; node = node->lastChild())
- last = node;
+ if (isHTMLSlotElement(scope.rootNode()) && !toHTMLSlotElement(scope.rootNode())->getAssignedNodes().isEmpty()) {
+ last = toHTMLSlotElement(scope.rootNode())->getAssignedNodes().last().get();
+ } else {
+ 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.
@@ -331,7 +376,8 @@ Element* previousFocusableElement(const FocusNavigationScope& scope, Node* start
Node* startingNode;
int startingTabIndex;
if (start) {
- startingNode = ElementTraversal::previous(*start);
+ CombinedNodeTraversal* traversal = new CombinedNodeTraversal(*start);
+ startingNode = traversal->previous();
startingTabIndex = adjustedTabIndex(*start);
} else {
startingNode = last;
@@ -340,7 +386,8 @@ Element* previousFocusableElement(const FocusNavigationScope& scope, Node* start
// 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)) {
+ CombinedNodeTraversal* traversal = new CombinedNodeTraversal(*startingNode);
+ for (Node* node = startingNode; node; node = traversal->previous()) {
if (shouldVisit(*node) && adjustedTabIndex(*node) >= 0)
return toElement(node);
}
@@ -394,7 +441,7 @@ Element* findFocusableElementRecursivelyForward(const FocusNavigationScope& scop
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);
@@ -410,6 +457,7 @@ Element* findFocusableElementRecursivelyBackward(const FocusNavigationScope& sco
{
// Starting node is exclusive.
Element* found = findFocusableElementInternal(WebFocusTypeBackward, scope, start);
+
while (found) {
// Now |found| is on a focusable shadow host.
// Find inside shadow backwards. If any focusable element is found, return it, otherwise return
@@ -433,7 +481,7 @@ Element* findFocusableElementRecursivelyBackward(const FocusNavigationScope& sco
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 node in descendant scope. If not found, find next focusable node within the
// current scope.
if (isNonFocusableFocusScopeOwner(*found)) {

Powered by Google App Engine
This is Rietveld 408576698