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

📄 render_layer.cpp

📁 最新Nokia手机浏览器全套源代码完美版。
💻 CPP
📖 第 1 页 / 共 5 页
字号:
{
    RenderLayer* prevSibling = beforeChild ? beforeChild->previousSibling() : lastChild();
    if (prevSibling) {
        child->setPreviousSibling(prevSibling);
        prevSibling->setNextSibling(child);
    }
    else
        setFirstChild(child);

    if (beforeChild) {
        beforeChild->setPreviousSibling(child);
        child->setNextSibling(beforeChild);
    }
    else
        setLastChild(child);

    child->setParent(this);

    // Dirty the z-order list in which we are contained.  The stackingContext() can be null in the
    // case where we're building up generated content layers.  This is ok, since the lists will start
    // off dirty in that case anyway.
    RenderLayer* stackingContext = child->stackingContext();
    if (stackingContext)
        stackingContext->dirtyZOrderLists();
}

RenderLayer* RenderLayer::removeChild(RenderLayer* oldChild)
{
    // remove the child
    if (oldChild->previousSibling())
        oldChild->previousSibling()->setNextSibling(oldChild->nextSibling());
    if (oldChild->nextSibling())
        oldChild->nextSibling()->setPreviousSibling(oldChild->previousSibling());

    if (m_first == oldChild)
        m_first = oldChild->nextSibling();
    if (m_last == oldChild)
        m_last = oldChild->previousSibling();

    // Dirty the z-order list in which we are contained.  When called via the
    // reattachment process in removeOnlyThisLayer, the layer may already be disconnected
    // from the main layer tree, so we need to null-check the |stackingContext| value.
    RenderLayer* stackingContext = oldChild->stackingContext();
    if (stackingContext)
        oldChild->stackingContext()->dirtyZOrderLists();

    oldChild->setPreviousSibling(0);
    oldChild->setNextSibling(0);
    oldChild->setParent(0);

    return oldChild;
}

void RenderLayer::removeOnlyThisLayer()
{
    if (!m_parent)
        return;

    // Dirty the clip rects.
    clearClipRects();

    // Remove us from the parent.
    RenderLayer* parent = m_parent;
    RenderLayer* nextSib = nextSibling();
    parent->removeChild(this);

    // Now walk our kids and reattach them to our parent.
    RenderLayer* current = m_first;
    while (current) {
        RenderLayer* next = current->nextSibling();
        removeChild(current);
        parent->addChild(current, nextSib);
        current = next;
    }

    detach(renderer()->renderArena());
}

void RenderLayer::insertOnlyThisLayer()
{
    if (!m_parent && renderer()->parent()) {
        // We need to connect ourselves when our renderer() has a parent.
        // Find our enclosingLayer and add ourselves.
        RenderLayer* parentLayer = renderer()->parent()->enclosingLayer();
        if (parentLayer)
            parentLayer->addChild(this,
                                  renderer()->parent()->findNextLayer(parentLayer, renderer()));
    }

    // Remove all descendant layers from the hierarchy and add them to the new position.
    for (RenderObject* curr = renderer()->firstChild(); curr; curr = curr->nextSibling())
        curr->moveLayers(m_parent, this);

    // Clear out all the clip rects.
    clearClipRects();
}

void
RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, int& x, int& y) const
{
    if (ancestorLayer == this)
        return;

    if (m_object->style()->position() == FIXED) {
        // Add in the offset of the view.  We can obtain this by calling
        // absolutePosition() on the RenderCanvas.
        int xOff, yOff;
        m_object->absolutePosition(xOff, yOff, true);
        x += xOff;
        y += yOff;
        return;
    }

    RenderLayer* parentLayer;
    if (m_object->style()->position() == ABSOLUTE)
        parentLayer = enclosingPositionedAncestor();
    else
        parentLayer = parent();

    if (!parentLayer) return;

    parentLayer->convertToLayerCoords(ancestorLayer, x, y);

    x += xPos();
    y += yPos();
}

void
RenderLayer::scrollOffset(int& x, int& y)
{
    x += scrollXOffset();
    y += scrollYOffset();
}

void
RenderLayer::subtractScrollOffset(int& x, int& y)
{
    x -= scrollXOffset();
    y -= scrollYOffset();
}

void
RenderLayer::scrollToOffset(int x, int y, bool updateScrollbars, bool repaint)
{
    if (renderer()->style()->overflow() != OMARQUEE) {
        if (x < 0) x = 0;
        if (y < 0) y = 0;

        // Call the scrollWidth/Height functions so that the dimensions will be computed if they need
        // to be (for overflow:hidden blocks).
        int maxX = scrollWidth() - m_object->clientWidth();
        int maxY = scrollHeight() - m_object->clientHeight();

        if (x > maxX) x = maxX;
        if (y > maxY) y = maxY;
    }

    // FIXME: Eventually, we will want to perform a blit.  For now never
    // blit, since the check for blitting is going to be very
    // complicated (since it will involve testing whether our layer
    // is either occluded by another layer or clipped by an enclosing
    // layer or contains fixed backgrounds, etc.).
    m_scrollX = x;
    m_scrollY = y;

    // Update the positions of our child layers.
    for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
        child->updateLayerPositions(false, false);

#if APPLE_CHANGES
    // Move our widgets.
    m_object->updateWidgetPositions();

    // Update dashboard regions, scrolling may change the clip of a
    // particular region.
    RenderCanvas *canvas = renderer()->canvas();
    if (canvas)
        canvas->view()->updateDashboardRegions();
#endif

    // Fire the scroll DOM event.
    m_object->element()->dispatchHTMLEvent(EventImpl::SCROLL_EVENT, true, false);

    // Just schedule a full repaint of our object.
    if (repaint)
        m_object->repaint();

    if (updateScrollbars) {
        if (m_hBar)
            m_hBar->setValue(m_scrollX);
        if (m_vBar)
            m_vBar->setValue(m_scrollY);
    }
}

void RenderLayer::scrollRectToVisible(const QRect &rect, const ScrollAlignment& alignX, const ScrollAlignment& alignY)
{
    RenderLayer* parentLayer = 0;
    QRect newRect = rect;
    int xOffset = 0, yOffset = 0;

    if (m_object->hasOverflowClip()) {
        QRect layerBounds = QRect(m_x + m_scrollX, m_y + m_scrollY, m_width, m_height);
        QRect exposeRect = QRect(rect.x() + m_scrollX, rect.y() + m_scrollY, rect.width(), rect.height());
        QRect r = getRectToExpose(layerBounds, exposeRect, alignX, alignY);

        xOffset = r.x() - m_x;
        yOffset = r.y() - m_y;
        // Adjust offsets if they're outside of the allowable range.
        xOffset = kMax(0, kMin(m_scrollWidth - m_width, xOffset));
        yOffset = kMax(0, kMin(m_scrollHeight - m_height, yOffset));

        if (xOffset != m_scrollX || yOffset != m_scrollY) {
            int diffX = m_scrollX;
            int diffY = m_scrollY;
            scrollToOffset(xOffset, yOffset);
            diffX = m_scrollX - diffX;
            diffY = m_scrollY - diffY;
            newRect.setX(rect.x() - diffX);
            newRect.setY(rect.y() - diffY);
        }

        if (m_object->parent())
            parentLayer = m_object->parent()->enclosingLayer();
    } else {
        QScrollView* view = m_object->document()->view();
        if (view) {
            QRect viewRect = QRect(view->scrollXOffset(), view->scrollYOffset(), view->visibleWidth(), view->visibleHeight());
            QRect r = getRectToExpose(viewRect, rect, alignX, alignY);

            xOffset = r.x();
            yOffset = r.y();
            // Adjust offsets if they're outside of the allowable range.
            xOffset = kMax(0, kMin(view->contentsWidth(), xOffset));
            yOffset = kMax(0, kMin(view->contentsHeight(), yOffset));


            if (m_object->document() && m_object->document()->ownerElement() && m_object->document()->ownerElement()->renderer()) {
                view->setContentsPos(xOffset, yOffset);
                parentLayer = m_object->document()->ownerElement()->renderer()->enclosingLayer();
                newRect.setX(rect.x() - view->contentsX() + view->viewport()->x());
                newRect.setY(rect.y() - view->contentsY() + view->viewport()->y());
            }
            else {
                // If this is the outermost view that RenderLayer needs to scroll, then we should scroll the view recursively
                // Other apps, like Mail, rely on this feature.
                view->scrollPointRecursively(xOffset, yOffset);
            }
        }
    }

    if (parentLayer)
        parentLayer->scrollRectToVisible(newRect, alignX, alignY);
}

QRect RenderLayer::getRectToExpose(const QRect &visibleRect, const QRect &exposeRect, const ScrollAlignment& alignX, const ScrollAlignment& alignY) {

    int x, y, w, h;
    x = exposeRect.x();
    y = exposeRect.y();
    w = exposeRect.width();
    h = exposeRect.height();

    // Find the appropriate X coordinate to scroll to.
    ScrollBehavior scrollX = getHiddenBehavior(alignX);
    int intersectWidth = visibleRect.intersect(exposeRect).width();
    // If the rectangle is fully visible, use the specified visible behavior.
    // If the rectangle is partially visible, but over a certain threshold, then treat it as fully visible to avoid unnecessary horizontal scrolling
    if (intersectWidth == w || intersectWidth >= MIN_INTERSECT_FOR_REVEAL)
        scrollX = getVisibleBehavior(alignX);
    else if (intersectWidth == visibleRect.width()) {
        // If the rect is bigger than the visible area, don't bother trying to center.  Other alignments will work.
        if (getVisibleBehavior(alignX) == alignCenter)
            scrollX = noScroll;
        else
            scrollX = getVisibleBehavior(alignX);
    }
    // If the rectangle is partially visible, but not above the minimum threshold, use the specified partial behavior
    else if (intersectWidth > 0)
        scrollX = getPartialBehavior(alignX);

    if (scrollX == noScroll)
        x = visibleRect.x();
    // If we're trying to align to the closest edge, and the exposeRect is further right than the visibleRect, and not bigger than the visible area, then alignRight.
    else if ((scrollX == alignRight) || ((scrollX == alignToClosestEdge) && exposeRect.right() > visibleRect.right() && w < visibleRect.width()))
        x = exposeRect.right() - visibleRect.width();
    else if (scrollX == alignCenter)
        x -= (visibleRect.width() - w) / 2;
    // By default, x is set to the left of the exposeRect, so for the alignLeft case,
    // or the alignToClosestEdge case where the closest edge is the left edge, then x does not need to be changed.
    w = visibleRect.width();

    // Find the appropriate Y coordinate to scroll to.
    ScrollBehavior scrollY = getHiddenBehavior(alignY);
    int intersectHeight = visibleRect.intersect(exposeRect).height();
    // If the rectangle is fully visible, use the specified visible behavior.
    if (intersectHeight == h)
        scrollY = getVisibleBehavior(alignY);
    else if (intersectHeight == visibleRect.height()) {
        // If the rect is bigger than the visible area, don't bother trying to center.  Other alignments will work.
        if (getVisibleBehavior(alignY) == alignCenter)
            scrollY = noScroll;
        else
            scrollY = getVisibleBehavior(alignY);
    }
    // If the rectangle is partially visible, use the specified partial behavior
    else if (intersectHeight > 0)
        scrollY = getPartialBehavior(alignY);

    if (scrollY == noScroll)
        y = visibleRect.y();
    // If we're trying to align to the closest edge, and the exposeRect is further down than the visibleRect, and not bigger than the visible area, then alignBottom.
    else if ((scrollY == alignBottom) || ((scrollY == alignToClosestEdge) && exposeRect.bottom() > visibleRect.bottom() && h < visibleRect.height()))
        y = exposeRect.bottom() - visibleRect.height();
    else if (scrollY == alignCenter)
        y -= (visibleRect.height() - h) / 2;
    // By default, y is set to the top of the exposeRect, so for the alignTop case,
    // or the alignToEdgeY case where the closest edge is the top edge, then y does not need to be changed.
    h = visibleRect.height();

    return QRect(x, y, w, h);
}

void RenderLayer::updateScrollPositionFromScrollbars()
{
    bool needUpdate = false;
    int newX = m_scrollX;
    int newY = m_scrollY;

    if (m_hBar) {
        newX = m_hBar->value();
        if (newX != m_scrollX)
           needUpdate = true;
    }

    if (m_vBar) {
        newY = m_vBar->value();
        if (newY != m_scrollY)
           needUpdate = true;
    }

    if (needUpdate)
        scrollToOffset(newX, newY, false);
}

void
RenderLayer::setHasHorizontalScrollbar(bool hasScrollbar)
{
    if (hasScrollbar && !m_hBar) {
        QScrollView* scrollView = m_object->element()->getDocument()->view();
        m_hBar = new QScrollBar(Qt::Horizontal, 0);
        scrollView->addChild(m_hBar, 0, -50000);
        if (!m_scrollMediator)
            m_scrollMediator = new RenderScrollMediator(this);
        m_scrollMediator->connect(m_hBar, SIGNAL(valueChanged(int)), SLOT(slotValueChanged(int)));
    }
    else if (!hasScrollbar && m_hBar) {
        QScrollView* scrollView = m_object->element()->getDocument()->view();
        scrollView->removeChild (m_hBar);

        m_scrollMediator->disconnect(m_hBar, SIGNAL(valueChanged(int)),
                                     m_scrollMediator, SLOT(slotValueChanged(int)));

⌨️ 快捷键说明

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