2 * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
3 * Copyright (C) 2008 Nuanti Ltd.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
28 #include "core/page/FocusController.h"
30 #include "core/HTMLNames.h"
31 #include "core/accessibility/AXObjectCache.h"
32 #include "core/dom/Document.h"
33 #include "core/dom/Element.h"
34 #include "core/dom/ElementTraversal.h"
35 #include "core/dom/NodeTraversal.h"
36 #include "core/dom/Range.h"
37 #include "core/dom/shadow/ElementShadow.h"
38 #include "core/dom/shadow/ShadowRoot.h"
39 #include "core/editing/Editor.h"
40 #include "core/editing/FrameSelection.h"
41 #include "core/editing/htmlediting.h" // For firstPositionInOrBeforeNode
42 #include "core/events/Event.h"
43 #include "core/frame/LocalDOMWindow.h"
44 #include "core/frame/FrameView.h"
45 #include "core/frame/LocalFrame.h"
46 #include "core/html/HTMLAreaElement.h"
47 #include "core/html/HTMLImageElement.h"
48 #include "core/html/HTMLPlugInElement.h"
49 #include "core/html/HTMLShadowElement.h"
50 #include "core/html/HTMLTextFormControlElement.h"
51 #include "core/page/Chrome.h"
52 #include "core/page/ChromeClient.h"
53 #include "core/page/EventHandler.h"
54 #include "core/page/FrameTree.h"
55 #include "core/page/Page.h"
56 #include "core/frame/Settings.h"
57 #include "core/page/SpatialNavigation.h"
58 #include "core/rendering/HitTestResult.h"
59 #include "core/rendering/RenderLayer.h"
64 using namespace HTMLNames;
66 static inline bool isShadowInsertionPointFocusScopeOwner(Node& node)
68 return isActiveShadowInsertionPoint(node) && toHTMLShadowElement(node).olderShadowRoot();
71 // FIXME: Some of Node* return values and Node* arguments should be Element*.
73 FocusNavigationScope::FocusNavigationScope(TreeScope* treeScope)
74 : m_rootTreeScope(treeScope)
79 Node* FocusNavigationScope::rootNode() const
81 return &m_rootTreeScope->rootNode();
84 Element* FocusNavigationScope::owner() const
86 Node* root = rootNode();
87 if (root->isShadowRoot()) {
88 ShadowRoot* shadowRoot = toShadowRoot(root);
89 return shadowRoot->isYoungest() ? shadowRoot->host() : shadowRoot->shadowInsertionPointOfYoungerShadowRoot();
91 // FIXME: Figure out the right thing for OOPI here.
92 if (Frame* frame = root->document().frame())
93 return frame->deprecatedLocalOwner();
97 FocusNavigationScope FocusNavigationScope::focusNavigationScopeOf(Node* node)
101 for (Node* n = node; n; n = n->parentNode())
103 // The result is not always a ShadowRoot nor a DocumentNode since
104 // a starting node is in an orphaned tree in composed shadow tree.
105 return FocusNavigationScope(&root->treeScope());
108 FocusNavigationScope FocusNavigationScope::ownedByNonFocusableFocusScopeOwner(Node* node)
111 if (isShadowHost(node))
112 return FocusNavigationScope::ownedByShadowHost(node);
113 ASSERT(isShadowInsertionPointFocusScopeOwner(*node));
114 return FocusNavigationScope::ownedByShadowInsertionPoint(toHTMLShadowElement(node));
117 FocusNavigationScope FocusNavigationScope::ownedByShadowHost(Node* node)
119 ASSERT(isShadowHost(node));
120 return FocusNavigationScope(toElement(node)->shadow()->youngestShadowRoot());
123 FocusNavigationScope FocusNavigationScope::ownedByIFrame(HTMLFrameOwnerElement* frame)
125 ASSERT(frame && frame->contentFrame() && frame->contentFrame()->isLocalFrame());
126 return FocusNavigationScope(toLocalFrame(frame->contentFrame())->document());
129 FocusNavigationScope FocusNavigationScope::ownedByShadowInsertionPoint(HTMLShadowElement* shadowInsertionPoint)
131 ASSERT(isShadowInsertionPointFocusScopeOwner(*shadowInsertionPoint));
132 return FocusNavigationScope(shadowInsertionPoint->olderShadowRoot());
135 static inline void dispatchEventsOnWindowAndFocusedNode(Document* document, bool focused)
137 // If we have a focused node we should dispatch blur on it before we blur the window.
138 // If we have a focused node we should dispatch focus on it after we focus the window.
139 // https://bugs.webkit.org/show_bug.cgi?id=27105
141 // Do not fire events while modal dialogs are up. See https://bugs.webkit.org/show_bug.cgi?id=33962
142 if (Page* page = document->page()) {
143 if (page->defersLoading())
147 if (!focused && document->focusedElement()) {
148 RefPtrWillBeRawPtr<Element> focusedElement(document->focusedElement());
149 focusedElement->setFocus(false);
150 focusedElement->dispatchBlurEvent(0);
151 if (focusedElement == document->focusedElement()) {
152 focusedElement->dispatchFocusOutEvent(EventTypeNames::focusout, 0);
153 if (focusedElement == document->focusedElement())
154 focusedElement->dispatchFocusOutEvent(EventTypeNames::DOMFocusOut, 0);
158 if (LocalDOMWindow* window = document->domWindow())
159 window->dispatchEvent(Event::create(focused ? EventTypeNames::focus : EventTypeNames::blur));
160 if (focused && document->focusedElement()) {
161 RefPtrWillBeRawPtr<Element> focusedElement(document->focusedElement());
162 focusedElement->setFocus(true);
163 focusedElement->dispatchFocusEvent(0, FocusTypePage);
164 if (focusedElement == document->focusedElement()) {
165 document->focusedElement()->dispatchFocusInEvent(EventTypeNames::focusin, 0);
166 if (focusedElement == document->focusedElement())
167 document->focusedElement()->dispatchFocusInEvent(EventTypeNames::DOMFocusIn, 0);
172 static inline bool hasCustomFocusLogic(Element* element)
174 return element->isHTMLElement() && toHTMLElement(element)->hasCustomFocusLogic();
178 static inline bool isNonFocusableShadowHost(Node* node)
181 if (!node->isElementNode())
183 Element* element = toElement(node);
184 return !element->isFocusable() && isShadowHost(element) && !hasCustomFocusLogic(element);
188 static inline bool isNonKeyboardFocusableShadowHost(Node* node)
191 if (!node->isElementNode())
193 Element* element = toElement(node);
194 return !element->isKeyboardFocusable() && isShadowHost(element) && !hasCustomFocusLogic(element);
197 static inline bool isKeyboardFocusableShadowHost(Node* node)
200 if (!node->isElementNode())
202 Element* element = toElement(node);
203 return element->isKeyboardFocusable() && isShadowHost(element) && !hasCustomFocusLogic(element);
206 static inline bool isNonFocusableFocusScopeOwner(Node* node)
209 return isNonKeyboardFocusableShadowHost(node) || isShadowInsertionPointFocusScopeOwner(*node);
212 static inline int adjustedTabIndex(Node* node)
215 return isNonFocusableFocusScopeOwner(node) ? 0 : node->tabIndex();
218 static inline bool shouldVisit(Node* node)
221 return (node->isElementNode() && toElement(node)->isKeyboardFocusable()) || isNonFocusableFocusScopeOwner(node);
224 FocusController::FocusController(Page* page)
228 , m_isChangingFocusedFrame(false)
232 PassOwnPtr<FocusController> FocusController::create(Page* page)
234 return adoptPtr(new FocusController(page));
237 void FocusController::setFocusedFrame(PassRefPtr<Frame> frame)
239 ASSERT(!frame || frame->page() == m_page);
240 if (m_focusedFrame == frame || m_isChangingFocusedFrame)
243 m_isChangingFocusedFrame = true;
245 RefPtr<LocalFrame> oldFrame = (m_focusedFrame && m_focusedFrame->isLocalFrame()) ? toLocalFrame(m_focusedFrame.get()) : 0;
246 RefPtr<LocalFrame> newFrame = (frame && frame->isLocalFrame()) ? toLocalFrame(frame.get()) : 0;
248 m_focusedFrame = frame.get();
250 // Now that the frame is updated, fire events and update the selection focused states of both frames.
251 if (oldFrame && oldFrame->view()) {
252 oldFrame->selection().setFocused(false);
253 oldFrame->domWindow()->dispatchEvent(Event::create(EventTypeNames::blur));
256 if (newFrame && newFrame->view() && isFocused()) {
257 newFrame->selection().setFocused(true);
258 newFrame->domWindow()->dispatchEvent(Event::create(EventTypeNames::focus));
261 m_isChangingFocusedFrame = false;
263 m_page->chrome().client().focusedFrameChanged(newFrame.get());
266 void FocusController::focusDocumentView(PassRefPtr<Frame> frame)
268 ASSERT(!frame || frame->page() == m_page);
269 if (m_focusedFrame == frame)
272 RefPtr<LocalFrame> focusedFrame = (m_focusedFrame && m_focusedFrame->isLocalFrame()) ? toLocalFrame(m_focusedFrame.get()) : 0;
273 if (focusedFrame && focusedFrame->view()) {
274 RefPtrWillBeRawPtr<Document> document = focusedFrame->document();
275 Element* focusedElement = document ? document->focusedElement() : 0;
276 if (focusedElement) {
277 focusedElement->dispatchBlurEvent(0);
278 if (focusedElement == document->focusedElement()) {
279 focusedElement->dispatchFocusOutEvent(EventTypeNames::focusout, 0);
280 if (focusedElement == document->focusedElement())
281 focusedElement->dispatchFocusOutEvent(EventTypeNames::DOMFocusOut, 0);
286 RefPtr<LocalFrame> newFocusedFrame = (frame && frame->isLocalFrame()) ? toLocalFrame(frame.get()) : 0;
287 if (newFocusedFrame && newFocusedFrame->view()) {
288 RefPtrWillBeRawPtr<Document> document = newFocusedFrame->document();
289 Element* focusedElement = document ? document->focusedElement() : 0;
290 if (focusedElement) {
291 focusedElement->dispatchFocusEvent(0, FocusTypePage);
292 if (focusedElement == document->focusedElement()) {
293 document->focusedElement()->dispatchFocusInEvent(EventTypeNames::focusin, 0);
294 if (focusedElement == document->focusedElement())
295 document->focusedElement()->dispatchFocusInEvent(EventTypeNames::DOMFocusIn, 0);
300 setFocusedFrame(frame);
303 Frame* FocusController::focusedOrMainFrame() const
305 if (Frame* frame = focusedFrame())
308 // FIXME: This is a temporary hack to ensure that we return a LocalFrame, even when the mainFrame is remote.
309 // FocusController needs to be refactored to deal with RemoteFrames cross-process focus transfers.
310 for (Frame* frame = m_page->mainFrame()->tree().top(); frame; frame = frame->tree().traverseNext()) {
311 if (frame->isLocalRoot())
315 return m_page->mainFrame();
318 void FocusController::setFocused(bool focused)
320 if (isFocused() == focused)
323 m_isFocused = focused;
325 if (!m_isFocused && focusedOrMainFrame()->isLocalFrame())
326 toLocalFrame(focusedOrMainFrame())->eventHandler().stopAutoscroll();
329 setFocusedFrame(m_page->mainFrame());
331 // setFocusedFrame above might reject to update m_focusedFrame, or
332 // m_focusedFrame might be changed by blur/focus event handlers.
333 if (m_focusedFrame && m_focusedFrame->isLocalFrame() && toLocalFrame(m_focusedFrame.get())->view()) {
334 toLocalFrame(m_focusedFrame.get())->selection().setFocused(focused);
335 dispatchEventsOnWindowAndFocusedNode(toLocalFrame(m_focusedFrame.get())->document(), focused);
339 Node* FocusController::findFocusableNodeDecendingDownIntoFrameDocument(FocusType type, Node* node)
341 // The node we found might be a HTMLFrameOwnerElement, so descend down the tree until we find either:
342 // 1) a focusable node, or
343 // 2) the deepest-nested HTMLFrameOwnerElement.
344 while (node && node->isFrameOwnerElement()) {
345 HTMLFrameOwnerElement* owner = toHTMLFrameOwnerElement(node);
346 if (!owner->contentFrame() || !owner->contentFrame()->isLocalFrame())
348 Node* foundNode = findFocusableNode(type, FocusNavigationScope::ownedByIFrame(owner), 0);
351 ASSERT(node != foundNode);
357 bool FocusController::setInitialFocus(FocusType type)
359 bool didAdvanceFocus = advanceFocus(type, true);
361 // If focus is being set initially, accessibility needs to be informed that system focus has moved
362 // into the web area again, even if focus did not change within WebCore. PostNotification is called instead
363 // of handleFocusedUIElementChanged, because this will send the notification even if the element is the same.
364 if (focusedOrMainFrame()->isLocalFrame()) {
365 Document* document = toLocalFrame(focusedOrMainFrame())->document();
366 if (AXObjectCache* cache = document->existingAXObjectCache())
367 cache->postNotification(document, AXObjectCache::AXFocusedUIElementChanged, true);
370 return didAdvanceFocus;
373 bool FocusController::advanceFocus(FocusType type, bool initialFocus)
376 case FocusTypeForward:
377 case FocusTypeBackward:
378 return advanceFocusInDocumentOrder(type, initialFocus);
383 return advanceFocusDirectionally(type);
385 ASSERT_NOT_REACHED();
391 bool FocusController::advanceFocusInDocumentOrder(FocusType type, bool initialFocus)
393 // FIXME: Focus advancement won't work with externally rendered frames until after
394 // inter-frame focus control is moved out of Blink.
395 if (!focusedOrMainFrame()->isLocalFrame())
397 LocalFrame* frame = toLocalFrame(focusedOrMainFrame());
399 Document* document = frame->document();
401 Node* currentNode = document->focusedElement();
402 // FIXME: Not quite correct when it comes to focus transitions leaving/entering the WebView itself
403 bool caretBrowsing = frame->settings() && frame->settings()->caretBrowsingEnabled();
405 if (caretBrowsing && !currentNode)
406 currentNode = frame->selection().start().deprecatedNode();
408 document->updateLayoutIgnorePendingStylesheets();
410 RefPtrWillBeRawPtr<Node> node = findFocusableNodeAcrossFocusScope(type, FocusNavigationScope::focusNavigationScopeOf(currentNode ? currentNode : document), currentNode);
413 // We didn't find a node to focus, so we should try to pass focus to Chrome.
414 if (!initialFocus && m_page->chrome().canTakeFocus(type)) {
415 document->setFocusedElement(nullptr);
416 setFocusedFrame(nullptr);
417 m_page->chrome().takeFocus(type);
421 // Chrome doesn't want focus, so we should wrap focus.
422 if (!m_page->mainFrame()->isLocalFrame())
424 node = findFocusableNodeRecursively(type, FocusNavigationScope::focusNavigationScopeOf(m_page->deprecatedLocalMainFrame()->document()), 0);
425 node = findFocusableNodeDecendingDownIntoFrameDocument(type, node.get());
433 if (node == document->focusedElement())
434 // Focus wrapped around to the same node.
437 if (!node->isElementNode())
438 // FIXME: May need a way to focus a document here.
441 Element* element = toElement(node);
442 if (element->isFrameOwnerElement() && (!isHTMLPlugInElement(*element) || !element->isKeyboardFocusable())) {
443 // We focus frames rather than frame owners.
444 // FIXME: We should not focus frames that have no scrollbars, as focusing them isn't useful to the user.
445 HTMLFrameOwnerElement* owner = toHTMLFrameOwnerElement(element);
446 if (!owner->contentFrame())
449 document->setFocusedElement(nullptr);
450 setFocusedFrame(owner->contentFrame());
454 // FIXME: It would be nice to just be able to call setFocusedElement(node)
455 // here, but we can't do that because some elements (e.g. HTMLInputElement
456 // and HTMLTextAreaElement) do extra work in their focus() methods.
457 Document& newDocument = element->document();
459 if (&newDocument != document) {
460 // Focus is going away from this document, so clear the focused node.
461 document->setFocusedElement(nullptr);
464 setFocusedFrame(newDocument.frame());
467 Position position = firstPositionInOrBeforeNode(element);
468 VisibleSelection newSelection(position, position, DOWNSTREAM);
469 frame->selection().setSelection(newSelection);
472 element->focus(false, type);
476 Node* FocusController::findFocusableNodeAcrossFocusScope(FocusType type, FocusNavigationScope scope, Node* currentNode)
478 ASSERT(!currentNode || !isNonFocusableShadowHost(currentNode));
480 if (currentNode && type == FocusTypeForward && isKeyboardFocusableShadowHost(currentNode)) {
481 Node* foundInInnerFocusScope = findFocusableNodeRecursively(type, FocusNavigationScope::ownedByShadowHost(currentNode), 0);
482 found = foundInInnerFocusScope ? foundInInnerFocusScope : findFocusableNodeRecursively(type, scope, currentNode);
484 found = findFocusableNodeRecursively(type, scope, currentNode);
487 // If there's no focusable node to advance to, move up the focus scopes until we find one.
489 Node* owner = scope.owner();
492 scope = FocusNavigationScope::focusNavigationScopeOf(owner);
493 if (type == FocusTypeBackward && isKeyboardFocusableShadowHost(owner)) {
497 found = findFocusableNodeRecursively(type, scope, owner);
499 found = findFocusableNodeDecendingDownIntoFrameDocument(type, found);
503 Node* FocusController::findFocusableNodeRecursively(FocusType type, FocusNavigationScope scope, Node* start)
505 // Starting node is exclusive.
506 Node* found = findFocusableNode(type, scope, start);
509 if (type == FocusTypeForward) {
510 if (!isNonFocusableFocusScopeOwner(found))
512 Node* foundInInnerFocusScope = findFocusableNodeRecursively(type, FocusNavigationScope::ownedByNonFocusableFocusScopeOwner(found), 0);
513 return foundInInnerFocusScope ? foundInInnerFocusScope : findFocusableNodeRecursively(type, scope, found);
515 ASSERT(type == FocusTypeBackward);
516 if (isKeyboardFocusableShadowHost(found)) {
517 Node* foundInInnerFocusScope = findFocusableNodeRecursively(type, FocusNavigationScope::ownedByShadowHost(found), 0);
518 return foundInInnerFocusScope ? foundInInnerFocusScope : found;
520 if (isNonFocusableFocusScopeOwner(found)) {
521 Node* foundInInnerFocusScope = findFocusableNodeRecursively(type, FocusNavigationScope::ownedByNonFocusableFocusScopeOwner(found), 0);
522 return foundInInnerFocusScope ? foundInInnerFocusScope :findFocusableNodeRecursively(type, scope, found);
527 Node* FocusController::findFocusableNode(FocusType type, FocusNavigationScope scope, Node* node)
529 return type == FocusTypeForward ? nextFocusableNode(scope, node) : previousFocusableNode(scope, node);
532 Node* FocusController::findNodeWithExactTabIndex(Node* start, int tabIndex, FocusType type)
534 // Search is inclusive of start
535 for (Node* node = start; node; node = type == FocusTypeForward ? NodeTraversal::next(*node) : NodeTraversal::previous(*node)) {
536 if (shouldVisit(node) && adjustedTabIndex(node) == tabIndex)
542 static Node* nextNodeWithGreaterTabIndex(Node* start, int tabIndex)
544 // Search is inclusive of start
545 int winningTabIndex = std::numeric_limits<short>::max() + 1;
547 for (Node* node = start; node; node = NodeTraversal::next(*node)) {
548 if (shouldVisit(node) && node->tabIndex() > tabIndex && node->tabIndex() < winningTabIndex) {
550 winningTabIndex = node->tabIndex();
557 static Node* previousNodeWithLowerTabIndex(Node* start, int tabIndex)
559 // Search is inclusive of start
560 int winningTabIndex = 0;
562 for (Node* node = start; node; node = NodeTraversal::previous(*node)) {
563 int currentTabIndex = adjustedTabIndex(node);
564 if ((shouldVisit(node) || isNonKeyboardFocusableShadowHost(node)) && currentTabIndex < tabIndex && currentTabIndex > winningTabIndex) {
566 winningTabIndex = currentTabIndex;
572 Node* FocusController::nextFocusableNode(FocusNavigationScope scope, Node* start)
575 int tabIndex = adjustedTabIndex(start);
576 // If a node is excluded from the normal tabbing cycle, the next focusable node is determined by tree order
578 for (Node* node = NodeTraversal::next(*start); node; node = NodeTraversal::next(*node)) {
579 if (shouldVisit(node) && adjustedTabIndex(node) >= 0)
584 // First try to find a node with the same tabindex as start that comes after start in the scope.
585 if (Node* winner = findNodeWithExactTabIndex(NodeTraversal::next(*start), tabIndex, FocusTypeForward))
589 // We've reached the last node in the document with a tabindex of 0. This is the end of the tabbing order.
593 // Look for the first node in the scope that:
594 // 1) has the lowest tabindex that is higher than start's tabindex (or 0, if start is null), and
595 // 2) comes first in the scope, if there's a tie.
596 if (Node* winner = nextNodeWithGreaterTabIndex(scope.rootNode(), start ? adjustedTabIndex(start) : 0))
599 // There are no nodes with a tabindex greater than start's tabindex,
600 // so find the first node with a tabindex of 0.
601 return findNodeWithExactTabIndex(scope.rootNode(), 0, FocusTypeForward);
604 Node* FocusController::previousFocusableNode(FocusNavigationScope scope, Node* start)
607 for (Node* node = scope.rootNode(); node; node = node->lastChild())
611 // First try to find the last node in the scope that comes before start and has the same tabindex as start.
612 // If start is null, find the last node in the scope with a tabindex of 0.
614 int startingTabIndex;
616 startingNode = NodeTraversal::previous(*start);
617 startingTabIndex = adjustedTabIndex(start);
620 startingTabIndex = 0;
623 // However, if a node is excluded from the normal tabbing cycle, the previous focusable node is determined by tree order
624 if (startingTabIndex < 0) {
625 for (Node* node = startingNode; node; node = NodeTraversal::previous(*node)) {
626 if (shouldVisit(node) && adjustedTabIndex(node) >= 0)
631 if (Node* winner = findNodeWithExactTabIndex(startingNode, startingTabIndex, FocusTypeBackward))
634 // There are no nodes before start with the same tabindex as start, so look for a node that:
635 // 1) has the highest non-zero tabindex (that is less than start's tabindex), and
636 // 2) comes last in the scope, if there's a tie.
637 startingTabIndex = (start && startingTabIndex) ? startingTabIndex : std::numeric_limits<short>::max();
638 return previousNodeWithLowerTabIndex(last, startingTabIndex);
641 static bool relinquishesEditingFocus(Node *node)
644 ASSERT(node->hasEditableStyle());
645 return node->document().frame() && node->rootEditableElement();
648 static void clearSelectionIfNeeded(LocalFrame* oldFocusedFrame, LocalFrame* newFocusedFrame, Node* newFocusedNode)
650 if (!oldFocusedFrame || !newFocusedFrame)
653 if (oldFocusedFrame->document() != newFocusedFrame->document())
656 FrameSelection& selection = oldFocusedFrame->selection();
657 if (selection.isNone())
660 bool caretBrowsing = oldFocusedFrame->settings()->caretBrowsingEnabled();
664 Node* selectionStartNode = selection.selection().start().deprecatedNode();
665 if (selectionStartNode == newFocusedNode || selectionStartNode->isDescendantOf(newFocusedNode))
668 if (!enclosingTextFormControl(selectionStartNode))
671 if (selectionStartNode->isInShadowTree() && selectionStartNode->shadowHost() == newFocusedNode)
677 bool FocusController::setFocusedElement(Element* element, PassRefPtr<Frame> newFocusedFrame, FocusType type)
679 RefPtr<LocalFrame> oldFocusedFrame = toLocalFrame(focusedFrame());
680 RefPtrWillBeRawPtr<Document> oldDocument = oldFocusedFrame ? oldFocusedFrame->document() : 0;
682 Element* oldFocusedElement = oldDocument ? oldDocument->focusedElement() : 0;
683 if (element && oldFocusedElement == element)
686 // FIXME: Might want to disable this check for caretBrowsing
687 if (oldFocusedElement && oldFocusedElement->isRootEditableElement() && !relinquishesEditingFocus(oldFocusedElement))
690 m_page->chrome().client().willSetInputMethodState();
692 RefPtrWillBeRawPtr<Document> newDocument = nullptr;
694 newDocument = &element->document();
695 else if (newFocusedFrame && newFocusedFrame->isLocalFrame())
696 newDocument = toLocalFrame(newFocusedFrame.get())->document();
698 if (newDocument && oldDocument == newDocument && newDocument->focusedElement() == element)
701 clearSelectionIfNeeded(oldFocusedFrame.get(), toLocalFrame(newFocusedFrame.get()), element);
703 if (oldDocument && oldDocument != newDocument)
704 oldDocument->setFocusedElement(nullptr);
706 if (newFocusedFrame && !newFocusedFrame->page()) {
707 setFocusedFrame(nullptr);
710 setFocusedFrame(newFocusedFrame);
712 // Setting the focused node can result in losing our last reft to node when JS event handlers fire.
713 RefPtrWillBeRawPtr<Element> protect ALLOW_UNUSED = element;
715 bool successfullyFocused = newDocument->setFocusedElement(element, type);
716 if (!successfullyFocused)
723 void FocusController::setActive(bool active)
725 if (m_isActive == active)
730 Frame* frame = focusedOrMainFrame();
731 if (frame->isLocalFrame())
732 toLocalFrame(frame)->selection().pageActivationChanged();
735 static void updateFocusCandidateIfNeeded(FocusType type, const FocusCandidate& current, FocusCandidate& candidate, FocusCandidate& closest)
737 ASSERT(candidate.visibleNode->isElementNode());
738 ASSERT(candidate.visibleNode->renderer());
740 // Ignore iframes that don't have a src attribute
741 if (frameOwnerElement(candidate) && (!frameOwnerElement(candidate)->contentFrame() || candidate.rect.isEmpty()))
744 // Ignore off screen child nodes of containers that do not scroll (overflow:hidden)
745 if (candidate.isOffscreen && !canBeScrolledIntoView(type, candidate))
748 distanceDataForNode(type, current, candidate);
749 if (candidate.distance == maxDistance())
752 if (candidate.isOffscreenAfterScrolling && candidate.alignment < Full)
755 if (closest.isNull()) {
760 LayoutRect intersectionRect = intersection(candidate.rect, closest.rect);
761 if (!intersectionRect.isEmpty() && !areElementsOnSameLine(closest, candidate)
762 && intersectionRect == candidate.rect) {
763 // If 2 nodes are intersecting, do hit test to find which node in on top.
764 LayoutUnit x = intersectionRect.x() + intersectionRect.width() / 2;
765 LayoutUnit y = intersectionRect.y() + intersectionRect.height() / 2;
766 if (!candidate.visibleNode->document().page()->mainFrame()->isLocalFrame())
768 HitTestResult result = candidate.visibleNode->document().page()->deprecatedLocalMainFrame()->eventHandler().hitTestResultAtPoint(IntPoint(x, y), HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::IgnoreClipping);
769 if (candidate.visibleNode->contains(result.innerNode())) {
773 if (closest.visibleNode->contains(result.innerNode()))
777 if (candidate.alignment == closest.alignment) {
778 if (candidate.distance < closest.distance)
783 if (candidate.alignment > closest.alignment)
787 void FocusController::findFocusCandidateInContainer(Node& container, const LayoutRect& startingRect, FocusType type, FocusCandidate& closest)
789 Element* focusedElement = (focusedFrame() && toLocalFrame(focusedFrame())->document()) ? toLocalFrame(focusedFrame())->document()->focusedElement() : 0;
791 Element* element = ElementTraversal::firstWithin(container);
792 FocusCandidate current;
793 current.rect = startingRect;
794 current.focusableNode = focusedElement;
795 current.visibleNode = focusedElement;
797 for (; element; element = (element->isFrameOwnerElement() || canScrollInDirection(element, type))
798 ? ElementTraversal::nextSkippingChildren(*element, &container)
799 : ElementTraversal::next(*element, &container)) {
800 if (element == focusedElement)
803 if (!element->isKeyboardFocusable() && !element->isFrameOwnerElement() && !canScrollInDirection(element, type))
806 FocusCandidate candidate = FocusCandidate(element, type);
807 if (candidate.isNull())
810 candidate.enclosingScrollableBox = &container;
811 updateFocusCandidateIfNeeded(type, current, candidate, closest);
815 bool FocusController::advanceFocusDirectionallyInContainer(Node* container, const LayoutRect& startingRect, FocusType type)
820 LayoutRect newStartingRect = startingRect;
822 if (startingRect.isEmpty())
823 newStartingRect = virtualRectForDirection(type, nodeRectInAbsoluteCoordinates(container));
825 // Find the closest node within current container in the direction of the navigation.
826 FocusCandidate focusCandidate;
827 findFocusCandidateInContainer(*container, newStartingRect, type, focusCandidate);
829 if (focusCandidate.isNull()) {
830 // Nothing to focus, scroll if possible.
831 // NOTE: If no scrolling is performed (i.e. scrollInDirection returns false), the
832 // spatial navigation algorithm will skip this container.
833 return scrollInDirection(container, type);
836 HTMLFrameOwnerElement* frameElement = frameOwnerElement(focusCandidate);
837 // If we have an iframe without the src attribute, it will not have a contentFrame().
838 // We ASSERT here to make sure that
839 // updateFocusCandidateIfNeeded() will never consider such an iframe as a candidate.
840 ASSERT(!frameElement || frameElement->contentFrame());
841 if (frameElement && frameElement->contentFrame()->isLocalFrame()) {
842 if (focusCandidate.isOffscreenAfterScrolling) {
843 scrollInDirection(&focusCandidate.visibleNode->document(), type);
846 // Navigate into a new frame.
848 Element* focusedElement = toLocalFrame(focusedOrMainFrame())->document()->focusedElement();
849 if (focusedElement && !hasOffscreenRect(focusedElement))
850 rect = nodeRectInAbsoluteCoordinates(focusedElement, true /* ignore border */);
851 toLocalFrame(frameElement->contentFrame())->document()->updateLayoutIgnorePendingStylesheets();
852 if (!advanceFocusDirectionallyInContainer(toLocalFrame(frameElement->contentFrame())->document(), rect, type)) {
853 // The new frame had nothing interesting, need to find another candidate.
854 return advanceFocusDirectionallyInContainer(container, nodeRectInAbsoluteCoordinates(focusCandidate.visibleNode, true), type);
859 if (canScrollInDirection(focusCandidate.visibleNode, type)) {
860 if (focusCandidate.isOffscreenAfterScrolling) {
861 scrollInDirection(focusCandidate.visibleNode, type);
864 // Navigate into a new scrollable container.
865 LayoutRect startingRect;
866 Element* focusedElement = toLocalFrame(focusedOrMainFrame())->document()->focusedElement();
867 if (focusedElement && !hasOffscreenRect(focusedElement))
868 startingRect = nodeRectInAbsoluteCoordinates(focusedElement, true);
869 return advanceFocusDirectionallyInContainer(focusCandidate.visibleNode, startingRect, type);
871 if (focusCandidate.isOffscreenAfterScrolling) {
872 Node* container = focusCandidate.enclosingScrollableBox;
873 scrollInDirection(container, type);
877 // We found a new focus node, navigate to it.
878 Element* element = toElement(focusCandidate.focusableNode);
881 element->focus(false, type);
885 bool FocusController::advanceFocusDirectionally(FocusType type)
887 // FIXME: Directional focus changes don't yet work with RemoteFrames.
888 if (!focusedOrMainFrame()->isLocalFrame())
890 LocalFrame* curFrame = toLocalFrame(focusedOrMainFrame());
893 Document* focusedDocument = curFrame->document();
894 if (!focusedDocument)
897 Element* focusedElement = focusedDocument->focusedElement();
898 Node* container = focusedDocument;
900 if (container->isDocumentNode())
901 toDocument(container)->updateLayoutIgnorePendingStylesheets();
903 // Figure out the starting rect.
904 LayoutRect startingRect;
905 if (focusedElement) {
906 if (!hasOffscreenRect(focusedElement)) {
907 container = scrollableEnclosingBoxOrParentFrameForNodeInDirection(type, focusedElement);
908 startingRect = nodeRectInAbsoluteCoordinates(focusedElement, true /* ignore border */);
909 } else if (isHTMLAreaElement(*focusedElement)) {
910 HTMLAreaElement& area = toHTMLAreaElement(*focusedElement);
911 container = scrollableEnclosingBoxOrParentFrameForNodeInDirection(type, area.imageElement());
912 startingRect = virtualRectForAreaElementAndDirection(area, type);
916 bool consumed = false;
918 consumed = advanceFocusDirectionallyInContainer(container, startingRect, type);
919 startingRect = nodeRectInAbsoluteCoordinates(container, true /* ignore border */);
920 container = scrollableEnclosingBoxOrParentFrameForNodeInDirection(type, container);
921 if (container && container->isDocumentNode())
922 toDocument(container)->updateLayoutIgnorePendingStylesheets();
923 } while (!consumed && container);