IntSize ScrollableArea::scrollbarIntrusion() const
{
    return {
        verticalScrollbar() ? verticalScrollbar()->occupiedWidth() : 0,
        horizontalScrollbar() ? horizontalScrollbar()->occupiedHeight() : 0
    };
}
ScrollPosition ScrollableArea::scrollPosition() const
{
    // FIXME: This relationship seems to be inverted. Scrollbars should be 'view', not 'model', and should get their values from us.
    int x = horizontalScrollbar() ? horizontalScrollbar()->value() : 0;
    int y = verticalScrollbar() ? verticalScrollbar()->value() : 0;
    return IntPoint(x, y);
}
void ScrollableArea::setScrollbarOverlayStyle(ScrollbarOverlayStyle overlayStyle)
{
    m_scrollbarOverlayStyle = overlayStyle;

    if (horizontalScrollbar()) {
        ScrollbarTheme::theme()->updateScrollbarOverlayStyle(horizontalScrollbar());
        horizontalScrollbar()->invalidate();
    }
    
    if (verticalScrollbar()) {
        ScrollbarTheme::theme()->updateScrollbarOverlayStyle(verticalScrollbar());
        verticalScrollbar()->invalidate();
    }
}
Example #4
0
/*
 * The following is assumed:
 *   (hadj && vadj) || (!hadj && !vadj)
 */
void ScrollView::setGtkAdjustments(GtkAdjustment* hadj, GtkAdjustment* vadj, bool resetValues)
{
    ASSERT(!hadj == !vadj);

    m_horizontalAdjustment = hadj;
    m_verticalAdjustment = vadj;

    // Reset the adjustments to a sane default
    if (m_horizontalAdjustment) {
        ScrollbarGtk* hScrollbar = reinterpret_cast<ScrollbarGtk*>(horizontalScrollbar());
        if (hScrollbar)
            hScrollbar->attachAdjustment(m_horizontalAdjustment);

        ScrollbarGtk* vScrollbar = reinterpret_cast<ScrollbarGtk*>(verticalScrollbar());
        if (vScrollbar)
            vScrollbar->attachAdjustment(m_verticalAdjustment);

        // We used to reset everything to 0 here, but when page cache
        // is enabled we reuse FrameViews that are cached. Since their
        // size is not going to change when being restored, (which is
        // what would cause the upper limit in the adjusments to be
        // set in the normal case), we make sure they are up-to-date
        // here. This is needed for the parent scrolling widget to be
        // able to report correct values.
        m_horizontalAdjustment->lower = 0;
        m_horizontalAdjustment->upper = resetValues ? 0 : frameRect().width();
        m_horizontalAdjustment->value = resetValues ? 0 : scrollOffset().width();
        gtk_adjustment_changed(m_horizontalAdjustment);
        gtk_adjustment_value_changed(m_horizontalAdjustment);

        m_verticalAdjustment->lower = 0;
        m_verticalAdjustment->upper = resetValues ? 0 : frameRect().height();
        m_verticalAdjustment->value = resetValues ? 0 : scrollOffset().height();
        gtk_adjustment_changed(m_verticalAdjustment);
        gtk_adjustment_value_changed(m_verticalAdjustment);
    } else {
        ScrollbarGtk* hScrollbar = reinterpret_cast<ScrollbarGtk*>(horizontalScrollbar());
        if (hScrollbar)
            hScrollbar->detachAdjustment();

        ScrollbarGtk* vScrollbar = reinterpret_cast<ScrollbarGtk*>(verticalScrollbar());
        if (vScrollbar)
            vScrollbar->detachAdjustment();
    }

    /* reconsider having a scrollbar */
    setHasVerticalScrollbar(false);
    setHasHorizontalScrollbar(false);
}
Example #5
0
/*
    Test that vertical and horizontal mac-style scrollbars paint their
    entire area.
*/
void tst_MacGui::scrollbarPainting()
{
    ColorWidget colorWidget;
    colorWidget.resize(400, 400);

    QSize scrollBarSize;

    QScrollBar verticalScrollbar(&colorWidget);
    verticalScrollbar.move(10, 10);
    scrollBarSize = verticalScrollbar.sizeHint();
    scrollBarSize.setHeight(200);
    verticalScrollbar.resize(scrollBarSize);

    QScrollBar horizontalScrollbar(&colorWidget);
    horizontalScrollbar.move(30, 10);
    horizontalScrollbar.setOrientation(Qt::Horizontal);
    scrollBarSize = horizontalScrollbar.sizeHint();
    scrollBarSize.setWidth(200);
    horizontalScrollbar.resize(scrollBarSize);

    colorWidget.show();
    colorWidget.raise();
    QTest::qWait(100);

    QImage image = grabWindowContents(&colorWidget).toImage();

    QVERIFY(isContent(image, verticalScrollbar.geometry(), GuiTester::Horizontal));
#ifdef Q_OS_MAC
    // this test seems to be unstable on OS X 10.6 (Snow Leopard)
    if (!isContent(image, horizontalScrollbar.geometry(), GuiTester::Vertical)) {
        QEXPECT_FAIL("", "QTBUG-20984", Abort);
    }
#endif
    QVERIFY(isContent(image, horizontalScrollbar.geometry(), GuiTester::Vertical));
}
IntRect ScrollView::visibleContentRect(bool includeScrollbars) const
{
    // If we are an interior frame scrollbar or are in some sort of transition
    // state, just calculate our size based on what the GTK+ theme says the
    // scrollbar width should be.
    if (parent() || !hostWindow() || !hostWindow()->platformPageClient()) {
        return IntRect(IntPoint(m_scrollOffset.width(), m_scrollOffset.height()),
                       IntSize(max(0, m_boundsSize.width() - (verticalScrollbar() && !includeScrollbars ? verticalScrollbar()->width() : 0)),
                               max(0, m_boundsSize.height() - (horizontalScrollbar() && !includeScrollbars ? horizontalScrollbar()->height() : 0))));
    }

    // We don't have a parent, so we are the main frame and thus have
    // a parent widget which we can use to measure the visible region.
    GtkWidget* measuredWidget = hostWindow()->platformPageClient();
    GtkWidget* parentWidget = gtk_widget_get_parent(measuredWidget);

    // We may not be in a widget that displays scrollbars, but we may
    // have other kinds of decoration that make us smaller.
    if (parentWidget && includeScrollbars)
        measuredWidget = parentWidget;

    GtkAllocation allocation;
    gtk_widget_get_allocation(measuredWidget, &allocation);
    return IntRect(IntPoint(m_scrollOffset.width(), m_scrollOffset.height()),
                   IntSize(allocation.width, allocation.height));
}
/*
    Test that vertical and horizontal mac-style scrollbars paint their
    entire area.
*/
void tst_MacGui::scrollbarPainting()
{
    ColorWidget colorWidget;
    colorWidget.resize(400, 400);

    QSize scrollBarSize;

    QScrollBar verticalScrollbar(&colorWidget);
    verticalScrollbar.move(10, 10);
    scrollBarSize = verticalScrollbar.sizeHint();
    scrollBarSize.setHeight(200);
    verticalScrollbar.resize(scrollBarSize);

    QScrollBar horizontalScrollbar(&colorWidget);
    horizontalScrollbar.move(30, 10);
    horizontalScrollbar.setOrientation(Qt::Horizontal);
    scrollBarSize = horizontalScrollbar.sizeHint();
    scrollBarSize.setWidth(200);
    horizontalScrollbar.resize(scrollBarSize);

    colorWidget.show();
    colorWidget.raise();
    QTest::qWait(100);

    QPixmap pixmap = grabWindowContents(&colorWidget);

    QVERIFY(isContent(pixmap.toImage(), verticalScrollbar.geometry(), GuiTester::Horizontal));
    QVERIFY(isContent(pixmap.toImage(), horizontalScrollbar.geometry(), GuiTester::Vertical));
}
Example #8
0
bool ScrollableArea::hasOverlayScrollbars() const
{
    Scrollbar* vScrollbar = verticalScrollbar();
    if (vScrollbar && vScrollbar->isOverlayScrollbar())
        return true;
    Scrollbar* hScrollbar = horizontalScrollbar();
    return hScrollbar && hScrollbar->isOverlayScrollbar();
}
Example #9
0
void ScrollableArea::setScrollbarOverlayStyle(ScrollbarOverlayStyle overlayStyle)
{
    m_scrollbarOverlayStyle = overlayStyle;

    if (horizontalScrollbar()) {
        ScrollbarTheme::theme()->updateScrollbarOverlayStyle(*horizontalScrollbar());
        horizontalScrollbar()->invalidate();
        if (ScrollAnimator* scrollAnimator = existingScrollAnimator())
            scrollAnimator->invalidateScrollbarPartLayers(horizontalScrollbar());
    }
    
    if (verticalScrollbar()) {
        ScrollbarTheme::theme()->updateScrollbarOverlayStyle(*verticalScrollbar());
        verticalScrollbar()->invalidate();
        if (ScrollAnimator* scrollAnimator = existingScrollAnimator())
            scrollAnimator->invalidateScrollbarPartLayers(verticalScrollbar());
    }
}
void ScrollView::setVerticalAdjustment(GtkAdjustment* vadj, bool resetValues)
{
    ASSERT(!parent() || !vadj);
    if (parent())
        return;

    m_verticalAdjustment = vadj;

    if (!m_verticalAdjustment) {
        MainFrameScrollbarGtk* vScrollbar = reinterpret_cast<MainFrameScrollbarGtk*>(verticalScrollbar());
        if (vScrollbar)
            vScrollbar->detachAdjustment();

        return;
    }

    // We may be lacking scrollbars when returning to a cached
    // page, this kicks the page to recreate the scrollbars.
    setHasVerticalScrollbar(true);

    MainFrameScrollbarGtk* vScrollbar = reinterpret_cast<MainFrameScrollbarGtk*>(verticalScrollbar());
    vScrollbar->attachAdjustment(m_verticalAdjustment.get());

    // We used to reset everything to 0 here, but when page cache
    // is enabled we reuse FrameViews that are cached. Since their
    // size is not going to change when being restored, (which is
    // what would cause the upper limit in the adjusments to be
    // set in the normal case), we make sure they are up-to-date
    // here. This is needed for the parent scrolling widget to be
    // able to report correct values.
    int verticalPageStep = max(max<int>(frameRect().width() * Scrollbar::minFractionToStepWhenPaging(), frameRect().width() - Scrollbar::maxOverlapBetweenPages()), 1);
    gtk_adjustment_configure(m_verticalAdjustment.get(),
                             resetValues ? 0 : scrollOffset().height(), 0,
                             resetValues ? 0 : contentsSize().height(),
                             resetValues ? 0 : Scrollbar::pixelsPerLineStep(),
                             resetValues ? 0 : verticalPageStep,
                             resetValues ? 0 : frameRect().height());
}
IntSize ScrollableArea::excludeScrollbars(const IntSize& size) const
{
    int verticalScrollbarWidth = 0;
    int horizontalScrollbarHeight = 0;

    if (Scrollbar* verticalBar = verticalScrollbar())
        verticalScrollbarWidth = !verticalBar->isOverlayScrollbar() ? verticalBar->width() : 0;
    if (Scrollbar* horizontalBar = horizontalScrollbar())
        horizontalScrollbarHeight = !horizontalBar->isOverlayScrollbar() ? horizontalBar->height() : 0;

    return IntSize(std::max(0, size.width() - verticalScrollbarWidth),
        std::max(0, size.height() - horizontalScrollbarHeight));

}
Example #12
0
void ScrollableArea::invalidateScrollbar(Scrollbar* scrollbar, const IntRect& rect)
{
#if USE(ACCELERATED_COMPOSITING)
    if (scrollbar == horizontalScrollbar()) {
        if (GraphicsLayer* graphicsLayer = layerForHorizontalScrollbar()) {
            graphicsLayer->setNeedsDisplay();
            return;
        }
    } else if (scrollbar == verticalScrollbar()) {
        if (GraphicsLayer* graphicsLayer = layerForVerticalScrollbar()) {
            graphicsLayer->setNeedsDisplay();
            return;
        }
    }
#endif
    invalidateScrollbarRect(scrollbar, rect);
}
IntRect ScrollableArea::visibleContentRectInternal(VisibleContentRectIncludesScrollbars scrollbarInclusion, VisibleContentRectBehavior) const
{
    int verticalScrollbarWidth = 0;
    int horizontalScrollbarHeight = 0;

    if (scrollbarInclusion == IncludeScrollbars) {
        if (Scrollbar* verticalBar = verticalScrollbar())
            verticalScrollbarWidth = verticalBar->occupiedWidth();
        if (Scrollbar* horizontalBar = horizontalScrollbar())
            horizontalScrollbarHeight = horizontalBar->occupiedHeight();
    }

    return IntRect(scrollPosition().x(),
                   scrollPosition().y(),
                   std::max(0, visibleWidth() + verticalScrollbarWidth),
                   std::max(0, visibleHeight() + horizontalScrollbarHeight));
}
void PaintInvalidationCapableScrollableArea::invalidatePaintOfScrollControlsIfNeeded(const PaintInvalidationState& paintInvalidationState, const LayoutBoxModelObject& paintInvalidationContainer)
{
    LayoutBox& box = boxForScrollControlPaintInvalidation();
    invalidatePaintOfScrollbarIfNeeded(horizontalScrollbar(), layerForHorizontalScrollbar(), m_horizontalScrollbarPreviouslyWasOverlay, m_horizontalScrollbarPreviousPaintInvalidationRect, horizontalScrollbarNeedsPaintInvalidation(), box, paintInvalidationState, paintInvalidationContainer);
    invalidatePaintOfScrollbarIfNeeded(verticalScrollbar(), layerForVerticalScrollbar(), m_verticalScrollbarPreviouslyWasOverlay, m_verticalScrollbarPreviousPaintInvalidationRect, verticalScrollbarNeedsPaintInvalidation(), box, paintInvalidationState, paintInvalidationContainer);

    LayoutRect scrollCornerPaintInvalidationRect = scrollControlPaintInvalidationRect(scrollCornerAndResizerRect(), box, paintInvalidationState, paintInvalidationContainer);
    if (invalidatePaintOfScrollControlIfNeeded(scrollCornerPaintInvalidationRect, m_scrollCornerAndResizerPreviousPaintInvalidationRect, scrollCornerNeedsPaintInvalidation(), box, paintInvalidationContainer)) {
        m_scrollCornerAndResizerPreviousPaintInvalidationRect = scrollCornerPaintInvalidationRect;
        if (LayoutScrollbarPart* scrollCorner = this->scrollCorner())
            scrollCorner->invalidateDisplayItemClientsIncludingNonCompositingDescendants(&paintInvalidationContainer, PaintInvalidationScroll);
        if (LayoutScrollbarPart* resizer = this->resizer())
            resizer->invalidateDisplayItemClientsIncludingNonCompositingDescendants(&paintInvalidationContainer, PaintInvalidationScroll);
    }

    clearNeedsPaintInvalidationForScrollControls();
}
Example #15
0
void ScrollableArea::invalidateScrollbar(Scrollbar* scrollbar, const IntRect& rect)
{
    if (scrollbar == horizontalScrollbar()) {
        if (GraphicsLayer* graphicsLayer = layerForHorizontalScrollbar()) {
            graphicsLayer->setNeedsDisplay();
            graphicsLayer->setContentsNeedsDisplay();
            return;
        }
    } else if (scrollbar == verticalScrollbar()) {
        if (GraphicsLayer* graphicsLayer = layerForVerticalScrollbar()) {
            graphicsLayer->setNeedsDisplay();
            graphicsLayer->setContentsNeedsDisplay();
            return;
        }
    }
    invalidateScrollbarRect(scrollbar, rect);
}
IntRect ScrollableArea::visibleContentRect(bool includeScrollbars) const
{
    int verticalScrollbarWidth = 0;
    int horizontalScrollbarHeight = 0;

    if (includeScrollbars) {
        if (Scrollbar* verticalBar = verticalScrollbar())
            verticalScrollbarWidth = !verticalBar->isOverlayScrollbar() ? verticalBar->width() : 0;
        if (Scrollbar* horizontalBar = horizontalScrollbar())
            horizontalScrollbarHeight = !horizontalBar->isOverlayScrollbar() ? horizontalBar->height() : 0;
    }

    return IntRect(scrollPosition().x(),
                   scrollPosition().y(),
                   std::max(0, visibleWidth() + verticalScrollbarWidth),
                   std::max(0, visibleHeight() + horizontalScrollbarHeight));
}
IntRect RenderLayerScrollableArea::scrollCornerRect() const
{
    // We have a scrollbar corner when a scrollbar is visible and not filling the entire length of the box.
    // This happens when both scrollbars are present.
    const Scrollbar* horizontalBar = horizontalScrollbar();
    const Scrollbar* verticalBar = verticalScrollbar();
    if (!horizontalBar || !verticalBar)
        return IntRect();

    const RenderStyle* style = box().style();
    int horizontalThickness = verticalBar->width();
    int verticalThickness = horizontalBar->height();
    const IntRect& bounds = box().pixelSnappedBorderBoxRect();
    return IntRect(cornerStart(style, bounds.x(), bounds.maxX(), horizontalThickness),
        bounds.maxY() - verticalThickness - style->borderBottomWidth(),
        horizontalThickness, verticalThickness);
}
Example #18
0
IntRect ScrollView::visibleContentRect(bool includeScrollbars) const
{
    if (!m_horizontalAdjustment)
        return IntRect(IntPoint(m_scrollOffset.width(), m_scrollOffset.height()),
                       IntSize(max(0, width() - (verticalScrollbar() && !includeScrollbars ? verticalScrollbar()->width() : 0)),
                               max(0, height() - (horizontalScrollbar() && !includeScrollbars ? horizontalScrollbar()->height() : 0))));

    // Main frame.
    GtkWidget* measuredWidget = hostWindow()->platformPageClient();
    GtkWidget* parent = gtk_widget_get_parent(measuredWidget);

    // We may not be in a widget that displays scrollbars, but we may
    // have other kinds of decoration that make us smaller.
    if (parent && includeScrollbars)
        measuredWidget = parent;

    return IntRect(IntPoint(m_scrollOffset.width(), m_scrollOffset.height()),
                   IntSize(measuredWidget->allocation.width,
                           measuredWidget->allocation.height));
}
bool ScrollableArea::scroll(ScrollDirection direction, ScrollGranularity granularity, float multiplier)
{
    ScrollbarOrientation orientation;
    Scrollbar* scrollbar;
    if (direction == ScrollUp || direction == ScrollDown) {
        orientation = VerticalScrollbar;
        scrollbar = verticalScrollbar();
    } else {
        orientation = HorizontalScrollbar;
        scrollbar = horizontalScrollbar();
    }

    if (!scrollbar)
        return false;

    float step = 0;
    switch (granularity) {
    case ScrollByLine:
        step = scrollbar->lineStep();
        break;
    case ScrollByPage:
        step = scrollbar->pageStep();
        break;
    case ScrollByDocument:
        step = scrollbar->totalSize();
        break;
    case ScrollByPixel:
    case ScrollByPrecisePixel:
        step = scrollbar->pixelStep();
        break;
    case ScrollByPixelVelocity:
        break;
    }

    if (granularity != ScrollByPixelVelocity && (direction == ScrollUp || direction == ScrollLeft))
        multiplier = -multiplier;

    return scrollAnimator()->scroll(orientation, granularity, step, multiplier);
}
void ScrollableArea::invalidateScrollbar(Scrollbar* scrollbar, const IntRect& rect)
{
    if (scrollbar == horizontalScrollbar()) {
        if (GraphicsLayer* graphicsLayer = layerForHorizontalScrollbar()) {
            graphicsLayer->setNeedsDisplay();
            graphicsLayer->setContentsNeedsDisplay();
            return;
        }
        invalidateScrollbarRect(scrollbar, rect);
        return;
    }
    if (scrollbar == verticalScrollbar()) {
        if (GraphicsLayer* graphicsLayer = layerForVerticalScrollbar()) {
            graphicsLayer->setNeedsDisplay();
            graphicsLayer->setContentsNeedsDisplay();
            return;
        }
        invalidateScrollbarRect(scrollbar, rect);
        return;
    }
    // Otherwise the scrollbar is just created and has not been set as either
    // horizontalScrollbar() or verticalScrollbar().
}
int ScrollableArea::horizontalScrollbarIntrusion() const
{
    return verticalScrollbar() ? verticalScrollbar()->occupiedWidth() : 0;
}
void RenderLayerScrollableArea::updateAfterLayout()
{
    m_scrollDimensionsDirty = true;
    IntSize originalScrollOffset = adjustedScrollOffset();

    computeScrollDimensions();

    // Layout may cause us to be at an invalid scroll position. In this case we need
    // to pull our scroll offsets back to the max (or push them up to the min).
    IntSize clampedScrollOffset = clampScrollOffset(adjustedScrollOffset());
    if (clampedScrollOffset != adjustedScrollOffset())
        scrollToOffset(clampedScrollOffset);

    if (originalScrollOffset != adjustedScrollOffset())
        scrollToOffsetWithoutAnimation(-scrollOrigin() + adjustedScrollOffset());

    bool hasHorizontalOverflow = this->hasHorizontalOverflow();
    bool hasVerticalOverflow = this->hasVerticalOverflow();

    {
        // Hits in compositing/overflow/automatically-opt-into-composited-scrolling-after-style-change.html.
        DisableCompositingQueryAsserts disabler;

        // overflow:scroll should just enable/disable.
        if (box().style()->overflowX() == OSCROLL)
            horizontalScrollbar()->setEnabled(hasHorizontalOverflow);
        if (box().style()->overflowY() == OSCROLL)
            verticalScrollbar()->setEnabled(hasVerticalOverflow);
    }

    // overflow:auto may need to lay out again if scrollbars got added/removed.
    bool autoHorizontalScrollBarChanged = box().hasAutoHorizontalScrollbar() && (hasHorizontalScrollbar() != hasHorizontalOverflow);
    bool autoVerticalScrollBarChanged = box().hasAutoVerticalScrollbar() && (hasVerticalScrollbar() != hasVerticalOverflow);

    if (autoHorizontalScrollBarChanged || autoVerticalScrollBarChanged) {
        if (box().hasAutoHorizontalScrollbar())
            setHasHorizontalScrollbar(hasHorizontalOverflow);
        if (box().hasAutoVerticalScrollbar())
            setHasVerticalScrollbar(hasVerticalOverflow);

        layer()->updateSelfPaintingLayer();

        if (box().style()->overflowX() == OAUTO || box().style()->overflowY() == OAUTO) {
            if (!m_inOverflowRelayout) {
                // Our proprietary overflow: overlay value doesn't trigger a layout.
                m_inOverflowRelayout = true;
                SubtreeLayoutScope layoutScope(box());
                layoutScope.setNeedsLayout(&box());
                if (box().isRenderBlock()) {
                    RenderBlock& block = toRenderBlock(box());
                    block.scrollbarsChanged(autoHorizontalScrollBarChanged, autoVerticalScrollBarChanged);
                    block.layoutBlock(true);
                } else {
                    box().layout();
                }
                m_inOverflowRelayout = false;
            }
        }
    }

    {
        // Hits in compositing/overflow/automatically-opt-into-composited-scrolling-after-style-change.html.
        DisableCompositingQueryAsserts disabler;

        // Set up the range (and page step/line step).
        if (Scrollbar* horizontalScrollbar = this->horizontalScrollbar()) {
            int clientWidth = box().pixelSnappedClientWidth();
            horizontalScrollbar->setProportion(clientWidth, overflowRect().width());
        }
        if (Scrollbar* verticalScrollbar = this->verticalScrollbar()) {
            int clientHeight = box().pixelSnappedClientHeight();
            verticalScrollbar->setProportion(clientHeight, overflowRect().height());
        }
    }

    bool hasOverflow = hasScrollableHorizontalOverflow() || hasScrollableVerticalOverflow();
    updateScrollableAreaSet(hasOverflow);

    if (hasOverflow) {
        DisableCompositingQueryAsserts disabler;
        positionOverflowControls(IntSize());
    }
}
IntPoint ScrollableArea::scrollPosition() const
{
    int x = horizontalScrollbar() ? horizontalScrollbar()->value() : 0;
    int y = verticalScrollbar() ? verticalScrollbar()->value() : 0;
    return IntPoint(x, y);
}
bool ScrollableArea::hasOverlayScrollbars() const
{
    return (verticalScrollbar() && verticalScrollbar()->isOverlayScrollbar())
        || (horizontalScrollbar() && horizontalScrollbar()->isOverlayScrollbar());
}
Example #25
0
bool ScrollbarGroup::userInputScrollable(ScrollbarOrientation orientation) const
{
    return orientation == HorizontalScrollbar ? horizontalScrollbar() : verticalScrollbar();
}