diff options
| author | 2011-03-17 01:41:30 -0700 | |
|---|---|---|
| committer | 2011-03-17 01:41:30 -0700 | |
| commit | 7270f62c1fcdf1e1133ba10f9765109c49e725ed (patch) | |
| tree | aab70b61c07b09bf786cf914fc884c1a1ae8ba16 | |
| parent | 8cb373ad858cdb19060cfa2fee43afca9c791ab4 (diff) | |
| parent | 9cd93f09d451afacb8fffeee5e71806e0f91cf31 (diff) | |
am 9cd93f09: am ea775ca3: am f8d1533b: Merge "Fix bug 4111271 and bug 4077526 - WebView touch event handling when WebCore is too slow" into honeycomb-mr1
* commit '9cd93f09d451afacb8fffeee5e71806e0f91cf31':
Fix bug 4111271 and bug 4077526 - WebView touch event handling when WebCore is too slow
| -rw-r--r-- | core/java/android/view/ScaleGestureDetector.java | 13 | ||||
| -rw-r--r-- | core/java/android/webkit/WebView.java | 56 |
2 files changed, 53 insertions, 16 deletions
diff --git a/core/java/android/view/ScaleGestureDetector.java b/core/java/android/view/ScaleGestureDetector.java index 5521e9292342..d638e7080b32 100644 --- a/core/java/android/view/ScaleGestureDetector.java +++ b/core/java/android/view/ScaleGestureDetector.java @@ -156,6 +156,7 @@ public class ScaleGestureDetector { private float mRightSlopEdge; private float mBottomSlopEdge; private boolean mSloppyGesture; + private boolean mInvalidGesture; // Pointer IDs currently responsible for the two fingers controlling the gesture private int mActiveId0; @@ -177,6 +178,8 @@ public class ScaleGestureDetector { reset(); // Start fresh } + if (mInvalidGesture) return false; + if (!mGestureInProgress) { switch (action) { case MotionEvent.ACTION_DOWN: { @@ -518,6 +521,15 @@ public class ScaleGestureDetector { final int currIndex0 = curr.findPointerIndex(mActiveId0); 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 py0 = prev.getY(prevIndex0); final float px1 = prev.getX(prevIndex1); @@ -556,6 +568,7 @@ public class ScaleGestureDetector { mGestureInProgress = false; mActiveId0 = -1; mActiveId1 = -1; + mInvalidGesture = false; } /** diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index bba8ed79745d..0c1e39edd7fb 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -7170,14 +7170,15 @@ public class WebView extends AbsoluteLayout private class TouchEventQueue { private long mNextTouchSequence = Long.MIN_VALUE + 1; private long mLastHandledTouchSequence = Long.MIN_VALUE; - private long mIgnoreUntilSequence = Long.MIN_VALUE; + private long mIgnoreUntilSequence = Long.MIN_VALUE + 1; private QueuedTouch mTouchEventQueue; private QueuedTouch mQueuedTouchRecycleBin; private int mQueuedTouchRecycleCount; + private long mLastEventTime = Long.MAX_VALUE; private static final int MAX_RECYCLED_QUEUED_TOUCH = 15; // 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() { if (mQueuedTouchRecycleBin != null) { @@ -7211,7 +7212,7 @@ public class WebView extends AbsoluteLayout public void reset() { mNextTouchSequence = Long.MIN_VALUE + 1; mLastHandledTouchSequence = Long.MIN_VALUE; - mIgnoreUntilSequence = Long.MIN_VALUE; + mIgnoreUntilSequence = Long.MIN_VALUE + 1; while (mTouchEventQueue != null) { QueuedTouch recycleMe = mTouchEventQueue; mTouchEventQueue = mTouchEventQueue.mNext; @@ -7245,7 +7246,9 @@ public class WebView extends AbsoluteLayout return; } - dropStaleGestures(ted.mMotionEvent, ted.mSequence); + if (dropStaleGestures(ted.mMotionEvent, ted.mSequence)) { + return; + } if (mLastHandledTouchSequence + 1 == ted.mSequence) { handleQueuedTouchEventData(ted); @@ -7280,7 +7283,9 @@ public class WebView extends AbsoluteLayout public void enqueueTouchEvent(MotionEvent ev) { final long sequence = nextTouchSequence(); - dropStaleGestures(ev, sequence); + if (dropStaleGestures(ev, sequence)) { + return; + } if (mLastHandledTouchSequence + 1 == sequence) { handleQueuedMotionEvent(ev); @@ -7303,16 +7308,30 @@ public class WebView extends AbsoluteLayout } } - private void dropStaleGestures(MotionEvent ev, long sequence) { - if (mTouchEventQueue == null) return; + private boolean dropStaleGestures(MotionEvent ev, long sequence) { + 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 ? - mTouchEventQueue.mTed.mMotionEvent : mTouchEventQueue.mEvent; + if (mTouchEventQueue == null) { + 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 nextQueueTime = nextQueueEvent.getEventTime(); - if (eventTime > nextQueueTime + QUEUED_GESTURE_TIMEOUT) { + long lastHandledEventTime = mLastEventTime; + if (eventTime > lastHandledEventTime + QUEUED_GESTURE_TIMEOUT) { Log.w(LOGTAG, "Got ACTION_DOWN but still waiting on stale event. " + "Ignoring previous queued events."); QueuedTouch qd = mTouchEventQueue; @@ -7326,17 +7345,18 @@ public class WebView extends AbsoluteLayout } } - if (mIgnoreUntilSequence > mLastHandledTouchSequence) { + if (mIgnoreUntilSequence - 1 > mLastHandledTouchSequence) { QueuedTouch qd = mTouchEventQueue; - while (qd != null && qd.mSequence < mIgnoreUntilSequence && - qd.mSequence < sequence) { - mLastHandledTouchSequence = qd.mSequence; + while (qd != null && qd.mSequence < mIgnoreUntilSequence) { QueuedTouch recycleMe = qd; qd = qd.mNext; recycleQueuedTouch(recycleMe); } mTouchEventQueue = qd; + mLastHandledTouchSequence = mIgnoreUntilSequence - 1; } + + return sequence <= mLastHandledTouchSequence; } private void handleQueuedTouch(QueuedTouch qt) { @@ -7349,6 +7369,7 @@ public class WebView extends AbsoluteLayout } private void handleQueuedMotionEvent(MotionEvent ev) { + mLastEventTime = ev.getEventTime(); int action = ev.getActionMasked(); if (ev.getPointerCount() > 1) { // Multi-touch handleMultiTouchInWebView(ev); @@ -7366,6 +7387,9 @@ public class WebView extends AbsoluteLayout } private void handleQueuedTouchEventData(TouchEventData ted) { + if (ted.mMotionEvent != null) { + mLastEventTime = ted.mMotionEvent.getEventTime(); + } if (!ted.mReprocess) { if (ted.mAction == MotionEvent.ACTION_DOWN && mPreventDefault == PREVENT_DEFAULT_MAYBE_YES) { |