Source code

Revision control

Copy as Markdown

Other Tools

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "APZCTreeManagerTester.h"
#include "APZTestCommon.h"
#include "InputUtils.h"
class APZScrollbarDraggingTester : public APZCTreeManagerTester {
public:
APZScrollbarDraggingTester() { CreateMockHitTester(); }
protected:
UniquePtr<ScopedLayerTreeRegistration> registration;
ScrollableLayerGuid::ViewID scrollId = ScrollableLayerGuid::START_SCROLL_ID;
TestAsyncPanZoomController* apzc = nullptr;
ParentLayerCoord ScrollY() const {
return apzc
->GetCurrentAsyncScrollOffset(AsyncPanZoomController::eForEventHandling)
.y;
}
void QueueHitOnVerticalScrollbar() {
mMockHitTester->QueueScrollbarThumbHitResult(scrollId,
ScrollDirection::eVertical);
}
void CreateLayerTreeWithVerticalScrollbar() {
// The first child is the scrollable node, the second child is the
// scrollbar.
const char* treeShape = "x(xx)";
LayerIntRect layerVisibleRect[] = {LayerIntRect(0, 0, 100, 100),
LayerIntRect(0, 0, 50, 100),
LayerIntRect(50, 0, 50, 10)};
CreateScrollData(treeShape, layerVisibleRect);
SetScrollableFrameMetrics(layers[1], scrollId, CSSRect(0, 0, 50, 1000));
registration = MakeUnique<ScopedLayerTreeRegistration>(LayersId{0}, mcc);
layers[2]->SetScrollbarData(ScrollbarData::CreateForThumb(
ScrollDirection::eVertical, 0.1, 0, 10, 10, true, 0, 100, scrollId));
UpdateHitTestingTree();
apzc = ApzcOf(layers[1]);
}
};
// Test that the scrollable rect shrinking during dragging does not result
// in scrolling out of bounds.
TEST_F(APZScrollbarDraggingTester, ScrollableRectShrinksDuringDragging) {
// Explicitly enable scrollbar dragging. This allows the test to run on
// Android as well.
SCOPED_GFX_PREF_BOOL("apz.drag.enabled", true);
CreateLayerTreeWithVerticalScrollbar();
EXPECT_EQ(ScrollY(), 0);
// Start a scrollbar drag at y=5.
QueueHitOnVerticalScrollbar();
auto dragBlockId =
MouseDown(manager, ScreenIntPoint(75, 5), mcc->Time()).mInputBlockId;
manager->StartScrollbarDrag(apzc->GetGuid(),
AsyncDragMetrics(scrollId, 0, dragBlockId, 5,
ScrollDirection::eVertical));
// Drag the scrollbar down to y=75. (The total height is 100.)
for (int mouseY = 10; mouseY <= 75; mouseY += 5) {
mcc->AdvanceByMillis(10);
// We do a hit test for every mouse event, including mousemoves.
QueueHitOnVerticalScrollbar();
MouseMove(manager, ScreenIntPoint(75, mouseY), mcc->Time());
}
// We should have scrolled past y>500 at least (total scrollable rect height
// is 1000).
EXPECT_GT(ScrollY(), 500);
// Shrink the scrollable rect height to 500.
ModifyFrameMetrics(layers[1], [](ScrollMetadata&, FrameMetrics& aMetrics) {
aMetrics.SetScrollableRect(CSSRect(0, 0, 50, 500));
});
UpdateHitTestingTree();
// Continue the drag to near the bottom, y=95.
// Check that the scroll position never gets out of bounds. (With the
// scrollable rect height now 500, the max vertical scroll position is 400.)
for (int mouseY = 80; mouseY <= 95; mouseY += 5) {
mcc->AdvanceByMillis(10);
QueueHitOnVerticalScrollbar();
MouseMove(manager, ScreenIntPoint(75, mouseY), mcc->Time());
EXPECT_LE(ScrollY(), 400);
}
// End the drag.
mcc->AdvanceByMillis(10);
QueueHitOnVerticalScrollbar();
MouseUp(manager, ScreenIntPoint(75, 95), mcc->Time());
// We should end up at the bottom of the new scroll range (and not out of
// bounds).
EXPECT_EQ(ScrollY(), 400);
}