Commit 5096aba5 authored by Sadrul Habib Chowdhury's avatar Sadrul Habib Chowdhury Committed by Commit Bot

[synthesized scroll] Fix precision of synthesized wheel scrolls.

Synthesized scrolls can generate fractional scroll-deltas. However, the
event-dispatch path converts the event into a ui::MouseWheelEvent object
and loses precision in the process, since it does not support fractional
scroll-deltas. Therefore, retain the dropped deltas and include that
with the subsequent wheel-event.

BUG=1085890

Change-Id: I797b04b48384b9f7c4bba44f48c2d1860dd7fc39
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2213296
Commit-Queue: Sadrul Chowdhury <sadrul@chromium.org>
Auto-Submit: Sadrul Chowdhury <sadrul@chromium.org>
Reviewed-by: default avatarDavid Bokan <bokan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#771638}
parent 13f2fef0
......@@ -90,10 +90,13 @@ void SyntheticGestureTargetAura::DispatchWebMouseWheelEventToPlatform(
modifiers |= ui::EF_SCROLL_BY_PAGE;
}
float delta_x = web_wheel.delta_x + wheel_precision_x_;
float delta_y = web_wheel.delta_y + wheel_precision_y_;
ui::MouseWheelEvent wheel_event(
gfx::Vector2d(web_wheel.delta_x, web_wheel.delta_y),
web_wheel.PositionInWidget(), web_wheel.PositionInWidget(), timestamp,
modifiers, ui::EF_NONE);
gfx::Vector2d(delta_x, delta_y), web_wheel.PositionInWidget(),
web_wheel.PositionInWidget(), timestamp, modifiers, ui::EF_NONE);
wheel_precision_x_ = delta_x - wheel_event.x_offset();
wheel_precision_y_ = delta_y - wheel_event.y_offset();
aura::Window* window = GetWindow();
wheel_event.ConvertLocationToTarget(window, window->GetRootWindow());
......
......@@ -58,6 +58,9 @@ class SyntheticGestureTargetAura : public SyntheticGestureTargetBase {
// before dispatching it into platform.
float device_scale_factor_;
float wheel_precision_x_ = 0.f;
float wheel_precision_y_ = 0.f;
aura::EventInjector event_injector_;
DISALLOW_COPY_AND_ASSIGN(SyntheticGestureTargetAura);
......
......@@ -6,6 +6,7 @@
#include "base/callback.h"
#include "base/run_loop.h"
#include "base/test/test_timeouts.h"
#include "build/build_config.h"
#include "cc/base/switches.h"
#include "content/browser/renderer_host/input/synthetic_gesture.h"
#include "content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h"
......@@ -133,7 +134,7 @@ IN_PROC_BROWSER_TEST_F(SyntheticInputTest, SmoothScrollWheel) {
// Use a speed that's fast enough that the entire scroll occurs in a single
// GSU, avoiding precision loss. SyntheticGestures can lose delta over time
// in slower scrolls.
// in slower scrolls on some platforms.
params.speed_in_pixels_s = 10000000.f;
// Use PrecisePixel to avoid animating.
......@@ -156,4 +157,59 @@ IN_PROC_BROWSER_TEST_F(SyntheticInputTest, SmoothScrollWheel) {
"document.scrollingElement.scrollTop"));
}
// Wheel events lose precision on android (crbug.com/934649)
#if defined(OS_ANDROID)
#define MAYBE_SlowSmoothScrollWheel DISABLED_SlowSmoothScrollWheel
#else
#define MAYBE_SlowSmoothScrollWheel SlowSmoothScrollWheel
#endif
// This test ensures that slow synthetic wheel scrolling does not lose precision
// over time.
IN_PROC_BROWSER_TEST_F(SyntheticInputTest, MAYBE_SlowSmoothScrollWheel) {
LoadURL(R"HTML(
data:text/html;charset=utf-8,
<!DOCTYPE html>
<meta name='viewport' content='width=device-width'>
<style>
body {
width: 10px;
height: 2000px;
}
</style>
<script>
document.title = 'ready';
</script>
)HTML");
SyntheticSmoothScrollGestureParams params;
params.gesture_source_type = SyntheticGestureParams::MOUSE_INPUT;
params.anchor = gfx::PointF(1, 1);
// Note: 1024 is precisely chosen since Android's minimum granularity is 64px.
// All other platforms can specify the delta per-pixel.
params.distances.push_back(gfx::Vector2d(0, -1024));
// Use a speed that's slow enough that it requires the browser to require
// multiple wheel-events to be dispatched, so that precision is needed to
// scroll the correct amount.
params.speed_in_pixels_s = 1000.f;
// Use PrecisePixel to avoid animating.
params.granularity = ui::ScrollGranularity::kScrollByPrecisePixel;
runner_ = std::make_unique<base::RunLoop>();
RenderFrameSubmissionObserver scroll_offset_wait(shell()->web_contents());
std::unique_ptr<SyntheticSmoothScrollGesture> gesture(
new SyntheticSmoothScrollGesture(params));
GetRenderWidgetHost()->QueueSyntheticGesture(
std::move(gesture),
base::BindOnce(&SyntheticInputTest::OnSyntheticGestureCompleted,
base::Unretained(this)));
scroll_offset_wait.WaitForScrollOffset(gfx::Vector2dF(0.f, 1024.f));
EXPECT_EQ(1024, EvalJs(shell()->web_contents(),
"document.scrollingElement.scrollTop"));
}
} // namespace content
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment