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

Side by Side 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: use ElementTraversal::lastWithin 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 unified diff | Download patch
« 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 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
65 namespace { 65 namespace {
66 66
67 inline bool isShadowInsertionPointFocusScopeOwner(Element& element) 67 inline bool isShadowInsertionPointFocusScopeOwner(Element& element)
68 { 68 {
69 return isActiveShadowInsertionPoint(element) && toHTMLShadowElement(element) .olderShadowRoot(); 69 return isActiveShadowInsertionPoint(element) && toHTMLShadowElement(element) .olderShadowRoot();
70 } 70 }
71 71
72 class FocusNavigationScope { 72 class FocusNavigationScope {
73 STACK_ALLOCATED(); 73 STACK_ALLOCATED();
74 public: 74 public:
75 Node* rootNode() const; 75 Element* firstElement() const;
76 Element* lastElement() const;
76 Element* owner() const; 77 Element* owner() const;
77 static FocusNavigationScope focusNavigationScopeOf(const Element&); 78 static FocusNavigationScope focusNavigationScopeOf(const Element&);
78 static FocusNavigationScope ownedByNonFocusableFocusScopeOwner(Element&); 79 static FocusNavigationScope ownedByNonFocusableFocusScopeOwner(Element&);
79 static FocusNavigationScope ownedByShadowHost(const Element&); 80 static FocusNavigationScope ownedByShadowHost(const Element&);
80 static FocusNavigationScope ownedByShadowInsertionPoint(HTMLShadowElement&); 81 static FocusNavigationScope ownedByShadowInsertionPoint(HTMLShadowElement&);
81 static FocusNavigationScope ownedByIFrame(const HTMLFrameOwnerElement&); 82 static FocusNavigationScope ownedByIFrame(const HTMLFrameOwnerElement&);
82 83
83 private: 84 private:
84 explicit FocusNavigationScope(TreeScope*); 85 explicit FocusNavigationScope(TreeScope*);
86 ContainerNode& rootNode() const;
85 RawPtrWillBeMember<TreeScope> m_rootTreeScope; 87 RawPtrWillBeMember<TreeScope> m_rootTreeScope;
86 }; 88 };
87 89
88 FocusNavigationScope::FocusNavigationScope(TreeScope* treeScope) 90 FocusNavigationScope::FocusNavigationScope(TreeScope* treeScope)
89 : m_rootTreeScope(treeScope) 91 : m_rootTreeScope(treeScope)
90 { 92 {
91 ASSERT(treeScope); 93 ASSERT(treeScope);
92 } 94 }
93 95
94 Node* FocusNavigationScope::rootNode() const 96 ContainerNode& FocusNavigationScope::rootNode() const
95 { 97 {
96 return &m_rootTreeScope->rootNode(); 98 return m_rootTreeScope->rootNode();
99 }
100
101 Element* FocusNavigationScope::firstElement() const
102 {
103 ContainerNode& root = m_rootTreeScope->rootNode();
kochi 2016/02/19 08:21:39 nit: |m_rootTreeScope->| can be omitted.
hayato 2016/02/19 08:25:55 Done.
104 return root.isElementNode() ? &toElement(root) : ElementTraversal::next(root );
105 }
106
107 Element* FocusNavigationScope::lastElement() const
108 {
109 return ElementTraversal::lastWithin(rootNode());
97 } 110 }
98 111
99 Element* FocusNavigationScope::owner() const 112 Element* FocusNavigationScope::owner() const
100 { 113 {
101 Node* root = rootNode(); 114 ContainerNode& root = rootNode();
102 if (root->isShadowRoot()) { 115 if (root.isShadowRoot()) {
103 ShadowRoot* shadowRoot = toShadowRoot(root); 116 ShadowRoot& shadowRoot = toShadowRoot(root);
104 return shadowRoot->isYoungest() ? shadowRoot->host() : shadowRoot->shado wInsertionPointOfYoungerShadowRoot(); 117 return shadowRoot.isYoungest() ? shadowRoot.host() : shadowRoot.shadowIn sertionPointOfYoungerShadowRoot();
105 } 118 }
106 // FIXME: Figure out the right thing for OOPI here. 119 // FIXME: Figure out the right thing for OOPI here.
107 if (Frame* frame = root->document().frame()) 120 if (Frame* frame = root.document().frame())
108 return frame->deprecatedLocalOwner(); 121 return frame->deprecatedLocalOwner();
109 return nullptr; 122 return nullptr;
110 } 123 }
111 124
112 FocusNavigationScope FocusNavigationScope::focusNavigationScopeOf(const Element& element) 125 FocusNavigationScope FocusNavigationScope::focusNavigationScopeOf(const Element& element)
113 { 126 {
114 return FocusNavigationScope(&element.treeScope()); 127 return FocusNavigationScope(&element.treeScope());
115 } 128 }
116 129
117 FocusNavigationScope FocusNavigationScope::ownedByNonFocusableFocusScopeOwner(El ement& element) 130 FocusNavigationScope FocusNavigationScope::ownedByNonFocusableFocusScopeOwner(El ement& element)
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
196 { 209 {
197 return element.isHTMLElement() && toHTMLElement(element).hasCustomFocusLogic (); 210 return element.isHTMLElement() && toHTMLElement(element).hasCustomFocusLogic ();
198 } 211 }
199 212
200 inline bool isShadowHostWithoutCustomFocusLogic(const Element& element) 213 inline bool isShadowHostWithoutCustomFocusLogic(const Element& element)
201 { 214 {
202 return isShadowHost(element) && !hasCustomFocusLogic(element); 215 return isShadowHost(element) && !hasCustomFocusLogic(element);
203 } 216 }
204 217
205 #if ENABLE(ASSERT) 218 #if ENABLE(ASSERT)
206 inline bool isNonFocusableShadowHost(const Node& node) 219 inline bool isNonFocusableShadowHost(const Element& element)
207 { 220 {
208 if (!node.isElementNode())
209 return false;
210 const Element& element = toElement(node);
211 return isShadowHostWithoutCustomFocusLogic(element) && !element.isFocusable( ); 221 return isShadowHostWithoutCustomFocusLogic(element) && !element.isFocusable( );
212 } 222 }
213 #endif 223 #endif
214 224
215 inline bool isNonKeyboardFocusableShadowHost(const Element& element) 225 inline bool isNonKeyboardFocusableShadowHost(const Element& element)
216 { 226 {
217 return isShadowHostWithoutCustomFocusLogic(element) && !element.isKeyboardFo cusable(); 227 return isShadowHostWithoutCustomFocusLogic(element) && !element.isKeyboardFo cusable();
218 } 228 }
219 229
220 inline bool isKeyboardFocusableShadowHost(const Element& element) 230 inline bool isKeyboardFocusableShadowHost(const Element& element)
221 { 231 {
222 return isShadowHostWithoutCustomFocusLogic(element) && element.isKeyboardFoc usable(); 232 return isShadowHostWithoutCustomFocusLogic(element) && element.isKeyboardFoc usable();
223 } 233 }
224 234
225 inline bool isNonFocusableFocusScopeOwner(Element& element) 235 inline bool isNonFocusableFocusScopeOwner(Element& element)
226 { 236 {
227 return isNonKeyboardFocusableShadowHost(element) || isShadowInsertionPointFo cusScopeOwner(element); 237 return isNonKeyboardFocusableShadowHost(element) || isShadowInsertionPointFo cusScopeOwner(element);
228 } 238 }
229 239
230 inline bool isShadowHostDelegatesFocus(const Element& element) 240 inline bool isShadowHostDelegatesFocus(const Element& element)
231 { 241 {
232 return element.authorShadowRoot() && element.authorShadowRoot()->delegatesFo cus(); 242 return element.authorShadowRoot() && element.authorShadowRoot()->delegatesFo cus();
233 } 243 }
234 244
235 inline int adjustedTabIndex(Node& node) 245 inline int adjustedTabIndex(Element& element)
236 { 246 {
237 return node.isElementNode() && isNonFocusableFocusScopeOwner(toElement(node) ) ? 0 : node.tabIndex(); 247 return isNonFocusableFocusScopeOwner(element) ? 0 : element.tabIndex();
238 } 248 }
239 249
240 inline bool shouldVisit(Node& node) 250 inline bool shouldVisit(Element& element)
241 { 251 {
242 if (!node.isElementNode())
243 return false;
244 Element& element = toElement(node);
245 return element.isKeyboardFocusable() || isNonFocusableFocusScopeOwner(elemen t); 252 return element.isKeyboardFocusable() || isNonFocusableFocusScopeOwner(elemen t);
246 } 253 }
247 254
248 Element* findElementWithExactTabIndex(Node* start, int tabIndex, WebFocusType ty pe) 255 Element* findElementWithExactTabIndex(Element* start, int tabIndex, WebFocusType type)
249 { 256 {
250 // Search is inclusive of start 257 // Search is inclusive of start
251 for (Node* node = start; node; node = type == WebFocusTypeForward ? ElementT raversal::next(*node) : ElementTraversal::previous(*node)) { 258 for (Element* element = start; element; element = type == WebFocusTypeForwar d ? ElementTraversal::next(*element) : ElementTraversal::previous(*element)) {
252 if (shouldVisit(*node) && adjustedTabIndex(*node) == tabIndex) 259 if (shouldVisit(*element) && adjustedTabIndex(*element) == tabIndex)
253 return toElement(node); 260 return element;
254 } 261 }
255 return nullptr; 262 return nullptr;
256 } 263 }
257 264
258 Element* nextElementWithGreaterTabIndex(Node* start, int tabIndex) 265 Element* nextElementWithGreaterTabIndex(Element* start, int tabIndex)
259 { 266 {
260 // Search is inclusive of start 267 // Search is inclusive of start
261 int winningTabIndex = std::numeric_limits<short>::max() + 1; 268 int winningTabIndex = std::numeric_limits<short>::max() + 1;
262 Node* winner = nullptr; 269 Element* winner = nullptr;
263 for (Node& node : NodeTraversal::startsAt(start)) { 270 for (Element& element : ElementTraversal::startsAt(start)) {
264 int currentTabIndex = adjustedTabIndex(node); 271 int currentTabIndex = adjustedTabIndex(element);
265 if (shouldVisit(node) && currentTabIndex > tabIndex && currentTabIndex < winningTabIndex) { 272 if (shouldVisit(element) && currentTabIndex > tabIndex && currentTabInde x < winningTabIndex) {
266 winner = &node; 273 winner = &element;
267 winningTabIndex = currentTabIndex; 274 winningTabIndex = currentTabIndex;
268 } 275 }
269 } 276 }
270 ASSERT(!winner || winner->isElementNode()); 277 return winner;
271 return toElement(winner);
272 } 278 }
273 279
274 Element* previousElementWithLowerTabIndex(Node* start, int tabIndex) 280 Element* previousElementWithLowerTabIndex(Element* start, int tabIndex)
275 { 281 {
276 // Search is inclusive of start 282 // Search is inclusive of start
277 int winningTabIndex = 0; 283 int winningTabIndex = 0;
278 Node* winner = nullptr; 284 Element* winner = nullptr;
279 for (Node* node = start; node; node = ElementTraversal::previous(*node)) { 285 for (Element* element = start; element; element = ElementTraversal::previous (*element)) {
280 int currentTabIndex = adjustedTabIndex(*node); 286 int currentTabIndex = adjustedTabIndex(*element);
281 if (shouldVisit(*node) && currentTabIndex < tabIndex && currentTabIndex > winningTabIndex) { 287 if (shouldVisit(*element) && currentTabIndex < tabIndex && currentTabInd ex > winningTabIndex) {
282 winner = node; 288 winner = element;
283 winningTabIndex = currentTabIndex; 289 winningTabIndex = currentTabIndex;
284 } 290 }
285 } 291 }
286 ASSERT(!winner || winner->isElementNode()); 292 return winner;
287 return toElement(winner);
288 } 293 }
289 294
290 Element* nextFocusableElement(const FocusNavigationScope& scope, Node* start) 295 Element* nextFocusableElement(const FocusNavigationScope& scope, Element* start)
291 { 296 {
292 if (start) { 297 if (start) {
293 int tabIndex = adjustedTabIndex(*start); 298 int tabIndex = adjustedTabIndex(*start);
294 // If a node is excluded from the normal tabbing cycle, the next focusab le node is determined by tree order 299 // If an element is excluded from the normal tabbing cycle, the next foc usable element is determined by tree order
295 if (tabIndex < 0) { 300 if (tabIndex < 0) {
296 for (Node& node : NodeTraversal::startsAfter(*start)) { 301 for (Element& element : ElementTraversal::startsAfter(*start)) {
297 if (shouldVisit(node) && adjustedTabIndex(node) >= 0) 302 if (shouldVisit(element) && adjustedTabIndex(element) >= 0)
298 return &toElement(node); 303 return &element;
299 } 304 }
300 } else { 305 } else {
301 // First try to find a node with the same tabindex as start that com es after start in the scope. 306 // First try to find an element with the same tabindex as start that comes after start in the scope.
302 if (Element* winner = findElementWithExactTabIndex(ElementTraversal: :next(*start), tabIndex, WebFocusTypeForward)) 307 if (Element* winner = findElementWithExactTabIndex(ElementTraversal: :next(*start), tabIndex, WebFocusTypeForward))
303 return winner; 308 return winner;
304 } 309 }
305 if (!tabIndex) { 310 if (!tabIndex) {
306 // We've reached the last node in the document with a tabindex of 0. This is the end of the tabbing order. 311 // We've reached the last element in the document with a tabindex of 0. This is the end of the tabbing order.
307 return nullptr; 312 return nullptr;
308 } 313 }
309 } 314 }
310 315
311 // Look for the first node in the scope that: 316 // Look for the first element in the scope that:
312 // 1) has the lowest tabindex that is higher than start's tabindex (or 0, if start is null), and 317 // 1) has the lowest tabindex that is higher than start's tabindex (or 0, if start is null), and
313 // 2) comes first in the scope, if there's a tie. 318 // 2) comes first in the scope, if there's a tie.
314 if (Element* winner = nextElementWithGreaterTabIndex(scope.rootNode(), start ? adjustedTabIndex(*start) : 0)) 319 if (Element* winner = nextElementWithGreaterTabIndex(scope.firstElement(), s tart ? adjustedTabIndex(*start) : 0))
315 return winner; 320 return winner;
316 321
317 // There are no nodes with a tabindex greater than start's tabindex, 322 // There are no elements with a tabindex greater than start's tabindex,
318 // so find the first node with a tabindex of 0. 323 // so find the first element with a tabindex of 0.
319 return findElementWithExactTabIndex(scope.rootNode(), 0, WebFocusTypeForward ); 324 return findElementWithExactTabIndex(scope.firstElement(), 0, WebFocusTypeFor ward);
320 } 325 }
321 326
322 Element* previousFocusableElement(const FocusNavigationScope& scope, Node* start ) 327 Element* previousFocusableElement(const FocusNavigationScope& scope, Element* st art)
323 { 328 {
324 Node* last = nullptr; 329 Element* lastElement = scope.lastElement();
325 for (Node* node = scope.rootNode(); node; node = node->lastChild())
326 last = node;
327 ASSERT(last);
328 330
329 // First try to find the last node in the scope that comes before start and has the same tabindex as start. 331 // First try to find the last element in the scope that comes before start a nd has the same tabindex as start.
330 // If start is null, find the last node in the scope with a tabindex of 0. 332 // If start is null, find the last element in the scope with a tabindex of 0 .
331 Node* startingNode; 333 Element* startElement;
332 int startingTabIndex; 334 int startTabIndex;
333 if (start) { 335 if (start) {
334 startingNode = ElementTraversal::previous(*start); 336 startElement = ElementTraversal::previous(*start);
335 startingTabIndex = adjustedTabIndex(*start); 337 startTabIndex = adjustedTabIndex(*start);
336 } else { 338 } else {
337 startingNode = last; 339 startElement = lastElement;
338 startingTabIndex = 0; 340 startTabIndex = 0;
339 } 341 }
340 342
341 // However, if a node is excluded from the normal tabbing cycle, the previou s focusable node is determined by tree order 343 // However, if an element is excluded from the normal tabbing cycle, the pre vious focusable element is determined by tree order
342 if (startingTabIndex < 0) { 344 if (startTabIndex < 0) {
343 for (Node* node = startingNode; node; node = ElementTraversal::previous( *node)) { 345 for (Element* element = startElement; element; element = ElementTraversa l::previous(*element)) {
344 if (shouldVisit(*node) && adjustedTabIndex(*node) >= 0) 346 if (shouldVisit(*element) && adjustedTabIndex(*element) >= 0)
345 return toElement(node); 347 return element;
346 } 348 }
347 } else { 349 } else {
348 if (Element* winner = findElementWithExactTabIndex(startingNode, startin gTabIndex, WebFocusTypeBackward)) 350 if (Element* winner = findElementWithExactTabIndex(startElement, startTa bIndex, WebFocusTypeBackward))
349 return winner; 351 return winner;
350 } 352 }
351 353
352 // There are no nodes before start with the same tabindex as start, so look for a node that: 354 // There are no elements before start with the same tabindex as start, so lo ok for an element that:
353 // 1) has the highest non-zero tabindex (that is less than start's tabindex) , and 355 // 1) has the highest non-zero tabindex (that is less than start's tabindex) , and
354 // 2) comes last in the scope, if there's a tie. 356 // 2) comes last in the scope, if there's a tie.
355 startingTabIndex = (start && startingTabIndex) ? startingTabIndex : std::num eric_limits<short>::max(); 357 startTabIndex = (start && startTabIndex) ? startTabIndex : std::numeric_limi ts<short>::max();
356 return previousElementWithLowerTabIndex(last, startingTabIndex); 358 return previousElementWithLowerTabIndex(lastElement, startTabIndex);
357 } 359 }
358 360
359 // Searches through the given tree scope, starting from start node, for the next /previous 361 // Searches through the given tree scope, starting from start element, for the n ext/previous
360 // selectable element that comes after/before start node. 362 // selectable element that comes after/before start element.
361 // The order followed is as specified in the HTML spec[1], which is elements wit h tab indexes 363 // The order followed is as specified in the HTML spec[1], which is elements wit h tab indexes
362 // first (from lowest to highest), and then elements without tab indexes (in doc ument order). 364 // first (from lowest to highest), and then elements without tab indexes (in doc ument order).
363 // The search algorithm also conforms the Shadow DOM spec[2], which inserts sequ ence in a shadow 365 // The search algorithm also conforms the Shadow DOM spec[2], which inserts sequ ence in a shadow
364 // tree into its host. 366 // tree into its host.
365 // 367 //
366 // @param start The node from which to start searching. The node after this will be focused. 368 // @param start The element from which to start searching. The element after thi s will be focused.
367 // May be null. 369 // May be null.
368 // @return The focus element that comes after/before start node. 370 // @return The focus element that comes after/before start element.
369 // 371 //
370 // [1] https://html.spec.whatwg.org/multipage/interaction.html#sequential-focus- navigation 372 // [1] https://html.spec.whatwg.org/multipage/interaction.html#sequential-focus- navigation
371 // [2] https://w3c.github.io/webcomponents/spec/shadow/#focus-navigation 373 // [2] https://w3c.github.io/webcomponents/spec/shadow/#focus-navigation
372 inline Element* findFocusableElementInternal(WebFocusType type, const FocusNavig ationScope& scope, Node* node) 374 inline Element* findFocusableElementInternal(WebFocusType type, const FocusNavig ationScope& scope, Element* element)
373 { 375 {
374 Element* found = (type == WebFocusTypeForward) ? nextFocusableElement(scope, node) : previousFocusableElement(scope, node); 376 Element* found = (type == WebFocusTypeForward) ? nextFocusableElement(scope, element) : previousFocusableElement(scope, element);
375 return found; 377 return found;
376 } 378 }
377 379
378 Element* findFocusableElementRecursivelyForward(const FocusNavigationScope& scop e, Node* start) 380 Element* findFocusableElementRecursivelyForward(const FocusNavigationScope& scop e, Element* start)
379 { 381 {
380 // Starting node is exclusive. 382 // Starting element is exclusive.
381 Element* found = findFocusableElementInternal(WebFocusTypeForward, scope, st art); 383 Element* found = findFocusableElementInternal(WebFocusTypeForward, scope, st art);
382 while (found) { 384 while (found) {
383 if (isShadowHostDelegatesFocus(*found)) { 385 if (isShadowHostDelegatesFocus(*found)) {
384 // If tabindex is positive, find focusable node inside its shadow tr ee. 386 // If tabindex is positive, find focusable element inside its shadow tree.
385 if (found->tabIndex() >= 0 && isShadowHostWithoutCustomFocusLogic(*f ound)) { 387 if (found->tabIndex() >= 0 && isShadowHostWithoutCustomFocusLogic(*f ound)) {
386 FocusNavigationScope innerScope = FocusNavigationScope::ownedByS hadowHost(*found); 388 FocusNavigationScope innerScope = FocusNavigationScope::ownedByS hadowHost(*found);
387 if (Element* foundInInnerFocusScope = findFocusableElementRecurs ivelyForward(innerScope, nullptr)) 389 if (Element* foundInInnerFocusScope = findFocusableElementRecurs ivelyForward(innerScope, nullptr))
388 return foundInInnerFocusScope; 390 return foundInInnerFocusScope;
389 } 391 }
390 // Skip to the next node in the same scope. 392 // Skip to the next element in the same scope.
391 found = findFocusableElementInternal(WebFocusTypeForward, scope, fou nd); 393 found = findFocusableElementInternal(WebFocusTypeForward, scope, fou nd);
392 continue; 394 continue;
393 } 395 }
394 if (!isNonFocusableFocusScopeOwner(*found)) 396 if (!isNonFocusableFocusScopeOwner(*found))
395 return found; 397 return found;
396 398
397 // Now |found| is on a non focusable scope owner (either shadow host or <shadow>) 399 // Now |found| is on a non focusable scope owner (either shadow host or <shadow>)
398 // Find inside the inward scope and return it if found. Otherwise contin ue searching in the same 400 // Find inside the inward scope and return it if found. Otherwise contin ue searching in the same
399 // scope. 401 // scope.
400 FocusNavigationScope innerScope = FocusNavigationScope::ownedByNonFocusa bleFocusScopeOwner(*found); 402 FocusNavigationScope innerScope = FocusNavigationScope::ownedByNonFocusa bleFocusScopeOwner(*found);
401 if (Element* foundInInnerFocusScope = findFocusableElementRecursivelyFor ward(innerScope, nullptr)) 403 if (Element* foundInInnerFocusScope = findFocusableElementRecursivelyFor ward(innerScope, nullptr))
402 return foundInInnerFocusScope; 404 return foundInInnerFocusScope;
403 405
404 found = findFocusableElementInternal(WebFocusTypeForward, scope, found); 406 found = findFocusableElementInternal(WebFocusTypeForward, scope, found);
405 } 407 }
406 return nullptr; 408 return nullptr;
407 } 409 }
408 410
409 Element* findFocusableElementRecursivelyBackward(const FocusNavigationScope& sco pe, Node* start) 411 Element* findFocusableElementRecursivelyBackward(const FocusNavigationScope& sco pe, Element* start)
410 { 412 {
411 // Starting node is exclusive. 413 // Starting element is exclusive.
412 Element* found = findFocusableElementInternal(WebFocusTypeBackward, scope, s tart); 414 Element* found = findFocusableElementInternal(WebFocusTypeBackward, scope, s tart);
413 while (found) { 415 while (found) {
414 // Now |found| is on a focusable shadow host. 416 // Now |found| is on a focusable shadow host.
415 // Find inside shadow backwards. If any focusable element is found, retu rn it, otherwise return 417 // Find inside shadow backwards. If any focusable element is found, retu rn it, otherwise return
416 // the host itself. 418 // the host itself.
417 if (isKeyboardFocusableShadowHost(*found)) { 419 if (isKeyboardFocusableShadowHost(*found)) {
418 FocusNavigationScope innerScope = FocusNavigationScope::ownedByShado wHost(*found); 420 FocusNavigationScope innerScope = FocusNavigationScope::ownedByShado wHost(*found);
419 Element* foundInInnerFocusScope = findFocusableElementRecursivelyBac kward(innerScope, nullptr); 421 Element* foundInInnerFocusScope = findFocusableElementRecursivelyBac kward(innerScope, nullptr);
420 if (foundInInnerFocusScope) 422 if (foundInInnerFocusScope)
421 return foundInInnerFocusScope; 423 return foundInInnerFocusScope;
422 if (isShadowHostDelegatesFocus(*found)) { 424 if (isShadowHostDelegatesFocus(*found)) {
423 found = findFocusableElementInternal(WebFocusTypeBackward, scope , found); 425 found = findFocusableElementInternal(WebFocusTypeBackward, scope , found);
424 continue; 426 continue;
425 } 427 }
426 return found; 428 return found;
427 } 429 }
428 430
429 // If delegatesFocus is true and tabindex is negative, skip the whole sh adow tree under the 431 // If delegatesFocus is true and tabindex is negative, skip the whole sh adow tree under the
430 // shadow host. 432 // shadow host.
431 if (isShadowHostDelegatesFocus(*found) && found->tabIndex() < 0) { 433 if (isShadowHostDelegatesFocus(*found) && found->tabIndex() < 0) {
432 found = findFocusableElementInternal(WebFocusTypeBackward, scope, fo und); 434 found = findFocusableElementInternal(WebFocusTypeBackward, scope, fo und);
433 continue; 435 continue;
434 } 436 }
435 437
436 // Now |found| is on a non focusable scope owner (either shadow host or <shadow>). 438 // Now |found| is on a non focusable scope owner (either shadow host or <shadow>).
437 // Find focusable node in descendant scope. If not found, find next focu sable node within the 439 // Find focusable element in descendant scope. If not found, find next f ocusable element within the
438 // current scope. 440 // current scope.
439 if (isNonFocusableFocusScopeOwner(*found)) { 441 if (isNonFocusableFocusScopeOwner(*found)) {
440 FocusNavigationScope innerScope = FocusNavigationScope::ownedByNonFo cusableFocusScopeOwner(*found); 442 FocusNavigationScope innerScope = FocusNavigationScope::ownedByNonFo cusableFocusScopeOwner(*found);
441 Element* foundInInnerFocusScope = findFocusableElementRecursivelyBac kward(innerScope, nullptr); 443 Element* foundInInnerFocusScope = findFocusableElementRecursivelyBac kward(innerScope, nullptr);
442 if (foundInInnerFocusScope) 444 if (foundInInnerFocusScope)
443 return foundInInnerFocusScope; 445 return foundInInnerFocusScope;
444 found = findFocusableElementInternal(WebFocusTypeBackward, scope, fo und); 446 found = findFocusableElementInternal(WebFocusTypeBackward, scope, fo und);
445 continue; 447 continue;
446 } 448 }
447 if (!isShadowHostDelegatesFocus(*found)) 449 if (!isShadowHostDelegatesFocus(*found))
448 return found; 450 return found;
449 found = findFocusableElementInternal(WebFocusTypeBackward, scope, found) ; 451 found = findFocusableElementInternal(WebFocusTypeBackward, scope, found) ;
450 } 452 }
451 return nullptr; 453 return nullptr;
452 } 454 }
453 455
454 Element* findFocusableElementRecursively(WebFocusType type, const FocusNavigatio nScope& scope, Node* start) 456 Element* findFocusableElementRecursively(WebFocusType type, const FocusNavigatio nScope& scope, Element* start)
455 { 457 {
456 return (type == WebFocusTypeForward) ? 458 return (type == WebFocusTypeForward) ?
457 findFocusableElementRecursivelyForward(scope, start) : 459 findFocusableElementRecursivelyForward(scope, start) :
458 findFocusableElementRecursivelyBackward(scope, start); 460 findFocusableElementRecursivelyBackward(scope, start);
459 } 461 }
460 462
461 Element* findFocusableElementDescendingDownIntoFrameDocument(WebFocusType type, Element* element) 463 Element* findFocusableElementDescendingDownIntoFrameDocument(WebFocusType type, Element* element)
462 { 464 {
463 // The element we found might be a HTMLFrameOwnerElement, so descend down th e tree until we find either: 465 // The element we found might be a HTMLFrameOwnerElement, so descend down th e tree until we find either:
464 // 1) a focusable element, or 466 // 1) a focusable element, or
465 // 2) the deepest-nested HTMLFrameOwnerElement. 467 // 2) the deepest-nested HTMLFrameOwnerElement.
466 while (element && element->isFrameOwnerElement()) { 468 while (element && element->isFrameOwnerElement()) {
467 HTMLFrameOwnerElement& owner = toHTMLFrameOwnerElement(*element); 469 HTMLFrameOwnerElement& owner = toHTMLFrameOwnerElement(*element);
468 if (!owner.contentFrame() || !owner.contentFrame()->isLocalFrame()) 470 if (!owner.contentFrame() || !owner.contentFrame()->isLocalFrame())
469 break; 471 break;
470 toLocalFrame(owner.contentFrame())->document()->updateLayoutIgnorePendin gStylesheets(); 472 toLocalFrame(owner.contentFrame())->document()->updateLayoutIgnorePendin gStylesheets();
471 Element* foundElement = findFocusableElementRecursively(type, FocusNavig ationScope::ownedByIFrame(owner), nullptr); 473 Element* foundElement = findFocusableElementRecursively(type, FocusNavig ationScope::ownedByIFrame(owner), nullptr);
472 if (!foundElement) 474 if (!foundElement)
473 break; 475 break;
474 ASSERT(element != foundElement); 476 ASSERT(element != foundElement);
475 element = foundElement; 477 element = foundElement;
476 } 478 }
477 return element; 479 return element;
478 } 480 }
479 481
480 Element* findFocusableElementAcrossFocusScopesForward(const FocusNavigationScope & scope, Node* currentNode) 482 Element* findFocusableElementAcrossFocusScopesForward(const FocusNavigationScope & scope, Element* current)
481 { 483 {
482 ASSERT(!currentNode || !isNonFocusableShadowHost(*currentNode)); 484 ASSERT(!current || !isNonFocusableShadowHost(*current));
483 Element* found; 485 Element* found;
484 if (currentNode && currentNode->isElementNode() && isShadowHostWithoutCustom FocusLogic(*toElement(currentNode))) { 486 if (current && isShadowHostWithoutCustomFocusLogic(*current)) {
485 FocusNavigationScope innerScope = FocusNavigationScope::ownedByShadowHos t(*toElement(currentNode)); 487 FocusNavigationScope innerScope = FocusNavigationScope::ownedByShadowHos t(*current);
486 Element* foundInInnerFocusScope = findFocusableElementRecursivelyForward (innerScope, nullptr); 488 Element* foundInInnerFocusScope = findFocusableElementRecursivelyForward (innerScope, nullptr);
487 found = foundInInnerFocusScope ? foundInInnerFocusScope : findFocusableE lementRecursivelyForward(scope, currentNode); 489 found = foundInInnerFocusScope ? foundInInnerFocusScope : findFocusableE lementRecursivelyForward(scope, current);
488 } else { 490 } else {
489 found = findFocusableElementRecursivelyForward(scope, currentNode); 491 found = findFocusableElementRecursivelyForward(scope, current);
490 } 492 }
491 493
492 // If there's no focusable node to advance to, move up the focus scopes unti l we find one. 494 // If there's no focusable element to advance to, move up the focus scopes u ntil we find one.
493 FocusNavigationScope currentScope = scope; 495 FocusNavigationScope currentScope = scope;
494 while (!found) { 496 while (!found) {
495 Element* owner = currentScope.owner(); 497 Element* owner = currentScope.owner();
496 if (!owner) 498 if (!owner)
497 break; 499 break;
498 currentScope = FocusNavigationScope::focusNavigationScopeOf(*owner); 500 currentScope = FocusNavigationScope::focusNavigationScopeOf(*owner);
499 found = findFocusableElementRecursivelyForward(currentScope, owner); 501 found = findFocusableElementRecursivelyForward(currentScope, owner);
500 } 502 }
501 return findFocusableElementDescendingDownIntoFrameDocument(WebFocusTypeForwa rd, found); 503 return findFocusableElementDescendingDownIntoFrameDocument(WebFocusTypeForwa rd, found);
502 } 504 }
503 505
504 Element* findFocusableElementAcrossFocusScopesBackward(const FocusNavigationScop e& scope, Node* currentNode) 506 Element* findFocusableElementAcrossFocusScopesBackward(const FocusNavigationScop e& scope, Element* current)
505 { 507 {
506 ASSERT(!currentNode || !isNonFocusableShadowHost(*currentNode)); 508 ASSERT(!current || !isNonFocusableShadowHost(*current));
507 Element* found = findFocusableElementRecursivelyBackward(scope, currentNode) ; 509 Element* found = findFocusableElementRecursivelyBackward(scope, current);
508 510
509 // If there's no focusable node to advance to, move up the focus scopes unti l we find one. 511 // If there's no focusable element to advance to, move up the focus scopes u ntil we find one.
510 FocusNavigationScope currentScope = scope; 512 FocusNavigationScope currentScope = scope;
511 while (!found) { 513 while (!found) {
512 Element* owner = currentScope.owner(); 514 Element* owner = currentScope.owner();
513 if (!owner) 515 if (!owner)
514 break; 516 break;
515 currentScope = FocusNavigationScope::focusNavigationScopeOf(*owner); 517 currentScope = FocusNavigationScope::focusNavigationScopeOf(*owner);
516 if (isKeyboardFocusableShadowHost(*owner) && !isShadowHostDelegatesFocus (*owner)) { 518 if (isKeyboardFocusableShadowHost(*owner) && !isShadowHostDelegatesFocus (*owner)) {
517 found = owner; 519 found = owner;
518 break; 520 break;
519 } 521 }
520 found = findFocusableElementRecursivelyBackward(currentScope, owner); 522 found = findFocusableElementRecursivelyBackward(currentScope, owner);
521 } 523 }
522 return findFocusableElementDescendingDownIntoFrameDocument(WebFocusTypeBackw ard, found); 524 return findFocusableElementDescendingDownIntoFrameDocument(WebFocusTypeBackw ard, found);
523 } 525 }
524 526
525 Element* findFocusableElementAcrossFocusScopes(WebFocusType type, const FocusNav igationScope& scope, Node* currentNode) 527 Element* findFocusableElementAcrossFocusScopes(WebFocusType type, const FocusNav igationScope& scope, Element* current)
526 { 528 {
527 return (type == WebFocusTypeForward) ? 529 return (type == WebFocusTypeForward) ?
528 findFocusableElementAcrossFocusScopesForward(scope, currentNode) : 530 findFocusableElementAcrossFocusScopesForward(scope, current) :
529 findFocusableElementAcrossFocusScopesBackward(scope, currentNode); 531 findFocusableElementAcrossFocusScopesBackward(scope, current);
530 } 532 }
531 533
532 inline Element* adjustToElement(Node* node, WebFocusType type) 534 inline Element* adjustToElement(Node* node, WebFocusType type)
533 { 535 {
534 ASSERT(type == WebFocusTypeForward || type == WebFocusTypeBackward); 536 ASSERT(type == WebFocusTypeForward || type == WebFocusTypeBackward);
535 if (!node) 537 if (!node)
536 return nullptr; 538 return nullptr;
537 if (node->isElementNode()) 539 if (node->isElementNode())
538 return toElement(node); 540 return toElement(node);
539 return (type == WebFocusTypeForward) ? ElementTraversal::next(*node) : Eleme ntTraversal::previous(*node); 541 return (type == WebFocusTypeForward) ? ElementTraversal::next(*node) : Eleme ntTraversal::previous(*node);
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after
774 element = findFocusableElementRecursively(type, FocusNavigationScope::fo cusNavigationScopeOf(*toLocalFrame(m_page->mainFrame())->document()->documentEle ment()), nullptr); 776 element = findFocusableElementRecursively(type, FocusNavigationScope::fo cusNavigationScopeOf(*toLocalFrame(m_page->mainFrame())->document()->documentEle ment()), nullptr);
775 element = findFocusableElementDescendingDownIntoFrameDocument(type, elem ent.get()); 777 element = findFocusableElementDescendingDownIntoFrameDocument(type, elem ent.get());
776 778
777 if (!element) 779 if (!element)
778 return false; 780 return false;
779 } 781 }
780 782
781 ASSERT(element); 783 ASSERT(element);
782 784
783 if (element == document->focusedElement()) { 785 if (element == document->focusedElement()) {
784 // Focus wrapped around to the same node. 786 // Focus wrapped around to the same element.
785 return true; 787 return true;
786 } 788 }
787 789
788 if (element->isFrameOwnerElement() && (!isHTMLPlugInElement(*element) || !el ement->isKeyboardFocusable())) { 790 if (element->isFrameOwnerElement() && (!isHTMLPlugInElement(*element) || !el ement->isKeyboardFocusable())) {
789 // We focus frames rather than frame owners. 791 // We focus frames rather than frame owners.
790 // FIXME: We should not focus frames that have no scrollbars, as focusin g them isn't useful to the user. 792 // FIXME: We should not focus frames that have no scrollbars, as focusin g them isn't useful to the user.
791 HTMLFrameOwnerElement* owner = toHTMLFrameOwnerElement(element); 793 HTMLFrameOwnerElement* owner = toHTMLFrameOwnerElement(element);
792 if (!owner->contentFrame()) 794 if (!owner->contentFrame())
793 return false; 795 return false;
794 796
795 document->clearFocusedElement(); 797 document->clearFocusedElement();
796 setFocusedFrame(owner->contentFrame()); 798 setFocusedFrame(owner->contentFrame());
797 799
798 // If contentFrame is remote, continue the search for focusable 800 // If contentFrame is remote, continue the search for focusable
799 // elements in that frame's process. 801 // elements in that frame's process.
800 // clearFocusedElement() fires events that might detach the 802 // clearFocusedElement() fires events that might detach the
801 // contentFrame, hence the need to null-check it again. 803 // contentFrame, hence the need to null-check it again.
802 if (owner->contentFrame() && owner->contentFrame()->isRemoteFrame()) 804 if (owner->contentFrame() && owner->contentFrame()->isRemoteFrame())
803 toRemoteFrame(owner->contentFrame())->advanceFocus(type, frame); 805 toRemoteFrame(owner->contentFrame())->advanceFocus(type, frame);
804 806
805 return true; 807 return true;
806 } 808 }
807 809
808 // FIXME: It would be nice to just be able to call setFocusedElement(node) 810 // FIXME: It would be nice to just be able to call setFocusedElement(element )
809 // here, but we can't do that because some elements (e.g. HTMLInputElement 811 // here, but we can't do that because some elements (e.g. HTMLInputElement
810 // and HTMLTextAreaElement) do extra work in their focus() methods. 812 // and HTMLTextAreaElement) do extra work in their focus() methods.
811 Document& newDocument = element->document(); 813 Document& newDocument = element->document();
812 814
813 if (&newDocument != document) { 815 if (&newDocument != document) {
814 // Focus is going away from this document, so clear the focused node. 816 // Focus is going away from this document, so clear the focused element.
815 document->clearFocusedElement(); 817 document->clearFocusedElement();
816 } 818 }
817 819
818 setFocusedFrame(newDocument.frame()); 820 setFocusedFrame(newDocument.frame());
819 821
820 if (caretBrowsing) { 822 if (caretBrowsing) {
821 Position position = firstPositionInOrBeforeNode(element.get()); 823 Position position = firstPositionInOrBeforeNode(element.get());
822 VisibleSelection newSelection(position, position); 824 VisibleSelection newSelection(position, position);
823 frame->selection().setSelection(newSelection); 825 frame->selection().setSelection(newSelection);
824 } 826 }
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
909 911
910 if (oldDocument && oldDocument != newDocument) 912 if (oldDocument && oldDocument != newDocument)
911 oldDocument->clearFocusedElement(); 913 oldDocument->clearFocusedElement();
912 914
913 if (newFocusedFrame && !newFocusedFrame->page()) { 915 if (newFocusedFrame && !newFocusedFrame->page()) {
914 setFocusedFrame(nullptr); 916 setFocusedFrame(nullptr);
915 return false; 917 return false;
916 } 918 }
917 setFocusedFrame(newFocusedFrame); 919 setFocusedFrame(newFocusedFrame);
918 920
919 // Setting the focused node can result in losing our last reft to node when JS event handlers fire. 921 // Setting the focused element can result in losing our last reft to element when JS event handlers fire.
920 RefPtrWillBeRawPtr<Element> protect = element; 922 RefPtrWillBeRawPtr<Element> protect = element;
921 ALLOW_UNUSED_LOCAL(protect); 923 ALLOW_UNUSED_LOCAL(protect);
922 if (newDocument) { 924 if (newDocument) {
923 bool successfullyFocused = newDocument->setFocusedElement(element, param s); 925 bool successfullyFocused = newDocument->setFocusedElement(element, param s);
924 if (!successfullyFocused) 926 if (!successfullyFocused)
925 return false; 927 return false;
926 } 928 }
927 929
928 return true; 930 return true;
929 } 931 }
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
1133 return consumed; 1135 return consumed;
1134 } 1136 }
1135 1137
1136 DEFINE_TRACE(FocusController) 1138 DEFINE_TRACE(FocusController)
1137 { 1139 {
1138 visitor->trace(m_page); 1140 visitor->trace(m_page);
1139 visitor->trace(m_focusedFrame); 1141 visitor->trace(m_focusedFrame);
1140 } 1142 }
1141 1143
1142 } // namespace blink 1144 } // 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