Bug 1265510 - Add a gtest for interrupting a scroll snap. r?botond draft
authorKartikaya Gupta <kgupta@mozilla.com>
Mon, 25 Apr 2016 19:56:01 -0400
changeset 356194 4882975b2d699ef92dad6c2f1823dc7f633201c8
parent 356193 06981fb0bbe86d35c1e20e32e388f3ab8459c8d7
child 356195 7b6deefea224728e476bb210890afe459f965295
push id16473
push userkgupta@mozilla.com
push dateMon, 25 Apr 2016 23:56:46 +0000
reviewersbotond
bugs1265510
milestone49.0a1
Bug 1265510 - Add a gtest for interrupting a scroll snap. r?botond MozReview-Commit-ID: 8qA6CQeyMM5
gfx/layers/apz/test/gtest/APZCTreeManagerTester.h
gfx/layers/apz/test/gtest/InputUtils.h
gfx/layers/apz/test/gtest/TestSnapping.cpp
gfx/layers/apz/test/gtest/moz.build
--- a/gfx/layers/apz/test/gtest/APZCTreeManagerTester.h
+++ b/gfx/layers/apz/test/gtest/APZCTreeManagerTester.h
@@ -67,16 +67,17 @@ protected:
     // By convention in this test file, START_SCROLL_ID is the root, so mark it as such.
     if (aScrollId == FrameMetrics::START_SCROLL_ID) {
       metrics.SetIsLayersIdRoot(true);
     }
     metrics.SetCompositionBounds(aCompositionBounds);
     metrics.SetScrollableRect(aScrollableRect);
     metrics.SetScrollOffset(CSSPoint(0, 0));
     metrics.SetPageScrollAmount(LayoutDeviceIntSize(50, 100));
+    metrics.SetLineScrollAmount(LayoutDeviceIntSize(5, 10));
     metrics.SetAllowVerticalScrollWithWheel(true);
     return metadata;
   }
 
   static void SetEventRegionsBasedOnBottommostMetrics(Layer* aLayer)
   {
     const FrameMetrics& metrics = aLayer->GetScrollMetadata(0).GetMetrics();
     CSSRect scrollableRect = metrics.GetScrollableRect();
--- a/gfx/layers/apz/test/gtest/InputUtils.h
+++ b/gfx/layers/apz/test/gtest/InputUtils.h
@@ -486,9 +486,20 @@ Wheel(const RefPtr<InputReceiver>& aTarg
       const ScreenPoint& aDelta, TimeStamp aTime, uint64_t* aOutInputBlockId = nullptr)
 {
   ScrollWheelInput input(MillisecondsSinceStartup(aTime), aTime, 0,
       ScrollWheelInput::SCROLLMODE_INSTANT, ScrollWheelInput::SCROLLDELTA_PIXEL,
       aPoint, aDelta.x, aDelta.y, false);
   return aTarget->ReceiveInputEvent(input, nullptr, aOutInputBlockId);
 }
 
+template<class InputReceiver>
+nsEventStatus
+SmoothWheel(const RefPtr<InputReceiver>& aTarget, const ScreenIntPoint& aPoint,
+            const ScreenPoint& aDelta, TimeStamp aTime, uint64_t* aOutInputBlockId = nullptr)
+{
+  ScrollWheelInput input(MillisecondsSinceStartup(aTime), aTime, 0,
+      ScrollWheelInput::SCROLLMODE_SMOOTH, ScrollWheelInput::SCROLLDELTA_LINE,
+      aPoint, aDelta.x, aDelta.y, false);
+  return aTarget->ReceiveInputEvent(input, nullptr, aOutInputBlockId);
+}
+
 #endif // mozilla_layers_InputUtils_h
new file mode 100644
--- /dev/null
+++ b/gfx/layers/apz/test/gtest/TestSnapping.cpp
@@ -0,0 +1,70 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et 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 APZCSnappingTester : public APZCTreeManagerTester
+{
+protected:
+  UniquePtr<ScopedLayerTreeRegistration> registration;
+
+  void CreateBug1265510LayerTree() {
+    const char* layerTreeSyntax = "c(t)";
+    nsIntRegion layerVisibleRegion[] = {
+      nsIntRegion(IntRect(0, 0, 100, 100)),
+      nsIntRegion(IntRect(0, 100, 100, 100))
+    };
+    root = CreateLayerTree(layerTreeSyntax, layerVisibleRegion, nullptr, lm, layers);
+    SetScrollableFrameMetrics(root, FrameMetrics::START_SCROLL_ID, CSSRect(0, 0, 100, 200));
+    SetScrollableFrameMetrics(layers[1], FrameMetrics::START_SCROLL_ID + 1, CSSRect(0, 0, 100, 200));
+    SetScrollHandoff(layers[1], root);
+
+    ScrollSnapInfo snap;
+    snap.mScrollSnapTypeY = NS_STYLE_SCROLL_SNAP_TYPE_MANDATORY;
+    snap.mScrollSnapIntervalY = Some(100 * AppUnitsPerCSSPixel());
+
+    ScrollMetadata metadata = root->GetScrollMetadata(0);
+    metadata.SetSnapInfo(ScrollSnapInfo(snap));
+    root->SetScrollMetadata(metadata);
+
+    registration = MakeUnique<ScopedLayerTreeRegistration>(manager, 0, root, mcc);
+    manager->UpdateHitTestingTree(nullptr, root, false, 0, 0);
+  }
+};
+
+TEST_F(APZCSnappingTester, Bug1265510)
+{
+  CreateBug1265510LayerTree();
+
+  TestAsyncPanZoomController* outer = ApzcOf(layers[0]);
+  TestAsyncPanZoomController* inner = ApzcOf(layers[1]);
+
+  // Position the mouse near the bottom of the outer frame and scroll by 60px.
+  // (6 lines of 10px each). APZC will actually scroll to y=100 because of the
+  // mandatory snap coordinate there.
+  TimeStamp now = mcc->Time();
+  SmoothWheel(manager, ScreenIntPoint(50, 80), ScreenPoint(0, 6), now);
+  // Advance in 5ms increments until we've scrolled by 70px. At this point, the
+  // closest snap point is y=100, and the inner frame should be under the mouse
+  // cursor.
+  while (outer->GetCurrentAsyncScrollOffset(AsyncPanZoomController::AsyncMode::NORMAL).y < 70) {
+    mcc->AdvanceByMillis(5);
+    outer->AdvanceAnimations(mcc->Time());
+  }
+  // Now do another wheel in a new transaction. This should start scrolling the
+  // inner frame; we verify that it does by checking the inner scroll position.
+  TimeStamp newTransactionTime = now + TimeDuration::FromMilliseconds(gfxPrefs::MouseWheelTransactionTimeoutMs() + 100);
+  SmoothWheel(manager, ScreenIntPoint(50, 80), ScreenPoint(0, 6), newTransactionTime);
+  inner->AdvanceAnimationsUntilEnd();
+  EXPECT_LT(0.0f, inner->GetCurrentAsyncScrollOffset(AsyncPanZoomController::AsyncMode::NORMAL).y);
+
+  // However, the outer frame should also continue to the snap point, otherwise
+  // it is demonstrating incorrect behaviour by violating the mandatory snapping.
+  outer->AdvanceAnimationsUntilEnd();
+  EXPECT_EQ(100.0f, outer->GetCurrentAsyncScrollOffset(AsyncPanZoomController::AsyncMode::NORMAL).y);
+}
--- a/gfx/layers/apz/test/gtest/moz.build
+++ b/gfx/layers/apz/test/gtest/moz.build
@@ -7,16 +7,17 @@
 UNIFIED_SOURCES += [
     'TestBasic.cpp',
     'TestEventRegions.cpp',
     'TestGestureDetector.cpp',
     'TestHitTesting.cpp',
     'TestPanning.cpp',
     'TestPinching.cpp',
     'TestScrollHandoff.cpp',
+    'TestSnapping.cpp',
     'TestTreeManager.cpp',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 LOCAL_INCLUDES += [
     '/gfx/2d',
     '/gfx/layers',