Chromium Code Reviews| Index: third_party/WebKit/Source/platform/scroll/ScrollableAreaTest.cpp |
| diff --git a/third_party/WebKit/Source/platform/scroll/ScrollableAreaTest.cpp b/third_party/WebKit/Source/platform/scroll/ScrollableAreaTest.cpp |
| index 87f1f6044f85689f02801f702def1a8380acea88..a9b9ba6800776834f2337eae1a8d36a117381dc9 100644 |
| --- a/third_party/WebKit/Source/platform/scroll/ScrollableAreaTest.cpp |
| +++ b/third_party/WebKit/Source/platform/scroll/ScrollableAreaTest.cpp |
| @@ -16,6 +16,7 @@ namespace blink { |
| namespace { |
| +using testing::_; |
| using testing::Return; |
| class MockScrollableArea : public NoBaseWillBeGarbageCollectedFinalized<MockScrollableArea>, public ScrollableArea { |
| @@ -30,12 +31,15 @@ public: |
| MOCK_CONST_METHOD1(scrollSize, int(ScrollbarOrientation)); |
| MOCK_CONST_METHOD0(isScrollCornerVisible, bool()); |
| MOCK_CONST_METHOD0(scrollCornerRect, IntRect()); |
| + MOCK_CONST_METHOD0(horizontalScrollbar, Scrollbar*()); |
| + MOCK_CONST_METHOD0(verticalScrollbar, Scrollbar*()); |
| MOCK_METHOD0(scrollControlWasSetNeedsPaintInvalidation, void()); |
| MOCK_CONST_METHOD0(enclosingScrollableArea, ScrollableArea*()); |
| MOCK_CONST_METHOD1(visibleContentRect, IntRect(IncludeScrollbarsInRect)); |
| MOCK_CONST_METHOD0(contentsSize, IntSize()); |
| MOCK_CONST_METHOD0(scrollableAreaBoundingBox, IntRect()); |
| MOCK_CONST_METHOD0(layerForHorizontalScrollbar, GraphicsLayer*()); |
| + MOCK_CONST_METHOD0(layerForVerticalScrollbar, GraphicsLayer*()); |
| bool userInputScrollable(ScrollbarOrientation) const override { return true; } |
| bool scrollbarsCanBeActive () const override { return true; } |
| @@ -49,6 +53,10 @@ public: |
| bool scrollAnimatorEnabled() const override { return false; } |
| int pageStep(ScrollbarOrientation) const override { return 0; } |
| + using ScrollableArea::horizontalScrollbarNeedsPaintInvalidation; |
| + using ScrollableArea::verticalScrollbarNeedsPaintInvalidation; |
| + using ScrollableArea::clearNeedsPaintInvalidationForScrollControls; |
| + |
| DEFINE_INLINE_VIRTUAL_TRACE() |
| { |
| ScrollableArea::trace(visitor); |
| @@ -100,6 +108,7 @@ namespace { |
| class ScrollbarThemeWithMockInvalidation : public ScrollbarThemeMock { |
| public: |
| MOCK_CONST_METHOD0(shouldRepaintAllPartsOnInvalidation, bool()); |
| + MOCK_CONST_METHOD3(invalidateOnThumbPositionChange, ScrollbarPart(const ScrollbarThemeClient&, float, float)); |
| }; |
| } // namespace |
| @@ -121,18 +130,20 @@ TEST_F(ScrollableAreaTest, ScrollbarTrackAndThumbRepaint) |
| scrollbar->clearThumbNeedsRepaint(); |
| EXPECT_FALSE(scrollbar->trackNeedsRepaint()); |
| EXPECT_FALSE(scrollbar->thumbNeedsRepaint()); |
| - scrollbar->setNeedsPaintInvalidation(NoPart); |
| + scrollbar->setNeedsPaintInvalidation(ThumbPart); |
| EXPECT_TRUE(scrollbar->trackNeedsRepaint()); |
| EXPECT_TRUE(scrollbar->thumbNeedsRepaint()); |
| + // When not all parts are repainted on invalidation, |
| + // setNeedsPaintInvalidation sets repaint bits only on the requested parts. |
| EXPECT_CALL(theme, shouldRepaintAllPartsOnInvalidation()).WillRepeatedly(Return(false)); |
| scrollbar->clearTrackNeedsRepaint(); |
| scrollbar->clearThumbNeedsRepaint(); |
| EXPECT_FALSE(scrollbar->trackNeedsRepaint()); |
| EXPECT_FALSE(scrollbar->thumbNeedsRepaint()); |
| - scrollbar->setNeedsPaintInvalidation(NoPart); |
| + scrollbar->setNeedsPaintInvalidation(ThumbPart); |
| EXPECT_FALSE(scrollbar->trackNeedsRepaint()); |
| - EXPECT_FALSE(scrollbar->thumbNeedsRepaint()); |
| + EXPECT_TRUE(scrollbar->thumbNeedsRepaint()); |
| // Forced GC in order to finalize objects depending on the mock object. |
| Heap::collectAllGarbage(); |
| @@ -168,4 +179,103 @@ TEST_F(ScrollableAreaTest, ScrollbarGraphicsLayerInvalidation) |
| EXPECT_TRUE(graphicsLayer.hasTrackedPaintInvalidations()); |
| } |
| +TEST_F(ScrollableAreaTest, InvalidatesNonCompositedScrollbarsWhenThumbMoves) |
| +{ |
| + ScrollbarThemeWithMockInvalidation theme; |
| + OwnPtrWillBeRawPtr<MockScrollableArea> scrollableArea = MockScrollableArea::create(IntPoint(100, 100)); |
| + RefPtrWillBeRawPtr<Scrollbar> horizontalScrollbar = Scrollbar::createForTesting(scrollableArea.get(), HorizontalScrollbar, RegularScrollbar, &theme); |
| + RefPtrWillBeRawPtr<Scrollbar> verticalScrollbar = Scrollbar::createForTesting(scrollableArea.get(), VerticalScrollbar, RegularScrollbar, &theme); |
| + EXPECT_CALL(*scrollableArea, horizontalScrollbar()).WillRepeatedly(Return(horizontalScrollbar.get())); |
| + EXPECT_CALL(*scrollableArea, verticalScrollbar()).WillRepeatedly(Return(verticalScrollbar.get())); |
| + |
| + // Regardless of whether the theme invalidates any parts, non-composited |
| + // scrollbars have to be repainted if the thumb moves. |
| + EXPECT_CALL(*scrollableArea, layerForHorizontalScrollbar()).WillRepeatedly(Return(nullptr)); |
| + EXPECT_CALL(*scrollableArea, layerForVerticalScrollbar()).WillRepeatedly(Return(nullptr)); |
| + ASSERT_FALSE(scrollableArea->hasLayerForVerticalScrollbar()); |
| + ASSERT_FALSE(scrollableArea->hasLayerForHorizontalScrollbar()); |
| + EXPECT_CALL(theme, shouldRepaintAllPartsOnInvalidation()).WillRepeatedly(Return(false)); |
| + EXPECT_CALL(theme, invalidateOnThumbPositionChange(_, _, _)).WillRepeatedly(Return(NoPart)); |
| + |
| + // A scroll in each direction should only invalidate one scrollbar. |
| + scrollableArea->setScrollPosition(DoublePoint(0, 50), ProgrammaticScroll); |
| + EXPECT_FALSE(scrollableArea->horizontalScrollbarNeedsPaintInvalidation()); |
| + EXPECT_TRUE(scrollableArea->verticalScrollbarNeedsPaintInvalidation()); |
| + scrollableArea->clearNeedsPaintInvalidationForScrollControls(); |
| + scrollableArea->setScrollPosition(DoublePoint(50, 50), ProgrammaticScroll); |
| + EXPECT_TRUE(scrollableArea->horizontalScrollbarNeedsPaintInvalidation()); |
| + EXPECT_FALSE(scrollableArea->verticalScrollbarNeedsPaintInvalidation()); |
| + scrollableArea->clearNeedsPaintInvalidationForScrollControls(); |
| + |
| + // Forced GC in order to finalize objects depending on the mock object. |
| + Heap::collectAllGarbage(); |
| +} |
| + |
|
skobes
2016/01/19 04:29:51
nit: extra blank line
jbroman
2016/01/19 15:08:06
Done.
|
| + |
| +TEST_F(ScrollableAreaTest, InvalidatesCompositedScrollbarsIfPartsNeedRepaint) |
| +{ |
| + ScrollbarThemeWithMockInvalidation theme; |
| + OwnPtrWillBeRawPtr<MockScrollableArea> scrollableArea = MockScrollableArea::create(IntPoint(100, 100)); |
| + RefPtrWillBeRawPtr<Scrollbar> horizontalScrollbar = Scrollbar::createForTesting(scrollableArea.get(), HorizontalScrollbar, RegularScrollbar, &theme); |
| + horizontalScrollbar->clearTrackNeedsRepaint(); |
| + horizontalScrollbar->clearThumbNeedsRepaint(); |
| + RefPtrWillBeRawPtr<Scrollbar> verticalScrollbar = Scrollbar::createForTesting(scrollableArea.get(), VerticalScrollbar, RegularScrollbar, &theme); |
| + verticalScrollbar->clearTrackNeedsRepaint(); |
| + verticalScrollbar->clearThumbNeedsRepaint(); |
| + EXPECT_CALL(*scrollableArea, horizontalScrollbar()).WillRepeatedly(Return(horizontalScrollbar.get())); |
| + EXPECT_CALL(*scrollableArea, verticalScrollbar()).WillRepeatedly(Return(verticalScrollbar.get())); |
| + |
| + // Composited scrollbars only need repainting when parts become invalid |
| + // (e.g. if the track changes appearance when the thumb reaches the end). |
| + MockGraphicsLayerClient graphicsLayerClient; |
| + MockGraphicsLayer layerForHorizontalScrollbar(&graphicsLayerClient); |
| + layerForHorizontalScrollbar.setDrawsContent(true); |
| + layerForHorizontalScrollbar.setSize(FloatSize(10, 10)); |
| + MockGraphicsLayer layerForVerticalScrollbar(&graphicsLayerClient); |
| + layerForVerticalScrollbar.setDrawsContent(true); |
| + layerForVerticalScrollbar.setSize(FloatSize(10, 10)); |
| + EXPECT_CALL(*scrollableArea, layerForHorizontalScrollbar()).WillRepeatedly(Return(&layerForHorizontalScrollbar)); |
| + EXPECT_CALL(*scrollableArea, layerForVerticalScrollbar()).WillRepeatedly(Return(&layerForVerticalScrollbar)); |
| + ASSERT_TRUE(scrollableArea->hasLayerForHorizontalScrollbar()); |
| + ASSERT_TRUE(scrollableArea->hasLayerForVerticalScrollbar()); |
| + EXPECT_CALL(theme, shouldRepaintAllPartsOnInvalidation()).WillRepeatedly(Return(false)); |
| + |
| + // First, we'll scroll horizontally, and the theme will require repainting |
| + // the back button (i.e. the track). |
| + EXPECT_CALL(theme, invalidateOnThumbPositionChange(_, _, _)).WillOnce(Return(BackButtonStartPart)); |
| + scrollableArea->setScrollPosition(DoublePoint(50, 0), ProgrammaticScroll); |
| + EXPECT_TRUE(layerForHorizontalScrollbar.hasTrackedPaintInvalidations()); |
| + EXPECT_FALSE(layerForVerticalScrollbar.hasTrackedPaintInvalidations()); |
| + EXPECT_TRUE(horizontalScrollbar->trackNeedsRepaint()); |
| + EXPECT_FALSE(horizontalScrollbar->thumbNeedsRepaint()); |
| + layerForHorizontalScrollbar.resetTrackedPaintInvalidations(); |
| + horizontalScrollbar->clearTrackNeedsRepaint(); |
| + |
| + // Next, we'll scroll vertically, but invalidate the thumb. |
| + EXPECT_CALL(theme, invalidateOnThumbPositionChange(_, _, _)).WillOnce(Return(ThumbPart)); |
| + scrollableArea->setScrollPosition(DoublePoint(50, 50), ProgrammaticScroll); |
| + EXPECT_FALSE(layerForHorizontalScrollbar.hasTrackedPaintInvalidations()); |
| + EXPECT_TRUE(layerForVerticalScrollbar.hasTrackedPaintInvalidations()); |
| + EXPECT_FALSE(verticalScrollbar->trackNeedsRepaint()); |
| + EXPECT_TRUE(verticalScrollbar->thumbNeedsRepaint()); |
| + layerForVerticalScrollbar.resetTrackedPaintInvalidations(); |
| + verticalScrollbar->clearThumbNeedsRepaint(); |
| + |
| + // Next we'll scroll in both, but the thumb position moving requires no |
| + // invalidations. Nonetheless the GraphicsLayer should be invalidated, |
| + // because we still need to update the underlying layer (though no |
| + // rasterization will be required). |
| + EXPECT_CALL(theme, invalidateOnThumbPositionChange(_, _, _)).Times(2).WillRepeatedly(Return(NoPart)); |
| + scrollableArea->setScrollPosition(DoublePoint(70, 70), ProgrammaticScroll); |
| + EXPECT_TRUE(layerForHorizontalScrollbar.hasTrackedPaintInvalidations()); |
| + EXPECT_TRUE(layerForVerticalScrollbar.hasTrackedPaintInvalidations()); |
| + EXPECT_FALSE(horizontalScrollbar->trackNeedsRepaint()); |
| + EXPECT_FALSE(horizontalScrollbar->thumbNeedsRepaint()); |
| + EXPECT_FALSE(verticalScrollbar->trackNeedsRepaint()); |
| + EXPECT_FALSE(verticalScrollbar->thumbNeedsRepaint()); |
| + |
| + // Forced GC in order to finalize objects depending on the mock object. |
| + Heap::collectAllGarbage(); |
| +} |
| + |
| } // namespace blink |