diff options
| -rw-r--r-- | core/java/android/webkit/WebView.java | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index 481cff0e841d..1bfd1d3e1c83 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -6004,6 +6004,7 @@ public class WebView extends AbsoluteLayout if (shouldForwardTouchEvent()) { if (removeEvents) { mWebViewCore.removeMessages(EventHub.TOUCH_EVENT); + mTouchEventQueue.ignoreCurrentlyMissingEvents(); } TouchEventData ted = new TouchEventData(); ted.mIds = new int[1]; @@ -7142,11 +7143,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 QueuedTouch mTouchEventQueue; private QueuedTouch mQueuedTouchRecycleBin; private int mQueuedTouchRecycleCount; 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 QueuedTouch obtainQueuedTouch() { if (mQueuedTouchRecycleBin != null) { QueuedTouch result = mQueuedTouchRecycleBin; @@ -7157,6 +7162,13 @@ public class WebView extends AbsoluteLayout return new QueuedTouch(); } + /** + * Allow events with any currently missing sequence numbers to be skipped in processing. + */ + public void ignoreCurrentlyMissingEvents() { + mIgnoreUntilSequence = mNextTouchSequence; + } + private void recycleQueuedTouch(QueuedTouch qd) { if (mQueuedTouchRecycleCount < MAX_RECYCLED_QUEUED_TOUCH) { qd.mNext = mQueuedTouchRecycleBin; @@ -7172,6 +7184,7 @@ public class WebView extends AbsoluteLayout public void reset() { mNextTouchSequence = Long.MIN_VALUE + 1; mLastHandledTouchSequence = Long.MIN_VALUE; + mIgnoreUntilSequence = Long.MIN_VALUE; while (mTouchEventQueue != null) { QueuedTouch recycleMe = mTouchEventQueue; mTouchEventQueue = mTouchEventQueue.mNext; @@ -7198,6 +7211,15 @@ public class WebView extends AbsoluteLayout * @param ted Touch data to be processed in order. */ public void enqueueTouchEvent(TouchEventData ted) { + if (ted.mSequence < mLastHandledTouchSequence) { + // Stale event and we already moved on; drop it. (Should not be common.) + Log.w(LOGTAG, "Stale touch event " + MotionEvent.actionToString(ted.mAction) + + " received from webcore; ignoring"); + return; + } + + dropStaleGestures(ted.mMotionEvent, ted.mSequence); + if (mLastHandledTouchSequence + 1 == ted.mSequence) { handleQueuedTouchEventData(ted); @@ -7230,6 +7252,9 @@ public class WebView extends AbsoluteLayout */ public void enqueueTouchEvent(MotionEvent ev) { final long sequence = nextTouchSequence(); + + dropStaleGestures(ev, sequence); + if (mLastHandledTouchSequence + 1 == sequence) { handleQueuedMotionEvent(ev); @@ -7251,6 +7276,40 @@ public class WebView extends AbsoluteLayout } } + private void dropStaleGestures(MotionEvent ev, long sequence) { + if (ev != null && ev.getAction() == MotionEvent.ACTION_DOWN && + mTouchEventQueue != null) { + long eventTime = ev.getEventTime(); + long nextQueueTime = mTouchEventQueue.mTed != null ? + mTouchEventQueue.mTed.mMotionEvent.getEventTime() : + mTouchEventQueue.mEvent.getEventTime(); + if (eventTime > nextQueueTime + QUEUED_GESTURE_TIMEOUT) { + Log.w(LOGTAG, "Got ACTION_DOWN but still waiting on stale event. " + + "Ignoring previous queued events."); + QueuedTouch qd = mTouchEventQueue; + while (qd != null && qd.mSequence < sequence) { + QueuedTouch recycleMe = qd; + qd = qd.mNext; + recycleQueuedTouch(recycleMe); + } + mTouchEventQueue = qd; + mLastHandledTouchSequence = sequence - 1; + } + } + + if (mIgnoreUntilSequence > mLastHandledTouchSequence) { + QueuedTouch qd = mTouchEventQueue; + while (qd != null && qd.mSequence < mIgnoreUntilSequence && + qd.mSequence < sequence) { + mLastHandledTouchSequence = qd.mSequence; + QueuedTouch recycleMe = qd; + qd = qd.mNext; + recycleQueuedTouch(recycleMe); + } + mTouchEventQueue = qd; + } + } + private void handleQueuedTouch(QueuedTouch qt) { if (qt.mTed != null) { handleQueuedTouchEventData(qt.mTed); |