Skip to content

Commit

Permalink
Bug 1827975 - Do not fire scrollend events for keyboard scrolls that …
Browse files Browse the repository at this point in the history
…do not change the scroll position. r=hiro

When a APZC handles a keyboard scroll or other smooth scroll,
no scrollend event should be fired if the scroll position will not
change as a result of the scroll.

Differential Revision: https://phabricator.services.mozilla.com/D187050
  • Loading branch information
dlrobertson committed Oct 1, 2023
1 parent ab4278b commit a19fdc4
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 16 deletions.
65 changes: 49 additions & 16 deletions gfx/layers/apz/src/AsyncPanZoomController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2109,6 +2109,12 @@ nsEventStatus AsyncPanZoomController::OnKeyboard(const KeyboardInput& aEvent) {
// exists
if (mState != KEYBOARD_SCROLL) {
CancelAnimation();
// Keyboard input that does not change the scroll position should not
// cause a TransformBegin state change, in order to avoid firing a
// scrollend event when no scrolling occurred.
if (ConvertDestinationToDelta(destination) == ParentLayerPoint()) {
return nsEventStatus_eConsumeDoDefault;
}
SetState(KEYBOARD_SCROLL);

nsPoint initialPosition =
Expand Down Expand Up @@ -3939,6 +3945,20 @@ void AsyncPanZoomController::HandleSmoothScrollOverscroll(
BuildOverscrollHandoffChain(), nullptr);
}

ParentLayerPoint AsyncPanZoomController::ConvertDestinationToDelta(
CSSPoint& aDestination) const {
ParentLayerPoint startPoint, endPoint;

{
RecursiveMutexAutoLock lock(mRecursiveMutex);

startPoint = aDestination * Metrics().GetZoom();
endPoint = Metrics().GetVisualScrollOffset() * Metrics().GetZoom();
}

return endPoint - startPoint;
}

void AsyncPanZoomController::SmoothScrollTo(
CSSSnapDestination&& aDestination,
ScrollTriggeredByScript aTriggeredByScript, const ScrollOrigin& aOrigin) {
Expand All @@ -3965,6 +3985,13 @@ void AsyncPanZoomController::SmoothScrollTo(
}

CancelAnimation();

// If no scroll is required, we should exit early to avoid triggering
// a scrollend event when no scrolling occurred.
if (ConvertDestinationToDelta(aDestination.mPosition) == ParentLayerPoint()) {
return;
}

SetState(SMOOTH_SCROLL);
nsPoint initialPosition =
CSSPoint::ToAppUnits(Metrics().GetVisualScrollOffset());
Expand All @@ -3986,24 +4013,30 @@ void AsyncPanZoomController::SmoothMsdScrollTo(
animation->SetDestination(aDestination.mPosition,
std::move(aDestination.mTargetIds),
aTriggeredByScript);
} else {
CancelAnimation();
SetState(SMOOTHMSD_SCROLL);
// Convert velocity from ParentLayerPoints/ms to ParentLayerPoints/s.
CSSPoint initialVelocity;
if (Metrics().GetZoom() != CSSToParentLayerScale(0)) {
initialVelocity = ParentLayerPoint(mX.GetVelocity() * 1000.0f,
mY.GetVelocity() * 1000.0f) /
Metrics().GetZoom();
}
return;
}

StartAnimation(new SmoothMsdScrollAnimation(
*this, Metrics().GetVisualScrollOffset(), initialVelocity,
aDestination.mPosition,
StaticPrefs::layout_css_scroll_behavior_spring_constant(),
StaticPrefs::layout_css_scroll_behavior_damping_ratio(),
std::move(aDestination.mTargetIds), aTriggeredByScript));
// If no scroll is required, we should exit early to avoid triggering
// a scrollend event when no scrolling occurred.
if (ConvertDestinationToDelta(aDestination.mPosition) == ParentLayerPoint()) {
return;
}
CancelAnimation();
SetState(SMOOTHMSD_SCROLL);
// Convert velocity from ParentLayerPoints/ms to ParentLayerPoints/s.
CSSPoint initialVelocity;
if (Metrics().GetZoom() != CSSToParentLayerScale(0)) {
initialVelocity = ParentLayerPoint(mX.GetVelocity() * 1000.0f,
mY.GetVelocity() * 1000.0f) /
Metrics().GetZoom();
}

StartAnimation(new SmoothMsdScrollAnimation(
*this, Metrics().GetVisualScrollOffset(), initialVelocity,
aDestination.mPosition,
StaticPrefs::layout_css_scroll_behavior_spring_constant(),
StaticPrefs::layout_css_scroll_behavior_damping_ratio(),
std::move(aDestination.mTargetIds), aTriggeredByScript));
}

void AsyncPanZoomController::StartOverscrollAnimation(
Expand Down
2 changes: 2 additions & 0 deletions gfx/layers/apz/src/AsyncPanZoomController.h
Original file line number Diff line number Diff line change
Expand Up @@ -1604,6 +1604,8 @@ class AsyncPanZoomController {
ScrollTriggeredByScript aTriggeredByScript,
const ScrollOrigin& aOrigin);

ParentLayerPoint ConvertDestinationToDelta(CSSPoint& aDestination) const;

// Start a smooth-scrolling animation to the given destination, with MSD
// physics that is suited for scroll-snapping.
void SmoothMsdScrollTo(CSSSnapDestination&& aDestination,
Expand Down

0 comments on commit a19fdc4

Please sign in to comment.