0

Remove impulse scroll animation curve and WSP feature

The CL removes remaining references to Windows Scrolling Personality
features - percent-based scrolling and impulse scroll animation.

I reverted the WSP-related changes to track-scroll.html web test made
in the CL [1]. The test fails on Mac due to the bug: crbug.com/40701909,
so I temporarily disabled it.

[1] https://chromium-review.googlesource.com/c/chromium/src/+/2612518

Bug: 359747082
Change-Id: I1efd57bcd12a375c5d6d5add8e315037b0502e6a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6040435
Reviewed-by: Peter Boström <pbos@chromium.org>
Reviewed-by: Robert Flack <flackr@chromium.org>
Commit-Queue: Yaroslav Shalivskyy <yshalivskyy@microsoft.com>
Reviewed-by: Olga Gerchikov <gerchiko@microsoft.com>
Cr-Commit-Position: refs/heads/main@{#1388551}
This commit is contained in:
Yaroslav Shalivskyy
2024-11-27 00:17:50 +00:00
committed by Chromium LUCI CQ
parent b235758e9a
commit 890cc838a0
17 changed files with 45 additions and 354 deletions

@ -6,7 +6,6 @@
#include <algorithm>
#include <cmath>
#include <ostream>
#include <utility>
#include "base/check_op.h"
@ -40,14 +39,6 @@ namespace cc {
namespace {
constexpr double kImpulseCurveX1 = 0.25;
constexpr double kImpulseCurveX2 = 0.0;
constexpr double kImpulseCurveY2 = 1.0;
constexpr double kImpulseMinDurationMs = 200.0;
constexpr double kImpulseMaxDurationMs = 500.0;
constexpr double kImpulseMillisecondsPerPixel = 1.5;
const double kEpsilon = 0.01f;
static float MaximumDimension(const gfx::Vector2dF& delta) {
@ -65,45 +56,6 @@ static std::unique_ptr<TimingFunction> EaseInOutWithInitialSlope(double slope) {
return CubicBezierTimingFunction::Create(x1, y1, 0.58, 1);
}
std::unique_ptr<TimingFunction> ImpulseCurveWithInitialSlope(double slope) {
DCHECK_GE(slope, 0);
double x1 = kImpulseCurveX1;
double y1 = 1.0;
if (x1 * slope < 1.0) {
y1 = x1 * slope;
} else {
x1 = y1 / slope;
}
const double x2 = kImpulseCurveX2;
const double y2 = kImpulseCurveY2;
return CubicBezierTimingFunction::Create(x1, y1, x2, y2);
}
bool IsNewTargetInOppositeDirection(const gfx::PointF& current_position,
const gfx::PointF& old_target,
const gfx::PointF& new_target) {
gfx::Vector2dF old_delta = old_target - current_position;
gfx::Vector2dF new_delta = new_target - current_position;
// We only declare the new target to be in the "opposite" direction when
// one of the dimensions doesn't change at all. This may sound a bit strange,
// but it avoids lots of issues.
// For instance, if we are moving to the down & right and we are updated to
// move down & left, then are we moving in the opposite direction? If we don't
// do the check this way, then it would be considered in the opposite
// direction and the velocity gets set to 0. The update would therefore look
// pretty janky.
if (std::abs(old_delta.x() - new_delta.x()) < kEpsilon) {
return (old_delta.y() >= 0.0f) != (new_delta.y() >= 0.0f);
} else if (std::abs(old_delta.y() - new_delta.y()) < kEpsilon) {
return (old_delta.x() >= 0.0f) != (new_delta.x() >= 0.0f);
} else {
return false;
}
}
base::TimeDelta VelocityBasedDurationBound(gfx::Vector2dF old_delta,
double velocity,
gfx::Vector2dF new_delta) {
@ -149,9 +101,6 @@ ScrollOffsetAnimationCurve::ScrollOffsetAnimationCurve(
case AnimationType::kLinear:
timing_function_ = LinearTimingFunction::Create();
break;
case AnimationType::kImpulse:
timing_function_ = ImpulseCurveWithInitialSlope(0);
break;
}
}
@ -233,8 +182,6 @@ base::TimeDelta ScrollOffsetAnimationCurve::SegmentDuration(
case AnimationType::kLinear:
DCHECK(velocity.has_value());
return LinearSegmentDuration(delta, delayed_by, velocity.value());
case AnimationType::kImpulse:
return ImpulseSegmentDuration(delta, delayed_by);
}
}
@ -254,25 +201,6 @@ base::TimeDelta ScrollOffsetAnimationCurve::LinearSegmentDuration(
: base::TimeDelta();
}
// static
base::TimeDelta ScrollOffsetAnimationCurve::ImpulseSegmentDuration(
const gfx::Vector2dF& delta,
base::TimeDelta delayed_by) {
base::TimeDelta duration;
if (animation_duration_for_testing_.has_value()) {
duration = base::Seconds(animation_duration_for_testing_.value());
} else {
double duration_in_milliseconds =
kImpulseMillisecondsPerPixel * std::abs(MaximumDimension(delta));
duration_in_milliseconds = std::clamp(
duration_in_milliseconds, kImpulseMinDurationMs, kImpulseMaxDurationMs);
duration = base::Milliseconds(duration_in_milliseconds);
}
duration -= delayed_by;
return (duration >= base::TimeDelta()) ? duration : base::TimeDelta();
}
void ScrollOffsetAnimationCurve::SetInitialValue(
const gfx::PointF& initial_value,
base::TimeDelta delayed_by,
@ -418,9 +346,7 @@ void ScrollOffsetAnimationCurve::UpdateTarget(base::TimeDelta t,
}
const base::TimeDelta new_duration =
(animation_type_ == AnimationType::kEaseInOut)
? EaseInOutBoundedSegmentDuration(new_delta, t, delayed_by)
: ImpulseSegmentDuration(new_delta, delayed_by);
EaseInOutBoundedSegmentDuration(new_delta, t, delayed_by);
if (new_duration.InSecondsF() < kEpsilon) {
// The duration is (close to) 0, so stop the animation.
target_value_ = new_target;
@ -434,19 +360,7 @@ void ScrollOffsetAnimationCurve::UpdateTarget(base::TimeDelta t,
double new_slope =
velocity * (new_duration.InSecondsF() / MaximumDimension(new_delta));
if (animation_type_ == AnimationType::kEaseInOut) {
timing_function_ = EaseInOutWithInitialSlope(new_slope);
} else {
DCHECK_EQ(animation_type_, AnimationType::kImpulse);
if (IsNewTargetInOppositeDirection(current_position, target_value_,
new_target)) {
// Prevent any rubber-banding by setting the velocity (and subsequently,
// the slope) to 0 when moving in the opposite direciton.
new_slope = 0;
}
timing_function_ = ImpulseCurveWithInitialSlope(new_slope);
}
timing_function_ = EaseInOutWithInitialSlope(new_slope);
initial_value_ = current_position;
target_value_ = new_target;
total_animation_duration_ = t + new_duration;

@ -8,7 +8,6 @@
#include <memory>
#include <optional>
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/time/time.h"
#include "cc/animation/animation_export.h"
@ -65,7 +64,7 @@ class CC_ANIMATION_EXPORT ScrollOffsetAnimationCurve
// here. This delay is represented by the |delayed_by| value. The way we have
// decided to factor this in is by reducing the duration of the resulting
// animation by this delayed amount. This also applies to
// LinearSegmentDuration and ImpulseSegmentDuration.
// LinearSegmentDuration.
static base::TimeDelta EaseInOutSegmentDuration(
const gfx::Vector2dF& delta,
DurationBehavior duration_behavior,
@ -75,9 +74,6 @@ class CC_ANIMATION_EXPORT ScrollOffsetAnimationCurve
base::TimeDelta delayed_by,
float velocity);
static base::TimeDelta ImpulseSegmentDuration(const gfx::Vector2dF& delta,
base::TimeDelta delayed_by);
ScrollOffsetAnimationCurve(const ScrollOffsetAnimationCurve&) = delete;
~ScrollOffsetAnimationCurve() override;
@ -120,7 +116,7 @@ class CC_ANIMATION_EXPORT ScrollOffsetAnimationCurve
private:
friend class ScrollOffsetAnimationCurveFactory;
enum class AnimationType { kLinear, kEaseInOut, kImpulse };
enum class AnimationType { kLinear, kEaseInOut };
// |duration_behavior| should be provided if (and only if) |animation_type| is
// kEaseInOut.

@ -6,8 +6,6 @@
#include "base/memory/ptr_util.h"
#include "base/notreached.h"
#include "cc/base/features.h"
#include "ui/gfx/animation/keyframe/timing_function.h"
namespace cc {
namespace {
@ -31,11 +29,9 @@ std::unique_ptr<ScrollOffsetAnimationCurve>
ScrollOffsetAnimationCurveFactory::CreateAnimation(
const gfx::PointF& target_value,
ScrollType scroll_type) {
if (scroll_type == ScrollType::kAutoScroll)
if (scroll_type == ScrollType::kAutoScroll) {
return CreateLinearAnimation(target_value);
if (features::IsImpulseScrollAnimationEnabled())
return CreateImpulseAnimation(target_value);
}
return CreateEaseInOutAnimation(
target_value, GetDurationBehaviorFromScrollType(scroll_type));
@ -56,13 +52,6 @@ ScrollOffsetAnimationCurveFactory::CreateLinearAnimationForTesting(
return CreateLinearAnimation(target_value);
}
// static
std::unique_ptr<ScrollOffsetAnimationCurve>
ScrollOffsetAnimationCurveFactory::CreateImpulseAnimationForTesting(
const gfx::PointF& target_value) {
return CreateImpulseAnimation(target_value);
}
// static
std::unique_ptr<ScrollOffsetAnimationCurve>
ScrollOffsetAnimationCurveFactory::CreateEaseInOutAnimation(
@ -81,11 +70,4 @@ ScrollOffsetAnimationCurveFactory::CreateLinearAnimation(
target_value, ScrollOffsetAnimationCurve::AnimationType::kLinear));
}
// static
std::unique_ptr<ScrollOffsetAnimationCurve>
ScrollOffsetAnimationCurveFactory::CreateImpulseAnimation(
const gfx::PointF& target_value) {
return base::WrapUnique(new ScrollOffsetAnimationCurve(
target_value, ScrollOffsetAnimationCurve::AnimationType::kImpulse));
}
} // namespace cc

@ -27,9 +27,6 @@ class CC_ANIMATION_EXPORT ScrollOffsetAnimationCurveFactory {
static std::unique_ptr<ScrollOffsetAnimationCurve>
CreateLinearAnimationForTesting(const gfx::PointF& target_value);
static std::unique_ptr<ScrollOffsetAnimationCurve>
CreateImpulseAnimationForTesting(const gfx::PointF& target_value);
private:
static std::unique_ptr<ScrollOffsetAnimationCurve> CreateEaseInOutAnimation(
const gfx::PointF& target_value,
@ -37,9 +34,6 @@ class CC_ANIMATION_EXPORT ScrollOffsetAnimationCurveFactory {
static std::unique_ptr<ScrollOffsetAnimationCurve> CreateLinearAnimation(
const gfx::PointF& target_value);
static std::unique_ptr<ScrollOffsetAnimationCurve> CreateImpulseAnimation(
const gfx::PointF& target_value);
};
} // namespace cc

@ -7,7 +7,6 @@
#include "base/time/time.h"
#include "cc/animation/scroll_offset_animation_curve_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/animation/keyframe/timing_function.h"
#include "ui/gfx/geometry/test/geometry_util.h"
using DurationBehavior = cc::ScrollOffsetAnimationCurve::DurationBehavior;
@ -17,12 +16,6 @@ const double kDurationDivisor = 60.0;
const double kInverseDeltaMaxDuration = 12.0;
namespace cc {
namespace {
// This is the value of the default Impulse bezier curve when t = 0.5
constexpr double halfway_through_default_impulse_curve = 0.874246;
} // namespace
TEST(ScrollOffsetAnimationCurveTest, DeltaBasedDuration) {
gfx::PointF target_value(100.f, 200.f);
@ -156,103 +149,6 @@ TEST(ScrollOffsetAnimationCurveTest, EaseInOutUpdateTarget) {
0.0002f);
}
TEST(ScrollOffsetAnimationCurveTest, ImpulseUpdateTarget) {
gfx::PointF initial_value(0.f, 0.f);
gfx::PointF initial_target_value(0.f, 3600.f);
gfx::Vector2dF initial_delta = initial_target_value - initial_value;
std::unique_ptr<ScrollOffsetAnimationCurve> curve(
ScrollOffsetAnimationCurveFactory::CreateImpulseAnimationForTesting(
initial_target_value));
curve->SetInitialValue(initial_value);
base::TimeDelta initial_duration =
ScrollOffsetAnimationCurve::ImpulseSegmentDuration(initial_delta,
base::TimeDelta());
EXPECT_NEAR(initial_duration.InSecondsF(), curve->Duration().InSecondsF(),
0.0002f);
EXPECT_NEAR(initial_delta.y() * halfway_through_default_impulse_curve,
curve->GetValue(initial_duration / 2).y(), 0.01f);
EXPECT_NEAR(initial_delta.y(), curve->GetValue(initial_duration).y(),
0.0002f);
base::TimeDelta time_of_update = initial_duration / 2;
gfx::PointF distance_halfway_through_initial_animation =
curve->GetValue(time_of_update);
gfx::PointF new_target_value(0.f, 9900.f);
curve->UpdateTarget(time_of_update, new_target_value);
gfx::Vector2dF new_delta =
new_target_value - distance_halfway_through_initial_animation;
base::TimeDelta updated_segment_duration =
ScrollOffsetAnimationCurve::ImpulseSegmentDuration(new_delta,
base::TimeDelta());
base::TimeDelta overall_duration = time_of_update + updated_segment_duration;
EXPECT_NEAR(overall_duration.InSecondsF(), curve->Duration().InSecondsF(),
0.0002f);
EXPECT_NEAR(distance_halfway_through_initial_animation.y(),
curve->GetValue(time_of_update).y(), 0.01f);
EXPECT_NEAR(new_target_value.y(), curve->GetValue(overall_duration).y(),
0.0002f);
// Ensure that UpdateTarget increases the initial slope of the generated curve
// (for velocity matching). To test this, we check if the value is greater
// than the default value would be half way through.
// Also - to ensure it isn't passing just due to floating point imprecision,
// some epsilon is added to the default amount.
EXPECT_LT(
new_delta.y() * halfway_through_default_impulse_curve + 0.01f,
curve->GetValue(time_of_update + (updated_segment_duration / 2)).y());
}
TEST(ScrollOffsetAnimationCurveTest, ImpulseUpdateTargetSwitchDirections) {
gfx::PointF initial_value(0.f, 0.f);
gfx::PointF initial_target_value(0.f, 200.f);
double initial_duration =
ScrollOffsetAnimationCurve::ImpulseSegmentDuration(
initial_target_value.OffsetFromOrigin(), base::TimeDelta())
.InSecondsF();
std::unique_ptr<ScrollOffsetAnimationCurve> curve(
ScrollOffsetAnimationCurveFactory::CreateImpulseAnimationForTesting(
initial_target_value));
curve->SetInitialValue(initial_value);
EXPECT_NEAR(initial_duration, curve->Duration().InSecondsF(), 0.0002f);
EXPECT_NEAR(initial_target_value.y() * halfway_through_default_impulse_curve,
curve->GetValue(base::Seconds(initial_duration / 2.0)).y(),
0.01f);
// Animate back to 0. This should force the new curve's initial velocity to be
// 0, so the default curve will be generated.
gfx::PointF updated_initial_value(
0, initial_target_value.y() * halfway_through_default_impulse_curve);
gfx::PointF updated_target(0.f, 0.f);
curve->UpdateTarget(base::Seconds(initial_duration / 2), updated_target);
EXPECT_NEAR(initial_target_value.y() * halfway_through_default_impulse_curve,
curve->GetValue(base::Seconds(initial_duration / 2.0)).y(),
0.01f);
double updated_duration =
ScrollOffsetAnimationCurve::ImpulseSegmentDuration(
gfx::Vector2dF(updated_initial_value.x(), updated_initial_value.y()),
base::TimeDelta())
.InSecondsF();
EXPECT_NEAR(
updated_initial_value.y() * (1.0 - halfway_through_default_impulse_curve),
curve
->GetValue(
base::Seconds(initial_duration / 2.0 + updated_duration / 2.0))
.y(),
0.01f);
EXPECT_NEAR(
0.0,
curve->GetValue(base::Seconds(initial_duration / 2.0 + updated_duration))
.y(),
0.0002f);
}
TEST(ScrollOffsetAnimationCurveTest, InverseDeltaDuration) {
std::unique_ptr<ScrollOffsetAnimationCurve> curve(
ScrollOffsetAnimationCurveFactory::CreateEaseInOutAnimationForTesting(
@ -300,27 +196,6 @@ TEST(ScrollOffsetAnimationCurveTest, LinearAnimation) {
EXPECT_FLOAT_EQ(0.f, curve->Duration().InSecondsF());
}
TEST(ScrollOffsetAnimationCurveTest, ImpulseDuration) {
// The duration of an impulse-style curve in milliseconds is simply 1.5x the
// scroll distance in physical pixels, with a minimum of 200ms and a maximum
// of 500ms.
gfx::Vector2dF small_delta(0.f, 100.f);
gfx::Vector2dF moderate_delta(0.f, 250.f);
gfx::Vector2dF large_delta(0.f, 400.f);
base::TimeDelta duration = ScrollOffsetAnimationCurve::ImpulseSegmentDuration(
small_delta, base::TimeDelta());
EXPECT_FLOAT_EQ(duration.InMillisecondsF(), 200.f);
duration = ScrollOffsetAnimationCurve::ImpulseSegmentDuration(
moderate_delta, base::TimeDelta());
EXPECT_NEAR(duration.InMillisecondsF(), moderate_delta.y() * 1.5f, 0.0002f);
duration = ScrollOffsetAnimationCurve::ImpulseSegmentDuration(
large_delta, base::TimeDelta());
EXPECT_FLOAT_EQ(duration.InMillisecondsF(), 500.f);
}
TEST(ScrollOffsetAnimationCurveTest, CurveWithDelay) {
std::unique_ptr<ScrollOffsetAnimationCurve> curve(
ScrollOffsetAnimationCurveFactory::CreateEaseInOutAnimationForTesting(

@ -8,7 +8,6 @@
#include "base/feature_list.h"
#include "build/build_config.h"
#include "ui/base/ui_base_features.h"
namespace features {
@ -31,11 +30,6 @@ BASE_FEATURE(kAnimatedImageResume,
"AnimatedImageResume",
base::FEATURE_DISABLED_BY_DEFAULT);
// The feature is deprecated. The code removal is tracked in crbug.com/359747082
bool IsImpulseScrollAnimationEnabled() {
return false;
}
// Whether the compositor should attempt to sync with the scroll handlers before
// submitting a frame.
BASE_FEATURE(kSynchronizedScrolling,

@ -16,7 +16,6 @@ namespace features {
CC_BASE_EXPORT BASE_DECLARE_FEATURE(kAlignSurfaceLayerImplToPixelGrid);
CC_BASE_EXPORT BASE_DECLARE_FEATURE(kAnimatedImageResume);
CC_BASE_EXPORT extern bool IsImpulseScrollAnimationEnabled();
CC_BASE_EXPORT BASE_DECLARE_FEATURE(kSynchronizedScrolling);
// Sets raster tree priority to NEW_CONTENT_TAKES_PRIORITY when performing a

@ -2943,11 +2943,8 @@ TEST_P(LayerTreeHostImplTest, SnapAnimationTargetUpdated) {
EXPECT_FALSE(
GetInputHandler().animating_for_snap_for_testing(overflow->element_id()));
// Finish the smooth scroll animation for wheel.
const int scroll_animation_duration_ms =
features::IsImpulseScrollAnimationEnabled() ? 300 : 150;
BeginImplFrameAndAnimate(
begin_frame_args,
start_time + base::Milliseconds(scroll_animation_duration_ms));
BeginImplFrameAndAnimate(begin_frame_args,
start_time + base::Milliseconds(150));
// At the end of the previous scroll animation, a new animation for the
// snapping should have started.
@ -15215,13 +15212,7 @@ TEST_P(LayerTreeHostImplTest, AnimatedScrollUpdateTargetBeforeStarting) {
// Verify no jump.
float y = CurrentScrollOffset(scrolling_layer).y();
if (features::IsImpulseScrollAnimationEnabled()) {
// Impulse scroll animation is faster than non-impulse, which results in a
// traveled distance larger than the original 50px.
EXPECT_TRUE(y > 50 && y < 100);
} else {
EXPECT_TRUE(y > 1 && y < 49);
}
EXPECT_TRUE(y > 1 && y < 49);
}
TEST_P(LayerTreeHostImplTest, ScrollAnimatedWithDelay) {
@ -15268,8 +15259,7 @@ TEST_P(LayerTreeHostImplTest, ScrollAnimatedWithDelay) {
begin_frame_args.frame_id.sequence_number++;
host_impl_->WillBeginImplFrame(begin_frame_args);
host_impl_->UpdateAnimationState(true);
EXPECT_NEAR((features::IsImpulseScrollAnimationEnabled() ? 87 : 50),
CurrentScrollOffset(scrolling_layer).y(), 1);
EXPECT_EQ(50, CurrentScrollOffset(scrolling_layer).y());
host_impl_->DidFinishImplFrame(begin_frame_args);
// Update target.

@ -9492,11 +9492,6 @@
"owners": [ "jiajunz@google.com", "cros-device-enablement@google.com" ],
"expiry_milestone": 135
},
{
"name": "windows-scrolling-personality",
"owners": [ "arakeri@microsoft.com", "gastonr@microsoft.com" ],
"expiry_milestone": 150
},
{
"name": "windows11-mica-titlebar",
"owners": [ "j@jloeffler.com", "pkasting@chromium.org" ],

@ -3,7 +3,6 @@
// found in the LICENSE file.
#include "base/test/scoped_feature_list.h"
#include "cc/base/features.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/features_generated.h"
#include "third_party/blink/public/mojom/frame/find_in_page.mojom-blink.h"
@ -256,8 +255,7 @@ TEST_P(ScrollIntoViewTest, SmoothScroll) {
Compositor().BeginFrame(); // update run_state_.
Compositor().BeginFrame(); // Set start_time = now.
Compositor().BeginFrame(0.2);
ASSERT_NEAR(Window().scrollY(),
(::features::IsImpulseScrollAnimationEnabled() ? 800 : 299), 1);
ASSERT_NEAR(Window().scrollY(), 299, 1);
// Finish scrolling the container
Compositor().BeginFrame(1);
@ -294,13 +292,11 @@ TEST_P(ScrollIntoViewTest, NestedContainer) {
Compositor().BeginFrame(); // update run_state_.
Compositor().BeginFrame(); // Set start_time = now.
Compositor().BeginFrame(0.2);
ASSERT_NEAR(Window().scrollY(),
(::features::IsImpulseScrollAnimationEnabled() ? 800 : 299), 1);
ASSERT_NEAR(Window().scrollY(), 299, 1);
if (RuntimeEnabledFeatures::MultiSmoothScrollIntoViewEnabled()) {
// If MultiSmoothScrollIntoView is enabled, the frames will also scroll the
// inner container.
ASSERT_NEAR(container->scrollTop(),
(::features::IsImpulseScrollAnimationEnabled() ? 800 : 299), 1);
ASSERT_NEAR(container->scrollTop(), 299, 1);
} else {
ASSERT_EQ(container->scrollTop(), 0);
}
@ -326,8 +322,7 @@ TEST_P(ScrollIntoViewTest, NestedContainer) {
// Scrolling the inner container
Compositor().BeginFrame(); // Set start_time = now.
Compositor().BeginFrame(0.2);
ASSERT_NEAR(container->scrollTop(),
(::features::IsImpulseScrollAnimationEnabled() ? 794 : 299), 1);
ASSERT_NEAR(container->scrollTop(), 299, 1);
// Finish scrolling the inner container
Compositor().BeginFrame(1);
@ -373,13 +368,11 @@ TEST_P(ScrollIntoViewTest, NewScrollIntoViewAbortsCurrentAnimation) {
Compositor().BeginFrame(); // update run_state_.
Compositor().BeginFrame(); // Set start_time = now.
Compositor().BeginFrame(0.2);
ASSERT_NEAR(Window().scrollY(),
(::features::IsImpulseScrollAnimationEnabled() ? 800 : 299), 1);
ASSERT_NEAR(Window().scrollY(), 299, 1);
if (RuntimeEnabledFeatures::MultiSmoothScrollIntoViewEnabled()) {
// If MultiSmoothScrollIntoView is enabled, the frames will also scroll
// container1.
ASSERT_NEAR(container1->scrollTop(),
(::features::IsImpulseScrollAnimationEnabled() ? 800 : 299), 1);
ASSERT_NEAR(container1->scrollTop(), 299, 1);
} else {
ASSERT_EQ(container1->scrollTop(), 0);
}
@ -388,13 +381,11 @@ TEST_P(ScrollIntoViewTest, NewScrollIntoViewAbortsCurrentAnimation) {
Compositor().BeginFrame(); // update run_state_.
Compositor().BeginFrame(); // Set start_time = now.
Compositor().BeginFrame(0.2);
ASSERT_NEAR(Window().scrollY(),
(::features::IsImpulseScrollAnimationEnabled() ? 171 : 61), 1);
ASSERT_NEAR(Window().scrollY(), 61, 1);
if (RuntimeEnabledFeatures::MultiSmoothScrollIntoViewEnabled()) {
// If MultiSmoothScrollIntoView is enabled, the new scrollIntoView does not
// cancel the first scrollIntoView so the scroll on container1 continues.
ASSERT_GT(container1->scrollTop(),
(::features::IsImpulseScrollAnimationEnabled() ? 800 : 299));
ASSERT_GT(container1->scrollTop(), 299);
} else {
ASSERT_EQ(container1->scrollTop(), 0); // container1 should not scroll.
}
@ -419,8 +410,7 @@ TEST_P(ScrollIntoViewTest, NewScrollIntoViewAbortsCurrentAnimation) {
// Scrolling content2 in container2
Compositor().BeginFrame(); // Set start_time = now.
Compositor().BeginFrame(0.2);
ASSERT_NEAR(container2->scrollTop(),
(::features::IsImpulseScrollAnimationEnabled() ? 952 : 300), 1);
ASSERT_NEAR(container2->scrollTop(), 300, 1);
// Finish all the animation to make sure there is no another animation queued
// on container1.
@ -474,11 +464,9 @@ TEST_P(ScrollIntoViewTest, NoOpScrollIntoViewContinuesCurrentAnimation) {
Compositor().BeginFrame(); // update run_state_.
Compositor().BeginFrame(); // Set start_time = now.
Compositor().BeginFrame(0.2);
ASSERT_NEAR(Window().scrollY(),
(::features::IsImpulseScrollAnimationEnabled() ? 250 : 241), 1);
ASSERT_NEAR(Window().scrollY(), 241, 1);
if (RuntimeEnabledFeatures::MultiSmoothScrollIntoViewEnabled()) {
ASSERT_NEAR(container->scrollTop(),
(::features::IsImpulseScrollAnimationEnabled() ? 800 : 299), 1);
ASSERT_NEAR(container->scrollTop(), 299, 1);
} else {
ASSERT_EQ(container->scrollTop(), 0);
}
@ -497,11 +485,9 @@ TEST_P(ScrollIntoViewTest, NoOpScrollIntoViewContinuesCurrentAnimation) {
// The window animation should continue running but the container shouldn't
// yet have started unless MultiSmoothScrollIntoView support is enabled.
Compositor().BeginFrame();
ASSERT_NEAR(Window().scrollY(),
(::features::IsImpulseScrollAnimationEnabled() ? 258 : 260), 1);
ASSERT_NEAR(Window().scrollY(), 260, 1);
if (RuntimeEnabledFeatures::MultiSmoothScrollIntoViewEnabled()) {
ASSERT_GT(container->scrollTop(),
(::features::IsImpulseScrollAnimationEnabled() ? 800 : 299));
ASSERT_GT(container->scrollTop(), 299);
} else {
// container should not have scrolled yet.
ASSERT_EQ(container->scrollTop(), 0);
@ -546,11 +532,9 @@ TEST_P(ScrollIntoViewTest, ScrollWindowAbortsCurrentAnimation) {
Compositor().BeginFrame(); // update run_state_.
Compositor().BeginFrame(); // Set start_time = now.
Compositor().BeginFrame(0.2);
ASSERT_NEAR(Window().scrollY(),
(::features::IsImpulseScrollAnimationEnabled() ? 800 : 299), 1);
ASSERT_NEAR(Window().scrollY(), 299, 1);
if (RuntimeEnabledFeatures::MultiSmoothScrollIntoViewEnabled()) {
ASSERT_NEAR(container->scrollTop(),
(::features::IsImpulseScrollAnimationEnabled() ? 800 : 299), 1);
ASSERT_NEAR(container->scrollTop(), 299, 1);
} else {
ASSERT_EQ(container->scrollTop(), 0);
}
@ -563,8 +547,7 @@ TEST_P(ScrollIntoViewTest, ScrollWindowAbortsCurrentAnimation) {
Compositor().BeginFrame(); // update run_state_.
Compositor().BeginFrame(); // Set start_time = now.
Compositor().BeginFrame(0.2);
ASSERT_NEAR(Window().scrollY(),
(::features::IsImpulseScrollAnimationEnabled() ? 165 : 58), 1);
ASSERT_NEAR(Window().scrollY(), 58, 1);
Compositor().BeginFrame(1);
ASSERT_EQ(Window().scrollY(), 0);
@ -679,8 +662,7 @@ TEST_P(ScrollIntoViewTest, SmoothAndInstantInChain) {
Compositor().BeginFrame(); // update run_state_.
Compositor().BeginFrame(); // Set start_time = now.
Compositor().BeginFrame(0.2);
ASSERT_NEAR(container->scrollTop(),
(::features::IsImpulseScrollAnimationEnabled() ? 794 : 299), 1);
ASSERT_NEAR(container->scrollTop(), 299, 1);
// Finish scrolling the container
Compositor().BeginFrame(1);
@ -714,8 +696,7 @@ TEST_P(ScrollIntoViewTest, SmoothScrollAnchor) {
Compositor().BeginFrame(); // update run_state_.
Compositor().BeginFrame(); // Set start_time = now.
Compositor().BeginFrame(0.2);
ASSERT_NEAR(container->scrollTop(),
(::features::IsImpulseScrollAnimationEnabled() ? 794 : 299), 1);
ASSERT_NEAR(container->scrollTop(), 299, 1);
// Finish scrolling the container
Compositor().BeginFrame(1);
@ -770,8 +751,7 @@ TEST_P(ScrollIntoViewTest, ApplyRootElementScrollBehaviorToViewport) {
Compositor().BeginFrame(); // update run_state_.
Compositor().BeginFrame(); // Set start_time = now.
Compositor().BeginFrame(0.2);
ASSERT_NEAR(Window().scrollY(),
(::features::IsImpulseScrollAnimationEnabled() ? 800 : 299), 1);
ASSERT_NEAR(Window().scrollY(), 299, 1);
// Finish scrolling the container
Compositor().BeginFrame(1);
@ -963,8 +943,7 @@ TEST_P(ScrollIntoViewTest, SmoothUserScrollNotAbortedByProgrammaticScrolls) {
Compositor().BeginFrame(); // update run_state_.
Compositor().BeginFrame(); // Set start_time = now.
Compositor().BeginFrame(0.2);
ASSERT_NEAR(Window().scrollY(),
(::features::IsImpulseScrollAnimationEnabled() ? 800 : 299), 1);
ASSERT_NEAR(Window().scrollY(), 299, 1);
// ProgrammaticScroll that could interrupt the current smooth scroll.
Window().scrollTo(0, 0);
@ -1000,9 +979,7 @@ TEST_P(ScrollIntoViewTest, LongDistanceSmoothScrollFinishedInThreeSeconds) {
Compositor().BeginFrame(); // update run_state_.
Compositor().BeginFrame(); // Set start_time = now.
Compositor().BeginFrame(0.2);
ASSERT_NEAR(Window().scrollY(),
(::features::IsImpulseScrollAnimationEnabled() ? 79389 : 16971),
1);
ASSERT_NEAR(Window().scrollY(), 16971, 1);
// Finish scrolling the container
Compositor().BeginFrame(0.5);

@ -35,7 +35,6 @@
#include "base/time/time.h"
#include "build/build_config.h"
#include "cc/animation/scroll_offset_animation_curve.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/scroll/scroll_animator_base.h"
#include "third_party/blink/renderer/platform/animation/compositor_animation_client.h"

@ -5,7 +5,6 @@
#include "third_party/blink/renderer/core/scroll/scroll_animator.h"
#include "base/test/bind.h"
#include "cc/base/features.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/web/web_script_source.h"
#include "third_party/blink/renderer/core/css/css_style_declaration.h"
@ -32,9 +31,7 @@
namespace blink {
namespace {
double ScrollAnimationDuration() {
return ::features::IsImpulseScrollAnimationEnabled() ? 1.5 : 0.5;
}
constexpr double kScrollAnimationDuration = 0.5;
} // namespace
class FractionalScrollSimTest : public SimTest, public PaintTestConfigurations {
@ -244,7 +241,7 @@ TEST_P(ScrollAnimatorSimTest, TestRootFrameLayoutViewportUserScrollCallBack) {
// The callback is executed when the animation finishes at
// ScrollAnimator::TickAnimation.
Compositor().BeginFrame();
Compositor().BeginFrame(ScrollAnimationDuration());
Compositor().BeginFrame(kScrollAnimationDuration);
ASSERT_TRUE(finished);
}
@ -288,7 +285,7 @@ TEST_P(ScrollAnimatorSimTest, TestRootFrameVisualViewporUserScrollCallBack) {
// The callback is executed when the animation finishes at
// ScrollAnimator::TickAnimation.
Compositor().BeginFrame();
Compositor().BeginFrame(ScrollAnimationDuration());
Compositor().BeginFrame(kScrollAnimationDuration);
ASSERT_TRUE(finished);
}
@ -332,7 +329,7 @@ TEST_P(ScrollAnimatorSimTest, TestRootFrameBothViewportsUserScrollCallBack) {
// The callback is executed when the animation finishes at
// ScrollAnimator::TickAnimation.
Compositor().BeginFrame();
Compositor().BeginFrame(ScrollAnimationDuration());
Compositor().BeginFrame(kScrollAnimationDuration);
ASSERT_TRUE(finished);
}
@ -382,7 +379,7 @@ TEST_P(ScrollAnimatorSimTest, TestDivUserScrollCallBack) {
// The callback is executed when the animation finishes at
// ScrollAnimator::TickAnimation.
Compositor().BeginFrame(ScrollAnimationDuration());
Compositor().BeginFrame(kScrollAnimationDuration);
ASSERT_TRUE(finished);
}

@ -5835,6 +5835,8 @@ crbug.com/1309756 [ Mac12-arm64 Release ] http/tests/images/force-reload.html [
crbug.com/1311431 [ Debug Mac13-arm64 ] fast/scroll-behavior/overscroll-behavior.html [ Failure Pass ]
crbug.com/1311431 [ Mac Release ] fast/scroll-behavior/overscroll-behavior.html [ Failure Pass ]
crbug.com/40701909 [ Mac ] fast/scroll-behavior/smooth-scroll/track-scroll.html [ Failure ]
# These tests fail on SwiftShader FEMU due to a change in log/exp implementation.
crbug.com/1311456 [ Fuchsia ] fast/css3-text/css3-text-decoration/text-decoration-style-inherit.html [ Crash Failure Pass Timeout ]
crbug.com/1311456 [ Fuchsia ] tables/mozilla/core/bloomberg.html [ Crash Failure Pass Timeout ]

@ -10,8 +10,12 @@ body {
<script>
// Compute ScrollableArea::pageStep.
var pageStep = innerHeight * 0.875;
if (navigator.userAgent.indexOf("Mac OS X") >= 0)
if (navigator.userAgent.indexOf("Mac OS X") >= 0) {
// TODO(crbug.com/40701909): the expectation is still broken on Mac since
// composited scrollbars implementation in ScrollbarController don't check
// for ScrollbarTheme::MaxOverlapBetweenPages() which is 40px on Mac.
pageStep = Math.max(pageStep, innerHeight - 40);
}
promise_test(async () => {
// Click in the vertical scrollbar track, below the thumb, and hold the
@ -21,20 +25,7 @@ body {
await mouseMoveTo(790, 280);
await mouseDownAt(790, 280);
// TODO(crbug.com/1172003): This needs to be fixed for track autoscrolls.
// Impulse based animations have a longer duration than the default ease
// in/out curve. So when an autoscroll animation is initiated (~250ms
// after the initial mousedown), the animation generated by the initial
// mousedown on the scrollbar track will need to be aborted by the
// cc::ScrollbarController (as the cc::KeyframeModel doesn't allow multiple
// sources animating the scroll offset). As a result, the thumb can be
// anywhere between 0 and pageStep. As long as the thumb doesn't cross the
// pointer location (i.e the offset at pageStep), this test is considered
// successful. (Note that this is not an issue while using the default ease
// in/out curve because the initial mousedown animation would've already
// finished by the time the autoscroll animation is being kicked off)
await waitForAnimationEndTimeBased( () => { return scrollY; } );
assert_true(window.scrollY > 0 && window.scrollY <= pageStep,
"window.scrollY = " + window.scrollY + " ");
assert_equals(window.scrollY, pageStep);
}, 'Scrollbar track autoscrolling doesn\'t overshoot cursor.');
</script>
</script>

@ -156,12 +156,6 @@ BASE_FEATURE(kInputMethodSettingsUiUpdate,
"InputMethodSettingsUiUpdate",
base::FEATURE_DISABLED_BY_DEFAULT);
// Enables percent-based scrolling for mousewheel and keyboard initiated
// scrolls and impulse curve animations.
BASE_FEATURE(kWindowsScrollingPersonality,
"WindowsScrollingPersonality",
base::FEATURE_DISABLED_BY_DEFAULT);
// Uses a stylus-specific tap slop region parameter for gestures. Stylus taps
// tend to slip more than touch taps (presumably because the user doesn't feel
// the movement friction with a stylus). As a result, it is harder to tap with

@ -22,9 +22,6 @@ BASE_DECLARE_FEATURE(kSettingsShowsPerKeyboardSettings);
#endif // BUILDFLAG(IS_CHROMEOS)
COMPONENT_EXPORT(UI_BASE_FEATURES)
BASE_DECLARE_FEATURE(kInputMethodSettingsUiUpdate);
COMPONENT_EXPORT(UI_BASE_FEATURES)
BASE_DECLARE_FEATURE(kWindowsScrollingPersonality);
COMPONENT_EXPORT(UI_BASE_FEATURES) bool IsPercentBasedScrollingEnabled();
COMPONENT_EXPORT(UI_BASE_FEATURES) BASE_DECLARE_FEATURE(kSystemCaptionStyle);
COMPONENT_EXPORT(UI_BASE_FEATURES) BASE_DECLARE_FEATURE(kSystemKeyboardLock);
COMPONENT_EXPORT(UI_BASE_FEATURES)

@ -12,10 +12,8 @@
#include <cstddef>
#include <cstdint>
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/ui_base_features.h"
#include "ui/events/base_event_utils.h"
#include "ui/events/blink/blink_event_util.h"
#include "ui/events/event.h"
@ -412,9 +410,6 @@ TEST(WebInputEventTest, KeyEvent) {
}
TEST(WebInputEventTest, WheelEvent) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndDisableFeature(
features::kWindowsScrollingPersonality);
const int kDeltaX = 14;
const int kDeltaY = -3;
ui::MouseWheelEvent ui_event(