⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 selectioncontroller.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 3 页
字号:
bool SelectionController::recomputeCaretRect(){    if (!m_frame)        return false;            FrameView* v = m_frame->document()->view();    if (!v)        return false;    if (!m_needsLayout)        return false;    IntRect oldRect = m_caretRect;    m_needsLayout = true;    IntRect newRect = localCaretRect();    if (oldRect == newRect && !m_absCaretBoundsDirty)        return false;    IntRect oldAbsRepaintRect = m_absCaretBounds;    m_absCaretBounds = caretRepaintRect();    m_absCaretBoundsDirty = false;        if (oldAbsRepaintRect == m_absCaretBounds)        return false;        if (RenderView* view = toRenderView(m_frame->document()->renderer())) {        // FIXME: make caret repainting container-aware.        view->repaintRectangleInViewAndCompositedLayers(oldAbsRepaintRect, false);        view->repaintRectangleInViewAndCompositedLayers(m_absCaretBounds, false);    }    return true;}void SelectionController::invalidateCaretRect(){    if (!isCaret())        return;    Document* d = m_sel.start().node()->document();    // recomputeCaretRect will always return false for the drag caret,    // because its m_frame is always 0.    bool caretRectChanged = recomputeCaretRect();    // EDIT FIXME: This is an unfortunate hack.    // Basically, we can't trust this layout position since we     // can't guarantee that the check to see if we are in unrendered     // content will work at this point. We may have to wait for    // a layout and re-render of the document to happen. So, resetting this    // flag will cause another caret layout to happen the first time    // that we try to paint the caret after this call. That one will work since    // it happens after the document has accounted for any editing    // changes which may have been done.    // And, we need to leave this layout here so the caret moves right     // away after clicking.    m_needsLayout = true;    if (!caretRectChanged) {        if (RenderView* view = toRenderView(d->renderer()))            view->repaintRectangleInViewAndCompositedLayers(caretRepaintRect(), false);    }}void SelectionController::paintCaret(GraphicsContext* p, int tx, int ty, const IntRect& clipRect){    if (! m_sel.isCaret())        return;    if (m_needsLayout)        layout();    IntRect drawingRect = localCaretRect();    drawingRect.move(tx, ty);    IntRect caret = intersection(drawingRect, clipRect);    if (!caret.isEmpty()) {        Color caretColor = Color::black;        Element* element = rootEditableElement();        if (element && element->renderer())            caretColor = element->renderer()->style()->color();        p->fillRect(caret, caretColor);    }}void SelectionController::debugRenderer(RenderObject *r, bool selected) const{    if (r->node()->isElementNode()) {        Element *element = static_cast<Element *>(r->node());        fprintf(stderr, "%s%s\n", selected ? "==> " : "    ", element->localName().string().utf8().data());    }    else if (r->isText()) {        RenderText* textRenderer = toRenderText(r);        if (textRenderer->textLength() == 0 || !textRenderer->firstTextBox()) {            fprintf(stderr, "%s#text (empty)\n", selected ? "==> " : "    ");            return;        }                static const int max = 36;        String text = textRenderer->text();        int textLength = text.length();        if (selected) {            int offset = 0;            if (r->node() == m_sel.start().node())                offset = m_sel.start().offset();            else if (r->node() == m_sel.end().node())                offset = m_sel.end().offset();                            int pos;            InlineTextBox *box = textRenderer->findNextInlineTextBox(offset, pos);            text = text.substring(box->start(), box->len());                        String show;            int mid = max / 2;            int caret = 0;                        // text is shorter than max            if (textLength < max) {                show = text;                caret = pos;            }                        // too few characters to left            else if (pos - mid < 0) {                show = text.left(max - 3) + "...";                caret = pos;            }                        // enough characters on each side            else if (pos - mid >= 0 && pos + mid <= textLength) {                show = "..." + text.substring(pos - mid + 3, max - 6) + "...";                caret = mid;            }                        // too few characters on right            else {                show = "..." + text.right(max - 3);                caret = pos - (textLength - show.length());            }                        show.replace('\n', ' ');            show.replace('\r', ' ');            fprintf(stderr, "==> #text : \"%s\" at offset %d\n", show.utf8().data(), pos);            fprintf(stderr, "           ");            for (int i = 0; i < caret; i++)                fprintf(stderr, " ");            fprintf(stderr, "^\n");        }        else {            if ((int)text.length() > max)                text = text.left(max - 3) + "...";            else                text = text.left(max);            fprintf(stderr, "    #text : \"%s\"\n", text.utf8().data());        }    }}bool SelectionController::contains(const IntPoint& point){    Document* document = m_frame->document();        // Treat a collapsed selection like no selection.    if (!isRange())        return false;    if (!document->renderer())         return false;        HitTestRequest request(HitTestRequest::ReadOnly |                           HitTestRequest::Active);    HitTestResult result(point);    document->renderView()->layer()->hitTest(request, result);    Node* innerNode = result.innerNode();    if (!innerNode || !innerNode->renderer())        return false;        VisiblePosition visiblePos(innerNode->renderer()->positionForPoint(result.localPoint()));    if (visiblePos.isNull())        return false;            if (m_sel.visibleStart().isNull() || m_sel.visibleEnd().isNull())        return false;            Position start(m_sel.visibleStart().deepEquivalent());    Position end(m_sel.visibleEnd().deepEquivalent());    Position p(visiblePos.deepEquivalent());    return comparePositions(start, p) <= 0 && comparePositions(p, end) <= 0;}// Workaround for the fact that it's hard to delete a frame.// Call this after doing user-triggered selections to make it easy to delete the frame you entirely selected.// Can't do this implicitly as part of every setSelection call because in some contexts it might not be good// for the focus to move to another frame. So instead we call it from places where we are selecting with the// mouse or the keyboard after setting the selection.void SelectionController::selectFrameElementInParentIfFullySelected(){    // Find the parent frame; if there is none, then we have nothing to do.    Frame* parent = m_frame->tree()->parent();    if (!parent)        return;    Page* page = m_frame->page();    if (!page)        return;    // Check if the selection contains the entire frame contents; if not, then there is nothing to do.    if (!isRange())        return;    if (!isStartOfDocument(selection().visibleStart()))        return;    if (!isEndOfDocument(selection().visibleEnd()))        return;    // Get to the <iframe> or <frame> (or even <object>) element in the parent frame.    Document* doc = m_frame->document();    Element* ownerElement = doc->ownerElement();    if (!ownerElement)        return;    Node* ownerElementParent = ownerElement->parentNode();    if (!ownerElementParent)        return;            // This method's purpose is it to make it easier to select iframes (in order to delete them).  Don't do anything if the iframe isn't deletable.    if (!ownerElementParent->isContentEditable())        return;    // Create compute positions before and after the element.    unsigned ownerElementNodeIndex = ownerElement->nodeIndex();    VisiblePosition beforeOwnerElement(VisiblePosition(ownerElementParent, ownerElementNodeIndex, SEL_DEFAULT_AFFINITY));    VisiblePosition afterOwnerElement(VisiblePosition(ownerElementParent, ownerElementNodeIndex + 1, VP_UPSTREAM_IF_POSSIBLE));    // Focus on the parent frame, and then select from before this element to after.    VisibleSelection newSelection(beforeOwnerElement, afterOwnerElement);    if (parent->shouldChangeSelection(newSelection)) {        page->focusController()->setFocusedFrame(parent);        parent->selection()->setSelection(newSelection);    }}void SelectionController::selectAll(){    Document* document = m_frame->document();        if (document->focusedNode() && document->focusedNode()->canSelectAll()) {        document->focusedNode()->selectAll();        return;    }        Node* root = 0;    if (isContentEditable())        root = highestEditableRoot(m_sel.start());    else {        root = shadowTreeRootNode();        if (!root)            root = document->documentElement();    }    if (!root)        return;    VisibleSelection newSelection(VisibleSelection::selectionFromContentsOfNode(root));    if (m_frame->shouldChangeSelection(newSelection))        setSelection(newSelection);    selectFrameElementInParentIfFullySelected();    m_frame->notifyRendererOfSelectionChange(true);}bool SelectionController::setSelectedRange(Range* range, EAffinity affinity, bool closeTyping){    if (!range)        return false;    ExceptionCode ec = 0;    Node* startContainer = range->startContainer(ec);    if (ec)        return false;    Node* endContainer = range->endContainer(ec);    if (ec)        return false;        ASSERT(startContainer);    ASSERT(endContainer);    ASSERT(startContainer->document() == endContainer->document());        m_frame->document()->updateLayoutIgnorePendingStylesheets();    // Non-collapsed ranges are not allowed to start at the end of a line that is wrapped,    // they start at the beginning of the next line instead    bool collapsed = range->collapsed(ec);    if (ec)        return false;        int startOffset = range->startOffset(ec);    if (ec)        return false;    int endOffset = range->endOffset(ec);    if (ec)        return false;        // FIXME: Can we provide extentAffinity?    VisiblePosition visibleStart(startContainer, startOffset, collapsed ? affinity : DOWNSTREAM);    VisiblePosition visibleEnd(endContainer, endOffset, SEL_DEFAULT_AFFINITY);    setSelection(VisibleSelection(visibleStart, visibleEnd), closeTyping);    return true;}bool SelectionController::isInPasswordField() const{    Node* startNode = start().node();    if (!startNode)        return false;    startNode = startNode->shadowAncestorNode();    if (!startNode)        return false;    if (!startNode->hasTagName(inputTag))        return false;        return static_cast<HTMLInputElement*>(startNode)->inputType() == HTMLInputElement::PASSWORD;}bool SelectionController::caretRendersInsideNode(Node* node) const{    if (!node)        return false;    return !isTableElement(node) && !editingIgnoresContent(node);}void SelectionController::focusedOrActiveStateChanged(){    bool activeAndFocused = isFocusedAndActive();    // Because RenderObject::selectionBackgroundColor() and    // RenderObject::selectionForegroundColor() check if the frame is active,    // we have to update places those colors were painted.    if (RenderView* view = toRenderView(m_frame->document()->renderer()))        view->repaintRectangleInViewAndCompositedLayers(enclosingIntRect(m_frame->selectionBounds()));    // Caret appears in the active frame.    if (activeAndFocused)        m_frame->setSelectionFromNone();    m_frame->setCaretVisible(activeAndFocused);    // Update for caps lock state    m_frame->eventHandler()->capsLockStateMayHaveChanged();    // Because CSSStyleSelector::checkOneSelector() and    // RenderTheme::isFocused() check if the frame is active, we have to    // update style and theme state that depended on those.    if (Node* node = m_frame->document()->focusedNode()) {        node->setChanged();        if (RenderObject* renderer = node->renderer())            if (renderer && renderer->style()->hasAppearance())                theme()->stateChanged(renderer, FocusState);    }    // Secure keyboard entry is set by the active frame.    if (m_frame->document()->useSecureKeyboardEntryWhenActive())        m_frame->setUseSecureKeyboardEntry(activeAndFocused);}void SelectionController::pageActivationChanged(){    focusedOrActiveStateChanged();}void SelectionController::setFocused(bool flag){    if (m_focused == flag)        return;    m_focused = flag;    focusedOrActiveStateChanged();    m_frame->document()->dispatchWindowEvent(flag ? eventNames().focusEvent : eventNames().blurEvent, false, false);}bool SelectionController::isFocusedAndActive() const{    return m_focused && m_frame->page() && m_frame->page()->focusController()->isActive();}#ifndef NDEBUGvoid SelectionController::formatForDebugger(char* buffer, unsigned length) const{    m_sel.formatForDebugger(buffer, length);}void SelectionController::showTreeForThis() const{    m_sel.showTreeForThis();}#endif}#ifndef NDEBUGvoid showTree(const WebCore::SelectionController& sel){    sel.showTreeForThis();}void showTree(const WebCore::SelectionController* sel){    if (sel)        sel->showTreeForThis();}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -