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

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