| 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 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 353 Node* FocusController::findFocusableNodeDecendingDownIntoFrameDocument(WebFocusT
ype type, Node* node) | 353 Node* FocusController::findFocusableNodeDecendingDownIntoFrameDocument(WebFocusT
ype type, Node* node) |
| 354 { | 354 { |
| 355 // The node we found might be a HTMLFrameOwnerElement, so descend down the t
ree until we find either: | 355 // The node we found might be a HTMLFrameOwnerElement, so descend down the t
ree until we find either: |
| 356 // 1) a focusable node, or | 356 // 1) a focusable node, or |
| 357 // 2) the deepest-nested HTMLFrameOwnerElement. | 357 // 2) the deepest-nested HTMLFrameOwnerElement. |
| 358 while (node && node->isFrameOwnerElement()) { | 358 while (node && node->isFrameOwnerElement()) { |
| 359 HTMLFrameOwnerElement& owner = toHTMLFrameOwnerElement(*node); | 359 HTMLFrameOwnerElement& owner = toHTMLFrameOwnerElement(*node); |
| 360 if (!owner.contentFrame() || !owner.contentFrame()->isLocalFrame()) | 360 if (!owner.contentFrame() || !owner.contentFrame()->isLocalFrame()) |
| 361 break; | 361 break; |
| 362 toLocalFrame(owner.contentFrame())->document()->updateLayoutIgnorePendin
gStylesheets(); | 362 toLocalFrame(owner.contentFrame())->document()->updateLayoutIgnorePendin
gStylesheets(); |
| 363 Node* foundNode = findFocusableNode(type, FocusNavigationScope::ownedByI
Frame(owner), nullptr); | 363 Element* foundElement = findFocusableElement(type, FocusNavigationScope:
:ownedByIFrame(owner), nullptr); |
| 364 if (!foundNode) | 364 if (!foundElement) |
| 365 break; | 365 break; |
| 366 ASSERT(node != foundNode); | 366 ASSERT(node != foundElement); |
| 367 node = foundNode; | 367 node = foundElement; |
| 368 } | 368 } |
| 369 return node; | 369 return node; |
| 370 } | 370 } |
| 371 | 371 |
| 372 bool FocusController::setInitialFocus(WebFocusType type) | 372 bool FocusController::setInitialFocus(WebFocusType type) |
| 373 { | 373 { |
| 374 bool didAdvanceFocus = advanceFocus(type, true); | 374 bool didAdvanceFocus = advanceFocus(type, true); |
| 375 | 375 |
| 376 // If focus is being set initially, accessibility needs to be informed that
system focus has moved | 376 // If focus is being set initially, accessibility needs to be informed that
system focus has moved |
| 377 // into the web area again, even if focus did not change within WebCore. Pos
tNotification is called instead | 377 // into the web area again, even if focus did not change within WebCore. Pos
tNotification is called instead |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 429 if (!initialFocus && m_page->chromeClient().canTakeFocus(type)) { | 429 if (!initialFocus && m_page->chromeClient().canTakeFocus(type)) { |
| 430 document->setFocusedElement(nullptr); | 430 document->setFocusedElement(nullptr); |
| 431 setFocusedFrame(nullptr); | 431 setFocusedFrame(nullptr); |
| 432 m_page->chromeClient().takeFocus(type); | 432 m_page->chromeClient().takeFocus(type); |
| 433 return true; | 433 return true; |
| 434 } | 434 } |
| 435 | 435 |
| 436 // Chrome doesn't want focus, so we should wrap focus. | 436 // Chrome doesn't want focus, so we should wrap focus. |
| 437 if (!m_page->mainFrame()->isLocalFrame()) | 437 if (!m_page->mainFrame()->isLocalFrame()) |
| 438 return false; | 438 return false; |
| 439 node = findFocusableNodeRecursively(type, FocusNavigationScope::focusNav
igationScopeOf(*m_page->deprecatedLocalMainFrame()->document()), nullptr); | 439 node = findFocusableElementRecursively(type, FocusNavigationScope::focus
NavigationScopeOf(*m_page->deprecatedLocalMainFrame()->document()), nullptr); |
| 440 node = findFocusableNodeDecendingDownIntoFrameDocument(type, node.get())
; | 440 node = findFocusableNodeDecendingDownIntoFrameDocument(type, node.get())
; |
| 441 | 441 |
| 442 if (!node) | 442 if (!node) |
| 443 return false; | 443 return false; |
| 444 } | 444 } |
| 445 | 445 |
| 446 ASSERT(node); | 446 ASSERT(node); |
| 447 | 447 |
| 448 if (node == document->focusedElement()) | 448 if (node == document->focusedElement()) |
| 449 // Focus wrapped around to the same node. | 449 // Focus wrapped around to the same node. |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 494 findFocusableNodeAcrossFocusScopesForward(scope, currentNode) : | 494 findFocusableNodeAcrossFocusScopesForward(scope, currentNode) : |
| 495 findFocusableNodeAcrossFocusScopesBackward(scope, currentNode); | 495 findFocusableNodeAcrossFocusScopesBackward(scope, currentNode); |
| 496 } | 496 } |
| 497 | 497 |
| 498 Node* FocusController::findFocusableNodeAcrossFocusScopesForward(const FocusNavi
gationScope& scope, Node* currentNode) | 498 Node* FocusController::findFocusableNodeAcrossFocusScopesForward(const FocusNavi
gationScope& scope, Node* currentNode) |
| 499 { | 499 { |
| 500 ASSERT(!currentNode || !isNonFocusableShadowHost(*currentNode)); | 500 ASSERT(!currentNode || !isNonFocusableShadowHost(*currentNode)); |
| 501 Node* found; | 501 Node* found; |
| 502 if (currentNode && isShadowHostWithoutCustomFocusLogic(*currentNode)) { | 502 if (currentNode && isShadowHostWithoutCustomFocusLogic(*currentNode)) { |
| 503 FocusNavigationScope innerScope = FocusNavigationScope::ownedByShadowHos
t(*currentNode); | 503 FocusNavigationScope innerScope = FocusNavigationScope::ownedByShadowHos
t(*currentNode); |
| 504 Node* foundInInnerFocusScope = findFocusableNodeRecursivelyForward(inner
Scope, nullptr); | 504 Node* foundInInnerFocusScope = findFocusableElementRecursivelyForward(in
nerScope, nullptr); |
| 505 found = foundInInnerFocusScope ? foundInInnerFocusScope : findFocusableN
odeRecursivelyForward(scope, currentNode); | 505 found = foundInInnerFocusScope ? foundInInnerFocusScope : findFocusableE
lementRecursivelyForward(scope, currentNode); |
| 506 } else { | 506 } else { |
| 507 found = findFocusableNodeRecursivelyForward(scope, currentNode); | 507 found = findFocusableElementRecursivelyForward(scope, currentNode); |
| 508 } | 508 } |
| 509 | 509 |
| 510 // If there's no focusable node to advance to, move up the focus scopes unti
l we find one. | 510 // If there's no focusable node to advance to, move up the focus scopes unti
l we find one. |
| 511 FocusNavigationScope currentScope = scope; | 511 FocusNavigationScope currentScope = scope; |
| 512 while (!found) { | 512 while (!found) { |
| 513 Node* owner = currentScope.owner(); | 513 Node* owner = currentScope.owner(); |
| 514 if (!owner) | 514 if (!owner) |
| 515 break; | 515 break; |
| 516 currentScope = FocusNavigationScope::focusNavigationScopeOf(*owner); | 516 currentScope = FocusNavigationScope::focusNavigationScopeOf(*owner); |
| 517 found = findFocusableNodeRecursivelyForward(currentScope, owner); | 517 found = findFocusableElementRecursivelyForward(currentScope, owner); |
| 518 } | 518 } |
| 519 return findFocusableNodeDecendingDownIntoFrameDocument(WebFocusTypeForward,
found); | 519 return findFocusableNodeDecendingDownIntoFrameDocument(WebFocusTypeForward,
found); |
| 520 } | 520 } |
| 521 | 521 |
| 522 Node* FocusController::findFocusableNodeAcrossFocusScopesBackward(const FocusNav
igationScope& scope, Node* currentNode) | 522 Node* FocusController::findFocusableNodeAcrossFocusScopesBackward(const FocusNav
igationScope& scope, Node* currentNode) |
| 523 { | 523 { |
| 524 ASSERT(!currentNode || !isNonFocusableShadowHost(*currentNode)); | 524 ASSERT(!currentNode || !isNonFocusableShadowHost(*currentNode)); |
| 525 Node* found = findFocusableNodeRecursivelyBackward(scope, currentNode); | 525 Node* found = findFocusableElementRecursivelyBackward(scope, currentNode); |
| 526 | 526 |
| 527 // If there's no focusable node to advance to, move up the focus scopes unti
l we find one. | 527 // If there's no focusable node to advance to, move up the focus scopes unti
l we find one. |
| 528 FocusNavigationScope currentScope = scope; | 528 FocusNavigationScope currentScope = scope; |
| 529 while (!found) { | 529 while (!found) { |
| 530 Node* owner = currentScope.owner(); | 530 Node* owner = currentScope.owner(); |
| 531 if (!owner) | 531 if (!owner) |
| 532 break; | 532 break; |
| 533 currentScope = FocusNavigationScope::focusNavigationScopeOf(*owner); | 533 currentScope = FocusNavigationScope::focusNavigationScopeOf(*owner); |
| 534 if (isKeyboardFocusableShadowHost(*owner) && !isShadowHostDelegatesFocus
(*owner)) { | 534 if (isKeyboardFocusableShadowHost(*owner) && !isShadowHostDelegatesFocus
(*owner)) { |
| 535 found = owner; | 535 found = owner; |
| 536 break; | 536 break; |
| 537 } | 537 } |
| 538 found = findFocusableNodeRecursivelyBackward(currentScope, owner); | 538 found = findFocusableElementRecursivelyBackward(currentScope, owner); |
| 539 } | 539 } |
| 540 return findFocusableNodeDecendingDownIntoFrameDocument(WebFocusTypeBackward,
found); | 540 return findFocusableNodeDecendingDownIntoFrameDocument(WebFocusTypeBackward,
found); |
| 541 } | 541 } |
| 542 | 542 |
| 543 Node* FocusController::findFocusableNodeRecursively(WebFocusType type, const Foc
usNavigationScope& scope, Node* start) | 543 Element* FocusController::findFocusableElementRecursively(WebFocusType type, con
st FocusNavigationScope& scope, Node* start) |
| 544 { | 544 { |
| 545 return (type == WebFocusTypeForward) ? | 545 return (type == WebFocusTypeForward) ? |
| 546 findFocusableNodeRecursivelyForward(scope, start) : | 546 findFocusableElementRecursivelyForward(scope, start) : |
| 547 findFocusableNodeRecursivelyBackward(scope, start); | 547 findFocusableElementRecursivelyBackward(scope, start); |
| 548 } | 548 } |
| 549 | 549 |
| 550 Node* FocusController::findFocusableNodeRecursivelyForward(const FocusNavigation
Scope& scope, Node* start) | 550 Element* FocusController::findFocusableElementRecursivelyForward(const FocusNavi
gationScope& scope, Node* start) |
| 551 { | 551 { |
| 552 // Starting node is exclusive. | 552 // Starting node is exclusive. |
| 553 Node* found = findFocusableNode(WebFocusTypeForward, scope, start); | 553 Element* found = findFocusableElement(WebFocusTypeForward, scope, start); |
| 554 if (!found) | 554 if (!found) |
| 555 return nullptr; | 555 return nullptr; |
| 556 if (isShadowHostDelegatesFocus(*found)) { | 556 if (isShadowHostDelegatesFocus(*found)) { |
| 557 if (isShadowHostWithoutCustomFocusLogic(*found)) { | 557 if (isShadowHostWithoutCustomFocusLogic(*found)) { |
| 558 FocusNavigationScope innerScope = FocusNavigationScope::ownedByShado
wHost(*found); | 558 FocusNavigationScope innerScope = FocusNavigationScope::ownedByShado
wHost(*found); |
| 559 Node* foundInInnerFocusScope = findFocusableNodeRecursivelyForward(i
nnerScope, nullptr); | 559 Element* foundInInnerFocusScope = findFocusableElementRecursivelyFor
ward(innerScope, nullptr); |
| 560 return foundInInnerFocusScope ? foundInInnerFocusScope : findFocusab
leNodeRecursivelyForward(scope, found); | 560 return foundInInnerFocusScope ? foundInInnerFocusScope : findFocusab
leElementRecursivelyForward(scope, found); |
| 561 } | 561 } |
| 562 // Skip to the next node. | 562 // Skip to the next node. |
| 563 if (!isNonFocusableFocusScopeOwner(*found)) | 563 if (!isNonFocusableFocusScopeOwner(*found)) |
| 564 found = findFocusableNodeRecursivelyForward(scope, found); | 564 found = findFocusableElementRecursivelyForward(scope, found); |
| 565 } | 565 } |
| 566 if (!found || !isNonFocusableFocusScopeOwner(*found)) | 566 if (!found || !isNonFocusableFocusScopeOwner(*found)) |
| 567 return found; | 567 return found; |
| 568 | 568 |
| 569 // Now |found| is on a focusable scope owner (either shadow host or <shadow>
) | 569 // Now |found| is on a focusable scope owner (either shadow host or <shadow>
) |
| 570 // Find inside the inward scope and return it if found. Otherwise continue s
earching in the same | 570 // Find inside the inward scope and return it if found. Otherwise continue s
earching in the same |
| 571 // scope. | 571 // scope. |
| 572 FocusNavigationScope innerScope = FocusNavigationScope::ownedByNonFocusableF
ocusScopeOwner(*found); | 572 FocusNavigationScope innerScope = FocusNavigationScope::ownedByNonFocusableF
ocusScopeOwner(*found); |
| 573 Node* foundInInnerFocusScope = findFocusableNodeRecursivelyForward(innerScop
e, nullptr); | 573 Element* foundInInnerFocusScope = findFocusableElementRecursivelyForward(inn
erScope, nullptr); |
| 574 return foundInInnerFocusScope ? foundInInnerFocusScope : findFocusableNodeRe
cursivelyForward(scope, found); | 574 return foundInInnerFocusScope ? foundInInnerFocusScope : findFocusableElemen
tRecursivelyForward(scope, found); |
| 575 } | 575 } |
| 576 | 576 |
| 577 Node* FocusController::findFocusableNodeRecursivelyBackward(const FocusNavigatio
nScope& scope, Node* start) | 577 Element* FocusController::findFocusableElementRecursivelyBackward(const FocusNav
igationScope& scope, Node* start) |
| 578 { | 578 { |
| 579 // Starting node is exclusive. | 579 // Starting node is exclusive. |
| 580 Node* found = findFocusableNode(WebFocusTypeBackward, scope, start); | 580 Element* found = findFocusableElement(WebFocusTypeBackward, scope, start); |
| 581 if (!found) | 581 if (!found) |
| 582 return nullptr; | 582 return nullptr; |
| 583 | 583 |
| 584 // Now |found| is on a focusable shadow host. | 584 // Now |found| is on a focusable shadow host. |
| 585 // Find inside shadow backwards. If any focusable element is found, return i
t, otherwise return | 585 // Find inside shadow backwards. If any focusable element is found, return i
t, otherwise return |
| 586 // the host itself. | 586 // the host itself. |
| 587 if (isKeyboardFocusableShadowHost(*found)) { | 587 if (isKeyboardFocusableShadowHost(*found)) { |
| 588 FocusNavigationScope innerScope = FocusNavigationScope::ownedByShadowHos
t(*found); | 588 FocusNavigationScope innerScope = FocusNavigationScope::ownedByShadowHos
t(*found); |
| 589 Node* foundInInnerFocusScope = findFocusableNodeRecursivelyBackward(inne
rScope, nullptr); | 589 Element* foundInInnerFocusScope = findFocusableElementRecursivelyBackwar
d(innerScope, nullptr); |
| 590 if (foundInInnerFocusScope) | 590 if (foundInInnerFocusScope) |
| 591 return foundInInnerFocusScope; | 591 return foundInInnerFocusScope; |
| 592 if (isShadowHostDelegatesFocus(*found)) | 592 if (isShadowHostDelegatesFocus(*found)) |
| 593 found = findFocusableNodeRecursivelyBackward(scope, found); | 593 found = findFocusableElementRecursivelyBackward(scope, found); |
| 594 return found; | 594 return found; |
| 595 } | 595 } |
| 596 | 596 |
| 597 // Now |found| is on a non focusable scope owner (either shadow host or <sha
dow>). | 597 // Now |found| is on a non focusable scope owner (either shadow host or <sha
dow>). |
| 598 // Find focusable node in decendant scope. If not found, find next focusable
node within the | 598 // Find focusable node in decendant scope. If not found, find next focusable
node within the |
| 599 // current scope. | 599 // current scope. |
| 600 if (isNonFocusableFocusScopeOwner(*found)) { | 600 if (isNonFocusableFocusScopeOwner(*found)) { |
| 601 FocusNavigationScope innerScope = FocusNavigationScope::ownedByNonFocusa
bleFocusScopeOwner(*found); | 601 FocusNavigationScope innerScope = FocusNavigationScope::ownedByNonFocusa
bleFocusScopeOwner(*found); |
| 602 Node* foundInInnerFocusScope = findFocusableNodeRecursivelyBackward(inne
rScope, nullptr); | 602 Element* foundInInnerFocusScope = findFocusableElementRecursivelyBackwar
d(innerScope, nullptr); |
| 603 return foundInInnerFocusScope ? foundInInnerFocusScope : findFocusableNo
deRecursivelyBackward(scope, found); | 603 return foundInInnerFocusScope ? foundInInnerFocusScope : findFocusableEl
ementRecursivelyBackward(scope, found); |
| 604 } | 604 } |
| 605 | 605 |
| 606 return found->isElementNode() && !isShadowHostDelegatesFocus(*found) ? found
: findFocusableNodeRecursivelyBackward(scope, found); | 606 return !isShadowHostDelegatesFocus(*found) ? found : findFocusableElementRec
ursivelyBackward(scope, found); |
| 607 } | 607 } |
| 608 | 608 |
| 609 static Node* findNodeWithExactTabIndex(Node* start, int tabIndex, WebFocusType t
ype) | 609 static Node* findNodeWithExactTabIndex(Node* start, int tabIndex, WebFocusType t
ype) |
| 610 { | 610 { |
| 611 // Search is inclusive of start | 611 // Search is inclusive of start |
| 612 for (Node* node = start; node; node = type == WebFocusTypeForward ? NodeTrav
ersal::next(*node) : NodeTraversal::previous(*node)) { | 612 for (Node* node = start; node; node = type == WebFocusTypeForward ? NodeTrav
ersal::next(*node) : NodeTraversal::previous(*node)) { |
| 613 if (shouldVisit(*node) && adjustedTabIndex(*node) == tabIndex) | 613 if (shouldVisit(*node) && adjustedTabIndex(*node) == tabIndex) |
| 614 return node; | 614 return node; |
| 615 } | 615 } |
| 616 return nullptr; | 616 return nullptr; |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 709 return winner; | 709 return winner; |
| 710 } | 710 } |
| 711 | 711 |
| 712 // There are no nodes before start with the same tabindex as start, so look
for a node that: | 712 // There are no nodes before start with the same tabindex as start, so look
for a node that: |
| 713 // 1) has the highest non-zero tabindex (that is less than start's tabindex)
, and | 713 // 1) has the highest non-zero tabindex (that is less than start's tabindex)
, and |
| 714 // 2) comes last in the scope, if there's a tie. | 714 // 2) comes last in the scope, if there's a tie. |
| 715 startingTabIndex = (start && startingTabIndex) ? startingTabIndex : std::num
eric_limits<short>::max(); | 715 startingTabIndex = (start && startingTabIndex) ? startingTabIndex : std::num
eric_limits<short>::max(); |
| 716 return previousNodeWithLowerTabIndex(last, startingTabIndex); | 716 return previousNodeWithLowerTabIndex(last, startingTabIndex); |
| 717 } | 717 } |
| 718 | 718 |
| 719 Node* FocusController::findFocusableNode(WebFocusType type, Node& node) | 719 Element* FocusController::findFocusableElement(WebFocusType type, Node& node) |
| 720 { | 720 { |
| 721 // FIXME: No spacial navigation code yet. | 721 // FIXME: No spacial navigation code yet. |
| 722 ASSERT(type == WebFocusTypeForward || type == WebFocusTypeBackward); | 722 ASSERT(type == WebFocusTypeForward || type == WebFocusTypeBackward); |
| 723 return findFocusableNodeAcrossFocusScopes(type, FocusNavigationScope::focusN
avigationScopeOf(node), &node); | 723 Node* found = findFocusableNodeAcrossFocusScopes(type, FocusNavigationScope:
:focusNavigationScopeOf(node), &node); |
| 724 ASSERT(!found || found->isElementNode()); |
| 725 return toElement(found); |
| 724 } | 726 } |
| 725 | 727 |
| 726 Node* FocusController::findFocusableNode(WebFocusType type, const FocusNavigatio
nScope& scope, Node* node) | 728 Element* FocusController::findFocusableElement(WebFocusType type, const FocusNav
igationScope& scope, Node* node) |
| 727 { | 729 { |
| 728 return type == WebFocusTypeForward ? nextFocusableNode(scope, node) : previo
usFocusableNode(scope, node); | 730 Node* found = (type == WebFocusTypeForward) ? nextFocusableNode(scope, node)
: previousFocusableNode(scope, node); |
| 731 ASSERT(!found || found->isElementNode()); |
| 732 return toElement(found); |
| 729 } | 733 } |
| 730 | 734 |
| 731 static bool relinquishesEditingFocus(const Element& element) | 735 static bool relinquishesEditingFocus(const Element& element) |
| 732 { | 736 { |
| 733 ASSERT(element.hasEditableStyle()); | 737 ASSERT(element.hasEditableStyle()); |
| 734 return element.document().frame() && element.rootEditableElement(); | 738 return element.document().frame() && element.rootEditableElement(); |
| 735 } | 739 } |
| 736 | 740 |
| 737 static void clearSelectionIfNeeded(LocalFrame* oldFocusedFrame, LocalFrame* newF
ocusedFrame, Node* newFocusedNode) | 741 static void clearSelectionIfNeeded(LocalFrame* oldFocusedFrame, LocalFrame* newF
ocusedFrame, Node* newFocusedNode) |
| 738 { | 742 { |
| (...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1015 return consumed; | 1019 return consumed; |
| 1016 } | 1020 } |
| 1017 | 1021 |
| 1018 DEFINE_TRACE(FocusController) | 1022 DEFINE_TRACE(FocusController) |
| 1019 { | 1023 { |
| 1020 visitor->trace(m_page); | 1024 visitor->trace(m_page); |
| 1021 visitor->trace(m_focusedFrame); | 1025 visitor->trace(m_focusedFrame); |
| 1022 } | 1026 } |
| 1023 | 1027 |
| 1024 } // namespace blink | 1028 } // namespace blink |
| OLD | NEW |