Diff
Modified: trunk/Source/WebCore/ChangeLog (87873 => 87874)
--- trunk/Source/WebCore/ChangeLog 2011-06-02 02:09:39 UTC (rev 87873)
+++ trunk/Source/WebCore/ChangeLog 2011-06-02 02:23:45 UTC (rev 87874)
@@ -1,3 +1,31 @@
+2011-06-01 Hayato Ito <[email protected]>
+
+ Reviewed by Kent Tamura.
+
+ Move {Next,Previous}FocusableNode functions from Document to FocusController.
+ https://bugs.webkit.org/show_bug.cgi?id=61839
+
+ There are some member functions in Document which use 'this'
+ pointer, but we should use TreeScope instead of Document in some
+ places to handle focus issues nicely. We have to move these
+ functions out of Document class so that we can give the TreeScope
+ as a parameter.
+
+ No new tests since no functionality was changed.
+
+ * dom/Document.cpp:
+ * dom/Document.h:
+ * page/FocusController.cpp:
+ (WebCore::FocusController::deepFocusableNode):
+ (WebCore::FocusController::advanceFocusInDocumentOrder):
+ (WebCore::nextNodeWithExactTabIndex):
+ (WebCore::previousNodeWithExactTabIndex):
+ (WebCore::nextNodeWithGreaterTabIndex):
+ (WebCore::previousNodeWithLowerTabIndex):
+ (WebCore::FocusController::nextFocusableNode):
+ (WebCore::FocusController::previousFocusableNode):
+ * page/FocusController.h:
+
2011-06-01 Adrienne Walker <[email protected]>
Reviewed by James Robinson.
Modified: trunk/Source/WebCore/dom/Document.cpp (87873 => 87874)
--- trunk/Source/WebCore/dom/Document.cpp 2011-06-02 02:09:39 UTC (rev 87873)
+++ trunk/Source/WebCore/dom/Document.cpp 2011-06-02 02:23:45 UTC (rev 87874)
@@ -2509,118 +2509,6 @@
return m_mappedElementSheet.get();
}
-static Node* nextNodeWithExactTabIndex(Node* start, int tabIndex, KeyboardEvent* event)
-{
- // Search is inclusive of start
- for (Node* n = start; n; n = n->traverseNextNode())
- if (n->isKeyboardFocusable(event) && n->tabIndex() == tabIndex)
- return n;
-
- return 0;
-}
-
-static Node* previousNodeWithExactTabIndex(Node* start, int tabIndex, KeyboardEvent* event)
-{
- // Search is inclusive of start
- for (Node* n = start; n; n = n->traversePreviousNode())
- if (n->isKeyboardFocusable(event) && n->tabIndex() == tabIndex)
- return n;
-
- return 0;
-}
-
-static Node* nextNodeWithGreaterTabIndex(Node* start, int tabIndex, KeyboardEvent* event)
-{
- // Search is inclusive of start
- int winningTabIndex = SHRT_MAX + 1;
- Node* winner = 0;
- for (Node* n = start; n; n = n->traverseNextNode())
- if (n->isKeyboardFocusable(event) && n->tabIndex() > tabIndex && n->tabIndex() < winningTabIndex) {
- winner = n;
- winningTabIndex = n->tabIndex();
- }
-
- return winner;
-}
-
-static Node* previousNodeWithLowerTabIndex(Node* start, int tabIndex, KeyboardEvent* event)
-{
- // Search is inclusive of start
- int winningTabIndex = 0;
- Node* winner = 0;
- for (Node* n = start; n; n = n->traversePreviousNode())
- if (n->isKeyboardFocusable(event) && n->tabIndex() < tabIndex && n->tabIndex() > winningTabIndex) {
- winner = n;
- winningTabIndex = n->tabIndex();
- }
-
- return winner;
-}
-
-Node* Document::nextFocusableNode(Node* start, KeyboardEvent* event)
-{
- if (start) {
- // If a node is excluded from the normal tabbing cycle, the next focusable node is determined by tree order
- if (start->tabIndex() < 0) {
- for (Node* n = start->traverseNextNode(); n; n = n->traverseNextNode())
- if (n->isKeyboardFocusable(event) && n->tabIndex() >= 0)
- return n;
- }
-
- // First try to find a node with the same tabindex as start that comes after start in the document.
- if (Node* winner = nextNodeWithExactTabIndex(start->traverseNextNode(), start->tabIndex(), event))
- return winner;
-
- if (!start->tabIndex())
- // We've reached the last node in the document with a tabindex of 0. This is the end of the tabbing order.
- return 0;
- }
-
- // Look for the first node in the document 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 document, if there's a tie.
- if (Node* winner = nextNodeWithGreaterTabIndex(this, start ? start->tabIndex() : 0, event))
- 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 nextNodeWithExactTabIndex(this, 0, event);
-}
-
-Node* Document::previousFocusableNode(Node* start, KeyboardEvent* event)
-{
- Node* last;
- for (last = this; last->lastChild(); last = last->lastChild()) { }
-
- // First try to find the last node in the document that comes before start and has the same tabindex as start.
- // If start is null, find the last node in the document with a tabindex of 0.
- Node* startingNode;
- int startingTabIndex;
- if (start) {
- startingNode = start->traversePreviousNode();
- startingTabIndex = start->tabIndex();
- } else {
- startingNode = last;
- startingTabIndex = 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* n = startingNode; n; n = n->traversePreviousNode())
- if (n->isKeyboardFocusable(event) && n->tabIndex() >= 0)
- return n;
- }
-
- if (Node* winner = previousNodeWithExactTabIndex(startingNode, startingTabIndex, event))
- return winner;
-
- // There are no nodes before start with the same tabindex as start, so look for a node that:
- // 1) has the highest non-zero tabindex (that is less than start's tabindex), and
- // 2) comes last in the document, if there's a tie.
- startingTabIndex = (start && start->tabIndex()) ? start->tabIndex() : SHRT_MAX;
- return previousNodeWithLowerTabIndex(last, startingTabIndex, event);
-}
-
int Document::nodeAbsIndex(Node *node)
{
ASSERT(node->document() == this);
Modified: trunk/Source/WebCore/dom/Document.h (87873 => 87874)
--- trunk/Source/WebCore/dom/Document.h 2011-06-02 02:09:39 UTC (rev 87873)
+++ trunk/Source/WebCore/dom/Document.h 2011-06-02 02:23:45 UTC (rev 87874)
@@ -767,32 +767,6 @@
CSSStyleDeclaration* getOverrideStyle(Element*, const String& pseudoElt);
- /**
- * Searches through the document, starting from fromNode, for the next selectable element that comes after fromNode.
- * The order followed is as specified in section 17.11.1 of the HTML4 spec, which is elements with tab indexes
- * first (from lowest to highest), and then elements without tab indexes (in document order).
- *
- * @param fromNode The node from which to start searching. The node after this will be focused. May be null.
- *
- * @return The focus node that comes after fromNode
- *
- * See http://www.w3.org/TR/html4/interact/forms.html#h-17.11.1
- */
- Node* nextFocusableNode(Node* start, KeyboardEvent*);
-
- /**
- * Searches through the document, starting from fromNode, for the previous selectable element (that comes _before_)
- * fromNode. The order followed is as specified in section 17.11.1 of the HTML4 spec, which is elements with tab
- * indexes first (from lowest to highest), and then elements without tab indexes (in document order).
- *
- * @param fromNode The node from which to start searching. The node before this will be focused. May be null.
- *
- * @return The focus node that comes before fromNode
- *
- * See http://www.w3.org/TR/html4/interact/forms.html#h-17.11.1
- */
- Node* previousFocusableNode(Node* start, KeyboardEvent*);
-
int nodeAbsIndex(Node*);
Node* nodeWithAbsIndex(int absIndex);
Modified: trunk/Source/WebCore/page/FocusController.cpp (87873 => 87874)
--- trunk/Source/WebCore/page/FocusController.cpp 2011-06-02 02:09:39 UTC (rev 87873)
+++ trunk/Source/WebCore/page/FocusController.cpp 2011-06-02 02:23:45 UTC (rev 87874)
@@ -56,6 +56,7 @@
#include "SpatialNavigation.h"
#include "Widget.h"
#include "htmlediting.h" // For firstPositionInOrBeforeNode
+#include <limits>
namespace WebCore {
@@ -144,7 +145,7 @@
}
}
-static Node* deepFocusableNode(FocusDirection direction, Node* node, KeyboardEvent* event)
+Node* FocusController::deepFocusableNode(FocusDirection direction, Node* node, KeyboardEvent* event)
{
// The node we found might be a HTMLFrameOwnerElement, so descend down the frame tree until we find either:
// 1) a focusable node, or
@@ -157,8 +158,8 @@
Document* document = owner->contentFrame()->document();
node = (direction == FocusDirectionForward)
- ? document->nextFocusableNode(0, event)
- : document->previousFocusableNode(0, event);
+ ? nextFocusableNode(document, 0, event)
+ : previousFocusableNode(document, 0, event);
if (!node) {
node = owner;
break;
@@ -215,8 +216,8 @@
document->updateLayoutIgnorePendingStylesheets();
Node* node = (direction == FocusDirectionForward)
- ? document->nextFocusableNode(currentNode, event)
- : document->previousFocusableNode(currentNode, event);
+ ? nextFocusableNode(document, currentNode, event)
+ : previousFocusableNode(document, currentNode, event);
// If there's no focusable node to advance to, move up the frame tree until we find one.
while (!node && frame) {
@@ -231,8 +232,8 @@
break;
node = (direction == FocusDirectionForward)
- ? parentDocument->nextFocusableNode(owner, event)
- : parentDocument->previousFocusableNode(owner, event);
+ ? nextFocusableNode(parentDocument, owner, event)
+ : previousFocusableNode(parentDocument, owner, event);
frame = parentFrame;
}
@@ -251,8 +252,8 @@
// Chrome doesn't want focus, so we should wrap focus.
Document* d = m_page->mainFrame()->document();
node = (direction == FocusDirectionForward)
- ? d->nextFocusableNode(0, event)
- : d->previousFocusableNode(0, event);
+ ? nextFocusableNode(d, 0, event)
+ : previousFocusableNode(d, 0, event);
node = deepFocusableNode(direction, node, event);
@@ -306,6 +307,118 @@
return true;
}
+static Node* nextNodeWithExactTabIndex(Node* start, int tabIndex, KeyboardEvent* event)
+{
+ // Search is inclusive of start
+ for (Node* node = start; node; node = node->traverseNextNode())
+ if (node->isKeyboardFocusable(event) && node->tabIndex() == tabIndex)
+ return node;
+
+ return 0;
+}
+
+static Node* previousNodeWithExactTabIndex(Node* start, int tabIndex, KeyboardEvent* event)
+{
+ // Search is inclusive of start
+ for (Node* n = start; n; n = n->traversePreviousNode())
+ if (n->isKeyboardFocusable(event) && n->tabIndex() == tabIndex)
+ return n;
+
+ return 0;
+}
+
+static Node* nextNodeWithGreaterTabIndex(Node* start, int tabIndex, KeyboardEvent* event)
+{
+ // Search is inclusive of start
+ int winningTabIndex = std::numeric_limits<short>::max() + 1;
+ Node* winner = 0;
+ for (Node* n = start; n; n = n->traverseNextNode())
+ if (n->isKeyboardFocusable(event) && n->tabIndex() > tabIndex && n->tabIndex() < winningTabIndex) {
+ winner = n;
+ winningTabIndex = n->tabIndex();
+ }
+
+ return winner;
+}
+
+static Node* previousNodeWithLowerTabIndex(Node* start, int tabIndex, KeyboardEvent* event)
+{
+ // Search is inclusive of start
+ int winningTabIndex = 0;
+ Node* winner = 0;
+ for (Node* n = start; n; n = n->traversePreviousNode())
+ if (n->isKeyboardFocusable(event) && n->tabIndex() < tabIndex && n->tabIndex() > winningTabIndex) {
+ winner = n;
+ winningTabIndex = n->tabIndex();
+ }
+
+ return winner;
+}
+
+Node* FocusController::nextFocusableNode(TreeScope* within, Node* start, KeyboardEvent* event)
+{
+ if (start) {
+ // If a node is excluded from the normal tabbing cycle, the next focusable node is determined by tree order
+ if (start->tabIndex() < 0) {
+ for (Node* n = start->traverseNextNode(); n; n = n->traverseNextNode())
+ if (n->isKeyboardFocusable(event) && n->tabIndex() >= 0)
+ return n;
+ }
+
+ // First try to find a node with the same tabindex as start that comes after start in the tree scope.
+ if (Node* winner = nextNodeWithExactTabIndex(start->traverseNextNode(), start->tabIndex(), event))
+ return winner;
+
+ if (!start->tabIndex())
+ // We've reached the last node in the document with a tabindex of 0. This is the end of the tabbing order.
+ return 0;
+ }
+
+ // Look for the first node in the tree 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 tree scope, if there's a tie.
+ if (Node* winner = nextNodeWithGreaterTabIndex(within, start ? start->tabIndex() : 0, event))
+ 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 nextNodeWithExactTabIndex(within, 0, event);
+}
+
+Node* FocusController::previousFocusableNode(TreeScope* within, Node* start, KeyboardEvent* event)
+{
+ Node* last;
+ for (last = within; last->lastChild(); last = last->lastChild()) { }
+
+ // First try to find the last node in the tree scope that comes before start and has the same tabindex as start.
+ // If start is null, find the last node in the tree scope with a tabindex of 0.
+ Node* startingNode;
+ int startingTabIndex;
+ if (start) {
+ startingNode = start->traversePreviousNode();
+ startingTabIndex = start->tabIndex();
+ } else {
+ startingNode = last;
+ startingTabIndex = 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* n = startingNode; n; n = n->traversePreviousNode())
+ if (n->isKeyboardFocusable(event) && n->tabIndex() >= 0)
+ return n;
+ }
+
+ if (Node* winner = previousNodeWithExactTabIndex(startingNode, startingTabIndex, event))
+ return winner;
+
+ // There are no nodes before start with the same tabindex as start, so look for a node that:
+ // 1) has the highest non-zero tabindex (that is less than start's tabindex), and
+ // 2) comes last in the tree scope, if there's a tie.
+ startingTabIndex = (start && start->tabIndex()) ? start->tabIndex() : std::numeric_limits<short>::max();
+ return previousNodeWithLowerTabIndex(last, startingTabIndex, event);
+}
+
static bool relinquishesEditingFocus(Node *node)
{
ASSERT(node);
Modified: trunk/Source/WebCore/page/FocusController.h (87873 => 87874)
--- trunk/Source/WebCore/page/FocusController.h 2011-06-02 02:09:39 UTC (rev 87873)
+++ trunk/Source/WebCore/page/FocusController.h 2011-06-02 02:23:45 UTC (rev 87874)
@@ -39,6 +39,7 @@
class KeyboardEvent;
class Node;
class Page;
+class TreeScope;
class FocusController {
WTF_MAKE_NONCOPYABLE(FocusController); WTF_MAKE_FAST_ALLOCATED;
@@ -64,6 +65,8 @@
bool advanceFocusDirectionally(FocusDirection, KeyboardEvent*);
bool advanceFocusInDocumentOrder(FocusDirection, KeyboardEvent*, bool initialFocus);
+ Node* deepFocusableNode(FocusDirection, Node*, KeyboardEvent*);
+
bool advanceFocusDirectionallyInContainer(Node* container, const IntRect& startingRect, FocusDirection, KeyboardEvent*);
void findFocusCandidateInContainer(Node* container, const IntRect& startingRect, FocusDirection, KeyboardEvent*, FocusCandidate& closest);
@@ -72,6 +75,30 @@
bool m_isActive;
bool m_isFocused;
bool m_isChangingFocusedFrame;
+
+ // Searches through the document, starting from start node, for the next selectable element that comes after start node.
+ // The order followed is as specified in section 17.11.1 of the HTML4 spec, which is elements with tab indexes
+ // first (from lowest to highest), and then elements without tab indexes (in document order).
+ //
+ // @param within The tree scope where a search is executed.
+ // @param start The node from which to start searching. The node before this will be focused. May be null.
+ //
+ // @return The focus node that comes after start node.
+ //
+ // See http://www.w3.org/TR/html4/interact/forms.html#h-17.11.1
+ Node* nextFocusableNode(TreeScope* within, Node* start, KeyboardEvent*);
+
+ // Searches through the document, starting from start node, for the previous selectable element that comes before start node.
+ // The order followed is as specified in section 17.11.1 of the HTML4 spec, which is elements with tab indexes
+ // first (from lowest to highest), and then elements without tab indexes (in document order).
+ //
+ // @param within The tree scope where a search is executed.
+ // @param start The node from which to start searching. The node before this will be focused. May be null.
+ //
+ // @return The focus node that comes before start node.
+ //
+ // See http://www.w3.org/TR/html4/interact/forms.html#h-17.11.1
+ Node* previousFocusableNode(TreeScope* within, Node* start, KeyboardEvent*);
};
} // namespace WebCore