bool FocusController::advanceFocusInDocumentOrder(FocusType type, bool initialFocus) { LocalFrame* frame = focusedOrMainFrame(); ASSERT(frame); Document* document = frame->document(); Node* currentNode = document->focusedElement(); document->updateLayout(); RefPtr<Node> node = findFocusableNodeAcrossFocusScope(type, FocusNavigationScope::focusNavigationScopeOf(currentNode ? currentNode : document), currentNode); if (!node) { // We didn't find a node to focus, so we should try to pass focus to Chrome. if (!initialFocus && m_page->canTakeFocus(type)) { document->setFocusedElement(nullptr); setFocusedFrame(nullptr); m_page->takeFocus(type); return true; } // Chrome doesn't want focus, so we should wrap focus. node = findFocusableNodeRecursively(type, FocusNavigationScope::focusNavigationScopeOf(m_page->mainFrame()->document()), 0); node = findFocusableNodeDecendingDownIntoFrameDocument(type, node.get()); if (!node) return false; } ASSERT(node); if (node == document->focusedElement()) // Focus wrapped around to the same node. return true; if (!node->isElementNode()) // FIXME: May need a way to focus a document here. return false; Element* element = toElement(node); // FIXME: It would be nice to just be able to call setFocusedElement(node) // here, but we can't do that because some elements (e.g. HTMLInputElement // and HTMLTextAreaElement) do extra work in their focus() methods. Document& newDocument = element->document(); if (&newDocument != document) { // Focus is going away from this document, so clear the focused node. document->setFocusedElement(nullptr); } setFocusedFrame(newDocument.frame()); element->focus(false, type); return true; }
void FocusController::focusDocumentView(PassRefPtr<LocalFrame> frame) { ASSERT(!frame || frame->page() == m_page); if (m_focusedFrame == frame) return; setFocusedFrame(frame); }
void FocusController::setFocused(bool focused) { if (isFocused() == focused) return; m_isFocused = focused; if (!m_focusedFrame) setFocusedFrame(m_page->mainFrame()); }
bool FocusController::setFocusedElement(Element* element, PassRefPtr<LocalFrame> newFocusedFrame, FocusType type) { RefPtr<LocalFrame> oldFocusedFrame = focusedFrame(); RefPtr<Document> oldDocument = oldFocusedFrame ? oldFocusedFrame->document() : 0; Element* oldFocusedElement = oldDocument ? oldDocument->focusedElement() : 0; if (element && oldFocusedElement == element) return true; // FIXME: Might want to disable this check for caretBrowsing if (oldFocusedElement && oldFocusedElement->isRootEditableElement() && !relinquishesEditingFocus(oldFocusedElement)) return false; RefPtr<Document> newDocument = nullptr; if (element) newDocument = &element->document(); else if (newFocusedFrame) newDocument = newFocusedFrame->document(); if (newDocument && oldDocument == newDocument && newDocument->focusedElement() == element) return true; if (oldDocument && oldDocument != newDocument) oldDocument->setFocusedElement(nullptr); if (newFocusedFrame && !newFocusedFrame->page()) { setFocusedFrame(nullptr); return false; } setFocusedFrame(newFocusedFrame); // Setting the focused node can result in losing our last reft to node when JS event handlers fire. RefPtr<Element> protect ALLOW_UNUSED = element; if (newDocument) { bool successfullyFocused = newDocument->setFocusedElement(element, type); if (!successfullyFocused) return false; } return true; }
bool FocusController::setFocusedNode(Node* node, PassRefPtr<Frame> newFocusedFrame) { RefPtr<Frame> oldFocusedFrame = focusedFrame(); RefPtr<Document> 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; #if ENABLE(WKC_SPATIAL_NAVI) // Set input method state before changing the focused node, so that the // input method can still have a chance to finish the ongoing composition // session. m_page->editorClient()->setInputMethodState(node ? node->shouldUseInputMethod() : false); #endif clearSelectionIfNeeded(oldFocusedFrame.get(), newFocusedFrame.get(), node); if (!node) { if (oldDocument) oldDocument->setFocusedNode(0); #if ENABLE(WKC_SPATIAL_NAVI) #else m_page->editorClient()->setInputMethodState(false); #endif return true; } RefPtr<Document> newDocument = node->document(); if (newDocument && newDocument->focusedNode() == node) { #if ENABLE(WKC_SPATIAL_NAVI) #else m_page->editorClient()->setInputMethodState(node->shouldUseInputMethod()); #endif return true; } if (oldDocument && oldDocument != newDocument) oldDocument->setFocusedNode(0); setFocusedFrame(newFocusedFrame); #if 1 // added at webkit.org trunk r65748 // Setting the focused node can result in losing our last reft to node when JS event handlers fire. RefPtr<Node> protect = node; #endif if (newDocument) newDocument->setFocusedNode(node); #if ENABLE(WKC_SPATIAL_NAVI) // do nothing #else #if 1 // modified at webkit.org trunk r65748 if (newDocument->focusedNode() == node) m_page->editorClient()->setInputMethodState(node->shouldUseInputMethod()); #else m_page->editorClient()->setInputMethodState(node->shouldUseInputMethod()); #endif #endif return true; }