| 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 |