Commit 85ff2462 authored by Matt Jones's avatar Matt Jones Committed by Commit Bot

Add new util in TouchCommon for drag

This patch adds a new method for generating a complete drag event in
TouchCommon: "performDrag". The difference between this method and the
existing ones is that it is a single call for the down/move/up stream
and most importantly uses deterministic timing. The existing methods
are inherently flaky because they use the system time when generating
sequential events. This will confuse gesture detectors and cause them
to fire flings or empty events when they otherwise wouldn't. The new
method specifies a duration that can be used to simulate a fast or
slow drag.

Bug: 813584, 882003, 947694
Change-Id: I42ab8e8803c8b4e3c81a2876240c365ffc39f4f6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2134200
Commit-Queue: Matthew Jones <mdjones@chromium.org>
Reviewed-by: default avatarTed Choc <tedchoc@chromium.org>
Cr-Commit-Position: refs/heads/master@{#756000}
parent 4fbf8226
...@@ -1619,15 +1619,13 @@ public class TabsTest { ...@@ -1619,15 +1619,13 @@ public class TabsTest {
final int toX = toolbarPos[0] + (direction == ScrollDirection.LEFT ? 0 : width); final int toX = toolbarPos[0] + (direction == ScrollDirection.LEFT ? 0 : width);
final int y = toolbarPos[1] + height / 2; final int y = toolbarPos[1] + height / 2;
final int stepCount = 25; final int stepCount = 25;
final long duration = 500;
View toolbarRoot = mActivityTestRule.getActivity() View toolbarRoot = mActivityTestRule.getActivity()
.getFullscreenManager() .getFullscreenManager()
.getControlContainer() .getControlContainer()
.getView(); .getView();
long downTime = SystemClock.uptimeMillis(); TouchCommon.performDrag(toolbarRoot, fromX, toX, y, y, stepCount, duration);
TouchCommon.dragStart(toolbarRoot, fromX, y, downTime);
TouchCommon.dragTo(toolbarRoot, fromX, toX, y, y, stepCount, downTime);
TouchCommon.dragEnd(toolbarRoot, toX, y, downTime);
} }
/** /**
......
...@@ -25,20 +25,50 @@ public class TouchCommon { ...@@ -25,20 +25,50 @@ public class TouchCommon {
private TouchCommon() {} private TouchCommon() {}
/** /**
* Starts (synchronously) a drag motion. Normally followed by dragTo() and dragEnd(). * Synchronously perform a start-to-end drag event on the specified view with deterministic
* timing (events do not use system time).
* *
* @param view The view to dispatch the events to. * @param view The view to dispatch events to.
* @param x X coordinate, in screen coordinates. * @param fromX X coordinate of the initial touch, in screen coordinates.
* @param y Y coordinate, in screen coordinates. * @param toX X coordinate of the drag destination, in screen coordinates.
* @param downTime When the drag was started, in millis since the epoch. * @param fromY X coordinate of the initial touch, in screen coordinates.
* @param toY Y coordinate of the drag destination, in screen coordinates.
* @param stepCount How many move steps to include in the drag.
* @param duration The amount of time that will be simulated for the event stream in ms.
*/ */
public static void dragStart(View view, float x, float y, long downTime) { public static void performDrag(View view, float fromX, float toX, float fromY, float toY,
float[] windowXY = screenToWindowCoordinates(view, x, y); int stepCount, long duration) {
float windowX = windowXY[0]; // Use the current time as the base to add to.
float windowY = windowXY[1]; final long downTime = SystemClock.uptimeMillis();
MotionEvent event = MotionEvent.obtain( float[] windowXY = screenToWindowCoordinates(view, fromX, fromY);
downTime, downTime, MotionEvent.ACTION_DOWN, windowX, windowY, 0);
dispatchTouchEvent(view, event); // Start by sending the down event.
dispatchTouchEvent(view,
MotionEvent.obtain(
downTime, downTime, MotionEvent.ACTION_DOWN, windowXY[0], windowXY[1], 0));
float x = fromX;
float y = fromY;
float yStep = (toY - fromY) / stepCount;
float xStep = (toX - fromX) / stepCount;
long eventTime = downTime;
// Follow with a stream of motion events to simulate the drag.
for (int i = 0; i < stepCount; ++i) {
y += yStep;
x += xStep;
eventTime += i * duration / stepCount;
windowXY = screenToWindowCoordinates(view, x, y);
dispatchTouchEvent(view,
MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE, windowXY[0],
windowXY[1], 0));
}
// Finally send the up event.
windowXY = screenToWindowCoordinates(view, toX, toY);
dispatchTouchEvent(view,
MotionEvent.obtain(
downTime, eventTime, MotionEvent.ACTION_UP, windowXY[0], windowXY[1], 0));
} }
/** /**
...@@ -49,15 +79,22 @@ public class TouchCommon { ...@@ -49,15 +79,22 @@ public class TouchCommon {
* @param y Y coordinate, in screen coordinates. * @param y Y coordinate, in screen coordinates.
* @param downTime When the drag was started, in millis since the epoch. * @param downTime When the drag was started, in millis since the epoch.
*/ */
@Deprecated
public static void dragStart(Activity activity, float x, float y, long downTime) { public static void dragStart(Activity activity, float x, float y, long downTime) {
dragStart(getRootViewForActivity(activity), x, y, downTime); View view = getRootViewForActivity(activity);
float[] windowXY = screenToWindowCoordinates(view, x, y);
float windowX = windowXY[0];
float windowY = windowXY[1];
MotionEvent event = MotionEvent.obtain(
downTime, downTime, MotionEvent.ACTION_DOWN, windowX, windowY, 0);
dispatchTouchEvent(view, event);
} }
/** /**
* Drags / moves (synchronously) to the specified coordinates. Normally preceeded by * Drags / moves (synchronously) to the specified coordinates. Normally preceeded by
* dragStart() and followed by dragEnd() * dragStart() and followed by dragEnd()
* *
* @param view The view to dispatch events to. * @activity activity The activity where the touch action is being performed.
* @param fromX X coordinate of the initial touch, in screen coordinates. * @param fromX X coordinate of the initial touch, in screen coordinates.
* @param toX X coordinate of the drag destination, in screen coordinates. * @param toX X coordinate of the drag destination, in screen coordinates.
* @param fromY X coordinate of the initial touch, in screen coordinates. * @param fromY X coordinate of the initial touch, in screen coordinates.
...@@ -65,8 +102,10 @@ public class TouchCommon { ...@@ -65,8 +102,10 @@ public class TouchCommon {
* @param stepCount How many move steps to include in the drag. * @param stepCount How many move steps to include in the drag.
* @param downTime When the drag was started, in millis since the epoch. * @param downTime When the drag was started, in millis since the epoch.
*/ */
public static void dragTo(View view, float fromX, float toX, float fromY, float toY, @Deprecated
public static void dragTo(Activity activity, float fromX, float toX, float fromY, float toY,
int stepCount, long downTime) { int stepCount, long downTime) {
View view = getRootViewForActivity(activity);
float x = fromX; float x = fromX;
float y = fromY; float y = fromY;
float yStep = (toY - fromY) / stepCount; float yStep = (toY - fromY) / stepCount;
...@@ -84,33 +123,18 @@ public class TouchCommon { ...@@ -84,33 +123,18 @@ public class TouchCommon {
} }
} }
/**
* Drags / moves (synchronously) to the specified coordinates. Normally preceded by
* dragStart() and followed by dragEnd()
*
* @activity activity The activity where the touch action is being performed.
* @param fromX X coordinate of the initial touch, in screen coordinates.
* @param toX X coordinate of the drag destination, in screen coordinates.
* @param fromY X coordinate of the initial touch, in screen coordinates.
* @param toY Y coordinate of the drag destination, in screen coordinates.
* @param stepCount How many move steps to include in the drag.
* @param downTime When the drag was started, in millis since the epoch.
*/
public static void dragTo(Activity activity, float fromX, float toX, float fromY, float toY,
int stepCount, long downTime) {
dragTo(getRootViewForActivity(activity), fromX, toX, fromY, toY, stepCount, downTime);
}
/** /**
* Finishes (synchronously) a drag / move at the specified coordinate. * Finishes (synchronously) a drag / move at the specified coordinate.
* Normally preceded by dragStart() and dragTo(). * Normally preceded by dragStart() and dragTo().
* *
* @param view The view to dispatch events to. * @activity activity The activity where the touch action is being performed.
* @param x X coordinate, in screen coordinates. * @param x X coordinate, in screen coordinates.
* @param y Y coordinate, in screen coordinates. * @param y Y coordinate, in screen coordinates.
* @param downTime When the drag was started, in millis since the epoch. * @param downTime When the drag was started, in millis since the epoch.
*/ */
public static void dragEnd(View view, float x, float y, long downTime) { @Deprecated
public static void dragEnd(Activity activity, float x, float y, long downTime) {
View view = getRootViewForActivity(activity);
float[] windowXY = screenToWindowCoordinates(view, x, y); float[] windowXY = screenToWindowCoordinates(view, x, y);
float windowX = windowXY[0]; float windowX = windowXY[0];
float windowY = windowXY[1]; float windowY = windowXY[1];
...@@ -120,19 +144,6 @@ public class TouchCommon { ...@@ -120,19 +144,6 @@ public class TouchCommon {
dispatchTouchEvent(view, event); dispatchTouchEvent(view, event);
} }
/**
* Finishes (synchronously) a drag / move at the specified coordinate.
* Normally preceded by dragStart() and dragTo().
*
* @activity activity The activity where the touch action is being performed.
* @param x X coordinate, in screen coordinates.
* @param y Y coordinate, in screen coordinates.
* @param downTime When the drag was started, in millis since the epoch.
*/
public static void dragEnd(Activity activity, float x, float y, long downTime) {
dragEnd(getRootViewForActivity(activity), x, y, downTime);
}
/** /**
* Sends (synchronously) a single click to the View at the specified view-relative coordinates. * Sends (synchronously) a single click to the View at the specified view-relative coordinates.
* *
......
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