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(); } }
/* * 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); }
/* 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)); }
bool ScrollableArea::hasOverlayScrollbars() const { Scrollbar* vScrollbar = verticalScrollbar(); if (vScrollbar && vScrollbar->isOverlayScrollbar()) return true; Scrollbar* hScrollbar = horizontalScrollbar(); return hScrollbar && hScrollbar->isOverlayScrollbar(); }
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)); }
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(); }
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); }
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()); }
bool ScrollbarGroup::userInputScrollable(ScrollbarOrientation orientation) const { return orientation == HorizontalScrollbar ? horizontalScrollbar() : verticalScrollbar(); }