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 #ifndef mozilla_layers_APZCTreeManagerTester_h
8 #define mozilla_layers_APZCTreeManagerTester_h
9 
10 /**
11  * Defines a test fixture used for testing multiple APZCs interacting in
12  * an APZCTreeManager.
13  */
14 
15 #include "APZTestCommon.h"
16 #include "gfxPlatform.h"
17 #include "gfxPrefs.h"
18 
19 class APZCTreeManagerTester : public APZCTesterBase {
20  protected:
SetUp()21   virtual void SetUp() {
22     gfxPrefs::GetSingleton();
23     gfxPlatform::GetPlatform();
24     APZThreadUtils::SetThreadAssertionsEnabled(false);
25     APZThreadUtils::SetControllerThread(MessageLoop::current());
26 
27     manager = new TestAPZCTreeManager(mcc);
28   }
29 
TearDown()30   virtual void TearDown() {
31     while (mcc->RunThroughDelayedTasks())
32       ;
33     manager->ClearTree();
34     manager->ClearContentController();
35   }
36 
37   /**
38    * Sample animations once for all APZCs, 1 ms later than the last sample.
39    */
SampleAnimationsOnce()40   void SampleAnimationsOnce() {
41     const TimeDuration increment = TimeDuration::FromMilliseconds(1);
42     ParentLayerPoint pointOut;
43     AsyncTransform viewTransformOut;
44     mcc->AdvanceBy(increment);
45 
46     for (const RefPtr<Layer>& layer : layers) {
47       if (TestAsyncPanZoomController* apzc = ApzcOf(layer)) {
48         apzc->SampleContentTransformForFrame(&viewTransformOut, pointOut);
49       }
50     }
51   }
52 
53   nsTArray<RefPtr<Layer> > layers;
54   RefPtr<LayerManager> lm;
55   RefPtr<Layer> root;
56 
57   RefPtr<TestAPZCTreeManager> manager;
58 
59  protected:
BuildScrollMetadata(FrameMetrics::ViewID aScrollId,const CSSRect & aScrollableRect,const ParentLayerRect & aCompositionBounds)60   static ScrollMetadata BuildScrollMetadata(
61       FrameMetrics::ViewID aScrollId, const CSSRect& aScrollableRect,
62       const ParentLayerRect& aCompositionBounds) {
63     ScrollMetadata metadata;
64     FrameMetrics& metrics = metadata.GetMetrics();
65     metrics.SetScrollId(aScrollId);
66     // By convention in this test file, START_SCROLL_ID is the root, so mark it
67     // as such.
68     if (aScrollId == FrameMetrics::START_SCROLL_ID) {
69       metadata.SetIsLayersIdRoot(true);
70     }
71     metrics.SetCompositionBounds(aCompositionBounds);
72     metrics.SetScrollableRect(aScrollableRect);
73     metrics.SetScrollOffset(CSSPoint(0, 0));
74     metadata.SetPageScrollAmount(LayoutDeviceIntSize(50, 100));
75     metadata.SetLineScrollAmount(LayoutDeviceIntSize(5, 10));
76     return metadata;
77   }
78 
SetEventRegionsBasedOnBottommostMetrics(Layer * aLayer)79   static void SetEventRegionsBasedOnBottommostMetrics(Layer* aLayer) {
80     const FrameMetrics& metrics = aLayer->GetScrollMetadata(0).GetMetrics();
81     CSSRect scrollableRect = metrics.GetScrollableRect();
82     if (!scrollableRect.IsEqualEdges(CSSRect(-1, -1, -1, -1))) {
83       // The purpose of this is to roughly mimic what layout would do in the
84       // case of a scrollable frame with the event regions and clip. This lets
85       // us exercise the hit-testing code in APZCTreeManager
86       EventRegions er = aLayer->GetEventRegions();
87       IntRect scrollRect =
88           RoundedToInt(scrollableRect * metrics.LayersPixelsPerCSSPixel())
89               .ToUnknownRect();
90       er.mHitRegion = nsIntRegion(IntRect(
91           RoundedToInt(
92               metrics.GetCompositionBounds().TopLeft().ToUnknownPoint()),
93           scrollRect.Size()));
94       aLayer->SetEventRegions(er);
95     }
96   }
97 
98   static void SetScrollableFrameMetrics(
99       Layer* aLayer, FrameMetrics::ViewID aScrollId,
100       CSSRect aScrollableRect = CSSRect(-1, -1, -1, -1)) {
101     ParentLayerIntRect compositionBounds =
102         RoundedToInt(aLayer->GetLocalTransformTyped().TransformBounds(
103             LayerRect(aLayer->GetVisibleRegion().GetBounds())));
104     ScrollMetadata metadata = BuildScrollMetadata(
105         aScrollId, aScrollableRect, ParentLayerRect(compositionBounds));
106     aLayer->SetScrollMetadata(metadata);
107     aLayer->SetClipRect(Some(compositionBounds));
108     SetEventRegionsBasedOnBottommostMetrics(aLayer);
109   }
110 
SetScrollHandoff(Layer * aChild,Layer * aParent)111   void SetScrollHandoff(Layer* aChild, Layer* aParent) {
112     ScrollMetadata metadata = aChild->GetScrollMetadata(0);
113     metadata.SetScrollParentId(aParent->GetFrameMetrics(0).GetScrollId());
114     aChild->SetScrollMetadata(metadata);
115   }
116 
ApzcOf(Layer * aLayer)117   static TestAsyncPanZoomController* ApzcOf(Layer* aLayer) {
118     EXPECT_EQ(1u, aLayer->GetScrollMetadataCount());
119     return (TestAsyncPanZoomController*)aLayer->GetAsyncPanZoomController(0);
120   }
121 
ApzcOf(Layer * aLayer,uint32_t aIndex)122   static TestAsyncPanZoomController* ApzcOf(Layer* aLayer, uint32_t aIndex) {
123     EXPECT_LT(aIndex, aLayer->GetScrollMetadataCount());
124     return (TestAsyncPanZoomController*)aLayer->GetAsyncPanZoomController(
125         aIndex);
126   }
127 
CreateSimpleScrollingLayer()128   void CreateSimpleScrollingLayer() {
129     const char* layerTreeSyntax = "t";
130     nsIntRegion layerVisibleRegion[] = {
131         nsIntRegion(IntRect(0, 0, 200, 200)),
132     };
133     root = CreateLayerTree(layerTreeSyntax, layerVisibleRegion, nullptr, lm,
134                            layers);
135     SetScrollableFrameMetrics(root, FrameMetrics::START_SCROLL_ID,
136                               CSSRect(0, 0, 500, 500));
137   }
138 
CreateSimpleDTCScrollingLayer()139   void CreateSimpleDTCScrollingLayer() {
140     const char* layerTreeSyntax = "t";
141     nsIntRegion layerVisibleRegion[] = {
142         nsIntRegion(IntRect(0, 0, 200, 200)),
143     };
144     root = CreateLayerTree(layerTreeSyntax, layerVisibleRegion, nullptr, lm,
145                            layers);
146     SetScrollableFrameMetrics(root, FrameMetrics::START_SCROLL_ID,
147                               CSSRect(0, 0, 500, 500));
148 
149     EventRegions regions;
150     regions.mHitRegion = nsIntRegion(IntRect(0, 0, 200, 200));
151     regions.mDispatchToContentHitRegion = regions.mHitRegion;
152     layers[0]->SetEventRegions(regions);
153   }
154 
CreateSimpleMultiLayerTree()155   void CreateSimpleMultiLayerTree() {
156     const char* layerTreeSyntax = "c(tt)";
157     // LayerID                     0 12
158     nsIntRegion layerVisibleRegion[] = {
159         nsIntRegion(IntRect(0, 0, 100, 100)),
160         nsIntRegion(IntRect(0, 0, 100, 50)),
161         nsIntRegion(IntRect(0, 50, 100, 50)),
162     };
163     root = CreateLayerTree(layerTreeSyntax, layerVisibleRegion, nullptr, lm,
164                            layers);
165   }
166 
CreatePotentiallyLeakingTree()167   void CreatePotentiallyLeakingTree() {
168     const char* layerTreeSyntax = "c(c(c(t))c(c(t)))";
169     // LayerID                     0 1 2 3  4 5 6
170     root = CreateLayerTree(layerTreeSyntax, nullptr, nullptr, lm, layers);
171     SetScrollableFrameMetrics(layers[0], FrameMetrics::START_SCROLL_ID);
172     SetScrollableFrameMetrics(layers[2], FrameMetrics::START_SCROLL_ID + 1);
173     SetScrollableFrameMetrics(layers[5], FrameMetrics::START_SCROLL_ID + 1);
174     SetScrollableFrameMetrics(layers[3], FrameMetrics::START_SCROLL_ID + 2);
175     SetScrollableFrameMetrics(layers[6], FrameMetrics::START_SCROLL_ID + 3);
176   }
177 
CreateBug1194876Tree()178   void CreateBug1194876Tree() {
179     const char* layerTreeSyntax = "c(t)";
180     // LayerID                     0 1
181     nsIntRegion layerVisibleRegion[] = {
182         nsIntRegion(IntRect(0, 0, 100, 100)),
183         nsIntRegion(IntRect(0, 0, 100, 100)),
184     };
185     root = CreateLayerTree(layerTreeSyntax, layerVisibleRegion, nullptr, lm,
186                            layers);
187     SetScrollableFrameMetrics(layers[0], FrameMetrics::START_SCROLL_ID);
188     SetScrollableFrameMetrics(layers[1], FrameMetrics::START_SCROLL_ID + 1);
189     SetScrollHandoff(layers[1], layers[0]);
190 
191     // Make layers[1] the root content
192     ScrollMetadata childMetadata = layers[1]->GetScrollMetadata(0);
193     childMetadata.GetMetrics().SetIsRootContent(true);
194     layers[1]->SetScrollMetadata(childMetadata);
195 
196     // Both layers are fully dispatch-to-content
197     EventRegions regions;
198     regions.mHitRegion = nsIntRegion(IntRect(0, 0, 100, 100));
199     regions.mDispatchToContentHitRegion = regions.mHitRegion;
200     layers[0]->SetEventRegions(regions);
201     layers[1]->SetEventRegions(regions);
202   }
203 };
204 
205 #endif  // mozilla_layers_APZCTreeManagerTester_h
206