Home | History | Annotate | Download | only in page
      1 /*
      2  * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
      3  * Copyright (C) 2008 Nuanti Ltd.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  * 1. Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  * 2. Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in the
     12  *    documentation and/or other materials provided with the distribution.
     13  *
     14  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
     15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
     18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     25  */
     26 
     27 #include "config.h"
     28 #include "core/page/FocusController.h"
     29 
     30 #include <limits>
     31 #include "HTMLNames.h"
     32 #include "core/accessibility/AXObjectCache.h"
     33 #include "core/dom/Document.h"
     34 #include "core/dom/Element.h"
     35 #include "core/dom/ElementTraversal.h"
     36 #include "core/dom/NodeTraversal.h"
     37 #include "core/dom/Range.h"
     38 #include "core/dom/shadow/ElementShadow.h"
     39 #include "core/dom/shadow/ShadowRoot.h"
     40 #include "core/editing/Editor.h"
     41 #include "core/editing/FrameSelection.h"
     42 #include "core/editing/htmlediting.h" // For firstPositionInOrBeforeNode
     43 #include "core/events/Event.h"
     44 #include "core/events/ThreadLocalEventNames.h"
     45 #include "core/frame/DOMWindow.h"
     46 #include "core/frame/Frame.h"
     47 #include "core/frame/FrameView.h"
     48 #include "core/html/HTMLAreaElement.h"
     49 #include "core/html/HTMLImageElement.h"
     50 #include "core/html/HTMLTextAreaElement.h"
     51 #include "core/html/shadow/HTMLShadowElement.h"
     52 #include "core/page/Chrome.h"
     53 #include "core/page/ChromeClient.h"
     54 #include "core/page/EventHandler.h"
     55 #include "core/page/FrameTree.h"
     56 #include "core/page/Page.h"
     57 #include "core/frame/Settings.h"
     58 #include "core/page/SpatialNavigation.h"
     59 #include "core/rendering/HitTestResult.h"
     60 
     61 namespace WebCore {
     62 
     63 using namespace HTMLNames;
     64 
     65 // FIXME: Some of Node* return values and Node* arguments should be Element*.
     66 
     67 FocusNavigationScope::FocusNavigationScope(TreeScope* treeScope)
     68     : m_rootTreeScope(treeScope)
     69 {
     70     ASSERT(treeScope);
     71 }
     72 
     73 Node* FocusNavigationScope::rootNode() const
     74 {
     75     return m_rootTreeScope->rootNode();
     76 }
     77 
     78 Element* FocusNavigationScope::owner() const
     79 {
     80     Node* root = rootNode();
     81     if (root->isShadowRoot()) {
     82         ShadowRoot* shadowRoot = toShadowRoot(root);
     83         return shadowRoot->isYoungest() ? shadowRoot->host() : shadowRoot->shadowInsertionPointOfYoungerShadowRoot();
     84     }
     85     if (Frame* frame = root->document().frame())
     86         return frame->ownerElement();
     87     return 0;
     88 }
     89 
     90 FocusNavigationScope FocusNavigationScope::focusNavigationScopeOf(Node* node)
     91 {
     92     ASSERT(node);
     93     Node* root = node;
     94     for (Node* n = node; n; n = n->parentNode())
     95         root = n;
     96     // The result is not always a ShadowRoot nor a DocumentNode since
     97     // a starting node is in an orphaned tree in composed shadow tree.
     98     return FocusNavigationScope(&root->treeScope());
     99 }
    100 
    101 FocusNavigationScope FocusNavigationScope::ownedByNonFocusableFocusScopeOwner(Node* node)
    102 {
    103     ASSERT(node);
    104     if (isShadowHost(node))
    105         return FocusNavigationScope::ownedByShadowHost(node);
    106     ASSERT(isActiveShadowInsertionPoint(*node));
    107     return FocusNavigationScope::ownedByShadowInsertionPoint(toHTMLShadowElement(node));
    108 }
    109 
    110 FocusNavigationScope FocusNavigationScope::ownedByShadowHost(Node* node)
    111 {
    112     ASSERT(isShadowHost(node));
    113     return FocusNavigationScope(toElement(node)->shadow()->youngestShadowRoot());
    114 }
    115 
    116 FocusNavigationScope FocusNavigationScope::ownedByIFrame(HTMLFrameOwnerElement* frame)
    117 {
    118     ASSERT(frame && frame->contentFrame());
    119     return FocusNavigationScope(frame->contentFrame()->document());
    120 }
    121 
    122 FocusNavigationScope FocusNavigationScope::ownedByShadowInsertionPoint(HTMLShadowElement* shadowInsertionPoint)
    123 {
    124     ASSERT(shadowInsertionPoint->isActive());
    125     return FocusNavigationScope(shadowInsertionPoint->olderShadowRoot());
    126 }
    127 
    128 static inline void dispatchEventsOnWindowAndFocusedNode(Document* document, bool focused)
    129 {
    130     // If we have a focused node we should dispatch blur on it before we blur the window.
    131     // If we have a focused node we should dispatch focus on it after we focus the window.
    132     // https://bugs.webkit.org/show_bug.cgi?id=27105
    133 
    134     // Do not fire events while modal dialogs are up.  See https://bugs.webkit.org/show_bug.cgi?id=33962
    135     if (Page* page = document->page()) {
    136         if (page->defersLoading())
    137             return;
    138     }
    139 
    140     if (!focused && document->focusedElement()) {
    141         RefPtr<Element> focusedElement(document->focusedElement());
    142         focusedElement->dispatchBlurEvent(0);
    143         if (focusedElement == document->focusedElement()) {
    144             focusedElement->dispatchFocusOutEvent(EventTypeNames::focusout, 0);
    145             if (focusedElement == document->focusedElement())
    146                 focusedElement->dispatchFocusOutEvent(EventTypeNames::DOMFocusOut, 0);
    147         }
    148     }
    149 
    150     if (DOMWindow* window = document->domWindow())
    151         window->dispatchEvent(Event::create(focused ? EventTypeNames::focus : EventTypeNames::blur));
    152     if (focused && document->focusedElement()) {
    153         RefPtr<Element> focusedElement(document->focusedElement());
    154         focusedElement->dispatchFocusEvent(0, FocusDirectionPage);
    155         if (focusedElement == document->focusedElement()) {
    156             document->focusedElement()->dispatchFocusInEvent(EventTypeNames::focusin, 0);
    157             if (focusedElement == document->focusedElement())
    158                 document->focusedElement()->dispatchFocusInEvent(EventTypeNames::DOMFocusIn, 0);
    159         }
    160     }
    161 }
    162 
    163 static inline bool hasCustomFocusLogic(Element* element)
    164 {
    165     return element->isHTMLElement() && toHTMLElement(element)->hasCustomFocusLogic();
    166 }
    167 
    168 #if !ASSERT_DISABLED
    169 static inline bool isNonFocusableShadowHost(Node* node)
    170 {
    171     ASSERT(node);
    172     if (!node->isElementNode())
    173         return false;
    174     Element* element = toElement(node);
    175     return !element->isFocusable() && isShadowHost(element) && !hasCustomFocusLogic(element);
    176 }
    177 #endif
    178 
    179 static inline bool isNonKeyboardFocusableShadowHost(Node* node)
    180 {
    181     ASSERT(node);
    182     if (!node->isElementNode())
    183         return false;
    184     Element* element = toElement(node);
    185     return !element->isKeyboardFocusable() && isShadowHost(element) && !hasCustomFocusLogic(element);
    186 }
    187 
    188 static inline bool isKeyboardFocusableShadowHost(Node* node)
    189 {
    190     ASSERT(node);
    191     if (!node->isElementNode())
    192         return false;
    193     Element* element = toElement(node);
    194     return element->isKeyboardFocusable() && isShadowHost(element) && !hasCustomFocusLogic(element);
    195 }
    196 
    197 static inline bool isNonFocusableFocusScopeOwner(Node* node)
    198 {
    199     ASSERT(node);
    200     return isNonKeyboardFocusableShadowHost(node) || isActiveShadowInsertionPoint(*node);
    201 }
    202 
    203 static inline int adjustedTabIndex(Node* node)
    204 {
    205     ASSERT(node);
    206     return isNonFocusableFocusScopeOwner(node) ? 0 : node->tabIndex();
    207 }
    208 
    209 static inline bool shouldVisit(Node* node)
    210 {
    211     ASSERT(node);
    212     return (node->isElementNode() && toElement(node)->isKeyboardFocusable()) || isNonFocusableFocusScopeOwner(node);
    213 }
    214 
    215 FocusController::FocusController(Page* page)
    216     : m_page(page)
    217     , m_isActive(false)
    218     , m_isFocused(false)
    219     , m_isChangingFocusedFrame(false)
    220     , m_containingWindowIsVisible(false)
    221 {
    222 }
    223 
    224 PassOwnPtr<FocusController> FocusController::create(Page* page)
    225 {
    226     return adoptPtr(new FocusController(page));
    227 }
    228 
    229 void FocusController::setFocusedFrame(PassRefPtr<Frame> frame)
    230 {
    231     ASSERT(!frame || frame->page() == m_page);
    232     if (m_focusedFrame == frame || m_isChangingFocusedFrame)
    233         return;
    234 
    235     m_isChangingFocusedFrame = true;
    236 
    237     RefPtr<Frame> oldFrame = m_focusedFrame;
    238     RefPtr<Frame> newFrame = frame;
    239 
    240     m_focusedFrame = newFrame;
    241 
    242     // Now that the frame is updated, fire events and update the selection focused states of both frames.
    243     if (oldFrame && oldFrame->view()) {
    244         oldFrame->selection().setFocused(false);
    245         oldFrame->domWindow()->dispatchEvent(Event::create(EventTypeNames::blur));
    246     }
    247 
    248     if (newFrame && newFrame->view() && isFocused()) {
    249         newFrame->selection().setFocused(true);
    250         newFrame->domWindow()->dispatchEvent(Event::create(EventTypeNames::focus));
    251     }
    252 
    253     m_isChangingFocusedFrame = false;
    254 }
    255 
    256 Frame* FocusController::focusedOrMainFrame() const
    257 {
    258     if (Frame* frame = focusedFrame())
    259         return frame;
    260     return m_page->mainFrame();
    261 }
    262 
    263 void FocusController::setFocused(bool focused)
    264 {
    265     if (isFocused() == focused)
    266         return;
    267 
    268     m_isFocused = focused;
    269 
    270     if (!m_isFocused)
    271         focusedOrMainFrame()->eventHandler().stopAutoscroll();
    272 
    273     if (!m_focusedFrame)
    274         setFocusedFrame(m_page->mainFrame());
    275 
    276     if (m_focusedFrame->view()) {
    277         m_focusedFrame->selection().setFocused(focused);
    278         dispatchEventsOnWindowAndFocusedNode(m_focusedFrame->document(), focused);
    279     }
    280 }
    281 
    282 Node* FocusController::findFocusableNodeDecendingDownIntoFrameDocument(FocusDirection direction, Node* node)
    283 {
    284     // The node we found might be a HTMLFrameOwnerElement, so descend down the tree until we find either:
    285     // 1) a focusable node, or
    286     // 2) the deepest-nested HTMLFrameOwnerElement.
    287     while (node && node->isFrameOwnerElement()) {
    288         HTMLFrameOwnerElement* owner = toHTMLFrameOwnerElement(node);
    289         if (!owner->contentFrame())
    290             break;
    291         Node* foundNode = findFocusableNode(direction, FocusNavigationScope::ownedByIFrame(owner), 0);
    292         if (!foundNode)
    293             break;
    294         ASSERT(node != foundNode);
    295         node = foundNode;
    296     }
    297     return node;
    298 }
    299 
    300 bool FocusController::setInitialFocus(FocusDirection direction)
    301 {
    302     bool didAdvanceFocus = advanceFocus(direction, true);
    303 
    304     // If focus is being set initially, accessibility needs to be informed that system focus has moved
    305     // into the web area again, even if focus did not change within WebCore. PostNotification is called instead
    306     // of handleFocusedUIElementChanged, because this will send the notification even if the element is the same.
    307     if (AXObjectCache* cache = focusedOrMainFrame()->document()->existingAXObjectCache())
    308         cache->postNotification(focusedOrMainFrame()->document(), AXObjectCache::AXFocusedUIElementChanged, true);
    309 
    310     return didAdvanceFocus;
    311 }
    312 
    313 bool FocusController::advanceFocus(FocusDirection direction, bool initialFocus)
    314 {
    315     switch (direction) {
    316     case FocusDirectionForward:
    317     case FocusDirectionBackward:
    318         return advanceFocusInDocumentOrder(direction, initialFocus);
    319     case FocusDirectionLeft:
    320     case FocusDirectionRight:
    321     case FocusDirectionUp:
    322     case FocusDirectionDown:
    323         return advanceFocusDirectionally(direction);
    324     default:
    325         ASSERT_NOT_REACHED();
    326     }
    327 
    328     return false;
    329 }
    330 
    331 bool FocusController::advanceFocusInDocumentOrder(FocusDirection direction, bool initialFocus)
    332 {
    333     Frame* frame = focusedOrMainFrame();
    334     ASSERT(frame);
    335     Document* document = frame->document();
    336 
    337     Node* currentNode = document->focusedElement();
    338     // FIXME: Not quite correct when it comes to focus transitions leaving/entering the WebView itself
    339     bool caretBrowsing = frame->settings() && frame->settings()->caretBrowsingEnabled();
    340 
    341     if (caretBrowsing && !currentNode)
    342         currentNode = frame->selection().start().deprecatedNode();
    343 
    344     document->updateLayoutIgnorePendingStylesheets();
    345 
    346     RefPtr<Node> node = findFocusableNodeAcrossFocusScope(direction, FocusNavigationScope::focusNavigationScopeOf(currentNode ? currentNode : document), currentNode);
    347 
    348     if (!node) {
    349         // We didn't find a node to focus, so we should try to pass focus to Chrome.
    350         if (!initialFocus && m_page->chrome().canTakeFocus(direction)) {
    351             document->setFocusedElement(0);
    352             setFocusedFrame(0);
    353             m_page->chrome().takeFocus(direction);
    354             return true;
    355         }
    356 
    357         // Chrome doesn't want focus, so we should wrap focus.
    358         node = findFocusableNodeRecursively(direction, FocusNavigationScope::focusNavigationScopeOf(m_page->mainFrame()->document()), 0);
    359         node = findFocusableNodeDecendingDownIntoFrameDocument(direction, node.get());
    360 
    361         if (!node)
    362             return false;
    363     }
    364 
    365     ASSERT(node);
    366 
    367     if (node == document->focusedElement())
    368         // Focus wrapped around to the same node.
    369         return true;
    370 
    371     if (!node->isElementNode())
    372         // FIXME: May need a way to focus a document here.
    373         return false;
    374 
    375     Element* element = toElement(node);
    376     if (element->isFrameOwnerElement() && (!element->isPluginElement() || !element->isKeyboardFocusable())) {
    377         // We focus frames rather than frame owners.
    378         // FIXME: We should not focus frames that have no scrollbars, as focusing them isn't useful to the user.
    379         HTMLFrameOwnerElement* owner = toHTMLFrameOwnerElement(element);
    380         if (!owner->contentFrame())
    381             return false;
    382 
    383         document->setFocusedElement(0);
    384         setFocusedFrame(owner->contentFrame());
    385         return true;
    386     }
    387 
    388     // FIXME: It would be nice to just be able to call setFocusedElement(node)
    389     // here, but we can't do that because some elements (e.g. HTMLInputElement
    390     // and HTMLTextAreaElement) do extra work in their focus() methods.
    391     Document& newDocument = element->document();
    392 
    393     if (&newDocument != document) {
    394         // Focus is going away from this document, so clear the focused node.
    395         document->setFocusedElement(0);
    396     }
    397 
    398     setFocusedFrame(newDocument.frame());
    399 
    400     if (caretBrowsing) {
    401         Position position = firstPositionInOrBeforeNode(element);
    402         VisibleSelection newSelection(position, position, DOWNSTREAM);
    403         frame->selection().setSelection(newSelection);
    404     }
    405 
    406     element->focus(false, direction);
    407     return true;
    408 }
    409 
    410 Node* FocusController::findFocusableNodeAcrossFocusScope(FocusDirection direction, FocusNavigationScope scope, Node* currentNode)
    411 {
    412     ASSERT(!currentNode || !isNonFocusableShadowHost(currentNode));
    413     Node* found;
    414     if (currentNode && direction == FocusDirectionForward && isKeyboardFocusableShadowHost(currentNode)) {
    415         Node* foundInInnerFocusScope = findFocusableNodeRecursively(direction, FocusNavigationScope::ownedByShadowHost(currentNode), 0);
    416         found = foundInInnerFocusScope ? foundInInnerFocusScope : findFocusableNodeRecursively(direction, scope, currentNode);
    417     } else {
    418         found = findFocusableNodeRecursively(direction, scope, currentNode);
    419     }
    420 
    421     // If there's no focusable node to advance to, move up the focus scopes until we find one.
    422     while (!found) {
    423         Node* owner = scope.owner();
    424         if (!owner)
    425             break;
    426         scope = FocusNavigationScope::focusNavigationScopeOf(owner);
    427         if (direction == FocusDirectionBackward && isKeyboardFocusableShadowHost(owner)) {
    428             found = owner;
    429             break;
    430         }
    431         found = findFocusableNodeRecursively(direction, scope, owner);
    432     }
    433     found = findFocusableNodeDecendingDownIntoFrameDocument(direction, found);
    434     return found;
    435 }
    436 
    437 Node* FocusController::findFocusableNodeRecursively(FocusDirection direction, FocusNavigationScope scope, Node* start)
    438 {
    439     // Starting node is exclusive.
    440     Node* found = findFocusableNode(direction, scope, start);
    441     if (!found)
    442         return 0;
    443     if (direction == FocusDirectionForward) {
    444         if (!isNonFocusableFocusScopeOwner(found))
    445             return found;
    446         Node* foundInInnerFocusScope = findFocusableNodeRecursively(direction, FocusNavigationScope::ownedByNonFocusableFocusScopeOwner(found), 0);
    447         return foundInInnerFocusScope ? foundInInnerFocusScope : findFocusableNodeRecursively(direction, scope, found);
    448     }
    449     ASSERT(direction == FocusDirectionBackward);
    450     if (isKeyboardFocusableShadowHost(found)) {
    451         Node* foundInInnerFocusScope = findFocusableNodeRecursively(direction, FocusNavigationScope::ownedByShadowHost(found), 0);
    452         return foundInInnerFocusScope ? foundInInnerFocusScope : found;
    453     }
    454     if (isNonFocusableFocusScopeOwner(found)) {
    455         Node* foundInInnerFocusScope = findFocusableNodeRecursively(direction, FocusNavigationScope::ownedByNonFocusableFocusScopeOwner(found), 0);
    456         return foundInInnerFocusScope ? foundInInnerFocusScope :findFocusableNodeRecursively(direction, scope, found);
    457     }
    458     return found;
    459 }
    460 
    461 Node* FocusController::findFocusableNode(FocusDirection direction, FocusNavigationScope scope, Node* node)
    462 {
    463     return (direction == FocusDirectionForward)
    464         ? nextFocusableNode(scope, node)
    465         : previousFocusableNode(scope, node);
    466 }
    467 
    468 Node* FocusController::findNodeWithExactTabIndex(Node* start, int tabIndex, FocusDirection direction)
    469 {
    470     // Search is inclusive of start
    471     for (Node* node = start; node; node = direction == FocusDirectionForward ? NodeTraversal::next(*node) : NodeTraversal::previous(*node)) {
    472         if (shouldVisit(node) && adjustedTabIndex(node) == tabIndex)
    473             return node;
    474     }
    475     return 0;
    476 }
    477 
    478 static Node* nextNodeWithGreaterTabIndex(Node* start, int tabIndex)
    479 {
    480     // Search is inclusive of start
    481     int winningTabIndex = std::numeric_limits<short>::max() + 1;
    482     Node* winner = 0;
    483     for (Node* node = start; node; node = NodeTraversal::next(*node)) {
    484         if (shouldVisit(node) && node->tabIndex() > tabIndex && node->tabIndex() < winningTabIndex) {
    485             winner = node;
    486             winningTabIndex = node->tabIndex();
    487         }
    488     }
    489 
    490     return winner;
    491 }
    492 
    493 static Node* previousNodeWithLowerTabIndex(Node* start, int tabIndex)
    494 {
    495     // Search is inclusive of start
    496     int winningTabIndex = 0;
    497     Node* winner = 0;
    498     for (Node* node = start; node; node = NodeTraversal::previous(*node)) {
    499         int currentTabIndex = adjustedTabIndex(node);
    500         if ((shouldVisit(node) || isNonKeyboardFocusableShadowHost(node)) && currentTabIndex < tabIndex && currentTabIndex > winningTabIndex) {
    501             winner = node;
    502             winningTabIndex = currentTabIndex;
    503         }
    504     }
    505     return winner;
    506 }
    507 
    508 Node* FocusController::nextFocusableNode(FocusNavigationScope scope, Node* start)
    509 {
    510     if (start) {
    511         int tabIndex = adjustedTabIndex(start);
    512         // If a node is excluded from the normal tabbing cycle, the next focusable node is determined by tree order
    513         if (tabIndex < 0) {
    514             for (Node* node = NodeTraversal::next(*start); node; node = NodeTraversal::next(*node)) {
    515                 if (shouldVisit(node) && adjustedTabIndex(node) >= 0)
    516                     return node;
    517             }
    518         }
    519 
    520         // First try to find a node with the same tabindex as start that comes after start in the scope.
    521         if (Node* winner = findNodeWithExactTabIndex(NodeTraversal::next(*start), tabIndex, FocusDirectionForward))
    522             return winner;
    523 
    524         if (!tabIndex)
    525             // We've reached the last node in the document with a tabindex of 0. This is the end of the tabbing order.
    526             return 0;
    527     }
    528 
    529     // Look for the first node in the scope that:
    530     // 1) has the lowest tabindex that is higher than start's tabindex (or 0, if start is null), and
    531     // 2) comes first in the scope, if there's a tie.
    532     if (Node* winner = nextNodeWithGreaterTabIndex(scope.rootNode(), start ? adjustedTabIndex(start) : 0))
    533         return winner;
    534 
    535     // There are no nodes with a tabindex greater than start's tabindex,
    536     // so find the first node with a tabindex of 0.
    537     return findNodeWithExactTabIndex(scope.rootNode(), 0, FocusDirectionForward);
    538 }
    539 
    540 Node* FocusController::previousFocusableNode(FocusNavigationScope scope, Node* start)
    541 {
    542     Node* last = 0;
    543     for (Node* node = scope.rootNode(); node; node = node->lastChild())
    544         last = node;
    545     ASSERT(last);
    546 
    547     // First try to find the last node in the scope that comes before start and has the same tabindex as start.
    548     // If start is null, find the last node in the scope with a tabindex of 0.
    549     Node* startingNode;
    550     int startingTabIndex;
    551     if (start) {
    552         startingNode = NodeTraversal::previous(*start);
    553         startingTabIndex = adjustedTabIndex(start);
    554     } else {
    555         startingNode = last;
    556         startingTabIndex = 0;
    557     }
    558 
    559     // However, if a node is excluded from the normal tabbing cycle, the previous focusable node is determined by tree order
    560     if (startingTabIndex < 0) {
    561         for (Node* node = startingNode; node; node = NodeTraversal::previous(*node)) {
    562             if (shouldVisit(node) && adjustedTabIndex(node) >= 0)
    563                 return node;
    564         }
    565     }
    566 
    567     if (Node* winner = findNodeWithExactTabIndex(startingNode, startingTabIndex, FocusDirectionBackward))
    568         return winner;
    569 
    570     // There are no nodes before start with the same tabindex as start, so look for a node that:
    571     // 1) has the highest non-zero tabindex (that is less than start's tabindex), and
    572     // 2) comes last in the scope, if there's a tie.
    573     startingTabIndex = (start && startingTabIndex) ? startingTabIndex : std::numeric_limits<short>::max();
    574     return previousNodeWithLowerTabIndex(last, startingTabIndex);
    575 }
    576 
    577 static bool relinquishesEditingFocus(Node *node)
    578 {
    579     ASSERT(node);
    580     ASSERT(node->rendererIsEditable());
    581     return node->document().frame() && node->rootEditableElement();
    582 }
    583 
    584 static void clearSelectionIfNeeded(Frame* oldFocusedFrame, Frame* newFocusedFrame, Node* newFocusedNode)
    585 {
    586     if (!oldFocusedFrame || !newFocusedFrame)
    587         return;
    588 
    589     if (oldFocusedFrame->document() != newFocusedFrame->document())
    590         return;
    591 
    592     FrameSelection& selection = oldFocusedFrame->selection();
    593     if (selection.isNone())
    594         return;
    595 
    596     bool caretBrowsing = oldFocusedFrame->settings()->caretBrowsingEnabled();
    597     if (caretBrowsing)
    598         return;
    599 
    600     Node* selectionStartNode = selection.selection().start().deprecatedNode();
    601     if (selectionStartNode == newFocusedNode || selectionStartNode->isDescendantOf(newFocusedNode) || selectionStartNode->deprecatedShadowAncestorNode() == newFocusedNode)
    602         return;
    603 
    604     if (Node* mousePressNode = newFocusedFrame->eventHandler().mousePressNode()) {
    605         if (mousePressNode->renderer() && !mousePressNode->canStartSelection()) {
    606             // Don't clear the selection for contentEditable elements, but do clear it for input and textarea. See bug 38696.
    607             Node* root = selection.rootEditableElement();
    608             if (!root)
    609                 return;
    610 
    611             if (Node* shadowAncestorNode = root->deprecatedShadowAncestorNode()) {
    612                 if (!shadowAncestorNode->hasTagName(inputTag) && !isHTMLTextAreaElement(shadowAncestorNode))
    613                     return;
    614             }
    615         }
    616     }
    617 
    618     selection.clear();
    619 }
    620 
    621 bool FocusController::setFocusedElement(Element* element, PassRefPtr<Frame> newFocusedFrame, FocusDirection direction)
    622 {
    623     RefPtr<Frame> oldFocusedFrame = focusedFrame();
    624     RefPtr<Document> oldDocument = oldFocusedFrame ? oldFocusedFrame->document() : 0;
    625 
    626     Element* oldFocusedElement = oldDocument ? oldDocument->focusedElement() : 0;
    627     if (element && oldFocusedElement == element)
    628         return true;
    629 
    630     // FIXME: Might want to disable this check for caretBrowsing
    631     if (oldFocusedElement && oldFocusedElement->isRootEditableElement() && !relinquishesEditingFocus(oldFocusedElement))
    632         return false;
    633 
    634     m_page->chrome().client().willSetInputMethodState();
    635 
    636     RefPtr<Document> newDocument;
    637     if (element)
    638         newDocument = &element->document();
    639     else if (newFocusedFrame)
    640         newDocument = newFocusedFrame->document();
    641 
    642     if (newDocument && oldDocument == newDocument && newDocument->focusedElement() == element)
    643         return true;
    644 
    645     clearSelectionIfNeeded(oldFocusedFrame.get(), newFocusedFrame.get(), element);
    646 
    647     if (oldDocument && oldDocument != newDocument)
    648         oldDocument->setFocusedElement(0);
    649 
    650     if (newFocusedFrame && !newFocusedFrame->page()) {
    651         setFocusedFrame(0);
    652         return false;
    653     }
    654     setFocusedFrame(newFocusedFrame);
    655 
    656     // Setting the focused node can result in losing our last reft to node when JS event handlers fire.
    657     RefPtr<Element> protect = element;
    658     if (newDocument) {
    659         bool successfullyFocused = newDocument->setFocusedElement(element, direction);
    660         if (!successfullyFocused)
    661             return false;
    662     }
    663 
    664     return true;
    665 }
    666 
    667 void FocusController::setActive(bool active)
    668 {
    669     if (m_isActive == active)
    670         return;
    671 
    672     m_isActive = active;
    673 
    674     if (FrameView* view = m_page->mainFrame()->view()) {
    675         view->updateLayoutAndStyleIfNeededRecursive();
    676         view->updateControlTints();
    677     }
    678 
    679     focusedOrMainFrame()->selection().pageActivationChanged();
    680 }
    681 
    682 static void contentAreaDidShowOrHide(ScrollableArea* scrollableArea, bool didShow)
    683 {
    684     if (didShow)
    685         scrollableArea->contentAreaDidShow();
    686     else
    687         scrollableArea->contentAreaDidHide();
    688 }
    689 
    690 void FocusController::setContainingWindowIsVisible(bool containingWindowIsVisible)
    691 {
    692     if (m_containingWindowIsVisible == containingWindowIsVisible)
    693         return;
    694 
    695     m_containingWindowIsVisible = containingWindowIsVisible;
    696 
    697     FrameView* view = m_page->mainFrame()->view();
    698     if (!view)
    699         return;
    700 
    701     contentAreaDidShowOrHide(view, containingWindowIsVisible);
    702 
    703     for (Frame* frame = m_page->mainFrame(); frame; frame = frame->tree().traverseNext()) {
    704         FrameView* frameView = frame->view();
    705         if (!frameView)
    706             continue;
    707 
    708         const HashSet<ScrollableArea*>* scrollableAreas = frameView->scrollableAreas();
    709         if (!scrollableAreas)
    710             continue;
    711 
    712         for (HashSet<ScrollableArea*>::const_iterator it = scrollableAreas->begin(), end = scrollableAreas->end(); it != end; ++it) {
    713             ScrollableArea* scrollableArea = *it;
    714             ASSERT(scrollableArea->scrollbarsCanBeActive());
    715 
    716             contentAreaDidShowOrHide(scrollableArea, containingWindowIsVisible);
    717         }
    718     }
    719 }
    720 
    721 static void updateFocusCandidateIfNeeded(FocusDirection direction, const FocusCandidate& current, FocusCandidate& candidate, FocusCandidate& closest)
    722 {
    723     ASSERT(candidate.visibleNode->isElementNode());
    724     ASSERT(candidate.visibleNode->renderer());
    725 
    726     // Ignore iframes that don't have a src attribute
    727     if (frameOwnerElement(candidate) && (!frameOwnerElement(candidate)->contentFrame() || candidate.rect.isEmpty()))
    728         return;
    729 
    730     // Ignore off screen child nodes of containers that do not scroll (overflow:hidden)
    731     if (candidate.isOffscreen && !canBeScrolledIntoView(direction, candidate))
    732         return;
    733 
    734     distanceDataForNode(direction, current, candidate);
    735     if (candidate.distance == maxDistance())
    736         return;
    737 
    738     if (candidate.isOffscreenAfterScrolling && candidate.alignment < Full)
    739         return;
    740 
    741     if (closest.isNull()) {
    742         closest = candidate;
    743         return;
    744     }
    745 
    746     LayoutRect intersectionRect = intersection(candidate.rect, closest.rect);
    747     if (!intersectionRect.isEmpty() && !areElementsOnSameLine(closest, candidate)) {
    748         // If 2 nodes are intersecting, do hit test to find which node in on top.
    749         LayoutUnit x = intersectionRect.x() + intersectionRect.width() / 2;
    750         LayoutUnit y = intersectionRect.y() + intersectionRect.height() / 2;
    751         HitTestResult result = candidate.visibleNode->document().page()->mainFrame()->eventHandler().hitTestResultAtPoint(IntPoint(x, y), HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::IgnoreClipping | HitTestRequest::ConfusingAndOftenMisusedDisallowShadowContent);
    752         if (candidate.visibleNode->contains(result.innerNode())) {
    753             closest = candidate;
    754             return;
    755         }
    756         if (closest.visibleNode->contains(result.innerNode()))
    757             return;
    758     }
    759 
    760     if (candidate.alignment == closest.alignment) {
    761         if (candidate.distance < closest.distance)
    762             closest = candidate;
    763         return;
    764     }
    765 
    766     if (candidate.alignment > closest.alignment)
    767         closest = candidate;
    768 }
    769 
    770 void FocusController::findFocusCandidateInContainer(Node& container, const LayoutRect& startingRect, FocusDirection direction, FocusCandidate& closest)
    771 {
    772     Element* focusedElement = (focusedFrame() && focusedFrame()->document()) ? focusedFrame()->document()->focusedElement() : 0;
    773 
    774     Element* element = ElementTraversal::firstWithin(container);
    775     FocusCandidate current;
    776     current.rect = startingRect;
    777     current.focusableNode = focusedElement;
    778     current.visibleNode = focusedElement;
    779 
    780     for (; element; element = (element->isFrameOwnerElement() || canScrollInDirection(element, direction))
    781         ? ElementTraversal::nextSkippingChildren(*element, &container)
    782         : ElementTraversal::next(*element, &container)) {
    783         if (element == focusedElement)
    784             continue;
    785 
    786         if (!element->isKeyboardFocusable() && !element->isFrameOwnerElement() && !canScrollInDirection(element, direction))
    787             continue;
    788 
    789         FocusCandidate candidate = FocusCandidate(element, direction);
    790         if (candidate.isNull())
    791             continue;
    792 
    793         candidate.enclosingScrollableBox = &container;
    794         updateFocusCandidateIfNeeded(direction, current, candidate, closest);
    795     }
    796 }
    797 
    798 bool FocusController::advanceFocusDirectionallyInContainer(Node* container, const LayoutRect& startingRect, FocusDirection direction)
    799 {
    800     if (!container)
    801         return false;
    802 
    803     LayoutRect newStartingRect = startingRect;
    804 
    805     if (startingRect.isEmpty())
    806         newStartingRect = virtualRectForDirection(direction, nodeRectInAbsoluteCoordinates(container));
    807 
    808     // Find the closest node within current container in the direction of the navigation.
    809     FocusCandidate focusCandidate;
    810     findFocusCandidateInContainer(*container, newStartingRect, direction, focusCandidate);
    811 
    812     if (focusCandidate.isNull()) {
    813         // Nothing to focus, scroll if possible.
    814         // NOTE: If no scrolling is performed (i.e. scrollInDirection returns false), the
    815         // spatial navigation algorithm will skip this container.
    816         return scrollInDirection(container, direction);
    817     }
    818 
    819     if (HTMLFrameOwnerElement* frameElement = frameOwnerElement(focusCandidate)) {
    820         // If we have an iframe without the src attribute, it will not have a contentFrame().
    821         // We ASSERT here to make sure that
    822         // updateFocusCandidateIfNeeded() will never consider such an iframe as a candidate.
    823         ASSERT(frameElement->contentFrame());
    824 
    825         if (focusCandidate.isOffscreenAfterScrolling) {
    826             scrollInDirection(&focusCandidate.visibleNode->document(), direction);
    827             return true;
    828         }
    829         // Navigate into a new frame.
    830         LayoutRect rect;
    831         Element* focusedElement = focusedOrMainFrame()->document()->focusedElement();
    832         if (focusedElement && !hasOffscreenRect(focusedElement))
    833             rect = nodeRectInAbsoluteCoordinates(focusedElement, true /* ignore border */);
    834         frameElement->contentFrame()->document()->updateLayoutIgnorePendingStylesheets();
    835         if (!advanceFocusDirectionallyInContainer(frameElement->contentFrame()->document(), rect, direction)) {
    836             // The new frame had nothing interesting, need to find another candidate.
    837             return advanceFocusDirectionallyInContainer(container, nodeRectInAbsoluteCoordinates(focusCandidate.visibleNode, true), direction);
    838         }
    839         return true;
    840     }
    841 
    842     if (canScrollInDirection(focusCandidate.visibleNode, direction)) {
    843         if (focusCandidate.isOffscreenAfterScrolling) {
    844             scrollInDirection(focusCandidate.visibleNode, direction);
    845             return true;
    846         }
    847         // Navigate into a new scrollable container.
    848         LayoutRect startingRect;
    849         Element* focusedElement = focusedOrMainFrame()->document()->focusedElement();
    850         if (focusedElement && !hasOffscreenRect(focusedElement))
    851             startingRect = nodeRectInAbsoluteCoordinates(focusedElement, true);
    852         return advanceFocusDirectionallyInContainer(focusCandidate.visibleNode, startingRect, direction);
    853     }
    854     if (focusCandidate.isOffscreenAfterScrolling) {
    855         Node* container = focusCandidate.enclosingScrollableBox;
    856         scrollInDirection(container, direction);
    857         return true;
    858     }
    859 
    860     // We found a new focus node, navigate to it.
    861     Element* element = toElement(focusCandidate.focusableNode);
    862     ASSERT(element);
    863 
    864     element->focus(false, direction);
    865     return true;
    866 }
    867 
    868 bool FocusController::advanceFocusDirectionally(FocusDirection direction)
    869 {
    870     Frame* curFrame = focusedOrMainFrame();
    871     ASSERT(curFrame);
    872 
    873     Document* focusedDocument = curFrame->document();
    874     if (!focusedDocument)
    875         return false;
    876 
    877     Element* focusedElement = focusedDocument->focusedElement();
    878     Node* container = focusedDocument;
    879 
    880     if (container->isDocumentNode())
    881         toDocument(container)->updateLayoutIgnorePendingStylesheets();
    882 
    883     // Figure out the starting rect.
    884     LayoutRect startingRect;
    885     if (focusedElement) {
    886         if (!hasOffscreenRect(focusedElement)) {
    887             container = scrollableEnclosingBoxOrParentFrameForNodeInDirection(direction, focusedElement);
    888             startingRect = nodeRectInAbsoluteCoordinates(focusedElement, true /* ignore border */);
    889         } else if (isHTMLAreaElement(focusedElement)) {
    890             HTMLAreaElement* area = toHTMLAreaElement(focusedElement);
    891             container = scrollableEnclosingBoxOrParentFrameForNodeInDirection(direction, area->imageElement());
    892             startingRect = virtualRectForAreaElementAndDirection(area, direction);
    893         }
    894     }
    895 
    896     bool consumed = false;
    897     do {
    898         consumed = advanceFocusDirectionallyInContainer(container, startingRect, direction);
    899         startingRect = nodeRectInAbsoluteCoordinates(container, true /* ignore border */);
    900         container = scrollableEnclosingBoxOrParentFrameForNodeInDirection(direction, container);
    901         if (container && container->isDocumentNode())
    902             toDocument(container)->updateLayoutIgnorePendingStylesheets();
    903     } while (!consumed && container);
    904 
    905     return consumed;
    906 }
    907 
    908 } // namespace WebCore
    909