TestScrollbarDragging.cpp (3968B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "APZCTreeManagerTester.h" 8 #include "APZTestCommon.h" 9 #include "InputUtils.h" 10 11 class APZScrollbarDraggingTester : public APZCTreeManagerTester { 12 public: 13 APZScrollbarDraggingTester() { CreateMockHitTester(); } 14 15 protected: 16 UniquePtr<ScopedLayerTreeRegistration> registration; 17 ScrollableLayerGuid::ViewID scrollId = ScrollableLayerGuid::START_SCROLL_ID; 18 TestAsyncPanZoomController* apzc = nullptr; 19 20 ParentLayerCoord ScrollY() const { 21 return apzc 22 ->GetCurrentAsyncScrollOffset(AsyncPanZoomController::eForEventHandling) 23 .y; 24 } 25 26 void QueueHitOnVerticalScrollbar() { 27 mMockHitTester->QueueScrollbarThumbHitResult(scrollId, 28 ScrollDirection::eVertical); 29 } 30 31 void CreateLayerTreeWithVerticalScrollbar() { 32 // The first child is the scrollable node, the second child is the 33 // scrollbar. 34 const char* treeShape = "x(xx)"; 35 LayerIntRect layerVisibleRect[] = {LayerIntRect(0, 0, 100, 100), 36 LayerIntRect(0, 0, 50, 100), 37 LayerIntRect(50, 0, 50, 10)}; 38 CreateScrollData(treeShape, layerVisibleRect); 39 SetScrollableFrameMetrics(layers[1], scrollId, CSSRect(0, 0, 50, 1000)); 40 registration = MakeUnique<ScopedLayerTreeRegistration>(LayersId{0}, mcc); 41 layers[2]->SetScrollbarData(ScrollbarData::CreateForThumb( 42 ScrollDirection::eVertical, 0.1, 0, 10, 10, true, 0, 100, scrollId)); 43 UpdateHitTestingTree(); 44 apzc = ApzcOf(layers[1]); 45 } 46 }; 47 48 // Test that the scrollable rect shrinking during dragging does not result 49 // in scrolling out of bounds. 50 TEST_F(APZScrollbarDraggingTester, ScrollableRectShrinksDuringDragging) { 51 // Explicitly enable scrollbar dragging. This allows the test to run on 52 // Android as well. 53 SCOPED_GFX_PREF_BOOL("apz.drag.enabled", true); 54 55 CreateLayerTreeWithVerticalScrollbar(); 56 EXPECT_EQ(ScrollY(), 0); 57 58 // Start a scrollbar drag at y=5. 59 QueueHitOnVerticalScrollbar(); 60 auto dragBlockId = 61 MouseDown(manager, ScreenIntPoint(75, 5), mcc->Time()).mInputBlockId; 62 manager->StartScrollbarDrag(apzc->GetGuid(), 63 AsyncDragMetrics(scrollId, 0, dragBlockId, 5, 64 ScrollDirection::eVertical)); 65 66 // Drag the scrollbar down to y=75. (The total height is 100.) 67 for (int mouseY = 10; mouseY <= 75; mouseY += 5) { 68 mcc->AdvanceByMillis(10); 69 // We do a hit test for every mouse event, including mousemoves. 70 QueueHitOnVerticalScrollbar(); 71 MouseMove(manager, ScreenIntPoint(75, mouseY), mcc->Time()); 72 } 73 74 // We should have scrolled past y>500 at least (total scrollable rect height 75 // is 1000). 76 EXPECT_GT(ScrollY(), 500); 77 78 // Shrink the scrollable rect height to 500. 79 ModifyFrameMetrics(layers[1], [](ScrollMetadata&, FrameMetrics& aMetrics) { 80 aMetrics.SetScrollableRect(CSSRect(0, 0, 50, 500)); 81 }); 82 UpdateHitTestingTree(); 83 84 // Continue the drag to near the bottom, y=95. 85 // Check that the scroll position never gets out of bounds. (With the 86 // scrollable rect height now 500, the max vertical scroll position is 400.) 87 for (int mouseY = 80; mouseY <= 95; mouseY += 5) { 88 mcc->AdvanceByMillis(10); 89 QueueHitOnVerticalScrollbar(); 90 MouseMove(manager, ScreenIntPoint(75, mouseY), mcc->Time()); 91 EXPECT_LE(ScrollY(), 400); 92 } 93 94 // End the drag. 95 mcc->AdvanceByMillis(10); 96 QueueHitOnVerticalScrollbar(); 97 MouseUp(manager, ScreenIntPoint(75, 95), mcc->Time()); 98 99 // We should end up at the bottom of the new scroll range (and not out of 100 // bounds). 101 EXPECT_EQ(ScrollY(), 400); 102 }