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 + -
显示快捷键?