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 
18 #include "mozilla/layers/APZSampler.h"
19 #include "mozilla/layers/APZUpdater.h"
20 
21 class APZCTreeManagerTester : public APZCTesterBase {
22  protected:
SetUp()23   virtual void SetUp() {
24     gfxPlatform::GetPlatform();
25     APZThreadUtils::SetThreadAssertionsEnabled(false);
26     APZThreadUtils::SetControllerThread(NS_GetCurrentThread());
27 
28     manager = new TestAPZCTreeManager(mcc);
29     updater = new APZUpdater(manager, false);
30     sampler = new APZSampler(manager, false);
31   }
32 
TearDown()33   virtual void TearDown() {
34     while (mcc->RunThroughDelayedTasks())
35       ;
36     manager->ClearTree();
37     manager->ClearContentController();
38   }
39 
40   /**
41    * Sample animations once for all APZCs, 1 ms later than the last sample.
42    */
SampleAnimationsOnce()43   void SampleAnimationsOnce() {
44     const TimeDuration increment = TimeDuration::FromMilliseconds(1);
45     ParentLayerPoint pointOut;
46     AsyncTransform viewTransformOut;
47     mcc->AdvanceBy(increment);
48 
49     for (const RefPtr<Layer>& layer : layers) {
50       if (TestAsyncPanZoomController* apzc = ApzcOf(layer)) {
51         apzc->SampleContentTransformForFrame(&viewTransformOut, pointOut);
52       }
53     }
54   }
55 
56   // A convenience function for letting a test modify the frame metrics
57   // stored on a particular layer. The layer doesn't let us modify it in-place,
58   // so we take care of the copying in this function.
59   template <typename Callback>
ModifyFrameMetrics(Layer * aLayer,Callback aCallback)60   void ModifyFrameMetrics(Layer* aLayer, Callback aCallback) {
61     ScrollMetadata metadata = aLayer->GetScrollMetadata(0);
62     aCallback(metadata.GetMetrics());
63     aLayer->SetScrollMetadata(metadata);
64   }
65 
66   // A convenience wrapper for manager->UpdateHitTestingTree().
67   void UpdateHitTestingTree(uint32_t aPaintSequenceNumber = 0) {
68     manager->UpdateHitTestingTree(root, /* is first paint = */ false,
69                                   LayersId{0}, aPaintSequenceNumber);
70   }
71 
72   nsTArray<RefPtr<Layer> > layers;
73   RefPtr<LayerManager> lm;
74   RefPtr<Layer> root;
75 
76   RefPtr<TestAPZCTreeManager> manager;
77   RefPtr<APZSampler> sampler;
78   RefPtr<APZUpdater> updater;
79 
80  protected:
BuildScrollMetadata(ScrollableLayerGuid::ViewID aScrollId,const CSSRect & aScrollableRect,const ParentLayerRect & aCompositionBounds)81   static ScrollMetadata BuildScrollMetadata(
82       ScrollableLayerGuid::ViewID aScrollId, const CSSRect& aScrollableRect,
83       const ParentLayerRect& aCompositionBounds) {
84     ScrollMetadata metadata;
85     FrameMetrics& metrics = metadata.GetMetrics();
86     metrics.SetScrollId(aScrollId);
87     // By convention in this test file, START_SCROLL_ID is the root, so mark it
88     // as such.
89     if (aScrollId == ScrollableLayerGuid::START_SCROLL_ID) {
90       metadata.SetIsLayersIdRoot(true);
91     }
92     metrics.SetCompositionBounds(aCompositionBounds);
93     metrics.SetScrollableRect(aScrollableRect);
94     metrics.SetScrollOffset(CSSPoint(0, 0));
95     metadata.SetPageScrollAmount(LayoutDeviceIntSize(50, 100));
96     metadata.SetLineScrollAmount(LayoutDeviceIntSize(5, 10));
97     return metadata;
98   }
99 
SetEventRegionsBasedOnBottommostMetrics(Layer * aLayer)100   static void SetEventRegionsBasedOnBottommostMetrics(Layer* aLayer) {
101     const FrameMetrics& metrics = aLayer->GetScrollMetadata(0).GetMetrics();
102     CSSRect scrollableRect = metrics.GetScrollableRect();
103     if (!scrollableRect.IsEqualEdges(CSSRect(-1, -1, -1, -1))) {
104       // The purpose of this is to roughly mimic what layout would do in the
105       // case of a scrollable frame with the event regions and clip. This lets
106       // us exercise the hit-testing code in APZCTreeManager
107       EventRegions er = aLayer->GetEventRegions();
108       IntRect scrollRect =
109           RoundedToInt(scrollableRect * metrics.LayersPixelsPerCSSPixel())
110               .ToUnknownRect();
111       er.mHitRegion = nsIntRegion(IntRect(
112           RoundedToInt(
113               metrics.GetCompositionBounds().TopLeft().ToUnknownPoint()),
114           scrollRect.Size()));
115       aLayer->SetEventRegions(er);
116     }
117   }
118 
119   static void SetScrollableFrameMetrics(
120       Layer* aLayer, ScrollableLayerGuid::ViewID aScrollId,
121       CSSRect aScrollableRect = CSSRect(-1, -1, -1, -1)) {
122     ParentLayerIntRect compositionBounds =
123         RoundedToInt(aLayer->GetLocalTransformTyped().TransformBounds(
124             LayerRect(aLayer->GetVisibleRegion().GetBounds())));
125     ScrollMetadata metadata = BuildScrollMetadata(
126         aScrollId, aScrollableRect, ParentLayerRect(compositionBounds));
127     aLayer->SetScrollMetadata(metadata);
128     aLayer->SetClipRect(Some(compositionBounds));
129     SetEventRegionsBasedOnBottommostMetrics(aLayer);
130   }
131 
SetScrollHandoff(Layer * aChild,Layer * aParent)132   void SetScrollHandoff(Layer* aChild, Layer* aParent) {
133     ScrollMetadata metadata = aChild->GetScrollMetadata(0);
134     metadata.SetScrollParentId(aParent->GetFrameMetrics(0).GetScrollId());
135     aChild->SetScrollMetadata(metadata);
136   }
137 
ApzcOf(Layer * aLayer)138   static TestAsyncPanZoomController* ApzcOf(Layer* aLayer) {
139     EXPECT_EQ(1u, aLayer->GetScrollMetadataCount());
140     return (TestAsyncPanZoomController*)aLayer->GetAsyncPanZoomController(0);
141   }
142 
ApzcOf(Layer * aLayer,uint32_t aIndex)143   static TestAsyncPanZoomController* ApzcOf(Layer* aLayer, uint32_t aIndex) {
144     EXPECT_LT(aIndex, aLayer->GetScrollMetadataCount());
145     return (TestAsyncPanZoomController*)aLayer->GetAsyncPanZoomController(
146         aIndex);
147   }
148 
CreateSimpleScrollingLayer()149   void CreateSimpleScrollingLayer() {
150     const char* layerTreeSyntax = "t";
151     nsIntRegion layerVisibleRegion[] = {
152         nsIntRegion(IntRect(0, 0, 200, 200)),
153     };
154     root = CreateLayerTree(layerTreeSyntax, layerVisibleRegion, nullptr, lm,
155                            layers);
156     SetScrollableFrameMetrics(root, ScrollableLayerGuid::START_SCROLL_ID,
157                               CSSRect(0, 0, 500, 500));
158   }
159 };
160 
161 #endif  // mozilla_layers_APZCTreeManagerTester_h
162