frame.cpp
来自「linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自Web」· C++ 代码 · 共 1,782 行 · 第 1/4 页
CPP
1,782 行
nodeToRemove = styleElement.get(); return styleElement->renderer() ? styleElement->renderer()->style() : 0;}void Frame::setSelectionFromNone(){ // Put a caret inside the body if the entire frame is editable (either the // entire WebView is editable or designMode is on for this document). Document *doc = document(); if (!selection()->isNone() || !isContentEditable()) return; Node* node = doc->documentElement(); while (node && !node->hasTagName(bodyTag)) node = node->traverseNextNode(); if (node) selection()->setSelection(VisibleSelection(Position(node, 0), DOWNSTREAM));}bool Frame::inViewSourceMode() const{ return m_inViewSourceMode;}void Frame::setInViewSourceMode(bool mode){ m_inViewSourceMode = mode;}// Searches from the beginning of the document if nothing is selected.bool Frame::findString(const String& target, bool forward, bool caseFlag, bool wrapFlag, bool startInSelection){ if (target.isEmpty()) return false; if (excludeFromTextSearch()) return false; // Start from an edge of the selection, if there's a selection that's not in shadow content. Which edge // is used depends on whether we're searching forward or backward, and whether startInSelection is set. RefPtr<Range> searchRange(rangeOfContents(document())); VisibleSelection selection = this->selection()->selection(); if (forward) setStart(searchRange.get(), startInSelection ? selection.visibleStart() : selection.visibleEnd()); else setEnd(searchRange.get(), startInSelection ? selection.visibleEnd() : selection.visibleStart()); Node* shadowTreeRoot = selection.shadowTreeRootNode(); if (shadowTreeRoot) { ExceptionCode ec = 0; if (forward) searchRange->setEnd(shadowTreeRoot, shadowTreeRoot->childNodeCount(), ec); else searchRange->setStart(shadowTreeRoot, 0, ec); } RefPtr<Range> resultRange(findPlainText(searchRange.get(), target, forward, caseFlag)); // If we started in the selection and the found range exactly matches the existing selection, find again. // Build a selection with the found range to remove collapsed whitespace. // Compare ranges instead of selection objects to ignore the way that the current selection was made. if (startInSelection && *VisibleSelection(resultRange.get()).toNormalizedRange() == *selection.toNormalizedRange()) { searchRange = rangeOfContents(document()); if (forward) setStart(searchRange.get(), selection.visibleEnd()); else setEnd(searchRange.get(), selection.visibleStart()); if (shadowTreeRoot) { ExceptionCode ec = 0; if (forward) searchRange->setEnd(shadowTreeRoot, shadowTreeRoot->childNodeCount(), ec); else searchRange->setStart(shadowTreeRoot, 0, ec); } resultRange = findPlainText(searchRange.get(), target, forward, caseFlag); } ExceptionCode exception = 0; // If nothing was found in the shadow tree, search in main content following the shadow tree. if (resultRange->collapsed(exception) && shadowTreeRoot) { searchRange = rangeOfContents(document()); if (forward) searchRange->setStartAfter(shadowTreeRoot->shadowParentNode(), exception); else searchRange->setEndBefore(shadowTreeRoot->shadowParentNode(), exception); resultRange = findPlainText(searchRange.get(), target, forward, caseFlag); } if (!editor()->insideVisibleArea(resultRange.get())) { resultRange = editor()->nextVisibleRange(resultRange.get(), target, forward, caseFlag, wrapFlag); if (!resultRange) return false; } // If we didn't find anything and we're wrapping, search again in the entire document (this will // redundantly re-search the area already searched in some cases). if (resultRange->collapsed(exception) && wrapFlag) { searchRange = rangeOfContents(document()); resultRange = findPlainText(searchRange.get(), target, forward, caseFlag); // We used to return false here if we ended up with the same range that we started with // (e.g., the selection was already the only instance of this text). But we decided that // this should be a success case instead, so we'll just fall through in that case. } if (resultRange->collapsed(exception)) return false; this->selection()->setSelection(VisibleSelection(resultRange.get(), DOWNSTREAM)); revealSelection(); return true;}unsigned Frame::markAllMatchesForText(const String& target, bool caseFlag, unsigned limit){ if (target.isEmpty()) return 0; RefPtr<Range> searchRange(rangeOfContents(document())); ExceptionCode exception = 0; unsigned matchCount = 0; do { RefPtr<Range> resultRange(findPlainText(searchRange.get(), target, true, caseFlag)); if (resultRange->collapsed(exception)) { if (!resultRange->startContainer()->isInShadowTree()) break; searchRange = rangeOfContents(document()); searchRange->setStartAfter(resultRange->startContainer()->shadowAncestorNode(), exception); continue; } // A non-collapsed result range can in some funky whitespace cases still not // advance the range's start position (4509328). Break to avoid infinite loop. VisiblePosition newStart = endVisiblePosition(resultRange.get(), DOWNSTREAM); if (newStart == startVisiblePosition(searchRange.get(), DOWNSTREAM)) break; // Only treat the result as a match if it is visible if (editor()->insideVisibleArea(resultRange.get())) { ++matchCount; document()->addMarker(resultRange.get(), DocumentMarker::TextMatch); } // Stop looking if we hit the specified limit. A limit of 0 means no limit. if (limit > 0 && matchCount >= limit) break; setStart(searchRange.get(), newStart); Node* shadowTreeRoot = searchRange->shadowTreeRootNode(); if (searchRange->collapsed(exception) && shadowTreeRoot) searchRange->setEnd(shadowTreeRoot, shadowTreeRoot->childNodeCount(), exception); } while (true); // Do a "fake" paint in order to execute the code that computes the rendered rect for // each text match. Document* doc = document(); if (m_view && contentRenderer()) { doc->updateLayout(); // Ensure layout is up to date. IntRect visibleRect = m_view->visibleContentRect(); if (!visibleRect.isEmpty()) { GraphicsContext context((PlatformGraphicsContext*)0); context.setPaintingDisabled(true); m_view->paintContents(&context, visibleRect); } } return matchCount;}bool Frame::markedTextMatchesAreHighlighted() const{ return m_highlightTextMatches;}void Frame::setMarkedTextMatchesAreHighlighted(bool flag){ if (flag == m_highlightTextMatches) return; m_highlightTextMatches = flag; document()->repaintMarkers(DocumentMarker::TextMatch);}FrameTree* Frame::tree() const{ return &m_treeNode;}void Frame::setDOMWindow(DOMWindow* domWindow){ if (m_domWindow) { m_liveFormerWindows.add(m_domWindow.get()); m_domWindow->clear(); } m_domWindow = domWindow;}DOMWindow* Frame::domWindow() const{ if (!m_domWindow) m_domWindow = DOMWindow::create(const_cast<Frame*>(this)); return m_domWindow.get();}void Frame::clearFormerDOMWindow(DOMWindow* window){ m_liveFormerWindows.remove(window); }Page* Frame::page() const{ return m_page;}EventHandler* Frame::eventHandler() const{ return &m_eventHandler;}void Frame::pageDestroyed(){ if (Frame* parent = tree()->parent()) parent->loader()->checkLoadComplete(); // FIXME: It's unclear as to why this is called more than once, but it is, // so page() could be NULL. if (page() && page()->focusController()->focusedFrame() == this) page()->focusController()->setFocusedFrame(0); script()->clearWindowShell(); // This will stop any JS timers if (script()->haveWindowShell()) script()->windowShell()->disconnectFrame(); script()->clearScriptObjects(); script()->updatePlatformScriptObjects(); m_page = 0;}void Frame::disconnectOwnerElement(){ if (m_ownerElement) { if (Document* doc = document()) doc->clearAXObjectCache(); m_ownerElement->m_contentFrame = 0; if (m_page) m_page->decrementFrameCount(); } m_ownerElement = 0;}String Frame::documentTypeString() const{ if (DocumentType* doctype = document()->doctype()) return createMarkup(doctype); return String();}void Frame::focusWindow(){ if (!page()) return; // If we're a top level window, bring the window to the front. if (!tree()->parent()) page()->chrome()->focus(); eventHandler()->focusDocumentView();}void Frame::unfocusWindow(){ if (!page()) return; // If we're a top level window, deactivate the window. if (!tree()->parent()) page()->chrome()->unfocus();}bool Frame::shouldClose(){ Chrome* chrome = page() ? page()->chrome() : 0; if (!chrome || !chrome->canRunBeforeUnloadConfirmPanel()) return true; RefPtr<Document> doc = document(); HTMLElement* body = doc->body(); if (!body) return true; RefPtr<BeforeUnloadEvent> beforeUnloadEvent = BeforeUnloadEvent::create(); beforeUnloadEvent->setTarget(doc); doc->handleWindowEvent(beforeUnloadEvent.get(), false); if (!beforeUnloadEvent->defaultPrevented()) doc->defaultEventHandler(beforeUnloadEvent.get()); if (beforeUnloadEvent->result().isNull()) return true; String text = doc->displayStringModifiedByEncoding(beforeUnloadEvent->result()); return chrome->runBeforeUnloadConfirmPanel(text, this);}void Frame::scheduleClose(){ if (!shouldClose()) return; Chrome* chrome = page() ? page()->chrome() : 0; if (chrome) chrome->closeWindowSoon();}void Frame::respondToChangedSelection(const VisibleSelection& oldSelection, bool closeTyping){ bool isContinuousSpellCheckingEnabled = editor()->isContinuousSpellCheckingEnabled(); bool isContinuousGrammarCheckingEnabled = isContinuousSpellCheckingEnabled && editor()->isGrammarCheckingEnabled(); if (isContinuousSpellCheckingEnabled) { VisibleSelection newAdjacentWords; VisibleSelection newSelectedSentence; if (selection()->selection().isContentEditable()) { VisiblePosition newStart(selection()->selection().visibleStart()); newAdjacentWords = VisibleSelection(startOfWord(newStart, LeftWordIfOnBoundary), endOfWord(newStart, RightWordIfOnBoundary)); if (isContinuousGrammarCheckingEnabled) newSelectedSentence = VisibleSelection(startOfSentence(newStart), endOfSentence(newStart)); } // When typing we check spelling elsewhere, so don't redo it here. // If this is a change in selection resulting from a delete operation, // oldSelection may no longer be in the document. if (closeTyping && oldSelection.isContentEditable() && oldSelection.start().node() && oldSelection.start().node()->inDocument()) { VisiblePosition oldStart(oldSelection.visibleStart()); VisibleSelection oldAdjacentWords = VisibleSelection(startOfWord(oldStart, LeftWordIfOnBoundary), endOfWord(oldStart, RightWordIfOnBoundary)); if (oldAdjacentWords != newAdjacentWords) { if (isContinuousGrammarCheckingEnabled) { VisibleSelection oldSelectedSentence = VisibleSelection(startOfSentence(oldStart), endOfSentence(oldStart)); editor()->markMisspellingsAndBadGrammar(oldAdjacentWords, oldSelectedSentence != newSelectedSentence, oldSelectedSentence); } else { editor()->markMisspellingsAndBadGrammar(oldAdjacentWords, false, oldAdjacentWords); } } } // This only erases markers that are in the first unit (word or sentence) of the selection. // Perhaps peculiar, but it matches AppKit. if (RefPtr<Range> wordRange = newAdjacentWords.toNormalizedRange()) document()->removeMarkers(wordRange.get(), DocumentMarker::Spelling); if (RefPtr<Range> sentenceRange = newSelectedSentence.toNormalizedRange()) document()->removeMarkers(sentenceRange.get(), DocumentMarker::Grammar); } // When continuous spell checking is off, existing markers disappear after the selection changes. if (!isContinuousSpellCheckingEnabled) document()->removeMarkers(DocumentMarker::Spelling); if (!isContinuousGrammarCheckingEnabled) document()->removeMarkers(DocumentMarker::Grammar); editor()->respondToChangedSelection(oldSelection);}VisiblePosition Frame::visiblePositionForPoint(const IntPoint& framePoint){ HitTestResult result = eventHandler()->hitTestResultAtPoint(framePoint, true); Node* node = result.innerNode(); if (!node) return VisiblePosition(); RenderObject* renderer = node->renderer(); if (!renderer) return VisiblePosition(); VisiblePosition visiblePos = renderer->positionForPoint(result.localPoint()); if (visiblePos.isNull()) visiblePos = VisiblePosition(Position(node, 0)); return visiblePos;} Document* Frame::documentAtPoint(const IntPoint& point){ if (!view()) return 0; IntPoint pt = view()->windowToContents(point); HitTestResult result = HitTestResult(pt); if (contentRenderer()) result = eventHandler()->hitTestResultAtPoint(pt, false); return result.innerNode() ? result.innerNode()->document() : 0;}void Frame::createView(const IntSize& viewportSize, const Color& backgroundColor, bool transparent, const IntSize& fixedLayoutSize, bool useFixedLayout, ScrollbarMode horizontalScrollbarMode, ScrollbarMode verticalScrollbarMode){ ASSERT(this); ASSERT(m_page); bool isMainFrame = this == m_page->mainFrame(); if (isMainFrame && view()) view()->setParentVisible(false); setView(0); FrameView* frameView; if (isMainFrame) { frameView = new FrameView(this, viewportSize); frameView->setFixedLayoutSize(fixedLayoutSize); frameView->setUseFixedLayout(useFixedLayout); } else frameView = new FrameView(this); frameView->setScrollbarModes(horizontalScrollbarMode, verticalScrollbarMode); frameView->updateDefaultScrollbarState(); setView(frameView); // FrameViews are created with a ref count of 1. Release this ref since we've assigned it to frame. frameView->deref(); if (backgroundColor.isValid()) frameView->updateBackgroundRecursively(backgroundColor, transparent); if (isMainFrame) frameView->setParentVisible(true); if (ownerRenderer()) ownerRenderer()->setWidget(frameView); if (HTMLFrameOwnerElement* owner = ownerElement()) view()->setCanHaveScrollbars(owner->scrollingMode() != ScrollbarAlwaysOff);}} // namespace WebCore
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?