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

📄 selectioncontroller.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 3 页
字号:
    switch (granularity) {        case CharacterGranularity:            if (isRange())                 pos = VisiblePosition(m_sel.start(), m_sel.affinity());            else                pos = VisiblePosition(m_sel.extent(), m_sel.affinity()).left(true);            break;        case WordGranularity:        case SentenceGranularity:        case LineGranularity:        case ParagraphGranularity:        case SentenceBoundary:        case LineBoundary:        case ParagraphBoundary:        case DocumentBoundary:            // FIXME: Implement all of the above.            pos = modifyMovingBackward(granularity);            break;    }    return pos;}VisiblePosition SelectionController::modifyMovingBackward(TextGranularity granularity){    VisiblePosition pos;    switch (granularity) {        case CharacterGranularity:            if (isRange())                 pos = VisiblePosition(m_sel.start(), m_sel.affinity());            else                pos = VisiblePosition(m_sel.extent(), m_sel.affinity()).previous(true);            break;        case WordGranularity:            pos = previousWordPosition(VisiblePosition(m_sel.extent(), m_sel.affinity()));            break;        case SentenceGranularity:            pos = previousSentencePosition(VisiblePosition(m_sel.extent(), m_sel.affinity()));            break;        case LineGranularity:            pos = previousLinePosition(VisiblePosition(m_sel.start(), m_sel.affinity()), xPosForVerticalArrowNavigation(START));            break;        case ParagraphGranularity:            pos = previousParagraphPosition(VisiblePosition(m_sel.start(), m_sel.affinity()), xPosForVerticalArrowNavigation(START));            break;        case SentenceBoundary:            pos = startOfSentence(VisiblePosition(m_sel.start(), m_sel.affinity()));            break;        case LineBoundary:            pos = startOfLine(VisiblePosition(m_sel.start(), m_sel.affinity()));            break;        case ParagraphBoundary:            pos = startOfParagraph(VisiblePosition(m_sel.start(), m_sel.affinity()));            break;        case DocumentBoundary:            pos = VisiblePosition(m_sel.start(), m_sel.affinity());            if (isEditablePosition(pos.deepEquivalent()))                pos = startOfEditableContent(pos);            else                 pos = startOfDocument(pos);            break;    }    return pos;}bool SelectionController::modify(EAlteration alter, EDirection dir, TextGranularity granularity, bool userTriggered){    if (userTriggered) {        SelectionController trialSelectionController;        trialSelectionController.setLastChangeWasHorizontalExtension(m_lastChangeWasHorizontalExtension);        trialSelectionController.setSelection(m_sel);        trialSelectionController.modify(alter, dir, granularity, false);        bool change = m_frame->shouldChangeSelection(trialSelectionController.selection());        if (!change)            return false;    }    if (m_frame)        m_frame->setSelectionGranularity(granularity);        willBeModified(alter, dir);    VisiblePosition pos;    switch (dir) {        case RIGHT:            if (alter == MOVE)                pos = modifyMovingRight(granularity);            else                pos = modifyExtendingRightForward(granularity);            break;        case FORWARD:            if (alter == EXTEND)                pos = modifyExtendingRightForward(granularity);            else                pos = modifyMovingForward(granularity);            break;        case LEFT:            if (alter == MOVE)                pos = modifyMovingLeft(granularity);            else                pos = modifyExtendingLeftBackward(granularity);            break;        case BACKWARD:            if (alter == EXTEND)                pos = modifyExtendingLeftBackward(granularity);            else                pos = modifyMovingBackward(granularity);            break;    }    if (pos.isNull())        return false;        // Some of the above operations set an xPosForVerticalArrowNavigation.    // Setting a selection will clear it, so save it to possibly restore later.    // Note: the START position type is arbitrary because it is unused, it would be    // the requested position type if there were no xPosForVerticalArrowNavigation set.    int x = xPosForVerticalArrowNavigation(START);    switch (alter) {        case MOVE:            moveTo(pos, userTriggered);            break;        case EXTEND:            setExtent(pos, userTriggered);            break;    }        if (granularity == LineGranularity || granularity == ParagraphGranularity)        m_xPosForVerticalArrowNavigation = x;    if (userTriggered) {        // User modified selection change also sets the granularity back to character.        // NOTE: The one exception is that we need to keep word granularity to        // preserve smart delete behavior when extending by word (e.g. double-click),        // then shift-option-right arrow, then delete needs to smart delete, per TextEdit.        if (!(alter == EXTEND && granularity == WordGranularity && m_frame->selectionGranularity() == WordGranularity))            m_frame->setSelectionGranularity(CharacterGranularity);    }    setNeedsLayout();    return true;}// FIXME: Maybe baseline would be better?static bool absoluteCaretY(const VisiblePosition &c, int &y){    IntRect rect = c.absoluteCaretBounds();    if (rect.isEmpty())        return false;    y = rect.y() + rect.height() / 2;    return true;}bool SelectionController::modify(EAlteration alter, int verticalDistance, bool userTriggered){    if (verticalDistance == 0)        return false;    if (userTriggered) {        SelectionController trialSelectionController;        trialSelectionController.setSelection(m_sel);        trialSelectionController.modify(alter, verticalDistance, false);        bool change = m_frame->shouldChangeSelection(trialSelectionController.selection());        if (!change)            return false;    }    bool up = verticalDistance < 0;    if (up)        verticalDistance = -verticalDistance;    willBeModified(alter, up ? BACKWARD : FORWARD);    VisiblePosition pos;    int xPos = 0;    switch (alter) {        case MOVE:            pos = VisiblePosition(up ? m_sel.start() : m_sel.end(), m_sel.affinity());            xPos = xPosForVerticalArrowNavigation(up ? START : END);            m_sel.setAffinity(up ? UPSTREAM : DOWNSTREAM);            break;        case EXTEND:            pos = VisiblePosition(m_sel.extent(), m_sel.affinity());            xPos = xPosForVerticalArrowNavigation(EXTENT);            m_sel.setAffinity(DOWNSTREAM);            break;    }    int startY;    if (!absoluteCaretY(pos, startY))        return false;    if (up)        startY = -startY;    int lastY = startY;    VisiblePosition result;    VisiblePosition next;    for (VisiblePosition p = pos; ; p = next) {        next = (up ? previousLinePosition : nextLinePosition)(p, xPos);        if (next.isNull() || next == p)            break;        int nextY;        if (!absoluteCaretY(next, nextY))            break;        if (up)            nextY = -nextY;        if (nextY - startY > verticalDistance)            break;        if (nextY >= lastY) {            lastY = nextY;            result = next;        }    }    if (result.isNull())        return false;    switch (alter) {        case MOVE:            moveTo(result, userTriggered);            break;        case EXTEND:            setExtent(result, userTriggered);            break;    }    if (userTriggered)        m_frame->setSelectionGranularity(CharacterGranularity);    return true;}bool SelectionController::expandUsingGranularity(TextGranularity granularity){    if (isNone())        return false;    m_sel.expandUsingGranularity(granularity);    m_needsLayout = true;    return true;}int SelectionController::xPosForVerticalArrowNavigation(EPositionType type){    int x = 0;    if (isNone())        return x;    Position pos;    switch (type) {        case START:            pos = m_sel.start();            break;        case END:            pos = m_sel.end();            break;        case BASE:            pos = m_sel.base();            break;        case EXTENT:            pos = m_sel.extent();            break;    }    Frame *frame = pos.node()->document()->frame();    if (!frame)        return x;            if (m_xPosForVerticalArrowNavigation == NoXPosForVerticalArrowNavigation) {        VisiblePosition visiblePosition(pos, m_sel.affinity());        // VisiblePosition creation can fail here if a node containing the selection becomes visibility:hidden        // after the selection is created and before this function is called.        x = visiblePosition.isNotNull() ? visiblePosition.xOffsetForVerticalNavigation() : 0;        m_xPosForVerticalArrowNavigation = x;    }    else        x = m_xPosForVerticalArrowNavigation;            return x;}void SelectionController::clear(){    setSelection(VisibleSelection());}void SelectionController::setBase(const VisiblePosition &pos, bool userTriggered){    setSelection(VisibleSelection(pos.deepEquivalent(), m_sel.extent(), pos.affinity()), true, true, userTriggered);}void SelectionController::setExtent(const VisiblePosition &pos, bool userTriggered){    setSelection(VisibleSelection(m_sel.base(), pos.deepEquivalent(), pos.affinity()), true, true, userTriggered);}void SelectionController::setBase(const Position &pos, EAffinity affinity, bool userTriggered){    setSelection(VisibleSelection(pos, m_sel.extent(), affinity), true, true, userTriggered);}void SelectionController::setExtent(const Position &pos, EAffinity affinity, bool userTriggered){    setSelection(VisibleSelection(m_sel.base(), pos, affinity), true, true, userTriggered);}void SelectionController::setNeedsLayout(bool flag){    m_needsLayout = flag;}void SelectionController::layout(){    if (isNone() || !m_sel.start().node()->inDocument() || !m_sel.end().node()->inDocument()) {        m_caretRect = IntRect();        return;    }    m_sel.start().node()->document()->updateRendering();        m_caretRect = IntRect();            if (isCaret()) {        VisiblePosition pos(m_sel.start(), m_sel.affinity());        if (pos.isNotNull()) {            ASSERT(pos.deepEquivalent().node()->renderer());                        // First compute a rect local to the renderer at the selection start            RenderObject* renderer;            IntRect localRect = pos.localCaretRect(renderer);            // Get the renderer that will be responsible for painting the caret (which            // is either the renderer we just found, or one of its containers)            RenderObject* caretPainter = caretRenderer();            // Compute an offset between the renderer and the caretPainter            IntSize offsetFromPainter;            bool unrooted = false;            while (renderer != caretPainter) {                RenderObject* containerObject = renderer->container();                if (!containerObject) {                    unrooted = true;                    break;                }                offsetFromPainter += renderer->offsetFromContainer(containerObject);                renderer = containerObject;            }                        if (!unrooted) {                // Move the caret rect to the coords of the painter                localRect.move(offsetFromPainter);                m_caretRect = localRect;            }                        m_absCaretBoundsDirty = true;        }    }    m_needsLayout = false;}RenderObject* SelectionController::caretRenderer() const{    Node* node = m_sel.start().node();    if (!node)        return 0;    RenderObject* renderer = node->renderer();    if (!renderer)        return 0;    // if caretNode is a block and caret is inside it then caret should be painted by that block    bool paintedByBlock = renderer->isBlockFlow() && caretRendersInsideNode(node);    return paintedByBlock ? renderer : renderer->containingBlock();}IntRect SelectionController::localCaretRect() const{    if (m_needsLayout)        const_cast<SelectionController *>(this)->layout();        return m_caretRect;}IntRect SelectionController::absoluteCaretBounds(){    recomputeCaretRect();    return m_absCaretBounds;}static IntRect repaintRectForCaret(IntRect caret){    if (caret.isEmpty())        return IntRect();    // Ensure that the dirty rect intersects the block that paints the caret even in the case where    // the caret itself is just outside the block. See <https://bugs.webkit.org/show_bug.cgi?id=19086>.    caret.inflateX(1);    return caret;}IntRect SelectionController::caretRepaintRect() const{    IntRect localRect = repaintRectForCaret(localCaretRect());        RenderObject* caretPainter = caretRenderer();    if (caretPainter)        return caretPainter->localToAbsoluteQuad(FloatRect(localRect)).enclosingBoundingBox();    return IntRect();}

⌨️ 快捷键说明

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