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

📄 renderlayer.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    // Schedule the scroll DOM event.    if (view) {        if (FrameView* frameView = view->frameView())            frameView->scheduleEvent(Event::create(eventNames().scrollEvent, false, false), renderer()->node());    }}void RenderLayer::scrollRectToVisible(const IntRect &rect, bool scrollToAnchor, const ScrollAlignment& alignX, const ScrollAlignment& alignY){    RenderLayer* parentLayer = 0;    IntRect newRect = rect;    int xOffset = 0, yOffset = 0;    // We may end up propagating a scroll event. It is important that we suspend events until     // the end of the function since they could delete the layer or the layer's renderer().    FrameView* frameView = renderer()->document()->view();    if (frameView)        frameView->pauseScheduledEvents();    bool restrictedByLineClamp = false;    if (renderer()->parent()) {        parentLayer = renderer()->parent()->enclosingLayer();        restrictedByLineClamp = renderer()->parent()->style()->lineClamp() >= 0;    }    if (renderer()->hasOverflowClip() && !restrictedByLineClamp) {        // Don't scroll to reveal an overflow layer that is restricted by the -webkit-line-clamp property.        // This will prevent us from revealing text hidden by the slider in Safari RSS.        RenderBox* box = renderBox();        ASSERT(box);        FloatPoint absPos = box->localToAbsolute();        absPos.move(box->borderLeft(), box->borderTop());        IntRect layerBounds = IntRect(absPos.x() + scrollXOffset(), absPos.y() + scrollYOffset(), box->clientWidth(), box->clientHeight());        IntRect exposeRect = IntRect(rect.x() + scrollXOffset(), rect.y() + scrollYOffset(), rect.width(), rect.height());        IntRect r = getRectToExpose(layerBounds, exposeRect, alignX, alignY);                xOffset = r.x() - absPos.x();        yOffset = r.y() - absPos.y();        // Adjust offsets if they're outside of the allowable range.        xOffset = max(0, min(scrollWidth() - layerBounds.width(), xOffset));        yOffset = max(0, min(scrollHeight() - layerBounds.height(), yOffset));                if (xOffset != scrollXOffset() || yOffset != scrollYOffset()) {            int diffX = scrollXOffset();            int diffY = scrollYOffset();            scrollToOffset(xOffset, yOffset);            diffX = scrollXOffset() - diffX;            diffY = scrollYOffset() - diffY;            newRect.setX(rect.x() - diffX);            newRect.setY(rect.y() - diffY);        }    } else if (!parentLayer && renderer()->isBox() && renderBox()->canBeProgramaticallyScrolled(scrollToAnchor)) {        if (frameView) {            if (renderer()->document() && renderer()->document()->ownerElement() && renderer()->document()->ownerElement()->renderer()) {                IntRect viewRect = frameView->visibleContentRect();                IntRect r = getRectToExpose(viewRect, rect, alignX, alignY);                                xOffset = r.x();                yOffset = r.y();                // Adjust offsets if they're outside of the allowable range.                xOffset = max(0, min(frameView->contentsWidth(), xOffset));                yOffset = max(0, min(frameView->contentsHeight(), yOffset));                frameView->setScrollPosition(IntPoint(xOffset, yOffset));                parentLayer = renderer()->document()->ownerElement()->renderer()->enclosingLayer();                newRect.setX(rect.x() - frameView->scrollX() + frameView->x());                newRect.setY(rect.y() - frameView->scrollY() + frameView->y());            } else {                IntRect viewRect = frameView->visibleContentRect(true);                IntRect r = getRectToExpose(viewRect, rect, alignX, alignY);                                // 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.                frameView->scrollRectIntoViewRecursively(r);            }        }    }        if (parentLayer)        parentLayer->scrollRectToVisible(newRect, scrollToAnchor, alignX, alignY);    if (frameView)        frameView->resumeScheduledEvents();}IntRect RenderLayer::getRectToExpose(const IntRect &visibleRect, const IntRect &exposeRect, const ScrollAlignment& alignX, const ScrollAlignment& alignY){    // Determine the appropriate X behavior.    ScrollBehavior scrollX;    IntRect exposeRectX(exposeRect.x(), visibleRect.y(), exposeRect.width(), visibleRect.height());    int intersectWidth = intersection(visibleRect, exposeRectX).width();    if (intersectWidth == exposeRect.width() || intersectWidth >= MIN_INTERSECT_FOR_REVEAL)        // 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        scrollX = ScrollAlignment::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.        scrollX = ScrollAlignment::getVisibleBehavior(alignX);        if (scrollX == alignCenter)            scrollX = noScroll;    } else if (intersectWidth > 0)        // If the rectangle is partially visible, but not above the minimum threshold, use the specified partial behavior        scrollX = ScrollAlignment::getPartialBehavior(alignX);    else        scrollX = ScrollAlignment::getHiddenBehavior(alignX);    // 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 align with the right.    if (scrollX == alignToClosestEdge && exposeRect.right() > visibleRect.right() && exposeRect.width() < visibleRect.width())        scrollX = alignRight;    // Given the X behavior, compute the X coordinate.    int x;    if (scrollX == noScroll)         x = visibleRect.x();    else if (scrollX == alignRight)        x = exposeRect.right() - visibleRect.width();    else if (scrollX == alignCenter)        x = exposeRect.x() + (exposeRect.width() - visibleRect.width()) / 2;    else        x = exposeRect.x();    // Determine the appropriate Y behavior.    ScrollBehavior scrollY;    IntRect exposeRectY(visibleRect.x(), exposeRect.y(), visibleRect.width(), exposeRect.height());    int intersectHeight = intersection(visibleRect, exposeRectY).height();    if (intersectHeight == exposeRect.height())        // If the rectangle is fully visible, use the specified visible behavior.        scrollY = ScrollAlignment::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.        scrollY = ScrollAlignment::getVisibleBehavior(alignY);        if (scrollY == alignCenter)            scrollY = noScroll;    } else if (intersectHeight > 0)        // If the rectangle is partially visible, use the specified partial behavior        scrollY = ScrollAlignment::getPartialBehavior(alignY);    else        scrollY = ScrollAlignment::getHiddenBehavior(alignY);    // 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 align with the bottom.    if (scrollY == alignToClosestEdge && exposeRect.bottom() > visibleRect.bottom() && exposeRect.height() < visibleRect.height())        scrollY = alignBottom;    // Given the Y behavior, compute the Y coordinate.    int y;    if (scrollY == noScroll)         y = visibleRect.y();    else if (scrollY == alignBottom)        y = exposeRect.bottom() - visibleRect.height();    else if (scrollY == alignCenter)        y = exposeRect.y() + (exposeRect.height() - visibleRect.height()) / 2;    else        y = exposeRect.y();    return IntRect(IntPoint(x, y), visibleRect.size());}void RenderLayer::autoscroll(){    Frame* frame = renderer()->document()->frame();    if (!frame)        return;    FrameView* frameView = frame->view();    if (!frameView)        return;    frame->eventHandler()->updateSelectionForMouseDrag();    IntPoint currentDocumentPosition = frameView->windowToContents(frame->eventHandler()->currentMousePosition());    scrollRectToVisible(IntRect(currentDocumentPosition, IntSize(1, 1)), false, ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded);}void RenderLayer::resize(const PlatformMouseEvent& evt, const IntSize& oldOffset){    // FIXME: This should be possible on generated content but is not right now.    if (!inResizeMode() || !renderer()->hasOverflowClip() || !renderer()->node())        return;    // Set the width and height of the shadow ancestor node if there is one.    // This is necessary for textarea elements since the resizable layer is in the shadow content.    Element* element = static_cast<Element*>(renderer()->node()->shadowAncestorNode());    RenderBox* renderer = toRenderBox(element->renderer());    EResize resize = renderer->style()->resize();    if (resize == RESIZE_NONE)        return;    Document* document = element->document();    if (!document->frame()->eventHandler()->mousePressed())        return;    float zoomFactor = renderer->style()->effectiveZoom();    IntSize newOffset = offsetFromResizeCorner(document->view()->windowToContents(evt.pos()));    newOffset.setWidth(newOffset.width() / zoomFactor);    newOffset.setHeight(newOffset.height() / zoomFactor);        IntSize currentSize = IntSize(renderer->width() / zoomFactor, renderer->height() / zoomFactor);    IntSize minimumSize = element->minimumSizeForResizing().shrunkTo(currentSize);    element->setMinimumSizeForResizing(minimumSize);        IntSize adjustedOldOffset = IntSize(oldOffset.width() / zoomFactor, oldOffset.height() / zoomFactor);        IntSize difference = (currentSize + newOffset - adjustedOldOffset).expandedTo(minimumSize) - currentSize;    CSSStyleDeclaration* style = element->style();    bool isBoxSizingBorder = renderer->style()->boxSizing() == BORDER_BOX;    ExceptionCode ec;    if (difference.width()) {        if (element && element->isFormControlElement()) {            // Make implicit margins from the theme explicit (see <http://bugs.webkit.org/show_bug.cgi?id=9547>).            style->setProperty(CSSPropertyMarginLeft, String::number(renderer->marginLeft() / zoomFactor) + "px", false, ec);            style->setProperty(CSSPropertyMarginRight, String::number(renderer->marginRight() / zoomFactor) + "px", false, ec);        }        int baseWidth = renderer->width() - (isBoxSizingBorder ? 0            : renderer->borderLeft() + renderer->paddingLeft() + renderer->borderRight() + renderer->paddingRight());        baseWidth = baseWidth / zoomFactor;        style->setProperty(CSSPropertyWidth, String::number(baseWidth + difference.width()) + "px", false, ec);    }    if (difference.height()) {        if (element && element->isFormControlElement()) {            // Make implicit margins from the theme explicit (see <http://bugs.webkit.org/show_bug.cgi?id=9547>).            style->setProperty(CSSPropertyMarginTop, String::number(renderer->marginTop() / zoomFactor) + "px", false, ec);            style->setProperty(CSSPropertyMarginBottom, String::number(renderer->marginBottom() / zoomFactor) + "px", false, ec);        }        int baseHeight = renderer->height() - (isBoxSizingBorder ? 0            : renderer->borderTop() + renderer->paddingTop() + renderer->borderBottom() + renderer->paddingBottom());        baseHeight = baseHeight / zoomFactor;        style->setProperty(CSSPropertyHeight, String::number(baseHeight + difference.height()) + "px", false, ec);    }    document->updateLayout();    // FIXME (Radar 4118564): We should also autoscroll the window as necessary to keep the point under the cursor in view.}void RenderLayer::valueChanged(Scrollbar*){    // Update scroll position from scrollbars.    bool needUpdate = false;    int newX = scrollXOffset();    int newY = m_scrollY;        if (m_hBar) {        newX = m_hBar->value();        if (newX != scrollXOffset())           needUpdate = true;    }    if (m_vBar) {        newY = m_vBar->value();        if (newY != m_scrollY)           needUpdate = true;    }    if (needUpdate)        scrollToOffset(newX, newY, false);}bool RenderLayer::isActive() const{    Page* page = renderer()->document()->frame()->page();    return page && page->focusController()->isActive();}static IntRect cornerRect(const RenderLayer* layer, const IntRect& bounds){    int horizontalThickness;    int verticalThickness;    if (!layer->verticalScrollbar() && !layer->horizontalScrollbar()) {        // FIXME: This isn't right.  We need to know the thickness of custom scrollbars        // even when they don't exist in order to set the resizer square size properly.        horizontalThickness = ScrollbarTheme::nativeTheme()->scrollbarThickness();        verticalThickness = horizontalThickness;    } else if (layer->verticalScrollbar() && !layer->horizontalScrollbar()) {        horizontalThickness = layer->verticalScrollbar()->width();        verticalThickness = horizontalThickness;    } else if (layer->horizontalScrollbar() && !layer->verticalScrollbar()) {        verticalThickness = layer->horizontalScrollbar()->height();        horizontalThickness = verticalThickness;    } else {        horizontalThickness = layer->verticalScrollbar()->width();        verticalThickness = layer->horizontalScrollbar()->height();    }    return IntRect(bounds.right() - horizontalThickness - layer->renderer()->style()->borderRightWidth(),                    bounds.bottom() - verticalThickness - layer->renderer()->style()->borderBottomWidth(),                   horizontalThickness, verticalThickness);}static IntRect scrollCornerRect(const RenderLayer* layer, const IntRect& bounds){    // We have a scrollbar corner when a scrollbar is visible and not filling the entire length of the box.    // This happens when:    // (a) A resizer is present and at least one scrollbar is present    // (b) Both scrollbars are present.    bool hasHorizontalBar = layer->horizontalScrollbar();    bool hasVerticalBar = layer->verticalScrollbar();    bool hasResizer = layer->renderer()->style()->resize() != RESIZE_NONE;    if ((hasHorizontalBar && hasVerticalBar) || (hasResizer && (hasHorizontalBar || hasVerticalBar)))        return cornerRect(layer, bounds);    return IntRect();}static IntRect resizerCornerRect(const RenderLayer* layer, const IntRect& bounds){    ASSERT(layer->renderer()->isBox());    if (layer->renderer()->style()->resize() == RESIZE_NONE)        return IntRect();    return cornerRect(layer, bounds);}bool RenderLayer::scrollbarCornerPresent() const{    ASSERT(renderer()->isBox());    return !scrollCornerRect(this, renderBox()->borderBoxRect()).isEmpty();}void RenderLayer::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& rect){    IntRect scrollRect = rect;    RenderBox* box = renderBox();    ASSERT(box);    if (scrollbar == m_vBar.get())        scrollRect.move(box->width() - box->borderRight() - box->width(), box->borderTop());    else        scrollRect.move(box->borderLeft(), box->height() - box->borderBottom() - scrollbar->height());    renderer()->repaintRectangle(scrollRect);}PassRefPtr<Scrollbar> RenderLayer::createScrollbar(ScrollbarOrientation orientation){    RefPtr<Scrollbar> widget;    RenderObject* actualRenderer = renderer()->node() ? renderer()->node()->shadowAncestorNode()->renderer() : renderer();    bool hasCustomScrollbarStyle = actualRenderer->isBox() && actualRenderer->style()->hasPseudoStyle(SCROLLBAR);    if (hasCustomScrollbarStyle)        widget = RenderScrollbar::createCustomScrollbar(this, orientation, toRenderBox(actualRenderer));    else        widget = Scrollbar::createNativeScrollbar(this, orientation, RegularScrollbar);    renderer()->document()->view()->addChild(widget.get());            return widget.release();}void RenderLayer::destroyScrollbar(ScrollbarOrientation orientation){    RefPtr<Scrollbar>& scrollbar = orientation == HorizontalScrollbar ? m_hBar : m_vBar;    if (scrollbar) {        scrollbar->removeFromParent();        scrollbar->setClient(0);

⌨️ 快捷键说明

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