Merge "Fix bug 4111271 and bug 4077526 - WebView touch event handling when WebCore is too slow" into honeycomb-mr1
This commit is contained in:
@ -156,6 +156,7 @@ public class ScaleGestureDetector {
|
|||||||
private float mRightSlopEdge;
|
private float mRightSlopEdge;
|
||||||
private float mBottomSlopEdge;
|
private float mBottomSlopEdge;
|
||||||
private boolean mSloppyGesture;
|
private boolean mSloppyGesture;
|
||||||
|
private boolean mInvalidGesture;
|
||||||
|
|
||||||
// Pointer IDs currently responsible for the two fingers controlling the gesture
|
// Pointer IDs currently responsible for the two fingers controlling the gesture
|
||||||
private int mActiveId0;
|
private int mActiveId0;
|
||||||
@ -177,6 +178,8 @@ public class ScaleGestureDetector {
|
|||||||
reset(); // Start fresh
|
reset(); // Start fresh
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mInvalidGesture) return false;
|
||||||
|
|
||||||
if (!mGestureInProgress) {
|
if (!mGestureInProgress) {
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case MotionEvent.ACTION_DOWN: {
|
case MotionEvent.ACTION_DOWN: {
|
||||||
@ -518,6 +521,15 @@ public class ScaleGestureDetector {
|
|||||||
final int currIndex0 = curr.findPointerIndex(mActiveId0);
|
final int currIndex0 = curr.findPointerIndex(mActiveId0);
|
||||||
final int currIndex1 = curr.findPointerIndex(mActiveId1);
|
final int currIndex1 = curr.findPointerIndex(mActiveId1);
|
||||||
|
|
||||||
|
if (prevIndex0 < 0 || prevIndex1 < 0 || currIndex0 < 0 || currIndex1 < 0) {
|
||||||
|
mInvalidGesture = true;
|
||||||
|
Log.e(TAG, "Invalid MotionEvent stream detected.", new Throwable());
|
||||||
|
if (mGestureInProgress) {
|
||||||
|
mListener.onScaleEnd(this);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
final float px0 = prev.getX(prevIndex0);
|
final float px0 = prev.getX(prevIndex0);
|
||||||
final float py0 = prev.getY(prevIndex0);
|
final float py0 = prev.getY(prevIndex0);
|
||||||
final float px1 = prev.getX(prevIndex1);
|
final float px1 = prev.getX(prevIndex1);
|
||||||
@ -556,6 +568,7 @@ public class ScaleGestureDetector {
|
|||||||
mGestureInProgress = false;
|
mGestureInProgress = false;
|
||||||
mActiveId0 = -1;
|
mActiveId0 = -1;
|
||||||
mActiveId1 = -1;
|
mActiveId1 = -1;
|
||||||
|
mInvalidGesture = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -7185,14 +7185,15 @@ public class WebView extends AbsoluteLayout
|
|||||||
private class TouchEventQueue {
|
private class TouchEventQueue {
|
||||||
private long mNextTouchSequence = Long.MIN_VALUE + 1;
|
private long mNextTouchSequence = Long.MIN_VALUE + 1;
|
||||||
private long mLastHandledTouchSequence = Long.MIN_VALUE;
|
private long mLastHandledTouchSequence = Long.MIN_VALUE;
|
||||||
private long mIgnoreUntilSequence = Long.MIN_VALUE;
|
private long mIgnoreUntilSequence = Long.MIN_VALUE + 1;
|
||||||
private QueuedTouch mTouchEventQueue;
|
private QueuedTouch mTouchEventQueue;
|
||||||
private QueuedTouch mQueuedTouchRecycleBin;
|
private QueuedTouch mQueuedTouchRecycleBin;
|
||||||
private int mQueuedTouchRecycleCount;
|
private int mQueuedTouchRecycleCount;
|
||||||
|
private long mLastEventTime = Long.MAX_VALUE;
|
||||||
private static final int MAX_RECYCLED_QUEUED_TOUCH = 15;
|
private static final int MAX_RECYCLED_QUEUED_TOUCH = 15;
|
||||||
|
|
||||||
// milliseconds until we abandon hope of getting all of a previous gesture
|
// milliseconds until we abandon hope of getting all of a previous gesture
|
||||||
private static final int QUEUED_GESTURE_TIMEOUT = 2000;
|
private static final int QUEUED_GESTURE_TIMEOUT = 1000;
|
||||||
|
|
||||||
private QueuedTouch obtainQueuedTouch() {
|
private QueuedTouch obtainQueuedTouch() {
|
||||||
if (mQueuedTouchRecycleBin != null) {
|
if (mQueuedTouchRecycleBin != null) {
|
||||||
@ -7226,7 +7227,7 @@ public class WebView extends AbsoluteLayout
|
|||||||
public void reset() {
|
public void reset() {
|
||||||
mNextTouchSequence = Long.MIN_VALUE + 1;
|
mNextTouchSequence = Long.MIN_VALUE + 1;
|
||||||
mLastHandledTouchSequence = Long.MIN_VALUE;
|
mLastHandledTouchSequence = Long.MIN_VALUE;
|
||||||
mIgnoreUntilSequence = Long.MIN_VALUE;
|
mIgnoreUntilSequence = Long.MIN_VALUE + 1;
|
||||||
while (mTouchEventQueue != null) {
|
while (mTouchEventQueue != null) {
|
||||||
QueuedTouch recycleMe = mTouchEventQueue;
|
QueuedTouch recycleMe = mTouchEventQueue;
|
||||||
mTouchEventQueue = mTouchEventQueue.mNext;
|
mTouchEventQueue = mTouchEventQueue.mNext;
|
||||||
@ -7260,7 +7261,9 @@ public class WebView extends AbsoluteLayout
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dropStaleGestures(ted.mMotionEvent, ted.mSequence);
|
if (dropStaleGestures(ted.mMotionEvent, ted.mSequence)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (mLastHandledTouchSequence + 1 == ted.mSequence) {
|
if (mLastHandledTouchSequence + 1 == ted.mSequence) {
|
||||||
handleQueuedTouchEventData(ted);
|
handleQueuedTouchEventData(ted);
|
||||||
@ -7295,7 +7298,9 @@ public class WebView extends AbsoluteLayout
|
|||||||
public void enqueueTouchEvent(MotionEvent ev) {
|
public void enqueueTouchEvent(MotionEvent ev) {
|
||||||
final long sequence = nextTouchSequence();
|
final long sequence = nextTouchSequence();
|
||||||
|
|
||||||
dropStaleGestures(ev, sequence);
|
if (dropStaleGestures(ev, sequence)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (mLastHandledTouchSequence + 1 == sequence) {
|
if (mLastHandledTouchSequence + 1 == sequence) {
|
||||||
handleQueuedMotionEvent(ev);
|
handleQueuedMotionEvent(ev);
|
||||||
@ -7318,16 +7323,30 @@ public class WebView extends AbsoluteLayout
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void dropStaleGestures(MotionEvent ev, long sequence) {
|
private boolean dropStaleGestures(MotionEvent ev, long sequence) {
|
||||||
if (mTouchEventQueue == null) return;
|
if (ev != null && ev.getAction() == MotionEvent.ACTION_MOVE && !mConfirmMove) {
|
||||||
|
// This is to make sure that we don't attempt to process a tap
|
||||||
|
// or long press when webkit takes too long to get back to us.
|
||||||
|
// The movement will be properly confirmed when we process the
|
||||||
|
// enqueued event later.
|
||||||
|
final int dx = Math.round(ev.getX()) - mLastTouchX;
|
||||||
|
final int dy = Math.round(ev.getY()) - mLastTouchY;
|
||||||
|
if (dx * dx + dy * dy > mTouchSlopSquare) {
|
||||||
|
mPrivateHandler.removeMessages(SWITCH_TO_SHORTPRESS);
|
||||||
|
mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MotionEvent nextQueueEvent = mTouchEventQueue.mTed != null ?
|
if (mTouchEventQueue == null) {
|
||||||
mTouchEventQueue.mTed.mMotionEvent : mTouchEventQueue.mEvent;
|
return sequence <= mLastHandledTouchSequence;
|
||||||
|
}
|
||||||
|
|
||||||
if (ev != null && ev.getAction() == MotionEvent.ACTION_DOWN && nextQueueEvent != null) {
|
// If we have a new down event and it's been a while since the last event
|
||||||
|
// we saw, just reset and keep going.
|
||||||
|
if (ev != null && ev.getAction() == MotionEvent.ACTION_DOWN) {
|
||||||
long eventTime = ev.getEventTime();
|
long eventTime = ev.getEventTime();
|
||||||
long nextQueueTime = nextQueueEvent.getEventTime();
|
long lastHandledEventTime = mLastEventTime;
|
||||||
if (eventTime > nextQueueTime + QUEUED_GESTURE_TIMEOUT) {
|
if (eventTime > lastHandledEventTime + QUEUED_GESTURE_TIMEOUT) {
|
||||||
Log.w(LOGTAG, "Got ACTION_DOWN but still waiting on stale event. " +
|
Log.w(LOGTAG, "Got ACTION_DOWN but still waiting on stale event. " +
|
||||||
"Ignoring previous queued events.");
|
"Ignoring previous queued events.");
|
||||||
QueuedTouch qd = mTouchEventQueue;
|
QueuedTouch qd = mTouchEventQueue;
|
||||||
@ -7341,17 +7360,18 @@ public class WebView extends AbsoluteLayout
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mIgnoreUntilSequence > mLastHandledTouchSequence) {
|
if (mIgnoreUntilSequence - 1 > mLastHandledTouchSequence) {
|
||||||
QueuedTouch qd = mTouchEventQueue;
|
QueuedTouch qd = mTouchEventQueue;
|
||||||
while (qd != null && qd.mSequence < mIgnoreUntilSequence &&
|
while (qd != null && qd.mSequence < mIgnoreUntilSequence) {
|
||||||
qd.mSequence < sequence) {
|
|
||||||
mLastHandledTouchSequence = qd.mSequence;
|
|
||||||
QueuedTouch recycleMe = qd;
|
QueuedTouch recycleMe = qd;
|
||||||
qd = qd.mNext;
|
qd = qd.mNext;
|
||||||
recycleQueuedTouch(recycleMe);
|
recycleQueuedTouch(recycleMe);
|
||||||
}
|
}
|
||||||
mTouchEventQueue = qd;
|
mTouchEventQueue = qd;
|
||||||
|
mLastHandledTouchSequence = mIgnoreUntilSequence - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return sequence <= mLastHandledTouchSequence;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleQueuedTouch(QueuedTouch qt) {
|
private void handleQueuedTouch(QueuedTouch qt) {
|
||||||
@ -7364,6 +7384,7 @@ public class WebView extends AbsoluteLayout
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void handleQueuedMotionEvent(MotionEvent ev) {
|
private void handleQueuedMotionEvent(MotionEvent ev) {
|
||||||
|
mLastEventTime = ev.getEventTime();
|
||||||
int action = ev.getActionMasked();
|
int action = ev.getActionMasked();
|
||||||
if (ev.getPointerCount() > 1) { // Multi-touch
|
if (ev.getPointerCount() > 1) { // Multi-touch
|
||||||
handleMultiTouchInWebView(ev);
|
handleMultiTouchInWebView(ev);
|
||||||
@ -7381,6 +7402,9 @@ public class WebView extends AbsoluteLayout
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void handleQueuedTouchEventData(TouchEventData ted) {
|
private void handleQueuedTouchEventData(TouchEventData ted) {
|
||||||
|
if (ted.mMotionEvent != null) {
|
||||||
|
mLastEventTime = ted.mMotionEvent.getEventTime();
|
||||||
|
}
|
||||||
if (!ted.mReprocess) {
|
if (!ted.mReprocess) {
|
||||||
if (ted.mAction == MotionEvent.ACTION_DOWN
|
if (ted.mAction == MotionEvent.ACTION_DOWN
|
||||||
&& mPreventDefault == PREVENT_DEFAULT_MAYBE_YES) {
|
&& mPreventDefault == PREVENT_DEFAULT_MAYBE_YES) {
|
||||||
|
Reference in New Issue
Block a user