Index: chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayout.java |
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayout.java |
index cea303618ba9dd3d025423d6c11edf2b981ad32a..5c336f2187576ce9f1ef7cd6ae1be7079d758ad7 100644 |
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayout.java |
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayout.java |
@@ -17,11 +17,14 @@ import org.chromium.base.VisibleForTesting; |
import org.chromium.chrome.browser.compositor.LayerTitleCache; |
import org.chromium.chrome.browser.compositor.layouts.ChromeAnimation.Animatable; |
import org.chromium.chrome.browser.compositor.layouts.Layout; |
+import org.chromium.chrome.browser.compositor.layouts.LayoutManager; |
import org.chromium.chrome.browser.compositor.layouts.LayoutRenderHost; |
import org.chromium.chrome.browser.compositor.layouts.LayoutUpdateHost; |
import org.chromium.chrome.browser.compositor.layouts.components.LayoutTab; |
import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager; |
import org.chromium.chrome.browser.compositor.layouts.eventfilter.EventFilter; |
+import org.chromium.chrome.browser.compositor.layouts.eventfilter.GestureEventFilter; |
+import org.chromium.chrome.browser.compositor.layouts.eventfilter.GestureHandler; |
import org.chromium.chrome.browser.compositor.layouts.eventfilter.ScrollDirection; |
import org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack; |
import org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab; |
@@ -132,18 +135,128 @@ public class StackLayout extends Layout implements Animatable<StackLayout.Proper |
private final ViewGroup mViewContainer; |
+ private final GestureEventFilter mGestureEventFilter; |
private final TabListSceneLayer mSceneLayer; |
+ private StackLayoutGestureHandler mGestureHandler; |
+ |
+ private class StackLayoutGestureHandler implements GestureHandler { |
+ @Override |
+ public void onDown(float x, float y, boolean fromMouse, int buttons) { |
+ long time = time(); |
+ mLastOnDownX = x; |
+ mLastOnDownY = y; |
+ mLastOnDownTimeStamp = time; |
+ mInputMode = computeInputMode(time, x, y, 0, 0); |
+ mStacks[getTabStackIndex()].onDown(time); |
+ } |
+ |
+ @Override |
+ public void onUpOrCancel() { |
+ onUpOrCancel(time()); |
+ } |
+ |
+ @Override |
+ public void drag(float x, float y, float dx, float dy, float tx, float ty) { |
+ SwipeMode oldInputMode = mInputMode; |
+ long time = time(); |
+ float amountX = dx; |
+ float amountY = dy; |
+ mInputMode = computeInputMode(time, x, y, amountX, amountY); |
+ |
+ if (oldInputMode == SwipeMode.SEND_TO_STACK && mInputMode == SwipeMode.SWITCH_STACK) { |
+ mStacks[getTabStackIndex()].onUpOrCancel(time); |
+ } else if (oldInputMode == SwipeMode.SWITCH_STACK |
+ && mInputMode == SwipeMode.SEND_TO_STACK) { |
+ onUpOrCancel(time); |
+ } |
+ |
+ if (mInputMode == SwipeMode.SEND_TO_STACK) { |
+ mStacks[getTabStackIndex()].drag(time, x, y, amountX, amountY); |
+ } else if (mInputMode == SwipeMode.SWITCH_STACK) { |
+ scrollStacks(getOrientation() == Orientation.PORTRAIT ? amountX : amountY); |
+ } |
+ } |
+ |
+ @Override |
+ public void click(float x, float y, boolean fromMouse, int buttons) { |
+ // Click event happens before the up event. mClicked is set to mute the up event. |
+ mClicked = true; |
+ PortraitViewport viewportParams = getViewportParameters(); |
+ int stackIndexAt = viewportParams.getStackIndexAt(x, y); |
+ if (stackIndexAt == getTabStackIndex()) { |
+ mStacks[getTabStackIndex()].click(time(), x, y); |
+ } else { |
+ flingStacks(getTabStackIndex() == 0); |
+ } |
+ requestStackUpdate(); |
+ } |
+ |
+ @Override |
+ public void fling(float x, float y, float velocityX, float velocityY) { |
+ long time = time(); |
+ float vx = velocityX; |
+ float vy = velocityY; |
+ |
+ if (mInputMode == SwipeMode.NONE) { |
+ mInputMode = computeInputMode( |
+ time, x, y, vx * SWITCH_STACK_FLING_DT, vy * SWITCH_STACK_FLING_DT); |
+ } |
+ |
+ if (mInputMode == SwipeMode.SEND_TO_STACK) { |
+ mStacks[getTabStackIndex()].fling(time, x, y, vx, vy); |
+ } else if (mInputMode == SwipeMode.SWITCH_STACK) { |
+ final float velocity = getOrientation() == Orientation.PORTRAIT ? vx : vy; |
+ final float origin = getOrientation() == Orientation.PORTRAIT ? x : y; |
+ final float max = |
+ getOrientation() == Orientation.PORTRAIT ? getWidth() : getHeight(); |
+ final float predicted = origin + velocity * SWITCH_STACK_FLING_DT; |
+ final float delta = MathUtils.clamp(predicted, 0, max) - origin; |
+ scrollStacks(delta); |
+ } |
+ requestStackUpdate(); |
+ } |
+ |
+ @Override |
+ public void onLongPress(float x, float y) { |
+ mStacks[getTabStackIndex()].onLongPress(time(), x, y); |
+ } |
+ |
+ @Override |
+ public void onPinch(float x0, float y0, float x1, float y1, boolean firstEvent) { |
+ mStacks[getTabStackIndex()].onPinch(time(), x0, y0, x1, y1, firstEvent); |
+ } |
+ |
+ private void onUpOrCancel(long time) { |
+ int currentIndex = getTabStackIndex(); |
+ int nextIndex = 1 - currentIndex; |
+ if (!mClicked |
+ && Math.abs(currentIndex + mRenderedScrollOffset) > THRESHOLD_TO_SWITCH_STACK |
+ && mStacks[nextIndex].isDisplayable()) { |
+ setActiveStackState(nextIndex == 1); |
+ } |
+ mClicked = false; |
+ finishScrollStacks(); |
+ mStacks[getTabStackIndex()].onUpOrCancel(time); |
+ mInputMode = SwipeMode.NONE; |
+ } |
+ |
+ private long time() { |
+ return LayoutManager.time(); |
+ } |
+ } |
+ |
/** |
* @param context The current Android's context. |
* @param updateHost The {@link LayoutUpdateHost} view for this layout. |
* @param renderHost The {@link LayoutRenderHost} view for this layout. |
* @param eventFilter The {@link EventFilter} that is needed for this view. |
*/ |
- public StackLayout(Context context, LayoutUpdateHost updateHost, LayoutRenderHost renderHost, |
- EventFilter eventFilter) { |
- super(context, updateHost, renderHost, eventFilter); |
+ public StackLayout(Context context, LayoutUpdateHost updateHost, LayoutRenderHost renderHost) { |
+ super(context, updateHost, renderHost); |
+ mGestureHandler = new StackLayoutGestureHandler(); |
+ mGestureEventFilter = new GestureEventFilter(context, mGestureHandler); |
final ViewConfiguration configuration = ViewConfiguration.get(context); |
mMinDirectionThreshold = configuration.getScaledTouchSlop(); |
mMinShortPressThresholdSqr = |
@@ -167,6 +280,32 @@ public class StackLayout extends Layout implements Animatable<StackLayout.Proper |
return true; |
} |
+ /** |
+ * Simulates a click on the view at the specified pixel offset |
+ * from the top left of the view. |
+ * This is used by UI tests. |
+ * @param x Coordinate of the click in dp. |
+ * @param y Coordinate of the click in dp. |
+ */ |
+ @VisibleForTesting |
+ public void simulateClick(float x, float y) { |
+ mGestureHandler.click(x, y, false, -1); |
+ } |
+ |
+ /** |
+ * Simulates a drag and issues Up-event to commit the drag. |
+ * @param x Coordinate to start the Drag from in dp. |
+ * @param y Coordinate to start the Drag from in dp. |
+ * @param dX Amount of drag in X direction in dp. |
+ * @param dY Amount of drag in Y direction in dp. |
+ */ |
+ @VisibleForTesting |
+ public void simulateDrag(float x, float y, float dX, float dY) { |
+ mGestureHandler.onDown(x, y, false, -1); |
+ mGestureHandler.drag(x, y, dX, dY, -1, -1); |
+ mGestureHandler.onUpOrCancel(); |
+ } |
+ |
@Override |
public ViewportMode getViewportMode() { |
return ViewportMode.ALWAYS_FULLSCREEN; |
@@ -598,25 +737,6 @@ public class StackLayout extends Layout implements Animatable<StackLayout.Proper |
requestStackUpdate(); |
} |
- @Override |
- public void drag(long time, float x, float y, float amountX, float amountY) { |
- SwipeMode oldInputMode = mInputMode; |
- mInputMode = computeInputMode(time, x, y, amountX, amountY); |
- |
- if (oldInputMode == SwipeMode.SEND_TO_STACK && mInputMode == SwipeMode.SWITCH_STACK) { |
- mStacks[getTabStackIndex()].onUpOrCancel(time); |
- } else if (oldInputMode == SwipeMode.SWITCH_STACK |
- && mInputMode == SwipeMode.SEND_TO_STACK) { |
- onUpOrCancel(time); |
- } |
- |
- if (mInputMode == SwipeMode.SEND_TO_STACK) { |
- mStacks[getTabStackIndex()].drag(time, x, y, amountX, amountY); |
- } else if (mInputMode == SwipeMode.SWITCH_STACK) { |
- scrollStacks(getOrientation() == Orientation.PORTRAIT ? amountX : amountY); |
- } |
- } |
- |
/** |
* Computes the input mode for drag and fling based on the first event position. |
* @param time The current time of the app in ms. |
@@ -666,26 +786,6 @@ public class StackLayout extends Layout implements Animatable<StackLayout.Proper |
return SwipeMode.NONE; |
} |
- @Override |
- public void fling(long time, float x, float y, float vx, float vy) { |
- if (mInputMode == SwipeMode.NONE) { |
- mInputMode = computeInputMode( |
- time, x, y, vx * SWITCH_STACK_FLING_DT, vy * SWITCH_STACK_FLING_DT); |
- } |
- |
- if (mInputMode == SwipeMode.SEND_TO_STACK) { |
- mStacks[getTabStackIndex()].fling(time, x, y, vx, vy); |
- } else if (mInputMode == SwipeMode.SWITCH_STACK) { |
- final float velocity = getOrientation() == Orientation.PORTRAIT ? vx : vy; |
- final float origin = getOrientation() == Orientation.PORTRAIT ? x : y; |
- final float max = getOrientation() == Orientation.PORTRAIT ? getWidth() : getHeight(); |
- final float predicted = origin + velocity * SWITCH_STACK_FLING_DT; |
- final float delta = MathUtils.clamp(predicted, 0, max) - origin; |
- scrollStacks(delta); |
- } |
- requestStackUpdate(); |
- } |
- |
class PortraitViewport { |
protected float mWidth, mHeight; |
PortraitViewport() { |
@@ -818,20 +918,6 @@ public class StackLayout extends Layout implements Animatable<StackLayout.Proper |
} |
} |
- @Override |
- public void click(long time, float x, float y) { |
- // Click event happens before the up event. mClicked is set to mute the up event. |
- mClicked = true; |
- PortraitViewport viewportParams = getViewportParameters(); |
- int stackIndexAt = viewportParams.getStackIndexAt(x, y); |
- if (stackIndexAt == getTabStackIndex()) { |
- mStacks[getTabStackIndex()].click(time, x, y); |
- } else { |
- flingStacks(getTabStackIndex() == 0); |
- } |
- requestStackUpdate(); |
- } |
- |
/** |
* Check if we are dragging stack in a wrong direction. |
* |
@@ -904,34 +990,6 @@ public class StackLayout extends Layout implements Animatable<StackLayout.Proper |
} |
} |
- @Override |
- public void onDown(long time, float x, float y) { |
- mLastOnDownX = x; |
- mLastOnDownY = y; |
- mLastOnDownTimeStamp = time; |
- mInputMode = computeInputMode(time, x, y, 0, 0); |
- mStacks[getTabStackIndex()].onDown(time); |
- } |
- |
- @Override |
- public void onLongPress(long time, float x, float y) { |
- mStacks[getTabStackIndex()].onLongPress(time, x, y); |
- } |
- |
- @Override |
- public void onUpOrCancel(long time) { |
- int currentIndex = getTabStackIndex(); |
- int nextIndex = 1 - currentIndex; |
- if (!mClicked && Math.abs(currentIndex + mRenderedScrollOffset) > THRESHOLD_TO_SWITCH_STACK |
- && mStacks[nextIndex].isDisplayable()) { |
- setActiveStackState(nextIndex == 1); |
- } |
- mClicked = false; |
- finishScrollStacks(); |
- mStacks[getTabStackIndex()].onUpOrCancel(time); |
- mInputMode = SwipeMode.NONE; |
- } |
- |
/** |
* Pushes a rectangle to be drawn on the screen on top of everything. |
* |
@@ -953,11 +1011,6 @@ public class StackLayout extends Layout implements Animatable<StackLayout.Proper |
} |
@Override |
- public void onPinch(long time, float x0, float y0, float x1, float y1, boolean firstEvent) { |
- mStacks[getTabStackIndex()].onPinch(time, x0, y0, x1, y1, firstEvent); |
- } |
- |
- @Override |
protected void updateLayout(long time, long dt) { |
super.updateLayout(time, dt); |
boolean needUpdate = false; |
@@ -1227,6 +1280,11 @@ public class StackLayout extends Layout implements Animatable<StackLayout.Proper |
} |
@Override |
+ protected EventFilter getEventFilter() { |
+ return mGestureEventFilter; |
+ } |
+ |
+ @Override |
protected SceneLayer getSceneLayer() { |
return mSceneLayer; |
} |