tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit df302ed05bddfa002cafa191cbc86880e9e80b55
parent 271284c1c82a7c27442f04d64bf5ad0545f8acd0
Author: Hiroyuki Ikezoe <hikezoe.birchill@mozilla.com>
Date:   Fri,  7 Nov 2025 01:58:04 +0000

Bug 1978682 - Use ScrollPositionUpdate::mSource as the scroll origin of relavei/instant scroll position updates if the APZC is default. r=botond

Differential Revision: https://phabricator.services.mozilla.com/D269175

Diffstat:
Mgfx/layers/FrameMetrics.cpp | 11+++++++++--
Mgfx/layers/FrameMetrics.h | 7++++++-
Mgfx/layers/apz/src/AsyncPanZoomController.cpp | 11++++++-----
Mgfx/layers/apz/test/gtest/TestBasic.cpp | 51+++++++++++++++++++++++++++++++++++++++++++++------
4 files changed, 66 insertions(+), 14 deletions(-)

diff --git a/gfx/layers/FrameMetrics.cpp b/gfx/layers/FrameMetrics.cpp @@ -168,11 +168,18 @@ bool FrameMetrics::ScrollLayoutViewportTo(const CSSPoint& aDestination) { } CSSPoint FrameMetrics::ApplyRelativeScrollUpdateFrom( - const ScrollPositionUpdate& aUpdate) { + const ScrollPositionUpdate& aUpdate, IsDefaultApzc aIsDefaultApzc) { MOZ_ASSERT(aUpdate.GetType() == ScrollUpdateType::Relative); MOZ_ASSERT(aUpdate.GetMode() != ScrollMode::Smooth && aUpdate.GetMode() != ScrollMode::SmoothMsd); - CSSPoint origin = GetVisualScrollOffset(); + + // If the APZC is default, i.e. newly created one, any relative instant + // scroll position update has been already reflected as the visual scroll + // offset, so we use the mSource in this ScrollPositionUpdate, which is the + // original scroll offset when this relative scroll update operation happened + // on the content. + CSSPoint origin = + bool(aIsDefaultApzc) ? aUpdate.GetSource() : GetVisualScrollOffset(); CSSPoint delta = (aUpdate.GetDestination() - aUpdate.GetSource()); SetVisualScrollOffset(origin + delta); return GetVisualScrollOffset() - origin; diff --git a/gfx/layers/FrameMetrics.h b/gfx/layers/FrameMetrics.h @@ -255,7 +255,12 @@ struct FrameMetrics { * * @returns The clamped scroll offset delta that was applied */ - CSSPoint ApplyRelativeScrollUpdateFrom(const ScrollPositionUpdate& aUpdate); + enum class IsDefaultApzc { + No, + Yes, + }; + CSSPoint ApplyRelativeScrollUpdateFrom(const ScrollPositionUpdate& aUpdate, + IsDefaultApzc aIsDefaultApzc); CSSPoint ApplyPureRelativeScrollUpdateFrom( const ScrollPositionUpdate& aUpdate); diff --git a/gfx/layers/apz/src/AsyncPanZoomController.cpp b/gfx/layers/apz/src/AsyncPanZoomController.cpp @@ -5921,10 +5921,11 @@ void AsyncPanZoomController::NotifyLayersUpdated( Maybe<CSSPoint> relativeDelta; if (scrollUpdate.GetType() == ScrollUpdateType::Relative) { APZC_LOG( - "%p relative updating scroll offset from %s by %s\n", this, - ToString(Metrics().GetVisualScrollOffset()).c_str(), + "%p relative updating scroll offset from %s by %s, isDefault(%d)\n", + this, ToString(Metrics().GetVisualScrollOffset()).c_str(), ToString(scrollUpdate.GetDestination() - scrollUpdate.GetSource()) - .c_str()); + .c_str(), + isDefault); scrollOffsetUpdated = true; @@ -5938,8 +5939,8 @@ void AsyncPanZoomController::NotifyLayersUpdated( contentRepaintType = RepaintUpdateType::eUserAction; } - relativeDelta = - Some(Metrics().ApplyRelativeScrollUpdateFrom(scrollUpdate)); + relativeDelta = Some(Metrics().ApplyRelativeScrollUpdateFrom( + scrollUpdate, FrameMetrics::IsDefaultApzc{isDefault})); Metrics().RecalculateLayoutViewportOffset(); } else if (scrollUpdate.GetType() == ScrollUpdateType::PureRelative) { APZC_LOG("%p pure-relative updating scroll offset from %s by %s\n", this, diff --git a/gfx/layers/apz/test/gtest/TestBasic.cpp b/gfx/layers/apz/test/gtest/TestBasic.cpp @@ -390,7 +390,7 @@ TEST_F(APZCBasicTester, MultipleSmoothScrollsSmooth) { } } -TEST_F(APZCBasicTester, NotifyLayersUpdate_WithScrollUpdates) { +TEST_F(APZCBasicTester, NotifyLayersUpdate_WithScrollUpdate) { // Set an empty metadata as if the APZC is now newly created. // This replicates when a document in a background tab now becomes forground. ScrollMetadata metadata; @@ -415,7 +415,7 @@ TEST_F(APZCBasicTester, NotifyLayersUpdate_WithScrollUpdates) { CSSPoint::ToAppUnits(CSSPoint(15, 15)))); metadata.SetScrollUpdates(scrollUpdates); metrics.SetScrollGeneration(scrollUpdates.LastElement().GetGeneration()); - // With the above scroll updates, now the layout/visual scroll offsets (on the + // With the above scroll update, now the layout/visual scroll offsets (on the // main-thread) need to be updated. metrics.SetVisualScrollOffset(CSSPoint(15, 15)); metrics.SetLayoutViewport(CSSRect(15, 15, 10, 10)); @@ -426,10 +426,49 @@ TEST_F(APZCBasicTester, NotifyLayersUpdate_WithScrollUpdates) { // The layout/visual scroll ofsets and the relative scroll update need to be // reflected. - ASSERT_EQ(apzc->GetFrameMetrics().GetLayoutScrollOffset(), CSSPoint(20, 20)) - << "If the actual value is (15, 15), you fixed bug 1978682, thanks!"; - ASSERT_EQ(apzc->GetFrameMetrics().GetVisualScrollOffset(), CSSPoint(20, 20)) - << "If the actual value is (15, 15), you fixed bug 1978682, thanks!"; + ASSERT_EQ(apzc->GetFrameMetrics().GetLayoutScrollOffset(), CSSPoint(15, 15)); + ASSERT_EQ(apzc->GetFrameMetrics().GetVisualScrollOffset(), CSSPoint(15, 15)); +} + +TEST_F(APZCBasicTester, NotifyLayersUpdate_WithMultipleScrollUpdates) { + // Set an empty metadata as if the APZC is now newly created. + // This replicates when a document in a background tab now becomes foreground. + ScrollMetadata metadata; + apzc->SetScrollMetadata(metadata); + ASSERT_TRUE(apzc->GetScrollMetadata().IsDefault()); + + FrameMetrics& metrics = metadata.GetMetrics(); + metrics.SetDisplayPort(CSSRect(0, 0, 10, 10)); + metrics.SetCompositionBounds(ParentLayerRect(0, 0, 10, 10)); + metrics.SetScrollableRect(CSSRect(0, 0, 100, 100)); + + metrics.SetVisualScrollOffset(CSSPoint(0, 0)); + metrics.SetLayoutViewport(CSSRect(0, 0, 10, 10)); + metrics.SetScrollId(ScrollableLayerGuid::START_SCROLL_ID); + + AutoTArray<ScrollPositionUpdate, 2> scrollUpdates; + // Append a new scroll frame as if the scroll frame was reconstructed. + scrollUpdates.AppendElement(ScrollPositionUpdate::NewScrollframe( + CSSPoint::ToAppUnits(CSSPoint(0, 0)))); + // Append a new relative scroll update (0, 0) -> (20, 20). + scrollUpdates.AppendElement(ScrollPositionUpdate::NewRelativeScroll( + CSSPoint::ToAppUnits(CSSPoint(0, 0)), + CSSPoint::ToAppUnits(CSSPoint(20, 20)))); + metadata.SetScrollUpdates(scrollUpdates); + metrics.SetScrollGeneration(scrollUpdates.LastElement().GetGeneration()); + // With the above scroll updates, now the layout/visual scroll offsets (on the + // main-thread) need to be updated. + metrics.SetVisualScrollOffset(CSSPoint(20, 20)); + metrics.SetLayoutViewport(CSSRect(20, 20, 10, 10)); + + // It's not first-paint when switching tab. + apzc->NotifyLayersUpdated(metadata, /*isFirstPaint=*/false, + /*thisLayerTreeUpdated=*/true); + + // The layout/visual scroll ofsets and the relative scroll update need to be + // reflected. + ASSERT_EQ(apzc->GetFrameMetrics().GetLayoutScrollOffset(), CSSPoint(20, 20)); + ASSERT_EQ(apzc->GetFrameMetrics().GetVisualScrollOffset(), CSSPoint(20, 20)); } class APZCSmoothScrollTester : public APZCBasicTester {