void CreateHitTesting2LayerTree() { const char* layerTreeSyntax = "c(tc(t))"; // LayerID 0 12 3 nsIntRegion layerVisibleRegion[] = { nsIntRegion(IntRect(0,0,100,100)), nsIntRegion(IntRect(10,10,40,40)), nsIntRegion(IntRect(10,60,40,40)), nsIntRegion(IntRect(10,60,40,40)), }; Matrix4x4 transforms[] = { Matrix4x4(), Matrix4x4(), Matrix4x4::Scaling(2, 1, 1), Matrix4x4(), }; root = CreateLayerTree(layerTreeSyntax, layerVisibleRegion, transforms, lm, layers); SetScrollableFrameMetrics(root, FrameMetrics::START_SCROLL_ID, CSSRect(0, 0, 200, 200)); SetScrollableFrameMetrics(layers[1], FrameMetrics::START_SCROLL_ID + 1, CSSRect(0, 0, 80, 80)); SetScrollableFrameMetrics(layers[3], FrameMetrics::START_SCROLL_ID + 2, CSSRect(0, 0, 80, 80)); }
void CreateObscuringLayerTree() { const char* layerTreeSyntax = "c(c(t)t)"; // LayerID 0 1 2 3 // 0 is the root. // 1 is a parent scrollable layer. // 2 is a child scrollable layer. // 3 is the Obscurer, who ruins everything. nsIntRegion layerVisibleRegions[] = { // x coordinates are uninteresting nsIntRegion(IntRect(0, 0, 200, 200)), // [0, 200] nsIntRegion(IntRect(0, 0, 200, 200)), // [0, 200] nsIntRegion(IntRect(0, 100, 200, 50)), // [100, 150] nsIntRegion(IntRect(0, 100, 200, 100)) // [100, 200] }; root = CreateLayerTree(layerTreeSyntax, layerVisibleRegions, nullptr, lm, layers); SetScrollableFrameMetrics(root, ScrollableLayerGuid::START_SCROLL_ID, CSSRect(0, 0, 200, 200)); SetScrollableFrameMetrics(layers[1], ScrollableLayerGuid::START_SCROLL_ID + 1, CSSRect(0, 0, 200, 300)); SetScrollableFrameMetrics(layers[2], ScrollableLayerGuid::START_SCROLL_ID + 2, CSSRect(0, 0, 200, 100)); SetScrollHandoff(layers[2], layers[1]); SetScrollHandoff(layers[1], root); EventRegions regions(nsIntRegion(IntRect(0, 0, 200, 200))); root->SetEventRegions(regions); regions.mHitRegion = nsIntRegion(IntRect(0, 0, 200, 300)); layers[1]->SetEventRegions(regions); regions.mHitRegion = nsIntRegion(IntRect(0, 100, 200, 100)); layers[2]->SetEventRegions(regions); registration = MakeUnique<ScopedLayerTreeRegistration>(manager, LayersId{0}, root, mcc); manager->UpdateHitTestingTree(LayersId{0}, root, false, LayersId{0}, 0); rootApzc = ApzcOf(root); }
void CreateEventRegionsLayerTree2() { const char* layerTreeSyntax = "c(t)"; nsIntRegion layerVisibleRegions[] = { nsIntRegion(IntRect(0, 0, 100, 500)), nsIntRegion(IntRect(0, 150, 100, 100)), }; root = CreateLayerTree(layerTreeSyntax, layerVisibleRegions, nullptr, lm, layers); SetScrollableFrameMetrics(root, ScrollableLayerGuid::START_SCROLL_ID); // Set up the event regions so that the child thebes layer is positioned far // away from the scrolling container layer. EventRegions regions(nsIntRegion(IntRect(0, 0, 100, 100))); root->SetEventRegions(regions); regions.mHitRegion = nsIntRegion(IntRect(0, 150, 100, 100)); layers[1]->SetEventRegions(regions); registration = MakeUnique<ScopedLayerTreeRegistration>(manager, LayersId{0}, root, mcc); manager->UpdateHitTestingTree(LayersId{0}, root, false, LayersId{0}, 0); rootApzc = ApzcOf(root); }
void CreateBug1119497LayerTree() { const char* layerTreeSyntax = "c(tt)"; // LayerID 0 12 // 0 is the root and has an APZC // 1 is behind 2 and has an APZC // 2 entirely covers 1 and should take all the input events, but has no APZC // so hits to 2 should go to to the root APZC nsIntRegion layerVisibleRegions[] = { nsIntRegion(IntRect(0, 0, 100, 100)), nsIntRegion(IntRect(0, 0, 100, 100)), nsIntRegion(IntRect(0, 0, 100, 100)), }; root = CreateLayerTree(layerTreeSyntax, layerVisibleRegions, nullptr, lm, layers); SetScrollableFrameMetrics(root, ScrollableLayerGuid::START_SCROLL_ID); SetScrollableFrameMetrics(layers[1], ScrollableLayerGuid::START_SCROLL_ID + 1); registration = MakeUnique<ScopedLayerTreeRegistration>(manager, LayersId{0}, root, mcc); manager->UpdateHitTestingTree(LayersId{0}, root, false, LayersId{0}, 0); }
void CreateEventRegionsLayerTree1() { const char* layerTreeSyntax = "c(tt)"; nsIntRegion layerVisibleRegions[] = { nsIntRegion(IntRect(0, 0, 200, 200)), // root nsIntRegion(IntRect(0, 0, 100, 200)), // left half nsIntRegion(IntRect(0, 100, 200, 100)), // bottom half }; root = CreateLayerTree(layerTreeSyntax, layerVisibleRegions, nullptr, lm, layers); SetScrollableFrameMetrics(root, ScrollableLayerGuid::START_SCROLL_ID); SetScrollableFrameMetrics(layers[1], ScrollableLayerGuid::START_SCROLL_ID + 1); SetScrollableFrameMetrics(layers[2], ScrollableLayerGuid::START_SCROLL_ID + 2); SetScrollHandoff(layers[1], root); SetScrollHandoff(layers[2], root); // Set up the event regions over a 200x200 area. The root layer has the // whole 200x200 as the hit region; layers[1] has the left half and // layers[2] has the bottom half. The bottom-left 100x100 area is also // in the d-t-c region for both layers[1] and layers[2] (but layers[2] is // on top so it gets the events by default if the main thread doesn't // respond). EventRegions regions(nsIntRegion(IntRect(0, 0, 200, 200))); root->SetEventRegions(regions); regions.mDispatchToContentHitRegion = nsIntRegion(IntRect(0, 100, 100, 100)); regions.mHitRegion = nsIntRegion(IntRect(0, 0, 100, 200)); layers[1]->SetEventRegions(regions); regions.mHitRegion = nsIntRegion(IntRect(0, 100, 200, 100)); layers[2]->SetEventRegions(regions); registration = MakeUnique<ScopedLayerTreeRegistration>(manager, LayersId{0}, root, mcc); manager->UpdateHitTestingTree(LayersId{0}, root, false, LayersId{0}, 0); rootApzc = ApzcOf(root); }
void CreateComplexMultiLayerTree() { const char* layerTreeSyntax = "c(tc(t)tc(c(t)tt))"; // LayerID 0 12 3 45 6 7 89 nsIntRegion layerVisibleRegion[] = { nsIntRegion(IntRect(0,0,300,400)), // root(0) nsIntRegion(IntRect(0,0,100,100)), // thebes(1) in top-left nsIntRegion(IntRect(50,50,200,300)), // container(2) centered in root(0) nsIntRegion(IntRect(50,50,200,300)), // thebes(3) fully occupying parent container(2) nsIntRegion(IntRect(0,200,100,100)), // thebes(4) in bottom-left nsIntRegion(IntRect(200,0,100,400)), // container(5) along the right 100px of root(0) nsIntRegion(IntRect(200,0,100,200)), // container(6) taking up the top half of parent container(5) nsIntRegion(IntRect(200,0,100,200)), // thebes(7) fully occupying parent container(6) nsIntRegion(IntRect(200,200,100,100)), // thebes(8) in bottom-right (below (6)) nsIntRegion(IntRect(200,300,100,100)), // thebes(9) in bottom-right (below (8)) }; root = CreateLayerTree(layerTreeSyntax, layerVisibleRegion, nullptr, lm, layers); SetScrollableFrameMetrics(layers[1], FrameMetrics::START_SCROLL_ID); SetScrollableFrameMetrics(layers[2], FrameMetrics::START_SCROLL_ID); SetScrollableFrameMetrics(layers[4], FrameMetrics::START_SCROLL_ID + 1); SetScrollableFrameMetrics(layers[6], FrameMetrics::START_SCROLL_ID + 1); SetScrollableFrameMetrics(layers[7], FrameMetrics::START_SCROLL_ID + 2); SetScrollableFrameMetrics(layers[8], FrameMetrics::START_SCROLL_ID + 1); SetScrollableFrameMetrics(layers[9], FrameMetrics::START_SCROLL_ID + 3); }
TEST_F(APZCBasicTester, ComplexTransform) { // This test assumes there is a page that gets rendered to // two layers. In CSS pixels, the first layer is 50x50 and // the second layer is 25x50. The widget scale factor is 3.0 // and the presShell resolution is 2.0. Therefore, these layers // end up being 300x300 and 150x300 in layer pixels. // // The second (child) layer has an additional CSS transform that // stretches it by 2.0 on the x-axis. Therefore, after applying // CSS transforms, the two layers are the same size in screen // pixels. // // The screen itself is 24x24 in screen pixels (therefore 4x4 in // CSS pixels). The displayport is 1 extra CSS pixel on all // sides. RefPtr<TestAsyncPanZoomController> childApzc = new TestAsyncPanZoomController(0, mcc, tm); const char* layerTreeSyntax = "c(c)"; // LayerID 0 1 nsIntRegion layerVisibleRegion[] = { nsIntRegion(IntRect(0, 0, 300, 300)), nsIntRegion(IntRect(0, 0, 150, 300)), }; Matrix4x4 transforms[] = { Matrix4x4(), Matrix4x4(), }; transforms[0].PostScale(0.5f, 0.5f, 1.0f); // this results from the 2.0 resolution on the root layer transforms[1].PostScale(2.0f, 1.0f, 1.0f); // this is the 2.0 x-axis CSS transform on the child layer nsTArray<RefPtr<Layer> > layers; RefPtr<LayerManager> lm; RefPtr<Layer> root = CreateLayerTree(layerTreeSyntax, layerVisibleRegion, transforms, lm, layers); ScrollMetadata metadata; FrameMetrics& metrics = metadata.GetMetrics(); metrics.SetCompositionBounds(ParentLayerRect(0, 0, 24, 24)); metrics.SetDisplayPort(CSSRect(-1, -1, 6, 6)); metrics.SetScrollOffset(CSSPoint(10, 10)); metrics.SetScrollableRect(CSSRect(0, 0, 50, 50)); metrics.SetCumulativeResolution(LayoutDeviceToLayerScale2D(2, 2)); metrics.SetPresShellResolution(2.0f); metrics.SetZoom(CSSToParentLayerScale2D(6, 6)); metrics.SetDevPixelsPerCSSPixel(CSSToLayoutDeviceScale(3)); metrics.SetScrollId(FrameMetrics::START_SCROLL_ID); ScrollMetadata childMetadata = metadata; FrameMetrics& childMetrics = childMetadata.GetMetrics(); childMetrics.SetScrollId(FrameMetrics::START_SCROLL_ID + 1); layers[0]->SetScrollMetadata(metadata); layers[1]->SetScrollMetadata(childMetadata); ParentLayerPoint pointOut; AsyncTransform viewTransformOut; // Both the parent and child layer should behave exactly the same here, because // the CSS transform on the child layer does not affect the SampleContentTransformForFrame code // initial transform apzc->SetFrameMetrics(metrics); apzc->NotifyLayersUpdated(metadata, true, true); apzc->SampleContentTransformForFrame(&viewTransformOut, pointOut); EXPECT_EQ(AsyncTransform(LayerToParentLayerScale(1), ParentLayerPoint()), viewTransformOut); EXPECT_EQ(ParentLayerPoint(60, 60), pointOut); childApzc->SetFrameMetrics(childMetrics); childApzc->NotifyLayersUpdated(childMetadata, true, true); childApzc->SampleContentTransformForFrame(&viewTransformOut, pointOut); EXPECT_EQ(AsyncTransform(LayerToParentLayerScale(1), ParentLayerPoint()), viewTransformOut); EXPECT_EQ(ParentLayerPoint(60, 60), pointOut); // do an async scroll by 5 pixels and check the transform metrics.ScrollBy(CSSPoint(5, 0)); apzc->SetFrameMetrics(metrics); apzc->SampleContentTransformForFrame(&viewTransformOut, pointOut); EXPECT_EQ(AsyncTransform(LayerToParentLayerScale(1), ParentLayerPoint(-30, 0)), viewTransformOut); EXPECT_EQ(ParentLayerPoint(90, 60), pointOut); childMetrics.ScrollBy(CSSPoint(5, 0)); childApzc->SetFrameMetrics(childMetrics); childApzc->SampleContentTransformForFrame(&viewTransformOut, pointOut); EXPECT_EQ(AsyncTransform(LayerToParentLayerScale(1), ParentLayerPoint(-30, 0)), viewTransformOut); EXPECT_EQ(ParentLayerPoint(90, 60), pointOut); // do an async zoom of 1.5x and check the transform metrics.ZoomBy(1.5f); apzc->SetFrameMetrics(metrics); apzc->SampleContentTransformForFrame(&viewTransformOut, pointOut); EXPECT_EQ(AsyncTransform(LayerToParentLayerScale(1.5), ParentLayerPoint(-45, 0)), viewTransformOut); EXPECT_EQ(ParentLayerPoint(135, 90), pointOut); childMetrics.ZoomBy(1.5f); childApzc->SetFrameMetrics(childMetrics); childApzc->SampleContentTransformForFrame(&viewTransformOut, pointOut); EXPECT_EQ(AsyncTransform(LayerToParentLayerScale(1.5), ParentLayerPoint(-45, 0)), viewTransformOut); EXPECT_EQ(ParentLayerPoint(135, 90), pointOut); childApzc->Destroy(); }