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

Side by Side Diff: Source/core/page/FocusController.cpp

Issue 1200423004: Remaining Node to Element conversion in FocusController (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 5 years, 6 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. 2 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
3 * Copyright (C) 2008 Nuanti Ltd. 3 * Copyright (C) 2008 Nuanti Ltd.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 6 * modification, are permitted provided that the following conditions
7 * are met: 7 * are met:
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
56 #include "core/layout/HitTestResult.h" 56 #include "core/layout/HitTestResult.h"
57 #include "core/page/SpatialNavigation.h" 57 #include "core/page/SpatialNavigation.h"
58 #include <limits> 58 #include <limits>
59 59
60 namespace blink { 60 namespace blink {
61 61
62 using namespace HTMLNames; 62 using namespace HTMLNames;
63 63
64 namespace { 64 namespace {
65 65
66 inline bool isShadowInsertionPointFocusScopeOwner(Node& node) 66 inline bool isShadowInsertionPointFocusScopeOwner(Element& element)
67 { 67 {
68 return isActiveShadowInsertionPoint(node) && toHTMLShadowElement(node).older ShadowRoot(); 68 return isActiveShadowInsertionPoint(element) && toHTMLShadowElement(element) .olderShadowRoot();
69 } 69 }
70 70
71 class FocusNavigationScope { 71 class FocusNavigationScope {
72 STACK_ALLOCATED(); 72 STACK_ALLOCATED();
73 public: 73 public:
74 Node* rootNode() const; 74 Node* rootNode() const;
75 Element* owner() const; 75 Element* owner() const;
76 static FocusNavigationScope focusNavigationScopeOf(const Node&); 76 static FocusNavigationScope focusNavigationScopeOf(const Node&);
77 static FocusNavigationScope ownedByNonFocusableFocusScopeOwner(Element&); 77 static FocusNavigationScope ownedByNonFocusableFocusScopeOwner(Element&);
78 static FocusNavigationScope ownedByShadowHost(const Element&); 78 static FocusNavigationScope ownedByShadowHost(const Element&);
79 static FocusNavigationScope ownedByShadowInsertionPoint(HTMLShadowElement&); 79 static FocusNavigationScope ownedByShadowInsertionPoint(HTMLShadowElement&);
80 static FocusNavigationScope ownedByIFrame(const HTMLFrameOwnerElement&); 80 static FocusNavigationScope ownedByIFrame(const HTMLFrameOwnerElement&);
81 81
82 private: 82 private:
83 explicit FocusNavigationScope(TreeScope*); 83 explicit FocusNavigationScope(TreeScope*);
84 RawPtrWillBeMember<TreeScope> m_rootTreeScope; 84 RawPtrWillBeMember<TreeScope> m_rootTreeScope;
85 }; 85 };
86 86
87 // FIXME: Some of Node* return values and Node* arguments should be Element*.
88
89 FocusNavigationScope::FocusNavigationScope(TreeScope* treeScope) 87 FocusNavigationScope::FocusNavigationScope(TreeScope* treeScope)
90 : m_rootTreeScope(treeScope) 88 : m_rootTreeScope(treeScope)
91 { 89 {
92 ASSERT(treeScope); 90 ASSERT(treeScope);
93 } 91 }
94 92
95 Node* FocusNavigationScope::rootNode() const 93 Node* FocusNavigationScope::rootNode() const
96 { 94 {
97 return &m_rootTreeScope->rootNode(); 95 return &m_rootTreeScope->rootNode();
98 } 96 }
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
196 focusedElement->setFocus(true); 194 focusedElement->setFocus(true);
197 dispatchFocusEvent(*document, *focusedElement); 195 dispatchFocusEvent(*document, *focusedElement);
198 } 196 }
199 } 197 }
200 198
201 inline bool hasCustomFocusLogic(const Element& element) 199 inline bool hasCustomFocusLogic(const Element& element)
202 { 200 {
203 return element.isHTMLElement() && toHTMLElement(element).hasCustomFocusLogic (); 201 return element.isHTMLElement() && toHTMLElement(element).hasCustomFocusLogic ();
204 } 202 }
205 203
206 inline bool isShadowHostWithoutCustomFocusLogic(const Node& node) 204 inline bool isShadowHostWithoutCustomFocusLogic(const Element& element)
207 { 205 {
208 if (!node.isElementNode())
209 return false;
210 const Element& element = toElement(node);
211 return isShadowHost(element) && !hasCustomFocusLogic(element); 206 return isShadowHost(element) && !hasCustomFocusLogic(element);
212 } 207 }
213 208
214 #if ENABLE(ASSERT) 209 #if ENABLE(ASSERT)
215 inline bool isNonFocusableShadowHost(const Node& node) 210 inline bool isNonFocusableShadowHost(const Node& node)
216 { 211 {
217 return isShadowHostWithoutCustomFocusLogic(node) && !toElement(node).isFocus able(); 212 if (!node.isElementNode())
213 return false;
214 const Element& element = toElement(node);
215 return isShadowHostWithoutCustomFocusLogic(element) && !element.isFocusable( );
218 } 216 }
219 #endif 217 #endif
220 218
221 inline bool isNonKeyboardFocusableShadowHost(const Node& node) 219 inline bool isNonKeyboardFocusableShadowHost(const Element& element)
222 { 220 {
223 return isShadowHostWithoutCustomFocusLogic(node) && !toElement(node).isKeybo ardFocusable(); 221 return isShadowHostWithoutCustomFocusLogic(element) && !element.isKeyboardFo cusable();
224 } 222 }
225 223
226 inline bool isKeyboardFocusableShadowHost(const Node& node) 224 inline bool isKeyboardFocusableShadowHost(const Element& element)
227 { 225 {
228 return isShadowHostWithoutCustomFocusLogic(node) && toElement(node).isKeyboa rdFocusable(); 226 return isShadowHostWithoutCustomFocusLogic(element) && element.isKeyboardFoc usable();
229 } 227 }
230 228
231 inline bool isNonFocusableFocusScopeOwner(Node& node) 229 inline bool isNonFocusableFocusScopeOwner(Element& element)
232 { 230 {
233 return isNonKeyboardFocusableShadowHost(node) || isShadowInsertionPointFocus ScopeOwner(node); 231 return isNonKeyboardFocusableShadowHost(element) || isShadowInsertionPointFo cusScopeOwner(element);
234 } 232 }
235 233
236 inline bool isShadowHostDelegatesFocus(const Node& node) 234 inline bool isShadowHostDelegatesFocus(const Element& element)
237 { 235 {
238 return node.isElementNode() && toElement(node).shadowRoot() && toElement(nod e).shadowRoot()->delegatesFocus(); 236 return element.shadowRoot() && element.shadowRoot()->delegatesFocus();
239 } 237 }
240 238
241 inline int adjustedTabIndex(Node& node) 239 inline int adjustedTabIndex(Node& node)
242 { 240 {
243 return isNonFocusableFocusScopeOwner(node) ? 0 : node.tabIndex(); 241 return node.isElementNode() && isNonFocusableFocusScopeOwner(toElement(node) ) ? 0 : node.tabIndex();
244 } 242 }
245 243
246 inline bool shouldVisit(Node& node) 244 inline bool shouldVisit(Node& node)
247 { 245 {
248 return (node.isElementNode() && toElement(node).isKeyboardFocusable()) || is NonFocusableFocusScopeOwner(node); 246 if (!node.isElementNode())
247 return false;
248 Element& element = toElement(node);
249 return element.isKeyboardFocusable() || isNonFocusableFocusScopeOwner(elemen t);
249 } 250 }
250 251
251 Element* findElementWithExactTabIndex(Node* start, int tabIndex, WebFocusType ty pe) 252 Element* findElementWithExactTabIndex(Node* start, int tabIndex, WebFocusType ty pe)
252 { 253 {
253 // Search is inclusive of start 254 // Search is inclusive of start
254 for (Node* node = start; node; node = type == WebFocusTypeForward ? NodeTrav ersal::next(*node) : NodeTraversal::previous(*node)) { 255 for (Node* node = start; node; node = type == WebFocusTypeForward ? ElementT raversal::next(*node) : ElementTraversal::previous(*node)) {
255 if (shouldVisit(*node) && adjustedTabIndex(*node) == tabIndex) 256 if (shouldVisit(*node) && adjustedTabIndex(*node) == tabIndex)
256 return toElement(node); 257 return toElement(node);
257 } 258 }
258 return nullptr; 259 return nullptr;
259 } 260 }
260 261
261 Element* nextElementWithGreaterTabIndex(Node* start, int tabIndex) 262 Element* nextElementWithGreaterTabIndex(Node* start, int tabIndex)
262 { 263 {
263 // Search is inclusive of start 264 // Search is inclusive of start
264 int winningTabIndex = std::numeric_limits<short>::max() + 1; 265 int winningTabIndex = std::numeric_limits<short>::max() + 1;
265 Node* winner = nullptr; 266 Node* winner = nullptr;
266 for (Node& node : NodeTraversal::startsAt(start)) { 267 for (Node& node : NodeTraversal::startsAt(start)) {
267 int currentTabIndex = adjustedTabIndex(node); 268 int currentTabIndex = adjustedTabIndex(node);
268 if (shouldVisit(node) && currentTabIndex > tabIndex && currentTabIndex < winningTabIndex) { 269 if (shouldVisit(node) && currentTabIndex > tabIndex && currentTabIndex < winningTabIndex) {
269 winner = &node; 270 winner = &node;
270 winningTabIndex = currentTabIndex; 271 winningTabIndex = currentTabIndex;
271 } 272 }
272 } 273 }
273 ASSERT(!winner || winner->isElementNode()); 274 ASSERT(!winner || winner->isElementNode());
274 return toElement(winner); 275 return toElement(winner);
275 } 276 }
276 277
277 Element* previousElementWithLowerTabIndex(Node* start, int tabIndex) 278 Element* previousElementWithLowerTabIndex(Node* start, int tabIndex)
278 { 279 {
279 // Search is inclusive of start 280 // Search is inclusive of start
280 int winningTabIndex = 0; 281 int winningTabIndex = 0;
281 Node* winner = nullptr; 282 Node* winner = nullptr;
282 for (Node* node = start; node; node = NodeTraversal::previous(*node)) { 283 for (Node* node = start; node; node = ElementTraversal::previous(*node)) {
283 int currentTabIndex = adjustedTabIndex(*node); 284 int currentTabIndex = adjustedTabIndex(*node);
284 if (shouldVisit(*node) && currentTabIndex < tabIndex && currentTabIndex > winningTabIndex) { 285 if (shouldVisit(*node) && currentTabIndex < tabIndex && currentTabIndex > winningTabIndex) {
285 winner = node; 286 winner = node;
286 winningTabIndex = currentTabIndex; 287 winningTabIndex = currentTabIndex;
287 } 288 }
288 } 289 }
289 ASSERT(!winner || winner->isElementNode()); 290 ASSERT(!winner || winner->isElementNode());
290 return toElement(winner); 291 return toElement(winner);
291 } 292 }
292 293
293 Element* nextFocusableElement(const FocusNavigationScope& scope, Node* start) 294 Element* nextFocusableElement(const FocusNavigationScope& scope, Node* start)
294 { 295 {
295 if (start) { 296 if (start) {
296 int tabIndex = adjustedTabIndex(*start); 297 int tabIndex = adjustedTabIndex(*start);
297 // If a node is excluded from the normal tabbing cycle, the next focusab le node is determined by tree order 298 // If a node is excluded from the normal tabbing cycle, the next focusab le node is determined by tree order
298 if (tabIndex < 0) { 299 if (tabIndex < 0) {
299 for (Node& node : NodeTraversal::startsAfter(*start)) { 300 for (Node& node : NodeTraversal::startsAfter(*start)) {
300 if (shouldVisit(node) && adjustedTabIndex(node) >= 0) 301 if (shouldVisit(node) && adjustedTabIndex(node) >= 0)
301 return &toElement(node); 302 return &toElement(node);
302 } 303 }
303 } else { 304 } else {
304 // First try to find a node with the same tabindex as start that com es after start in the scope. 305 // First try to find a node with the same tabindex as start that com es after start in the scope.
305 if (Element* winner = findElementWithExactTabIndex(NodeTraversal::ne xt(*start), tabIndex, WebFocusTypeForward)) 306 if (Element* winner = findElementWithExactTabIndex(ElementTraversal: :next(*start), tabIndex, WebFocusTypeForward))
306 return winner; 307 return winner;
307 } 308 }
308 if (!tabIndex) { 309 if (!tabIndex) {
309 // We've reached the last node in the document with a tabindex of 0. This is the end of the tabbing order. 310 // We've reached the last node in the document with a tabindex of 0. This is the end of the tabbing order.
310 return nullptr; 311 return nullptr;
311 } 312 }
312 } 313 }
313 314
314 // Look for the first node in the scope that: 315 // Look for the first node in the scope that:
315 // 1) has the lowest tabindex that is higher than start's tabindex (or 0, if start is null), and 316 // 1) has the lowest tabindex that is higher than start's tabindex (or 0, if start is null), and
(...skipping 11 matching lines...) Expand all
327 Node* last = nullptr; 328 Node* last = nullptr;
328 for (Node* node = scope.rootNode(); node; node = node->lastChild()) 329 for (Node* node = scope.rootNode(); node; node = node->lastChild())
329 last = node; 330 last = node;
330 ASSERT(last); 331 ASSERT(last);
331 332
332 // First try to find the last node in the scope that comes before start and has the same tabindex as start. 333 // First try to find the last node in the scope that comes before start and has the same tabindex as start.
333 // If start is null, find the last node in the scope with a tabindex of 0. 334 // If start is null, find the last node in the scope with a tabindex of 0.
334 Node* startingNode; 335 Node* startingNode;
335 int startingTabIndex; 336 int startingTabIndex;
336 if (start) { 337 if (start) {
337 startingNode = NodeTraversal::previous(*start); 338 startingNode = ElementTraversal::previous(*start);
338 startingTabIndex = adjustedTabIndex(*start); 339 startingTabIndex = adjustedTabIndex(*start);
339 } else { 340 } else {
340 startingNode = last; 341 startingNode = last;
341 startingTabIndex = 0; 342 startingTabIndex = 0;
342 } 343 }
343 344
344 // However, if a node is excluded from the normal tabbing cycle, the previou s focusable node is determined by tree order 345 // However, if a node is excluded from the normal tabbing cycle, the previou s focusable node is determined by tree order
345 if (startingTabIndex < 0) { 346 if (startingTabIndex < 0) {
346 for (Node* node = startingNode; node; node = NodeTraversal::previous(*no de)) { 347 for (Node* node = startingNode; node; node = ElementTraversal::previous( *node)) {
347 if (shouldVisit(*node) && adjustedTabIndex(*node) >= 0) 348 if (shouldVisit(*node) && adjustedTabIndex(*node) >= 0)
348 return toElement(node); 349 return toElement(node);
349 } 350 }
350 } else { 351 } else {
351 if (Element* winner = findElementWithExactTabIndex(startingNode, startin gTabIndex, WebFocusTypeBackward)) 352 if (Element* winner = findElementWithExactTabIndex(startingNode, startin gTabIndex, WebFocusTypeBackward))
352 return winner; 353 return winner;
353 } 354 }
354 355
355 // There are no nodes before start with the same tabindex as start, so look for a node that: 356 // There are no nodes before start with the same tabindex as start, so look for a node that:
356 // 1) has the highest non-zero tabindex (that is less than start's tabindex) , and 357 // 1) has the highest non-zero tabindex (that is less than start's tabindex) , and
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
466 ASSERT(element != foundElement); 467 ASSERT(element != foundElement);
467 element = foundElement; 468 element = foundElement;
468 } 469 }
469 return element; 470 return element;
470 } 471 }
471 472
472 Element* findFocusableElementAcrossFocusScopesForward(const FocusNavigationScope & scope, Node* currentNode) 473 Element* findFocusableElementAcrossFocusScopesForward(const FocusNavigationScope & scope, Node* currentNode)
473 { 474 {
474 ASSERT(!currentNode || !isNonFocusableShadowHost(*currentNode)); 475 ASSERT(!currentNode || !isNonFocusableShadowHost(*currentNode));
475 Element* found; 476 Element* found;
476 if (currentNode && isShadowHostWithoutCustomFocusLogic(*currentNode)) { 477 if (currentNode && currentNode->isElementNode() && isShadowHostWithoutCustom FocusLogic(*toElement(currentNode))) {
477 FocusNavigationScope innerScope = FocusNavigationScope::ownedByShadowHos t(*toElement(currentNode)); 478 FocusNavigationScope innerScope = FocusNavigationScope::ownedByShadowHos t(*toElement(currentNode));
478 Element* foundInInnerFocusScope = findFocusableElementRecursivelyForward (innerScope, nullptr); 479 Element* foundInInnerFocusScope = findFocusableElementRecursivelyForward (innerScope, nullptr);
479 found = foundInInnerFocusScope ? foundInInnerFocusScope : findFocusableE lementRecursivelyForward(scope, currentNode); 480 found = foundInInnerFocusScope ? foundInInnerFocusScope : findFocusableE lementRecursivelyForward(scope, currentNode);
480 } else { 481 } else {
481 found = findFocusableElementRecursivelyForward(scope, currentNode); 482 found = findFocusableElementRecursivelyForward(scope, currentNode);
482 } 483 }
483 484
484 // If there's no focusable node to advance to, move up the focus scopes unti l we find one. 485 // If there's no focusable node to advance to, move up the focus scopes unti l we find one.
485 FocusNavigationScope currentScope = scope; 486 FocusNavigationScope currentScope = scope;
486 while (!found) { 487 while (!found) {
(...skipping 549 matching lines...) Expand 10 before | Expand all | Expand 10 after
1036 return consumed; 1037 return consumed;
1037 } 1038 }
1038 1039
1039 DEFINE_TRACE(FocusController) 1040 DEFINE_TRACE(FocusController)
1040 { 1041 {
1041 visitor->trace(m_page); 1042 visitor->trace(m_page);
1042 visitor->trace(m_focusedFrame); 1043 visitor->trace(m_focusedFrame);
1043 } 1044 }
1044 1045
1045 } // namespace blink 1046 } // namespace blink
OLDNEW
« 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