OLD | NEW |
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 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
87 if (root->isShadowRoot()) { | 87 if (root->isShadowRoot()) { |
88 ShadowRoot* shadowRoot = toShadowRoot(root); | 88 ShadowRoot* shadowRoot = toShadowRoot(root); |
89 return shadowRoot->isYoungest() ? shadowRoot->host() : shadowRoot->shado
wInsertionPointOfYoungerShadowRoot(); | 89 return shadowRoot->isYoungest() ? shadowRoot->host() : shadowRoot->shado
wInsertionPointOfYoungerShadowRoot(); |
90 } | 90 } |
91 // FIXME: Figure out the right thing for OOPI here. | 91 // FIXME: Figure out the right thing for OOPI here. |
92 if (Frame* frame = root->document().frame()) | 92 if (Frame* frame = root->document().frame()) |
93 return frame->deprecatedLocalOwner(); | 93 return frame->deprecatedLocalOwner(); |
94 return nullptr; | 94 return nullptr; |
95 } | 95 } |
96 | 96 |
97 FocusNavigationScope FocusNavigationScope::focusNavigationScopeOf(Node* node) | 97 FocusNavigationScope FocusNavigationScope::focusNavigationScopeOf(Node& node) |
98 { | 98 { |
99 ASSERT(node); | 99 Node* root = &node; |
100 Node* root = node; | 100 for (Node* n = &node; n; n = n->parentNode()) |
101 for (Node* n = node; n; n = n->parentNode()) | |
102 root = n; | 101 root = n; |
103 // The result is not always a ShadowRoot nor a DocumentNode since | 102 // The result is not always a ShadowRoot nor a DocumentNode since |
104 // a starting node is in an orphaned tree in composed shadow tree. | 103 // a starting node is in an orphaned tree in composed shadow tree. |
105 return FocusNavigationScope(&root->treeScope()); | 104 return FocusNavigationScope(&root->treeScope()); |
106 } | 105 } |
107 | 106 |
108 FocusNavigationScope FocusNavigationScope::ownedByNonFocusableFocusScopeOwner(No
de* node) | 107 FocusNavigationScope FocusNavigationScope::ownedByNonFocusableFocusScopeOwner(No
de& node) |
109 { | 108 { |
110 ASSERT(node); | |
111 if (isShadowHost(node)) | 109 if (isShadowHost(node)) |
112 return FocusNavigationScope::ownedByShadowHost(node); | 110 return FocusNavigationScope::ownedByShadowHost(node); |
113 ASSERT(isShadowInsertionPointFocusScopeOwner(*node)); | 111 ASSERT(isShadowInsertionPointFocusScopeOwner(node)); |
114 return FocusNavigationScope::ownedByShadowInsertionPoint(toHTMLShadowElement
(node)); | 112 return FocusNavigationScope::ownedByShadowInsertionPoint(toHTMLShadowElement
(node)); |
115 } | 113 } |
116 | 114 |
117 FocusNavigationScope FocusNavigationScope::ownedByShadowHost(Node* node) | 115 FocusNavigationScope FocusNavigationScope::ownedByShadowHost(Node& node) |
118 { | 116 { |
119 ASSERT(isShadowHost(node)); | 117 ASSERT(isShadowHost(node)); |
120 return FocusNavigationScope(toElement(node)->shadow()->youngestShadowRoot())
; | 118 return FocusNavigationScope(toElement(node).shadow()->youngestShadowRoot()); |
121 } | 119 } |
122 | 120 |
123 FocusNavigationScope FocusNavigationScope::ownedByIFrame(HTMLFrameOwnerElement*
frame) | 121 FocusNavigationScope FocusNavigationScope::ownedByIFrame(HTMLFrameOwnerElement&
frame) |
124 { | 122 { |
125 ASSERT(frame && frame->contentFrame() && frame->contentFrame()->isLocalFrame
()); | 123 ASSERT(frame.contentFrame()); |
126 return FocusNavigationScope(toLocalFrame(frame->contentFrame())->document())
; | 124 ASSERT(frame.contentFrame()->isLocalFrame()); |
| 125 return FocusNavigationScope(toLocalFrame(frame.contentFrame())->document()); |
127 } | 126 } |
128 | 127 |
129 FocusNavigationScope FocusNavigationScope::ownedByShadowInsertionPoint(HTMLShado
wElement* shadowInsertionPoint) | 128 FocusNavigationScope FocusNavigationScope::ownedByShadowInsertionPoint(HTMLShado
wElement& shadowInsertionPoint) |
130 { | 129 { |
131 ASSERT(isShadowInsertionPointFocusScopeOwner(*shadowInsertionPoint)); | 130 ASSERT(isShadowInsertionPointFocusScopeOwner(shadowInsertionPoint)); |
132 return FocusNavigationScope(shadowInsertionPoint->olderShadowRoot()); | 131 return FocusNavigationScope(shadowInsertionPoint.olderShadowRoot()); |
133 } | 132 } |
134 | 133 |
135 static inline void dispatchEventsOnWindowAndFocusedNode(Document* document, bool
focused) | 134 static inline void dispatchEventsOnWindowAndFocusedNode(Document* document, bool
focused) |
136 { | 135 { |
137 // If we have a focused node we should dispatch blur on it before we blur th
e window. | 136 // If we have a focused node we should dispatch blur on it before we blur th
e window. |
138 // If we have a focused node we should dispatch focus on it after we focus t
he window. | 137 // If we have a focused node we should dispatch focus on it after we focus t
he window. |
139 // https://bugs.webkit.org/show_bug.cgi?id=27105 | 138 // https://bugs.webkit.org/show_bug.cgi?id=27105 |
140 | 139 |
141 // Do not fire events while modal dialogs are up. See https://bugs.webkit.o
rg/show_bug.cgi?id=33962 | 140 // Do not fire events while modal dialogs are up. See https://bugs.webkit.o
rg/show_bug.cgi?id=33962 |
142 if (Page* page = document->page()) { | 141 if (Page* page = document->page()) { |
(...skipping 19 matching lines...) Expand all Loading... |
162 focusedElement->setFocus(true); | 161 focusedElement->setFocus(true); |
163 focusedElement->dispatchFocusEvent(0, FocusTypePage); | 162 focusedElement->dispatchFocusEvent(0, FocusTypePage); |
164 if (focusedElement == document->focusedElement()) { | 163 if (focusedElement == document->focusedElement()) { |
165 document->focusedElement()->dispatchFocusInEvent(EventTypeNames::foc
usin, nullptr, FocusTypePage); | 164 document->focusedElement()->dispatchFocusInEvent(EventTypeNames::foc
usin, nullptr, FocusTypePage); |
166 if (focusedElement == document->focusedElement()) | 165 if (focusedElement == document->focusedElement()) |
167 document->focusedElement()->dispatchFocusInEvent(EventTypeNames:
:DOMFocusIn, nullptr, FocusTypePage); | 166 document->focusedElement()->dispatchFocusInEvent(EventTypeNames:
:DOMFocusIn, nullptr, FocusTypePage); |
168 } | 167 } |
169 } | 168 } |
170 } | 169 } |
171 | 170 |
172 static inline bool hasCustomFocusLogic(Element* element) | 171 static inline bool hasCustomFocusLogic(const Element& element) |
173 { | 172 { |
174 return element->isHTMLElement() && toHTMLElement(element)->hasCustomFocusLog
ic(); | 173 return element.isHTMLElement() && toHTMLElement(element).hasCustomFocusLogic
(); |
175 } | 174 } |
176 | 175 |
177 #if ENABLE(ASSERT) | 176 #if ENABLE(ASSERT) |
178 static inline bool isNonFocusableShadowHost(Node* node) | 177 static inline bool isNonFocusableShadowHost(const Node& node) |
179 { | 178 { |
180 ASSERT(node); | 179 if (!node.isElementNode()) |
181 if (!node->isElementNode()) | |
182 return false; | 180 return false; |
183 Element* element = toElement(node); | 181 const Element& element = toElement(node); |
184 return !element->isFocusable() && isShadowHost(element) && !hasCustomFocusLo
gic(element); | 182 return !element.isFocusable() && isShadowHost(element) && !hasCustomFocusLog
ic(element); |
185 } | 183 } |
186 #endif | 184 #endif |
187 | 185 |
188 static inline bool isNonKeyboardFocusableShadowHost(Node* node) | 186 static inline bool isNonKeyboardFocusableShadowHost(const Node& node) |
189 { | 187 { |
190 ASSERT(node); | 188 if (!node.isElementNode()) |
191 if (!node->isElementNode()) | |
192 return false; | 189 return false; |
193 Element* element = toElement(node); | 190 const Element& element = toElement(node); |
194 return !element->isKeyboardFocusable() && isShadowHost(element) && !hasCusto
mFocusLogic(element); | 191 return !element.isKeyboardFocusable() && isShadowHost(element) && !hasCustom
FocusLogic(element); |
195 } | 192 } |
196 | 193 |
197 static inline bool isKeyboardFocusableShadowHost(Node* node) | 194 static inline bool isKeyboardFocusableShadowHost(const Node& node) |
198 { | 195 { |
199 ASSERT(node); | 196 if (!node.isElementNode()) |
200 if (!node->isElementNode()) | |
201 return false; | 197 return false; |
202 Element* element = toElement(node); | 198 const Element& element = toElement(node); |
203 return element->isKeyboardFocusable() && isShadowHost(element) && !hasCustom
FocusLogic(element); | 199 return element.isKeyboardFocusable() && isShadowHost(element) && !hasCustomF
ocusLogic(element); |
204 } | 200 } |
205 | 201 |
206 static inline bool isNonFocusableFocusScopeOwner(Node* node) | 202 static inline bool isNonFocusableFocusScopeOwner(Node& node) |
207 { | 203 { |
208 ASSERT(node); | 204 return isNonKeyboardFocusableShadowHost(node) || isShadowInsertionPointFocus
ScopeOwner(node); |
209 return isNonKeyboardFocusableShadowHost(node) || isShadowInsertionPointFocus
ScopeOwner(*node); | |
210 } | 205 } |
211 | 206 |
212 static inline int adjustedTabIndex(Node* node) | 207 static inline int adjustedTabIndex(Node& node) |
213 { | 208 { |
214 ASSERT(node); | 209 return isNonFocusableFocusScopeOwner(node) ? 0 : node.tabIndex(); |
215 return isNonFocusableFocusScopeOwner(node) ? 0 : node->tabIndex(); | |
216 } | 210 } |
217 | 211 |
218 static inline bool shouldVisit(Node* node) | 212 static inline bool shouldVisit(Node& node) |
219 { | 213 { |
220 ASSERT(node); | 214 return (node.isElementNode() && toElement(node).isKeyboardFocusable()) || is
NonFocusableFocusScopeOwner(node); |
221 return (node->isElementNode() && toElement(node)->isKeyboardFocusable()) ||
isNonFocusableFocusScopeOwner(node); | |
222 } | 215 } |
223 | 216 |
224 FocusController::FocusController(Page* page) | 217 FocusController::FocusController(Page* page) |
225 : m_page(page) | 218 : m_page(page) |
226 , m_isActive(false) | 219 , m_isActive(false) |
227 , m_isFocused(false) | 220 , m_isFocused(false) |
228 , m_isChangingFocusedFrame(false) | 221 , m_isChangingFocusedFrame(false) |
229 { | 222 { |
230 } | 223 } |
231 | 224 |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
336 dispatchEventsOnWindowAndFocusedNode(toLocalFrame(m_focusedFrame.get())-
>document(), focused); | 329 dispatchEventsOnWindowAndFocusedNode(toLocalFrame(m_focusedFrame.get())-
>document(), focused); |
337 } | 330 } |
338 } | 331 } |
339 | 332 |
340 Node* FocusController::findFocusableNodeDecendingDownIntoFrameDocument(FocusType
type, Node* node) | 333 Node* FocusController::findFocusableNodeDecendingDownIntoFrameDocument(FocusType
type, Node* node) |
341 { | 334 { |
342 // The node we found might be a HTMLFrameOwnerElement, so descend down the t
ree until we find either: | 335 // The node we found might be a HTMLFrameOwnerElement, so descend down the t
ree until we find either: |
343 // 1) a focusable node, or | 336 // 1) a focusable node, or |
344 // 2) the deepest-nested HTMLFrameOwnerElement. | 337 // 2) the deepest-nested HTMLFrameOwnerElement. |
345 while (node && node->isFrameOwnerElement()) { | 338 while (node && node->isFrameOwnerElement()) { |
346 HTMLFrameOwnerElement* owner = toHTMLFrameOwnerElement(node); | 339 HTMLFrameOwnerElement& owner = toHTMLFrameOwnerElement(*node); |
347 if (!owner->contentFrame() || !owner->contentFrame()->isLocalFrame()) | 340 if (!owner.contentFrame() || !owner.contentFrame()->isLocalFrame()) |
348 break; | 341 break; |
349 Node* foundNode = findFocusableNode(type, FocusNavigationScope::ownedByI
Frame(owner), nullptr); | 342 Node* foundNode = findFocusableNode(type, FocusNavigationScope::ownedByI
Frame(owner), nullptr); |
350 if (!foundNode) | 343 if (!foundNode) |
351 break; | 344 break; |
352 ASSERT(node != foundNode); | 345 ASSERT(node != foundNode); |
353 node = foundNode; | 346 node = foundNode; |
354 } | 347 } |
355 return node; | 348 return node; |
356 } | 349 } |
357 | 350 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
401 | 394 |
402 Node* currentNode = document->focusedElement(); | 395 Node* currentNode = document->focusedElement(); |
403 // FIXME: Not quite correct when it comes to focus transitions leaving/enter
ing the WebView itself | 396 // FIXME: Not quite correct when it comes to focus transitions leaving/enter
ing the WebView itself |
404 bool caretBrowsing = frame->settings() && frame->settings()->caretBrowsingEn
abled(); | 397 bool caretBrowsing = frame->settings() && frame->settings()->caretBrowsingEn
abled(); |
405 | 398 |
406 if (caretBrowsing && !currentNode) | 399 if (caretBrowsing && !currentNode) |
407 currentNode = frame->selection().start().deprecatedNode(); | 400 currentNode = frame->selection().start().deprecatedNode(); |
408 | 401 |
409 document->updateLayoutIgnorePendingStylesheets(); | 402 document->updateLayoutIgnorePendingStylesheets(); |
410 | 403 |
411 RefPtrWillBeRawPtr<Node> node = findFocusableNodeAcrossFocusScope(type, Focu
sNavigationScope::focusNavigationScopeOf(currentNode ? currentNode : document),
currentNode); | 404 RefPtrWillBeRawPtr<Node> node = findFocusableNodeAcrossFocusScope(type, Focu
sNavigationScope::focusNavigationScopeOf(currentNode ? *currentNode : *document)
, currentNode); |
412 | 405 |
413 if (!node) { | 406 if (!node) { |
414 // We didn't find a node to focus, so we should try to pass focus to Chr
ome. | 407 // We didn't find a node to focus, so we should try to pass focus to Chr
ome. |
415 if (!initialFocus && m_page->chrome().canTakeFocus(type)) { | 408 if (!initialFocus && m_page->chrome().canTakeFocus(type)) { |
416 document->setFocusedElement(nullptr); | 409 document->setFocusedElement(nullptr); |
417 setFocusedFrame(nullptr); | 410 setFocusedFrame(nullptr); |
418 m_page->chrome().takeFocus(type); | 411 m_page->chrome().takeFocus(type); |
419 return true; | 412 return true; |
420 } | 413 } |
421 | 414 |
422 // Chrome doesn't want focus, so we should wrap focus. | 415 // Chrome doesn't want focus, so we should wrap focus. |
423 if (!m_page->mainFrame()->isLocalFrame()) | 416 if (!m_page->mainFrame()->isLocalFrame()) |
424 return false; | 417 return false; |
425 node = findFocusableNodeRecursively(type, FocusNavigationScope::focusNav
igationScopeOf(m_page->deprecatedLocalMainFrame()->document()), nullptr); | 418 node = findFocusableNodeRecursively(type, FocusNavigationScope::focusNav
igationScopeOf(*m_page->deprecatedLocalMainFrame()->document()), nullptr); |
426 node = findFocusableNodeDecendingDownIntoFrameDocument(type, node.get())
; | 419 node = findFocusableNodeDecendingDownIntoFrameDocument(type, node.get())
; |
427 | 420 |
428 if (!node) | 421 if (!node) |
429 return false; | 422 return false; |
430 } | 423 } |
431 | 424 |
432 ASSERT(node); | 425 ASSERT(node); |
433 | 426 |
434 if (node == document->focusedElement()) | 427 if (node == document->focusedElement()) |
435 // Focus wrapped around to the same node. | 428 // Focus wrapped around to the same node. |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
469 VisibleSelection newSelection(position, position, DOWNSTREAM); | 462 VisibleSelection newSelection(position, position, DOWNSTREAM); |
470 frame->selection().setSelection(newSelection); | 463 frame->selection().setSelection(newSelection); |
471 } | 464 } |
472 | 465 |
473 element->focus(false, type); | 466 element->focus(false, type); |
474 return true; | 467 return true; |
475 } | 468 } |
476 | 469 |
477 Node* FocusController::findFocusableNodeAcrossFocusScope(FocusType type, FocusNa
vigationScope scope, Node* currentNode) | 470 Node* FocusController::findFocusableNodeAcrossFocusScope(FocusType type, FocusNa
vigationScope scope, Node* currentNode) |
478 { | 471 { |
479 ASSERT(!currentNode || !isNonFocusableShadowHost(currentNode)); | 472 ASSERT(!currentNode || !isNonFocusableShadowHost(*currentNode)); |
480 Node* found; | 473 Node* found; |
481 if (currentNode && type == FocusTypeForward && isKeyboardFocusableShadowHost
(currentNode)) { | 474 if (currentNode && type == FocusTypeForward && isKeyboardFocusableShadowHost
(*currentNode)) { |
482 Node* foundInInnerFocusScope = findFocusableNodeRecursively(type, FocusN
avigationScope::ownedByShadowHost(currentNode), nullptr); | 475 Node* foundInInnerFocusScope = findFocusableNodeRecursively(type, FocusN
avigationScope::ownedByShadowHost(*currentNode), nullptr); |
483 found = foundInInnerFocusScope ? foundInInnerFocusScope : findFocusableN
odeRecursively(type, scope, currentNode); | 476 found = foundInInnerFocusScope ? foundInInnerFocusScope : findFocusableN
odeRecursively(type, scope, currentNode); |
484 } else { | 477 } else { |
485 found = findFocusableNodeRecursively(type, scope, currentNode); | 478 found = findFocusableNodeRecursively(type, scope, currentNode); |
486 } | 479 } |
487 | 480 |
488 // If there's no focusable node to advance to, move up the focus scopes unti
l we find one. | 481 // If there's no focusable node to advance to, move up the focus scopes unti
l we find one. |
489 while (!found) { | 482 while (!found) { |
490 Node* owner = scope.owner(); | 483 Node* owner = scope.owner(); |
491 if (!owner) | 484 if (!owner) |
492 break; | 485 break; |
493 scope = FocusNavigationScope::focusNavigationScopeOf(owner); | 486 scope = FocusNavigationScope::focusNavigationScopeOf(*owner); |
494 if (type == FocusTypeBackward && isKeyboardFocusableShadowHost(owner)) { | 487 if (type == FocusTypeBackward && isKeyboardFocusableShadowHost(*owner))
{ |
495 found = owner; | 488 found = owner; |
496 break; | 489 break; |
497 } | 490 } |
498 found = findFocusableNodeRecursively(type, scope, owner); | 491 found = findFocusableNodeRecursively(type, scope, owner); |
499 } | 492 } |
500 found = findFocusableNodeDecendingDownIntoFrameDocument(type, found); | 493 found = findFocusableNodeDecendingDownIntoFrameDocument(type, found); |
501 return found; | 494 return found; |
502 } | 495 } |
503 | 496 |
504 Node* FocusController::findFocusableNodeRecursively(FocusType type, FocusNavigat
ionScope scope, Node* start) | 497 Node* FocusController::findFocusableNodeRecursively(FocusType type, FocusNavigat
ionScope scope, Node* start) |
505 { | 498 { |
506 // Starting node is exclusive. | 499 // Starting node is exclusive. |
507 Node* found = findFocusableNode(type, scope, start); | 500 Node* foundOrNull = findFocusableNode(type, scope, start); |
508 if (!found) | 501 if (!foundOrNull) |
509 return nullptr; | 502 return nullptr; |
| 503 Node& found = *foundOrNull; |
510 if (type == FocusTypeForward) { | 504 if (type == FocusTypeForward) { |
511 if (!isNonFocusableFocusScopeOwner(found)) | 505 if (!isNonFocusableFocusScopeOwner(found)) |
512 return found; | 506 return &found; |
513 Node* foundInInnerFocusScope = findFocusableNodeRecursively(type, FocusN
avigationScope::ownedByNonFocusableFocusScopeOwner(found), nullptr); | 507 Node* foundInInnerFocusScope = findFocusableNodeRecursively(type, FocusN
avigationScope::ownedByNonFocusableFocusScopeOwner(found), nullptr); |
514 return foundInInnerFocusScope ? foundInInnerFocusScope : findFocusableNo
deRecursively(type, scope, found); | 508 return foundInInnerFocusScope ? foundInInnerFocusScope : findFocusableNo
deRecursively(type, scope, &found); |
515 } | 509 } |
516 ASSERT(type == FocusTypeBackward); | 510 ASSERT(type == FocusTypeBackward); |
517 if (isKeyboardFocusableShadowHost(found)) { | 511 if (isKeyboardFocusableShadowHost(found)) { |
518 Node* foundInInnerFocusScope = findFocusableNodeRecursively(type, FocusN
avigationScope::ownedByShadowHost(found), nullptr); | 512 Node* foundInInnerFocusScope = findFocusableNodeRecursively(type, FocusN
avigationScope::ownedByShadowHost(found), nullptr); |
519 return foundInInnerFocusScope ? foundInInnerFocusScope : found; | 513 return foundInInnerFocusScope ? foundInInnerFocusScope : &found; |
520 } | 514 } |
521 if (isNonFocusableFocusScopeOwner(found)) { | 515 if (isNonFocusableFocusScopeOwner(found)) { |
522 Node* foundInInnerFocusScope = findFocusableNodeRecursively(type, FocusN
avigationScope::ownedByNonFocusableFocusScopeOwner(found), nullptr); | 516 Node* foundInInnerFocusScope = findFocusableNodeRecursively(type, FocusN
avigationScope::ownedByNonFocusableFocusScopeOwner(found), nullptr); |
523 return foundInInnerFocusScope ? foundInInnerFocusScope :findFocusableNod
eRecursively(type, scope, found); | 517 return foundInInnerFocusScope ? foundInInnerFocusScope :findFocusableNod
eRecursively(type, scope, &found); |
524 } | 518 } |
525 return found; | 519 return &found; |
526 } | 520 } |
527 | 521 |
528 Node* FocusController::findFocusableNode(FocusType type, FocusNavigationScope sc
ope, Node* node) | 522 Node* FocusController::findFocusableNode(FocusType type, FocusNavigationScope sc
ope, Node* node) |
529 { | 523 { |
530 return type == FocusTypeForward ? nextFocusableNode(scope, node) : previousF
ocusableNode(scope, node); | 524 return type == FocusTypeForward ? nextFocusableNode(scope, node) : previousF
ocusableNode(scope, node); |
531 } | 525 } |
532 | 526 |
533 Node* FocusController::findNodeWithExactTabIndex(Node* start, int tabIndex, Focu
sType type) | 527 Node* FocusController::findNodeWithExactTabIndex(Node* start, int tabIndex, Focu
sType type) |
534 { | 528 { |
535 // Search is inclusive of start | 529 // Search is inclusive of start |
536 for (Node* node = start; node; node = type == FocusTypeForward ? NodeTravers
al::next(*node) : NodeTraversal::previous(*node)) { | 530 for (Node* node = start; node; node = type == FocusTypeForward ? NodeTravers
al::next(*node) : NodeTraversal::previous(*node)) { |
537 if (shouldVisit(node) && adjustedTabIndex(node) == tabIndex) | 531 if (shouldVisit(*node) && adjustedTabIndex(*node) == tabIndex) |
538 return node; | 532 return node; |
539 } | 533 } |
540 return nullptr; | 534 return nullptr; |
541 } | 535 } |
542 | 536 |
543 static Node* nextNodeWithGreaterTabIndex(Node* start, int tabIndex) | 537 static Node* nextNodeWithGreaterTabIndex(Node* start, int tabIndex) |
544 { | 538 { |
545 // Search is inclusive of start | 539 // Search is inclusive of start |
546 int winningTabIndex = std::numeric_limits<short>::max() + 1; | 540 int winningTabIndex = std::numeric_limits<short>::max() + 1; |
547 Node* winner = nullptr; | 541 Node* winner = nullptr; |
548 for (Node& node : NodeTraversal::startsAt(start)) { | 542 for (Node& node : NodeTraversal::startsAt(start)) { |
549 int currentTabIndex = adjustedTabIndex(&node); | 543 int currentTabIndex = adjustedTabIndex(node); |
550 if (shouldVisit(&node) && currentTabIndex > tabIndex && currentTabIndex
< winningTabIndex) { | 544 if (shouldVisit(node) && currentTabIndex > tabIndex && currentTabIndex <
winningTabIndex) { |
551 winner = &node; | 545 winner = &node; |
552 winningTabIndex = currentTabIndex; | 546 winningTabIndex = currentTabIndex; |
553 } | 547 } |
554 } | 548 } |
555 | 549 |
556 return winner; | 550 return winner; |
557 } | 551 } |
558 | 552 |
559 static Node* previousNodeWithLowerTabIndex(Node* start, int tabIndex) | 553 static Node* previousNodeWithLowerTabIndex(Node* start, int tabIndex) |
560 { | 554 { |
561 // Search is inclusive of start | 555 // Search is inclusive of start |
562 int winningTabIndex = 0; | 556 int winningTabIndex = 0; |
563 Node* winner = nullptr; | 557 Node* winner = nullptr; |
564 for (Node* node = start; node; node = NodeTraversal::previous(*node)) { | 558 for (Node* node = start; node; node = NodeTraversal::previous(*node)) { |
565 int currentTabIndex = adjustedTabIndex(node); | 559 int currentTabIndex = adjustedTabIndex(*node); |
566 if (shouldVisit(node) && currentTabIndex < tabIndex && currentTabIndex >
winningTabIndex) { | 560 if (shouldVisit(*node) && currentTabIndex < tabIndex && currentTabIndex
> winningTabIndex) { |
567 winner = node; | 561 winner = node; |
568 winningTabIndex = currentTabIndex; | 562 winningTabIndex = currentTabIndex; |
569 } | 563 } |
570 } | 564 } |
571 return winner; | 565 return winner; |
572 } | 566 } |
573 | 567 |
574 Node* FocusController::nextFocusableNode(FocusNavigationScope scope, Node* start
) | 568 Node* FocusController::nextFocusableNode(FocusNavigationScope scope, Node* start
) |
575 { | 569 { |
576 if (start) { | 570 if (start) { |
577 int tabIndex = adjustedTabIndex(start); | 571 int tabIndex = adjustedTabIndex(*start); |
578 // If a node is excluded from the normal tabbing cycle, the next focusab
le node is determined by tree order | 572 // If a node is excluded from the normal tabbing cycle, the next focusab
le node is determined by tree order |
579 if (tabIndex < 0) { | 573 if (tabIndex < 0) { |
580 for (Node& node : NodeTraversal::startsAfter(*start)) { | 574 for (Node& node : NodeTraversal::startsAfter(*start)) { |
581 if (shouldVisit(&node) && adjustedTabIndex(&node) >= 0) | 575 if (shouldVisit(node) && adjustedTabIndex(node) >= 0) |
582 return &node; | 576 return &node; |
583 } | 577 } |
584 } else { | 578 } else { |
585 // First try to find a node with the same tabindex as start that com
es after start in the scope. | 579 // First try to find a node with the same tabindex as start that com
es after start in the scope. |
586 if (Node* winner = findNodeWithExactTabIndex(NodeTraversal::next(*st
art), tabIndex, FocusTypeForward)) | 580 if (Node* winner = findNodeWithExactTabIndex(NodeTraversal::next(*st
art), tabIndex, FocusTypeForward)) |
587 return winner; | 581 return winner; |
588 } | 582 } |
589 if (!tabIndex) { | 583 if (!tabIndex) { |
590 // We've reached the last node in the document with a tabindex of 0.
This is the end of the tabbing order. | 584 // We've reached the last node in the document with a tabindex of 0.
This is the end of the tabbing order. |
591 return nullptr; | 585 return nullptr; |
592 } | 586 } |
593 } | 587 } |
594 | 588 |
595 // Look for the first node in the scope that: | 589 // Look for the first node in the scope that: |
596 // 1) has the lowest tabindex that is higher than start's tabindex (or 0, if
start is null), and | 590 // 1) has the lowest tabindex that is higher than start's tabindex (or 0, if
start is null), and |
597 // 2) comes first in the scope, if there's a tie. | 591 // 2) comes first in the scope, if there's a tie. |
598 if (Node* winner = nextNodeWithGreaterTabIndex(scope.rootNode(), start ? adj
ustedTabIndex(start) : 0)) | 592 if (Node* winner = nextNodeWithGreaterTabIndex(scope.rootNode(), start ? adj
ustedTabIndex(*start) : 0)) |
599 return winner; | 593 return winner; |
600 | 594 |
601 // There are no nodes with a tabindex greater than start's tabindex, | 595 // There are no nodes with a tabindex greater than start's tabindex, |
602 // so find the first node with a tabindex of 0. | 596 // so find the first node with a tabindex of 0. |
603 return findNodeWithExactTabIndex(scope.rootNode(), 0, FocusTypeForward); | 597 return findNodeWithExactTabIndex(scope.rootNode(), 0, FocusTypeForward); |
604 } | 598 } |
605 | 599 |
606 Node* FocusController::previousFocusableNode(FocusNavigationScope scope, Node* s
tart) | 600 Node* FocusController::previousFocusableNode(FocusNavigationScope scope, Node* s
tart) |
607 { | 601 { |
608 Node* last = nullptr; | 602 Node* last = nullptr; |
609 for (Node* node = scope.rootNode(); node; node = node->lastChild()) | 603 for (Node* node = scope.rootNode(); node; node = node->lastChild()) |
610 last = node; | 604 last = node; |
611 ASSERT(last); | 605 ASSERT(last); |
612 | 606 |
613 // First try to find the last node in the scope that comes before start and
has the same tabindex as start. | 607 // First try to find the last node in the scope that comes before start and
has the same tabindex as start. |
614 // If start is null, find the last node in the scope with a tabindex of 0. | 608 // If start is null, find the last node in the scope with a tabindex of 0. |
615 Node* startingNode; | 609 Node* startingNode; |
616 int startingTabIndex; | 610 int startingTabIndex; |
617 if (start) { | 611 if (start) { |
618 startingNode = NodeTraversal::previous(*start); | 612 startingNode = NodeTraversal::previous(*start); |
619 startingTabIndex = adjustedTabIndex(start); | 613 startingTabIndex = adjustedTabIndex(*start); |
620 } else { | 614 } else { |
621 startingNode = last; | 615 startingNode = last; |
622 startingTabIndex = 0; | 616 startingTabIndex = 0; |
623 } | 617 } |
624 | 618 |
625 // However, if a node is excluded from the normal tabbing cycle, the previou
s focusable node is determined by tree order | 619 // However, if a node is excluded from the normal tabbing cycle, the previou
s focusable node is determined by tree order |
626 if (startingTabIndex < 0) { | 620 if (startingTabIndex < 0) { |
627 for (Node* node = startingNode; node; node = NodeTraversal::previous(*no
de)) { | 621 for (Node* node = startingNode; node; node = NodeTraversal::previous(*no
de)) { |
628 if (shouldVisit(node) && adjustedTabIndex(node) >= 0) | 622 if (shouldVisit(*node) && adjustedTabIndex(*node) >= 0) |
629 return node; | 623 return node; |
630 } | 624 } |
631 } else { | 625 } else { |
632 if (Node* winner = findNodeWithExactTabIndex(startingNode, startingTabIn
dex, FocusTypeBackward)) | 626 if (Node* winner = findNodeWithExactTabIndex(startingNode, startingTabIn
dex, FocusTypeBackward)) |
633 return winner; | 627 return winner; |
634 } | 628 } |
635 | 629 |
636 // There are no nodes before start with the same tabindex as start, so look
for a node that: | 630 // There are no nodes before start with the same tabindex as start, so look
for a node that: |
637 // 1) has the highest non-zero tabindex (that is less than start's tabindex)
, and | 631 // 1) has the highest non-zero tabindex (that is less than start's tabindex)
, and |
638 // 2) comes last in the scope, if there's a tie. | 632 // 2) comes last in the scope, if there's a tie. |
639 startingTabIndex = (start && startingTabIndex) ? startingTabIndex : std::num
eric_limits<short>::max(); | 633 startingTabIndex = (start && startingTabIndex) ? startingTabIndex : std::num
eric_limits<short>::max(); |
640 return previousNodeWithLowerTabIndex(last, startingTabIndex); | 634 return previousNodeWithLowerTabIndex(last, startingTabIndex); |
641 } | 635 } |
642 | 636 |
643 static bool relinquishesEditingFocus(Node *node) | 637 static bool relinquishesEditingFocus(const Element& element) |
644 { | 638 { |
645 ASSERT(node); | 639 ASSERT(element.hasEditableStyle()); |
646 ASSERT(node->hasEditableStyle()); | 640 return element.document().frame() && element.rootEditableElement(); |
647 return node->document().frame() && node->rootEditableElement(); | |
648 } | 641 } |
649 | 642 |
650 static void clearSelectionIfNeeded(LocalFrame* oldFocusedFrame, LocalFrame* newF
ocusedFrame, Node* newFocusedNode) | 643 static void clearSelectionIfNeeded(LocalFrame* oldFocusedFrame, LocalFrame* newF
ocusedFrame, Node* newFocusedNode) |
651 { | 644 { |
652 if (!oldFocusedFrame || !newFocusedFrame) | 645 if (!oldFocusedFrame || !newFocusedFrame) |
653 return; | 646 return; |
654 | 647 |
655 if (oldFocusedFrame->document() != newFocusedFrame->document()) | 648 if (oldFocusedFrame->document() != newFocusedFrame->document()) |
656 return; | 649 return; |
657 | 650 |
(...skipping 21 matching lines...) Expand all Loading... |
679 bool FocusController::setFocusedElement(Element* element, PassRefPtrWillBeRawPtr
<Frame> newFocusedFrame, FocusType type) | 672 bool FocusController::setFocusedElement(Element* element, PassRefPtrWillBeRawPtr
<Frame> newFocusedFrame, FocusType type) |
680 { | 673 { |
681 RefPtrWillBeRawPtr<LocalFrame> oldFocusedFrame = toLocalFrame(focusedFrame()
); | 674 RefPtrWillBeRawPtr<LocalFrame> oldFocusedFrame = toLocalFrame(focusedFrame()
); |
682 RefPtrWillBeRawPtr<Document> oldDocument = oldFocusedFrame ? oldFocusedFrame
->document() : nullptr; | 675 RefPtrWillBeRawPtr<Document> oldDocument = oldFocusedFrame ? oldFocusedFrame
->document() : nullptr; |
683 | 676 |
684 Element* oldFocusedElement = oldDocument ? oldDocument->focusedElement() : n
ullptr; | 677 Element* oldFocusedElement = oldDocument ? oldDocument->focusedElement() : n
ullptr; |
685 if (element && oldFocusedElement == element) | 678 if (element && oldFocusedElement == element) |
686 return true; | 679 return true; |
687 | 680 |
688 // FIXME: Might want to disable this check for caretBrowsing | 681 // FIXME: Might want to disable this check for caretBrowsing |
689 if (oldFocusedElement && oldFocusedElement->isRootEditableElement() && !reli
nquishesEditingFocus(oldFocusedElement)) | 682 if (oldFocusedElement && oldFocusedElement->isRootEditableElement() && !reli
nquishesEditingFocus(*oldFocusedElement)) |
690 return false; | 683 return false; |
691 | 684 |
692 m_page->chrome().client().willSetInputMethodState(); | 685 m_page->chrome().client().willSetInputMethodState(); |
693 | 686 |
694 RefPtrWillBeRawPtr<Document> newDocument = nullptr; | 687 RefPtrWillBeRawPtr<Document> newDocument = nullptr; |
695 if (element) | 688 if (element) |
696 newDocument = &element->document(); | 689 newDocument = &element->document(); |
697 else if (newFocusedFrame && newFocusedFrame->isLocalFrame()) | 690 else if (newFocusedFrame && newFocusedFrame->isLocalFrame()) |
698 newDocument = toLocalFrame(newFocusedFrame.get())->document(); | 691 newDocument = toLocalFrame(newFocusedFrame.get())->document(); |
699 | 692 |
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
928 return consumed; | 921 return consumed; |
929 } | 922 } |
930 | 923 |
931 void FocusController::trace(Visitor* visitor) | 924 void FocusController::trace(Visitor* visitor) |
932 { | 925 { |
933 visitor->trace(m_page); | 926 visitor->trace(m_page); |
934 visitor->trace(m_focusedFrame); | 927 visitor->trace(m_focusedFrame); |
935 } | 928 } |
936 | 929 |
937 } // namespace blink | 930 } // namespace blink |
OLD | NEW |