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