From e39bf21627c91e39941f6e4749ea5b925730c806 Mon Sep 17 00:00:00 2001 From: "wjmaclean@chromium.org" Date: Thu, 22 Nov 2012 21:04:03 +0000 Subject: implTransform needs to scale scroll delta with deviceScaleFactor. This CL fixes a number of issues. First, it fixes the implTransform for non-unit device scale factors, fixing the issue about not being able to pan the zoom viewport all the way to the right/bottom margins. It also allows remove the "fudge-factor" used for hit testing in LayerTreeHost::adjustEventPointForPinchZoom, and finally it resolves the issue regarding pinch-zoom not handling the anchor point properly when device scale factor != 1. BUG=158089 Review URL: https://chromiumcodereview.appspot.com/11414035 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@169308 0039d316-1c4b-4281-b951-d872f2087c98 --- cc/layer_tree_host.cc | 29 ++-- cc/layer_tree_host.h | 6 +- cc/layer_tree_host_impl.cc | 14 +- cc/layer_tree_host_impl.h | 12 +- cc/layer_tree_host_impl_unittest.cc | 304 +++++++++++++++++++++++++++++++++++- cc/layer_tree_host_unittest.cc | 6 +- 6 files changed, 345 insertions(+), 26 deletions(-) (limited to 'cc') diff --git a/cc/layer_tree_host.cc b/cc/layer_tree_host.cc index 003f130..f030a8e 100644 --- a/cc/layer_tree_host.cc +++ b/cc/layer_tree_host.cc @@ -731,25 +731,26 @@ void LayerTreeHost::applyScrollAndScale(const ScrollAndScaleSet& info) m_client->applyScrollAndScale(rootScrollDelta, info.pageScaleDelta); } -gfx::PointF LayerTreeHost::adjustEventPointForPinchZoom(const gfx::PointF& point) +gfx::PointF LayerTreeHost::adjustEventPointForPinchZoom(const gfx::PointF& zoomedViewportPoint) const { - WebKit::WebTransformationMatrix inverseImplTransform = m_implTransform; - // TODO(wjmaclean) Need to determine why the next two lines are - // necessary for this to work ... it seems like just inverting - // m_implTransform should be sufficient. - DCHECK(inverseImplTransform.m11()); - DCHECK(inverseImplTransform.m22()); - inverseImplTransform.setM41(inverseImplTransform.m41() - / inverseImplTransform.m11()); - inverseImplTransform.setM42(inverseImplTransform.m42() - / inverseImplTransform.m22()); - inverseImplTransform = inverseImplTransform.inverse(); + if (m_implTransform.isIdentity()) + return zoomedViewportPoint; + + DCHECK(m_implTransform.isInvertible()); + + // Scale to screen space before applying implTransform inverse. + gfx::PointF zoomedScreenspacePoint = gfx::ScalePoint(zoomedViewportPoint, deviceScaleFactor()); + WebKit::WebTransformationMatrix inverseImplTransform = m_implTransform.inverse(); + bool wasClipped = false; - gfx::PointF adjustedPoint = MathUtil::projectPoint(inverseImplTransform, point, wasClipped); + gfx::PointF unzoomedScreenspacePoint = MathUtil::projectPoint(inverseImplTransform, zoomedScreenspacePoint, wasClipped); DCHECK(!wasClipped); - return adjustedPoint; + // Convert back to logical pixels for hit testing. + gfx::PointF unzoomedViewportPoint = gfx::ScalePoint(unzoomedScreenspacePoint, 1 / deviceScaleFactor()); + + return unzoomedViewportPoint; } void LayerTreeHost::setImplTransform(const WebKit::WebTransformationMatrix& transform) diff --git a/cc/layer_tree_host.h b/cc/layer_tree_host.h index 5056345..9718a4d 100644 --- a/cc/layer_tree_host.h +++ b/cc/layer_tree_host.h @@ -201,7 +201,11 @@ public: void startPageScaleAnimation(gfx::Vector2d targetOffset, bool useAnchor, float scale, base::TimeDelta duration); void applyScrollAndScale(const ScrollAndScaleSet&); - gfx::PointF adjustEventPointForPinchZoom(const gfx::PointF&) const; + // This function converts event coordinates when the deviceViewport is zoomed. + // Coordinates are transformed from logical pixels in the zoomed viewport to + // logical pixels in the un-zoomed viewport, the latter being the coordinates + // required for hit-testing. + gfx::PointF adjustEventPointForPinchZoom(const gfx::PointF& zoomedViewportPoint) const; void setImplTransform(const WebKit::WebTransformationMatrix&); void startRateLimiter(WebKit::WebGraphicsContext3D*); diff --git a/cc/layer_tree_host_impl.cc b/cc/layer_tree_host_impl.cc index 057c363..0f96a43 100644 --- a/cc/layer_tree_host_impl.cc +++ b/cc/layer_tree_host_impl.cc @@ -60,6 +60,7 @@ PinchZoomViewport::PinchZoomViewport() , m_sentPageScaleDelta(1) , m_minPageScaleFactor(0) , m_maxPageScaleFactor(0) + , m_deviceScaleFactor(1) { } @@ -101,7 +102,7 @@ gfx::RectF PinchZoomViewport::bounds() const { gfx::RectF bounds(gfx::PointF(), m_layoutViewportSize); bounds.Scale(1 / totalPageScaleFactor()); - bounds += m_pinchViewportScrollDelta; + bounds += m_zoomedViewportOffset; return bounds; } @@ -129,7 +130,7 @@ gfx::Vector2dF PinchZoomViewport::applyScroll(const gfx::Vector2dF& delta) overflow.set_y(pinchedBounds.bottom() - m_layoutViewportSize.height()); pinchedBounds += gfx::Vector2dF(0, m_layoutViewportSize.height() - pinchedBounds.bottom()); } - m_pinchViewportScrollDelta = pinchedBounds.OffsetFromOrigin(); + m_zoomedViewportOffset = pinchedBounds.OffsetFromOrigin(); return overflow; } @@ -143,8 +144,10 @@ WebTransformationMatrix PinchZoomViewport::implTransform(bool pageScalePinchZoom // impl transform, otherwise the scale is handled by WebCore. if (pageScalePinchZoomEnabled) { transform.scale(m_pageScaleFactor); - transform.translate(-m_pinchViewportScrollDelta.x(), - -m_pinchViewportScrollDelta.y()); + // The offset needs to be scaled by deviceScaleFactor as this transform + // needs to work with physical pixels. + gfx::Vector2dF zoomedDeviceViewportOffset = gfx::ScaleVector2d(m_zoomedViewportOffset, m_deviceScaleFactor); + transform.translate(-zoomedDeviceViewportOffset.x(), -zoomedDeviceViewportOffset.y()); } return transform; @@ -1043,6 +1046,7 @@ void LayerTreeHostImpl::setDeviceScaleFactor(float deviceScaleFactor) if (deviceScaleFactor == m_deviceScaleFactor) return; m_deviceScaleFactor = deviceScaleFactor; + m_pinchZoomViewport.setDeviceScaleFactor(m_deviceScaleFactor); updateMaxScrollOffset(); } @@ -1340,7 +1344,7 @@ void LayerTreeHostImpl::pinchGestureUpdate(float magnifyDelta, gfx::Point anchor if (m_settings.pageScalePinchZoomEnabled) { // Compute the application of the delta with respect to the current page zoom of the page. - move.Scale(1 / (m_pinchZoomViewport.pageScaleFactor() * m_deviceScaleFactor)); + move.Scale(1 / m_pinchZoomViewport.pageScaleFactor()); } gfx::Vector2dF scrollOverflow = m_settings.pageScalePinchZoomEnabled ? m_pinchZoomViewport.applyScroll(move) : move; diff --git a/cc/layer_tree_host_impl.h b/cc/layer_tree_host_impl.h index 0aa250d..4b41759 100644 --- a/cc/layer_tree_host_impl.h +++ b/cc/layer_tree_host_impl.h @@ -76,6 +76,9 @@ public: void setSentPageScaleDelta(float delta) { m_sentPageScaleDelta = delta; } float sentPageScaleDelta() const { return m_sentPageScaleDelta; } + void setDeviceScaleFactor(float factor) { m_deviceScaleFactor = factor; } + float deviceScaleFactor() const { return m_deviceScaleFactor; } + // Returns true if the passed parameters were different from those previously // cached. bool setPageScaleFactorAndLimits(float pageScaleFactor, @@ -84,7 +87,7 @@ public: // Returns the bounds and offset of the scaled and translated viewport to use for pinch-zoom. gfx::RectF bounds() const; - const gfx::Vector2dF& scrollDelta() const { return m_pinchViewportScrollDelta; } + const gfx::Vector2dF& zoomedViewportOffset() const { return m_zoomedViewportOffset; } void setLayoutViewportSize(const gfx::SizeF& size) { m_layoutViewportSize = size; } @@ -93,6 +96,10 @@ public: // this constraint. gfx::Vector2dF applyScroll(const gfx::Vector2dF&); + // The implTransform goes from the origin of the unzoomedDeviceViewport to the + // origin of the zoomedDeviceViewport. + // + // implTransform = S[pageScale] * Tr[-zoomedDeviceViewportOffset] WebKit::WebTransformationMatrix implTransform(bool pageScalePinchZoomEnabled) const; private: @@ -101,8 +108,9 @@ private: float m_sentPageScaleDelta; float m_maxPageScaleFactor; float m_minPageScaleFactor; + float m_deviceScaleFactor; - gfx::Vector2dF m_pinchViewportScrollDelta; + gfx::Vector2dF m_zoomedViewportOffset; gfx::SizeF m_layoutViewportSize; }; diff --git a/cc/layer_tree_host_impl_unittest.cc b/cc/layer_tree_host_impl_unittest.cc index 3e35986..859c9b7 100644 --- a/cc/layer_tree_host_impl_unittest.cc +++ b/cc/layer_tree_host_impl_unittest.cc @@ -144,6 +144,19 @@ public: ASSERT_EQ(timesEncountered, 1); } + static void expectNone(const ScrollAndScaleSet& scrollInfo, int id) + { + int timesEncountered = 0; + + for (size_t i = 0; i < scrollInfo.scrolls.size(); ++i) { + if (scrollInfo.scrolls[i].layerId != id) + continue; + timesEncountered++; + } + + ASSERT_EQ(0, timesEncountered); + } + void setupScrollAndContentsLayers(const gfx::Size& contentSize) { scoped_ptr root = LayerImpl::create(1); @@ -186,6 +199,9 @@ public: } void pinchZoomPanViewportForcesCommitRedraw(const float deviceScaleFactor); + void pinchZoomPanViewportTest(const float deviceScaleFactor); + void pinchZoomPanViewportAndScrollTest(const float deviceScaleFactor); + void pinchZoomPanViewportAndScrollBoundaryTest(const float deviceScaleFactor); protected: scoped_ptr createContext() @@ -538,7 +554,7 @@ TEST_P(LayerTreeHostImplTest, implPinchZoom) const float minPageScale = 1, maxPageScale = 4; const WebTransformationMatrix identityScaleTransform; - // The impl-based pinch zoome should not adjust the max scroll position. + // The impl-based pinch zoom should not adjust the max scroll position. { m_hostImpl->setPageScaleFactorAndLimits(1, minPageScale, maxPageScale); scrollLayer->setImplTransform(identityScaleTransform); @@ -4568,6 +4584,292 @@ TEST_P(LayerTreeHostImplTest, pinchZoomPanViewportForcesCommitDeviceScaleFactor2 pinchZoomPanViewportForcesCommitRedraw(2); } +// The following test confirms correct operation of scroll of the pinchZoomViewport. +// The device scale factor directly affects computation of the implTransform, so +// we test the two most common use cases. +void LayerTreeHostImplTest::pinchZoomPanViewportTest(const float deviceScaleFactor) +{ + m_hostImpl->setDeviceScaleFactor(deviceScaleFactor); + + gfx::Size layoutSurfaceSize(10, 20); + gfx::Size deviceSurfaceSize(layoutSurfaceSize.width() * static_cast(deviceScaleFactor), + layoutSurfaceSize.height() * static_cast(deviceScaleFactor)); + float pageScale = 2; + scoped_ptr root = createScrollableLayer(1, layoutSurfaceSize); + // For this test we want to force scrolls to move the pinchZoomViewport so + // we can see the scroll component on the implTransform. + root->setMaxScrollOffset(gfx::Vector2d()); + m_hostImpl->setRootLayer(root.Pass()); + m_hostImpl->setViewportSize(layoutSurfaceSize, deviceSurfaceSize); + m_hostImpl->setPageScaleFactorAndLimits(1, 1, pageScale); + initializeRendererAndDrawFrame(); + + // Set new page scale on impl thread by pinching. + m_hostImpl->pinchGestureBegin(); + m_hostImpl->pinchGestureUpdate(pageScale, gfx::Point()); + m_hostImpl->pinchGestureEnd(); + m_hostImpl->updateRootScrollLayerImplTransform(); + + WebTransformationMatrix expectedImplTransform; + expectedImplTransform.scale(pageScale); + + EXPECT_EQ(m_hostImpl->rootLayer()->implTransform(), expectedImplTransform); + + // The implTransform ignores the scroll if !pageScalePinchZoomEnabled, + // so no point in continuing without it. + if (!m_hostImpl->settings().pageScalePinchZoomEnabled) + return; + + gfx::Vector2d scrollDelta(5, 0); + gfx::Vector2d expectedMaxScroll(m_hostImpl->rootLayer()->maxScrollOffset()); + EXPECT_EQ(InputHandlerClient::ScrollStarted, m_hostImpl->scrollBegin(gfx::Point(0, 0), InputHandlerClient::Gesture)); + m_hostImpl->scrollBy(gfx::Point(), scrollDelta); + m_hostImpl->scrollEnd(); + m_hostImpl->updateRootScrollLayerImplTransform(); + + gfx::Vector2dF expectedTranslation = gfx::ScaleVector2d(scrollDelta, m_hostImpl->deviceScaleFactor()); + expectedImplTransform.translate(-expectedTranslation.x(), -expectedTranslation.y()); + + EXPECT_EQ(expectedImplTransform, m_hostImpl->rootLayer()->implTransform()); + // No change expected. + EXPECT_EQ(expectedMaxScroll, m_hostImpl->rootLayer()->maxScrollOffset()); + // None of the scroll delta should have been used for document scroll. + scoped_ptr scrollInfo = m_hostImpl->processScrollDeltas(); + expectNone(*scrollInfo.get(), m_hostImpl->rootLayer()->id()); + + // Test scroll in y-direction also. + scrollDelta = gfx::Vector2d(0, 5); + EXPECT_EQ(InputHandlerClient::ScrollStarted, m_hostImpl->scrollBegin(gfx::Point(0, 0), InputHandlerClient::Gesture)); + m_hostImpl->scrollBy(gfx::Point(), scrollDelta); + m_hostImpl->scrollEnd(); + m_hostImpl->updateRootScrollLayerImplTransform(); + + expectedTranslation = gfx::ScaleVector2d(scrollDelta, m_hostImpl->deviceScaleFactor()); + expectedImplTransform.translate(-expectedTranslation.x(), -expectedTranslation.y()); + + EXPECT_EQ(expectedImplTransform, m_hostImpl->rootLayer()->implTransform()); + // No change expected. + EXPECT_EQ(expectedMaxScroll, m_hostImpl->rootLayer()->maxScrollOffset()); + // None of the scroll delta should have been used for document scroll. + scrollInfo = m_hostImpl->processScrollDeltas(); + expectNone(*scrollInfo.get(), m_hostImpl->rootLayer()->id()); +} + +TEST_P(LayerTreeHostImplTest, pinchZoomPanViewportWithDeviceScaleFactor1) +{ + pinchZoomPanViewportTest(1); +} + +TEST_P(LayerTreeHostImplTest, pinchZoomPanViewportWithDeviceScaleFactor2) +{ + pinchZoomPanViewportTest(2); +} + +// This test verifies the correct behaviour of the document-then-pinchZoomViewport +// scrolling model, in both x- and y-directions. +void LayerTreeHostImplTest::pinchZoomPanViewportAndScrollTest(const float deviceScaleFactor) +{ + m_hostImpl->setDeviceScaleFactor(deviceScaleFactor); + + gfx::Size layoutSurfaceSize(10, 20); + gfx::Size deviceSurfaceSize(layoutSurfaceSize.width() * static_cast(deviceScaleFactor), + layoutSurfaceSize.height() * static_cast(deviceScaleFactor)); + float pageScale = 2; + scoped_ptr root = createScrollableLayer(1, layoutSurfaceSize); + // For this test we want to scrolls to move both the document and the + // pinchZoomViewport so we can see some scroll component on the implTransform. + root->setMaxScrollOffset(gfx::Vector2d(3, 4)); + m_hostImpl->setRootLayer(root.Pass()); + m_hostImpl->setViewportSize(layoutSurfaceSize, deviceSurfaceSize); + m_hostImpl->setPageScaleFactorAndLimits(1, 1, pageScale); + initializeRendererAndDrawFrame(); + + // Set new page scale on impl thread by pinching. + m_hostImpl->pinchGestureBegin(); + m_hostImpl->pinchGestureUpdate(pageScale, gfx::Point()); + m_hostImpl->pinchGestureEnd(); + m_hostImpl->updateRootScrollLayerImplTransform(); + + WebTransformationMatrix expectedImplTransform; + expectedImplTransform.scale(pageScale); + + EXPECT_EQ(expectedImplTransform, m_hostImpl->rootLayer()->implTransform()); + + // The implTransform ignores the scroll if !pageScalePinchZoomEnabled, + // so no point in continuing without it. + if (!m_hostImpl->settings().pageScalePinchZoomEnabled) + return; + + // Scroll document only: scrollDelta chosen to move document horizontally + // to its max scroll offset. + gfx::Vector2d scrollDelta(3, 0); + gfx::Vector2d expectedScrollDelta(scrollDelta); + gfx::Vector2d expectedMaxScroll(m_hostImpl->rootLayer()->maxScrollOffset()); + EXPECT_EQ(InputHandlerClient::ScrollStarted, m_hostImpl->scrollBegin(gfx::Point(0, 0), InputHandlerClient::Gesture)); + m_hostImpl->scrollBy(gfx::Point(), scrollDelta); + m_hostImpl->scrollEnd(); + m_hostImpl->updateRootScrollLayerImplTransform(); + + // The scroll delta is not scaled because the main thread did not scale. + scoped_ptr scrollInfo = m_hostImpl->processScrollDeltas(); + expectContains(*scrollInfo.get(), m_hostImpl->rootLayer()->id(), expectedScrollDelta); + EXPECT_EQ(expectedMaxScroll, m_hostImpl->rootLayer()->maxScrollOffset()); + + // Verify we did not change the implTransform this time. + EXPECT_EQ(expectedImplTransform, m_hostImpl->rootLayer()->implTransform()); + + // Further scrolling should move the pinchZoomViewport only. + scrollDelta = gfx::Vector2d(2, 0); + EXPECT_EQ(InputHandlerClient::ScrollStarted, m_hostImpl->scrollBegin(gfx::Point(0, 0), InputHandlerClient::Gesture)); + m_hostImpl->scrollBy(gfx::Point(), scrollDelta); + m_hostImpl->scrollEnd(); + m_hostImpl->updateRootScrollLayerImplTransform(); + + gfx::Vector2d expectedPanDelta(scrollDelta); + gfx::Vector2dF expectedTranslation = gfx::ScaleVector2d(expectedPanDelta, m_hostImpl->deviceScaleFactor()); + expectedImplTransform.translate(-expectedTranslation.x(), -expectedTranslation.y()); + + EXPECT_EQ(m_hostImpl->rootLayer()->implTransform(), expectedImplTransform); + + // The scroll delta on the main thread should not have been affected by this. + scrollInfo = m_hostImpl->processScrollDeltas(); + expectContains(*scrollInfo.get(), m_hostImpl->rootLayer()->id(), expectedScrollDelta); + EXPECT_EQ(expectedMaxScroll, m_hostImpl->rootLayer()->maxScrollOffset()); + + // Perform same test sequence in y-direction also. + // Document only scroll. + scrollDelta = gfx::Vector2d(0, 4); + expectedScrollDelta += scrollDelta; + EXPECT_EQ(InputHandlerClient::ScrollStarted, m_hostImpl->scrollBegin(gfx::Point(0, 0), InputHandlerClient::Gesture)); + m_hostImpl->scrollBy(gfx::Point(), scrollDelta); + m_hostImpl->scrollEnd(); + m_hostImpl->updateRootScrollLayerImplTransform(); + + // The scroll delta is not scaled because the main thread did not scale. + scrollInfo = m_hostImpl->processScrollDeltas(); + expectContains(*scrollInfo.get(), m_hostImpl->rootLayer()->id(), expectedScrollDelta); + EXPECT_EQ(expectedMaxScroll, m_hostImpl->rootLayer()->maxScrollOffset()); + + // Verify we did not change the implTransform this time. + EXPECT_EQ(expectedImplTransform, m_hostImpl->rootLayer()->implTransform()); + + // pinchZoomViewport scroll only. + scrollDelta = gfx::Vector2d(0, 1); + EXPECT_EQ(InputHandlerClient::ScrollStarted, m_hostImpl->scrollBegin(gfx::Point(0, 0), InputHandlerClient::Gesture)); + m_hostImpl->scrollBy(gfx::Point(), scrollDelta); + m_hostImpl->scrollEnd(); + m_hostImpl->updateRootScrollLayerImplTransform(); + + expectedPanDelta = scrollDelta; + expectedTranslation = gfx::ScaleVector2d(expectedPanDelta, m_hostImpl->deviceScaleFactor()); + expectedImplTransform.translate(-expectedTranslation.x(), -expectedTranslation.y()); + + EXPECT_EQ(expectedImplTransform, m_hostImpl->rootLayer()->implTransform()); + + // The scroll delta on the main thread should not have been affected by this. + scrollInfo = m_hostImpl->processScrollDeltas(); + expectContains(*scrollInfo.get(), m_hostImpl->rootLayer()->id(), expectedScrollDelta); + EXPECT_EQ(expectedMaxScroll, m_hostImpl->rootLayer()->maxScrollOffset()); +} + +TEST_P(LayerTreeHostImplTest, pinchZoomPanViewportAndScrollWithDeviceScaleFactor) +{ + pinchZoomPanViewportAndScrollTest(1); +} + +TEST_P(LayerTreeHostImplTest, pinchZoomPanViewportAndScrollWithDeviceScaleFactor2) +{ + pinchZoomPanViewportAndScrollTest(2); +} + +// This test verifies the correct behaviour of the document-then-pinchZoomViewport +// scrolling model, in both x- and y-directions, but this time using a single scroll +// that crosses the 'boundary' of what will cause document-only scroll and what will +// cause both document-scroll and zoomViewport panning. +void LayerTreeHostImplTest::pinchZoomPanViewportAndScrollBoundaryTest(const float deviceScaleFactor) +{ + m_hostImpl->setDeviceScaleFactor(deviceScaleFactor); + + gfx::Size layoutSurfaceSize(10, 20); + gfx::Size deviceSurfaceSize(layoutSurfaceSize.width() * static_cast(deviceScaleFactor), + layoutSurfaceSize.height() * static_cast(deviceScaleFactor)); + float pageScale = 2; + scoped_ptr root = createScrollableLayer(1, layoutSurfaceSize); + // For this test we want to scrolls to move both the document and the + // pinchZoomViewport so we can see some scroll component on the implTransform. + root->setMaxScrollOffset(gfx::Vector2d(3, 4)); + m_hostImpl->setRootLayer(root.Pass()); + m_hostImpl->setViewportSize(layoutSurfaceSize, deviceSurfaceSize); + m_hostImpl->setPageScaleFactorAndLimits(1, 1, pageScale); + initializeRendererAndDrawFrame(); + + // Set new page scale on impl thread by pinching. + m_hostImpl->pinchGestureBegin(); + m_hostImpl->pinchGestureUpdate(pageScale, gfx::Point()); + m_hostImpl->pinchGestureEnd(); + m_hostImpl->updateRootScrollLayerImplTransform(); + + WebTransformationMatrix expectedImplTransform; + expectedImplTransform.scale(pageScale); + + EXPECT_EQ(expectedImplTransform, m_hostImpl->rootLayer()->implTransform()); + + // The implTransform ignores the scroll if !pageScalePinchZoomEnabled, + // so no point in continuing without it. + if (!m_hostImpl->settings().pageScalePinchZoomEnabled) + return; + + // Scroll document and pann zoomViewport in one scroll-delta. + gfx::Vector2d scrollDelta(5, 0); + gfx::Vector2d expectedScrollDelta(gfx::Vector2d(3, 0)); // This component gets handled by document scroll. + gfx::Vector2d expectedMaxScroll(m_hostImpl->rootLayer()->maxScrollOffset()); + + EXPECT_EQ(InputHandlerClient::ScrollStarted, m_hostImpl->scrollBegin(gfx::Point(0, 0), InputHandlerClient::Gesture)); + m_hostImpl->scrollBy(gfx::Point(), scrollDelta); + m_hostImpl->scrollEnd(); + m_hostImpl->updateRootScrollLayerImplTransform(); + + // The scroll delta is not scaled because the main thread did not scale. + scoped_ptr scrollInfo = m_hostImpl->processScrollDeltas(); + expectContains(*scrollInfo.get(), m_hostImpl->rootLayer()->id(), expectedScrollDelta); + EXPECT_EQ(expectedMaxScroll, m_hostImpl->rootLayer()->maxScrollOffset()); + + gfx::Vector2d expectedPanDelta(2, 0); // This component gets handled by zoomViewport pan. + gfx::Vector2dF expectedTranslation = gfx::ScaleVector2d(expectedPanDelta, m_hostImpl->deviceScaleFactor()); + expectedImplTransform.translate(-expectedTranslation.x(), -expectedTranslation.y()); + + EXPECT_EQ(m_hostImpl->rootLayer()->implTransform(), expectedImplTransform); + + // Perform same test sequence in y-direction also. + scrollDelta = gfx::Vector2d(0, 5); + expectedScrollDelta += gfx::Vector2d(0, 4); // This component gets handled by document scroll. + EXPECT_EQ(InputHandlerClient::ScrollStarted, m_hostImpl->scrollBegin(gfx::Point(0, 0), InputHandlerClient::Gesture)); + m_hostImpl->scrollBy(gfx::Point(), scrollDelta); + m_hostImpl->scrollEnd(); + m_hostImpl->updateRootScrollLayerImplTransform(); + + // The scroll delta is not scaled because the main thread did not scale. + scrollInfo = m_hostImpl->processScrollDeltas(); // This component gets handled by zoomViewport pan. + expectContains(*scrollInfo.get(), m_hostImpl->rootLayer()->id(), expectedScrollDelta); + EXPECT_EQ(expectedMaxScroll, m_hostImpl->rootLayer()->maxScrollOffset()); + + expectedPanDelta = gfx::Vector2d(0, 1); + expectedTranslation = gfx::ScaleVector2d(expectedPanDelta, m_hostImpl->deviceScaleFactor()); + expectedImplTransform.translate(-expectedTranslation.x(), -expectedTranslation.y()); + + EXPECT_EQ(expectedImplTransform, m_hostImpl->rootLayer()->implTransform()); +} + +TEST_P(LayerTreeHostImplTest, pinchZoomPanViewportAndScrollBoundaryWithDeviceScaleFactor) +{ + pinchZoomPanViewportAndScrollBoundaryTest(1); +} + +TEST_P(LayerTreeHostImplTest, pinchZoomPanViewportAndScrollBoundaryWithDeviceScaleFactor2) +{ + pinchZoomPanViewportAndScrollBoundaryTest(2); +} + INSTANTIATE_TEST_CASE_P(LayerTreeHostImplTests, LayerTreeHostImplTest, ::testing::Values(false, true)); diff --git a/cc/layer_tree_host_unittest.cc b/cc/layer_tree_host_unittest.cc index 034c789..5135441 100644 --- a/cc/layer_tree_host_unittest.cc +++ b/cc/layer_tree_host_unittest.cc @@ -3137,10 +3137,10 @@ public: m_layerTreeHost->setImplTransform(m); - // Apply m^(-1): 138 = 400/2 - 250/4; 185 = 550/2 - 360/4. + // Apply m^(-1): 75 = (400 - 250) / 2; 95 = (550 - 360) / 2. transformedPoint = gfx::ToRoundedPoint(m_layerTreeHost->adjustEventPointForPinchZoom(point)); - EXPECT_EQ(138, transformedPoint.x()); - EXPECT_EQ(185, transformedPoint.y()); + EXPECT_EQ(75, transformedPoint.x()); + EXPECT_EQ(95, transformedPoint.y()); endTest(); } -- cgit v1.1