(container);
+ if (!owner->contentFrame())
+ return;
+
+ Document* innerDocument = owner->contentFrame()->document();
+ if (!innerDocument)
+ return;
+
+ descendantOfContainer = isNodeDeepDescendantOfDocument(focusedNode, innerDocument);
+ firstChild = innerDocument->firstChild();
+
+ // Scrollable block elements (e.g. , etc)
+ } else if (isScrollableContainerNode(container)) {
+
+ firstChild = container->firstChild();
+ descendantOfContainer = focusedNode->isDescendantOf(container);
+ }
+
+ if (descendantOfContainer) {
+ findFocusableNodeInDirection(firstChild, focusedNode, direction, event, closest);
+ return;
+ }
+
+ // Check if the current container element itself is a good candidate
+ // to move focus to. If it is, then we traverse its inner nodes.
+ FocusCandidate candidateParent = FocusCandidate(container);
+ distanceDataForNode(direction, focusedNode, candidateParent);
+
+ // Bail out if distance is maximum.
+ if (candidateParent.distance == maxDistance())
+ return;
+
+ // FIXME: Consider alignment?
+ if (candidateParent.distance < closest.distance)
+ findFocusableNodeInDirection(firstChild, focusedNode, direction, event, closest, candidateParent);
+}
+
+static bool relinquishesEditingFocus(Node *node)
+{
+ ASSERT(node);
+ ASSERT(node->isContentEditable());
+
+ Node* root = node->rootEditableElement();
+ Frame* frame = node->document()->frame();
+ if (!frame || !root)
+ return false;
+
+ return frame->editor()->shouldEndEditing(rangeOfContents(root).get());
+}
+
+static void clearSelectionIfNeeded(Frame* oldFocusedFrame, Frame* newFocusedFrame, Node* newFocusedNode)
+{
+ if (!oldFocusedFrame || !newFocusedFrame)
+ return;
+
+ if (oldFocusedFrame->document() != newFocusedFrame->document())
+ return;
+
+ SelectionController* s = oldFocusedFrame->selection();
+ if (s->isNone())
+ return;
+
+ bool caretBrowsing = oldFocusedFrame->settings()->caretBrowsingEnabled();
+ if (caretBrowsing)
+ return;
+
+ Node* selectionStartNode = s->selection().start().node();
+ if (selectionStartNode == newFocusedNode || selectionStartNode->isDescendantOf(newFocusedNode) || selectionStartNode->shadowAncestorNode() == newFocusedNode)
+ return;
+
+ if (Node* mousePressNode = newFocusedFrame->eventHandler()->mousePressNode()) {
+ if (mousePressNode->renderer() && !mousePressNode->canStartSelection()) {
+ // Don't clear the selection for contentEditable elements, but do clear it for input and textarea. See bug 38696.
+ Node * root = s->rootEditableElement();
+ if (!root)
+ return;
+
+ if (Node* shadowAncestorNode = root->shadowAncestorNode()) {
+ if (!shadowAncestorNode->hasTagName(inputTag) && !shadowAncestorNode->hasTagName(textareaTag))
+ return;
+ }
+ }
+ }
+
+ s->clear();
+}
+
+bool FocusController::setFocusedNode(Node* node, PassRefPtr newFocusedFrame)
+{
+ RefPtr oldFocusedFrame = focusedFrame();
+ RefPtr oldDocument = oldFocusedFrame ? oldFocusedFrame->document() : 0;
+
+ Node* oldFocusedNode = oldDocument ? oldDocument->focusedNode() : 0;
+ if (oldFocusedNode == node)
+ return true;
+
+ // FIXME: Might want to disable this check for caretBrowsing
+ if (oldFocusedNode && oldFocusedNode->rootEditableElement() == oldFocusedNode && !relinquishesEditingFocus(oldFocusedNode))
+ return false;
+
+ m_page->editorClient()->willSetInputMethodState();
+
+ clearSelectionIfNeeded(oldFocusedFrame.get(), newFocusedFrame.get(), node);
+
+ if (!node) {
+ if (oldDocument)
+ oldDocument->setFocusedNode(0);
+ m_page->editorClient()->setInputMethodState(false);
+ return true;
+ }
+
+ RefPtr newDocument = node->document();
+
+ if (newDocument && newDocument->focusedNode() == node) {
+ m_page->editorClient()->setInputMethodState(node->shouldUseInputMethod());
+ return true;
+ }
+
+ if (oldDocument && oldDocument != newDocument)
+ oldDocument->setFocusedNode(0);
+
+ setFocusedFrame(newFocusedFrame);
+
+ if (newDocument)
+ newDocument->setFocusedNode(node);
+
+ m_page->editorClient()->setInputMethodState(node->shouldUseInputMethod());
+
+ return true;
+}
+
+void FocusController::setActive(bool active)
+{
+ if (m_isActive == active)
+ return;
+
+ m_isActive = active;
+
+ if (FrameView* view = m_page->mainFrame()->view()) {
+ if (!view->platformWidget()) {
+ view->layoutIfNeededRecursive();
+ view->updateControlTints();
+ }
+ }
+
+ focusedOrMainFrame()->selection()->pageActivationChanged();
+
+ if (m_focusedFrame && isFocused())
+ dispatchEventsOnWindowAndFocusedNode(m_focusedFrame->document(), active);
+}
+
+} // namespace WebCore