LayoutUnit RenderIFrame::minPreferredLogicalWidth() const
{
    if (!isSeamless())
        return RenderFrameBase::minPreferredLogicalWidth();

    RenderView* childRoot = contentRootRenderer();
    if (!childRoot)
        return 0;

    return childRoot->minPreferredLogicalWidth() + borderAndPaddingLogicalWidth();
}
void RenderFrameBase::layoutWithFlattening(bool fixedWidth, bool fixedHeight)
{
    FrameView* childFrameView = static_cast<FrameView*>(widget());
    RenderView* childRoot = childFrameView ? static_cast<RenderView*>(childFrameView->frame()->contentRenderer()) : 0;

    // Do not expand frames which has zero width or height
    if (!width() || !height() || !childRoot) {
        updateWidgetPosition();
        if (childFrameView)
            childFrameView->layout();
        setNeedsLayout(false);
        return;
    }

    // need to update to calculate min/max correctly
    updateWidgetPosition();
    if (childRoot->preferredLogicalWidthsDirty())
        childRoot->computePreferredLogicalWidths();

    // if scrollbars are off, and the width or height are fixed
    // we obey them and do not expand. With frame flattening
    // no subframe much ever become scrollable.

    HTMLFrameElementBase* element = static_cast<HTMLFrameElementBase*>(node());
    bool isScrollable = element->scrollingMode() != ScrollbarAlwaysOff;

    // consider iframe inset border
    int hBorder = borderLeft() + borderRight();
    int vBorder = borderTop() + borderBottom();

    // make sure minimum preferred width is enforced
    if (isScrollable || !fixedWidth) {
        setWidth(max(width(), childRoot->minPreferredLogicalWidth() + hBorder));
        // update again to pass the new width to the child frame
        updateWidgetPosition();
        childFrameView->layout();
    }

    // expand the frame by setting frame height = content height
    if (isScrollable || !fixedHeight || childRoot->isFrameSet())
        setHeight(max(height(), childFrameView->contentsHeight() + vBorder));
    if (isScrollable || !fixedWidth || childRoot->isFrameSet())
        setWidth(max(width(), childFrameView->contentsWidth() + hBorder));

    updateWidgetPosition();

    ASSERT(!childFrameView->layoutPending());
    ASSERT(!childRoot->needsLayout());
    ASSERT(!childRoot->firstChild() || !childRoot->firstChild()->firstChild() || !childRoot->firstChild()->firstChild()->needsLayout());

    setNeedsLayout(false);
}
Example #3
0
void RenderFrameBase::layoutWithFlattening(bool hasFixedWidth, bool hasFixedHeight)
{
    FrameView* childFrameView = toFrameView(widget());
    RenderView* childRoot = childFrameView ? childFrameView->frame().contentRenderer() : 0;

    if (!childRoot || !shouldExpandFrame(width(), height(), hasFixedWidth, hasFixedHeight)) {
        updateWidgetPosition();
        if (childFrameView)
            childFrameView->layout();
        clearNeedsLayout();
        return;
    }

    // need to update to calculate min/max correctly
    updateWidgetPosition();

    // if scrollbars are off, and the width or height are fixed
    // we obey them and do not expand. With frame flattening
    // no subframe much ever become scrollable.

    bool isScrollable = frameOwnerElement().scrollingMode() != ScrollbarAlwaysOff;

    // consider iframe inset border
    int hBorder = borderLeft() + borderRight();
    int vBorder = borderTop() + borderBottom();

    // make sure minimum preferred width is enforced
    if (isScrollable || !hasFixedWidth) {
        setWidth(std::max(width(), childRoot->minPreferredLogicalWidth() + hBorder));
        // update again to pass the new width to the child frame
        updateWidgetPosition();
        childFrameView->layout();
    }

    // expand the frame by setting frame height = content height
    if (isScrollable || !hasFixedHeight || childRoot->isFrameSet())
        setHeight(std::max<LayoutUnit>(height(), childFrameView->contentsHeight() + vBorder));
    if (isScrollable || !hasFixedWidth || childRoot->isFrameSet())
        setWidth(std::max<LayoutUnit>(width(), childFrameView->contentsWidth() + hBorder));

    updateWidgetPosition();

    ASSERT(!childFrameView->layoutPending());
    ASSERT(!childRoot->needsLayout());
    ASSERT(!childRoot->firstChild() || !childRoot->firstChild()->firstChildSlow() || !childRoot->firstChild()->firstChildSlow()->needsLayout());

    clearNeedsLayout();
}
void FrameViewAutoSizeInfo::autoSizeIfNeeded()
{
    if (m_inAutoSize)
        return;

    TemporaryChange<bool> changeInAutoSize(m_inAutoSize, true);

    Document* document = m_frameView->frame().document();
    if (!document || !document->isActive())
        return;

    Element* documentElement = document->documentElement();
    if (!documentElement)
        return;

    // If this is the first time we run autosize, start from small height and
    // allow it to grow.
    if (!m_didRunAutosize)
        m_frameView->resize(m_frameView->frameRect().width(), m_minAutoSize.height());

    IntSize size = m_frameView->frameRect().size();

    // Do the resizing twice. The first time is basically a rough calculation using the preferred width
    // which may result in a height change during the second iteration.
    for (int i = 0; i < 2; i++) {
        // Update various sizes including contentsSize, scrollHeight, etc.
        document->updateLayoutIgnorePendingStylesheets();

        RenderView* renderView = document->renderView();
        if (!renderView)
            return;

        int width = renderView->minPreferredLogicalWidth();

        RenderBox* documentRenderBox = documentElement->renderBox();
        if (!documentRenderBox)
            return;

        int height = documentRenderBox->scrollHeight();
        IntSize newSize(width, height);

        // Check to see if a scrollbar is needed for a given dimension and
        // if so, increase the other dimension to account for the scrollbar.
        // Since the dimensions are only for the view rectangle, once a
        // dimension exceeds the maximum, there is no need to increase it further.
        if (newSize.width() > m_maxAutoSize.width()) {
            RefPtrWillBeRawPtr<Scrollbar> localHorizontalScrollbar = m_frameView->horizontalScrollbar();
            if (!localHorizontalScrollbar)
                localHorizontalScrollbar = m_frameView->createScrollbar(HorizontalScrollbar);
            if (!localHorizontalScrollbar->isOverlayScrollbar())
                newSize.setHeight(newSize.height() + localHorizontalScrollbar->height());

            // Don't bother checking for a vertical scrollbar because the width is at
            // already greater the maximum.
        } else if (newSize.height() > m_maxAutoSize.height()) {
            RefPtrWillBeRawPtr<Scrollbar> localVerticalScrollbar = m_frameView->verticalScrollbar();
            if (!localVerticalScrollbar)
                localVerticalScrollbar = m_frameView->createScrollbar(VerticalScrollbar);
            if (!localVerticalScrollbar->isOverlayScrollbar())
                newSize.setWidth(newSize.width() + localVerticalScrollbar->width());

            // Don't bother checking for a horizontal scrollbar because the height is
            // already greater the maximum.
        }

        // Ensure the size is at least the min bounds.
        newSize = newSize.expandedTo(m_minAutoSize);

        // Bound the dimensions by the max bounds and determine what scrollbars to show.
        ScrollbarMode horizonalScrollbarMode = ScrollbarAlwaysOff;
        if (newSize.width() > m_maxAutoSize.width()) {
            newSize.setWidth(m_maxAutoSize.width());
            horizonalScrollbarMode = ScrollbarAlwaysOn;
        }
        ScrollbarMode verticalScrollbarMode = ScrollbarAlwaysOff;
        if (newSize.height() > m_maxAutoSize.height()) {
            newSize.setHeight(m_maxAutoSize.height());
            verticalScrollbarMode = ScrollbarAlwaysOn;
        }

        if (newSize == size)
            continue;

        // While loading only allow the size to increase (to avoid twitching during intermediate smaller states)
        // unless autoresize has just been turned on or the maximum size is smaller than the current size.
        if (m_didRunAutosize && size.height() <= m_maxAutoSize.height() && size.width() <= m_maxAutoSize.width()
            && !m_frameView->frame().document()->loadEventFinished() && (newSize.height() < size.height() || newSize.width() < size.width()))
            break;

        m_frameView->resize(newSize.width(), newSize.height());
        // Force the scrollbar state to avoid the scrollbar code adding them and causing them to be needed. For example,
        // a vertical scrollbar may cause text to wrap and thus increase the height (which is the only reason the scollbar is needed).
        m_frameView->setVerticalScrollbarLock(false);
        m_frameView->setHorizontalScrollbarLock(false);
        m_frameView->setScrollbarModes(horizonalScrollbarMode, verticalScrollbarMode, true, true);
    }
    m_didRunAutosize = true;
}