Commit b0af8423 authored by David Bokan's avatar David Bokan Committed by Commit Bot

Fix synthetic wheel generation on Android

This CL adds back the source bit on injected ACTION_SCROLL motion
events.

This got lost when [1] tried to make this bit a parameter and then
subsequently removed the option due to performance regressions in [2].

The reason this breaks is because in ContentUiEventHandler.java,
onGenericMotionEvent only dispatches a wheel event if the ACTION_SCROLL
event comes from a Pointer source[3].

[1] https://crrev.com/02cd150c24de8bdebb14d88c1a144b921a47756f
[2] https://crrev.com/14e88d0ddbdd58d346bc9c3bb0629af3fdf56f0f
[3] https://cs.chromium.org/chromium/src/content/public/android/java/src/org/chromium/content/browser/ContentUiEventHandler.java?rcl=3df6abb639be7564b7743ade8db455a3564e7d32&l=67

Change-Id: I1ba4143f61ad889173735b0a168d7790a00d0865
Bug: 1025789
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1935432Reviewed-by: default avatarBo <boliu@chromium.org>
Commit-Queue: Bo <boliu@chromium.org>
Auto-Submit: David Bokan <bokan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#719233}
parent 6e2ca090
...@@ -7,13 +7,22 @@ ...@@ -7,13 +7,22 @@
#include "base/run_loop.h" #include "base/run_loop.h"
#include "base/test/test_timeouts.h" #include "base/test/test_timeouts.h"
#include "cc/base/switches.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"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/input/input_event.h" #include "content/common/input/input_event.h"
#include "content/common/input/synthetic_gesture_params.h"
#include "content/common/input/synthetic_smooth_scroll_gesture_params.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host.h" #include "content/public/browser/render_widget_host.h"
#include "content/public/browser/render_widget_host_view.h" #include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
#include "content/public/test/browser_test_utils.h" #include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h" #include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h" #include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/hit_test_region_observer.h"
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h" #include "content/shell/browser/shell.h"
#include "third_party/blink/public/platform/web_input_event.h" #include "third_party/blink/public/platform/web_input_event.h"
...@@ -27,14 +36,35 @@ class SyntheticInputTest : public ContentBrowserTest { ...@@ -27,14 +36,35 @@ class SyntheticInputTest : public ContentBrowserTest {
command_line->AppendSwitch(cc::switches::kEnableGpuBenchmarking); command_line->AppendSwitch(cc::switches::kEnableGpuBenchmarking);
} }
RenderWidgetHost* GetRenderWidgetHost() const { RenderWidgetHostImpl* GetRenderWidgetHost() const {
RenderWidgetHost* const rwh = shell() return RenderWidgetHostImpl::From(
->web_contents() shell()->web_contents()->GetRenderViewHost()->GetWidget());
->GetRenderWidgetHostView()
->GetRenderWidgetHost();
CHECK(rwh);
return rwh;
} }
void LoadURL(const char* url) {
const GURL data_url(url);
EXPECT_TRUE(NavigateToURL(shell(), data_url));
RenderWidgetHostImpl* host = GetRenderWidgetHost();
HitTestRegionObserver observer(GetRenderWidgetHost()->GetFrameSinkId());
host->GetView()->SetSize(gfx::Size(400, 400));
base::string16 ready_title(base::ASCIIToUTF16("ready"));
TitleWatcher watcher(shell()->web_contents(), ready_title);
ignore_result(watcher.WaitAndGetTitle());
// Wait for the hit test data to be ready after initiating URL loading
// before returning
observer.WaitForHitTestData();
}
void OnSyntheticGestureCompleted(SyntheticGesture::Result result) {
EXPECT_EQ(SyntheticGesture::GESTURE_FINISHED, result);
runner_->Quit();
}
protected:
std::unique_ptr<base::RunLoop> runner_;
}; };
class GestureScrollObserver : public RenderWidgetHost::InputEventObserver { class GestureScrollObserver : public RenderWidgetHost::InputEventObserver {
...@@ -76,4 +106,55 @@ IN_PROC_BROWSER_TEST_F(SyntheticInputTest, DestroyWidgetWithOngoingGesture) { ...@@ -76,4 +106,55 @@ IN_PROC_BROWSER_TEST_F(SyntheticInputTest, DestroyWidgetWithOngoingGesture) {
shell()->Close(); shell()->Close();
} }
// This test ensures that synthetic wheel scrolling works on all platforms.
IN_PROC_BROWSER_TEST_F(SyntheticInputTest, SmoothScrollWheel) {
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: 256 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, -256));
// 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.
params.speed_in_pixels_s = 10000000.f;
// Use PrecisePixel to avoid animating.
params.granularity =
ui::input_types::ScrollGranularity::kScrollByPrecisePixel;
runner_.reset(new base::RunLoop());
std::unique_ptr<SyntheticSmoothScrollGesture> gesture(
new SyntheticSmoothScrollGesture(params));
GetRenderWidgetHost()->QueueSyntheticGesture(
std::move(gesture),
base::BindOnce(&SyntheticInputTest::OnSyntheticGestureCompleted,
base::Unretained(this)));
// Run until we get the OnSyntheticGestureCompleted callback
runner_->Run();
runner_.reset();
EXPECT_EQ(256, EvalJs(shell()->web_contents(),
"document.scrollingElement.scrollTop"));
}
} // namespace content } // namespace content
...@@ -156,7 +156,7 @@ public class MotionEventSynthesizerImpl implements MotionEventSynthesizer { ...@@ -156,7 +156,7 @@ public class MotionEventSynthesizerImpl implements MotionEventSynthesizer {
assert pointerCount == 1; assert pointerCount == 1;
MotionEvent event = MotionEvent.obtain(mDownTimeInMs, timeInMs, MotionEvent event = MotionEvent.obtain(mDownTimeInMs, timeInMs,
MotionEvent.ACTION_SCROLL, pointerCount, mPointerProperties, mPointerCoords, MotionEvent.ACTION_SCROLL, pointerCount, mPointerProperties, mPointerCoords,
0, 0, 1, 1, 0, 0, 0, 0); 0, 0, 1, 1, 0, 0, InputDevice.SOURCE_CLASS_POINTER, 0);
mTarget.dispatchGenericMotionEvent(event); mTarget.dispatchGenericMotionEvent(event);
event.recycle(); event.recycle();
break; break;
......
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