void AppendToString(std::stringstream& aStream, const ScrollMetadata& m, const char* pfx, const char* sfx) { aStream << pfx; AppendToString(aStream, m.GetMetrics(), "{ [metrics="); AppendToString(aStream, m.GetBackgroundColor(), "] [color="); if (m.GetScrollParentId() != FrameMetrics::NULL_SCROLL_ID) { AppendToString(aStream, m.GetScrollParentId(), "] [scrollParent="); } if (m.HasScrollClip()) { AppendToString(aStream, m.ScrollClip().GetClipRect(), "] [clip="); } if (m.HasMaskLayer()) { AppendToString(aStream, m.ScrollClip().GetMaskLayerIndex().value(), "] [mask="); } OverscrollBehavior overscrollX = m.GetOverscrollBehavior().mBehaviorX; OverscrollBehavior overscrollY = m.GetOverscrollBehavior().mBehaviorY; if (overscrollX == overscrollY && overscrollX != OverscrollBehavior::Auto) { AppendToString(aStream, overscrollX, "] [overscroll="); } else { if (overscrollX != OverscrollBehavior::Auto) { AppendToString(aStream, overscrollX, "] [overscroll-x="); } if (overscrollY != OverscrollBehavior::Auto) { AppendToString(aStream, overscrollY, "] [overscroll-y="); } } aStream << "] }" << sfx; }
void AppendToString(std::stringstream& aStream, const ScrollMetadata& m, const char* pfx, const char* sfx) { aStream << pfx; AppendToString(aStream, m.GetMetrics(), "{ [metrics=", "]"); if (m.HasClipRect()) { AppendToString(aStream, m.ClipRect(), " [clip=", "]"); } aStream << "}" << sfx; }
TEST_F(APZCSnappingTester, Bug1265510) { 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); UniquePtr<ScopedLayerTreeRegistration> registration = MakeUnique<ScopedLayerTreeRegistration>(manager, 0, root, mcc); manager->UpdateHitTestingTree(nullptr, root, false, 0, 0); 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); }
size_t WebRenderScrollData::AddMetadata(const ScrollMetadata& aMetadata) { ScrollableLayerGuid::ViewID scrollId = aMetadata.GetMetrics().GetScrollId(); auto insertResult = mScrollIdMap.insert(std::make_pair(scrollId, 0)); if (insertResult.second) { // Insertion took place, therefore it's a scrollId we hadn't seen before insertResult.first->second = mScrollMetadatas.Length(); mScrollMetadatas.AppendElement(aMetadata); } // else we didn't insert, because it already existed return insertResult.first->second; }
TEST_F(APZHitTestingTester, HitTestingRespectsScrollClip_Bug1257288) { // Create the layer tree. const char* layerTreeSyntax = "c(tt)"; // LayerID 0 12 nsIntRegion layerVisibleRegion[] = { nsIntRegion(IntRect(0,0,200,200)), nsIntRegion(IntRect(0,0,200,200)), nsIntRegion(IntRect(0,0,200,100)) }; root = CreateLayerTree(layerTreeSyntax, layerVisibleRegion, nullptr, lm, layers); // Add root scroll metadata to the first painted layer. SetScrollableFrameMetrics(layers[1], FrameMetrics::START_SCROLL_ID, CSSRect(0,0,200,200)); // Add root and subframe scroll metadata to the second painted layer. // Give the subframe metadata a scroll clip corresponding to the subframe's // composition bounds. // Importantly, give the layer a layer clip which leaks outside of the // subframe's composition bounds. ScrollMetadata rootMetadata = BuildScrollMetadata( FrameMetrics::START_SCROLL_ID, CSSRect(0,0,200,200), ParentLayerRect(0,0,200,200)); ScrollMetadata subframeMetadata = BuildScrollMetadata( FrameMetrics::START_SCROLL_ID + 1, CSSRect(0,0,200,200), ParentLayerRect(0,0,200,100)); subframeMetadata.SetScrollClip(Some(LayerClip(ParentLayerIntRect(0,0,200,100)))); layers[2]->SetScrollMetadata({subframeMetadata, rootMetadata}); layers[2]->SetClipRect(Some(ParentLayerIntRect(0,0,200,200))); SetEventRegionsBasedOnBottommostMetrics(layers[2]); // Build the hit testing tree. ScopedLayerTreeRegistration registration(manager, 0, root, mcc); manager->UpdateHitTestingTree(nullptr, root, false, 0, 0); // Pan on a region that's inside layers[2]'s layer clip, but outside // its subframe metadata's scroll clip. Pan(manager, 120, 110); // Test that the subframe hasn't scrolled. EXPECT_EQ(CSSPoint(0,0), ApzcOf(layers[2], 0)->GetFrameMetrics().GetScrollOffset()); }
void AppendToString(std::stringstream& aStream, const ScrollMetadata& m, const char* pfx, const char* sfx) { aStream << pfx; AppendToString(aStream, m.GetMetrics(), "{ [metrics="); AppendToString(aStream, m.GetBackgroundColor(), "] [color="); if (m.GetScrollParentId() != FrameMetrics::NULL_SCROLL_ID) { AppendToString(aStream, m.GetScrollParentId(), "] [scrollParent="); } if (m.HasScrollClip()) { AppendToString(aStream, m.ScrollClip().GetClipRect(), "] [clip="); } aStream << "] }" << sfx; }
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(); }
static ScrollMetadata MakeMetadata(FrameMetrics::ViewID aId) { ScrollMetadata metadata; metadata.GetMetrics().SetScrollId(aId); return metadata; }
void DisableApzOn(Layer* aLayer) { ScrollMetadata m = aLayer->GetScrollMetadata(0); m.SetForceDisableApz(true); aLayer->SetScrollMetadata(m); }