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