diff options
author | Adam Powell <adamp@google.com> | 2011-04-05 11:14:27 -0700 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2011-04-05 11:14:27 -0700 |
commit | 2bb59637caa71d7e05f7c94d3da425fbfd425ea7 (patch) | |
tree | 6d7d7a522e8bf828568c4b75675341122c84936a /core/java/android | |
parent | f0d2c1c4eb613130e34a4f377d8f82f935170873 (diff) | |
parent | 030b38ffc21ef3962b31d5bac5170531293b6046 (diff) | |
download | frameworks_base-2bb59637caa71d7e05f7c94d3da425fbfd425ea7.zip frameworks_base-2bb59637caa71d7e05f7c94d3da425fbfd425ea7.tar.gz frameworks_base-2bb59637caa71d7e05f7c94d3da425fbfd425ea7.tar.bz2 |
am 030b38ff: Merge "Fix bug 4207704 - Gestures can be lost when Flash is enabled" into honeycomb-mr1
* commit '030b38ffc21ef3962b31d5bac5170531293b6046':
Fix bug 4207704 - Gestures can be lost when Flash is enabled
Diffstat (limited to 'core/java/android')
-rw-r--r-- | core/java/android/webkit/WebView.java | 157 |
1 files changed, 136 insertions, 21 deletions
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java index a3ced9e..57d6108 100644 --- a/core/java/android/webkit/WebView.java +++ b/core/java/android/webkit/WebView.java @@ -5584,6 +5584,7 @@ public class WebView extends AbsoluteLayout ted.mNativeLayer = nativeScrollableLayer( contentX, contentY, ted.mNativeLayerRect, null); ted.mSequence = mTouchEventQueue.nextTouchSequence(); + mTouchEventQueue.preQueueTouchEventData(ted); mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted); if (mDeferTouchProcess) { // still needs to set them for compute deltaX/Y @@ -5633,6 +5634,7 @@ public class WebView extends AbsoluteLayout ted.mNativeLayer = mScrollingLayer; ted.mNativeLayerRect.set(mScrollingLayerRect); ted.mSequence = mTouchEventQueue.nextTouchSequence(); + mTouchEventQueue.preQueueTouchEventData(ted); mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted); mLastSentTouchTime = eventTime; if (mDeferTouchProcess) { @@ -5817,6 +5819,7 @@ public class WebView extends AbsoluteLayout ted.mNativeLayer = mScrollingLayer; ted.mNativeLayerRect.set(mScrollingLayerRect); ted.mSequence = mTouchEventQueue.nextTouchSequence(); + mTouchEventQueue.preQueueTouchEventData(ted); mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted); } mLastTouchUpTime = eventTime; @@ -5842,6 +5845,7 @@ public class WebView extends AbsoluteLayout contentX, contentY, ted.mNativeLayerRect, null); ted.mSequence = mTouchEventQueue.nextTouchSequence(); + mTouchEventQueue.preQueueTouchEventData(ted); mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted); } else if (mPreventDefault != PREVENT_DEFAULT_YES){ mZoomManager.handleDoubleTap(mLastTouchX, mLastTouchY); @@ -5988,6 +5992,7 @@ public class WebView extends AbsoluteLayout ted.mReprocess = true; ted.mMotionEvent = MotionEvent.obtain(ev); ted.mSequence = sequence; + mTouchEventQueue.preQueueTouchEventData(ted); mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted); cancelLongPress(); mPrivateHandler.removeMessages(SWITCH_TO_LONGPRESS); @@ -7205,9 +7210,17 @@ public class WebView extends AbsoluteLayout private long mNextTouchSequence = Long.MIN_VALUE + 1; private long mLastHandledTouchSequence = Long.MIN_VALUE; private long mIgnoreUntilSequence = Long.MIN_VALUE + 1; + + // Events waiting to be processed. private QueuedTouch mTouchEventQueue; + + // Known events that are waiting on a response before being enqueued. + private QueuedTouch mPreQueue; + + // Pool of QueuedTouch objects saved for later use. private QueuedTouch mQueuedTouchRecycleBin; private int mQueuedTouchRecycleCount; + private long mLastEventTime = Long.MAX_VALUE; private static final int MAX_RECYCLED_QUEUED_TOUCH = 15; @@ -7229,6 +7242,57 @@ public class WebView extends AbsoluteLayout */ public void ignoreCurrentlyMissingEvents() { mIgnoreUntilSequence = mNextTouchSequence; + + // Run any events we have available and complete, pre-queued or otherwise. + runQueuedAndPreQueuedEvents(); + } + + private void runQueuedAndPreQueuedEvents() { + QueuedTouch qd = mPreQueue; + boolean fromPreQueue = true; + while (qd != null && qd.mSequence == mLastHandledTouchSequence + 1) { + handleQueuedTouch(qd); + QueuedTouch recycleMe = qd; + if (fromPreQueue) { + mPreQueue = qd.mNext; + } else { + mTouchEventQueue = qd.mNext; + } + recycleQueuedTouch(recycleMe); + mLastHandledTouchSequence++; + + long nextPre = mPreQueue != null ? mPreQueue.mSequence : Long.MAX_VALUE; + long nextQueued = mTouchEventQueue != null ? + mTouchEventQueue.mSequence : Long.MAX_VALUE; + fromPreQueue = nextPre < nextQueued; + qd = fromPreQueue ? mPreQueue : mTouchEventQueue; + } + } + + /** + * Add a TouchEventData to the pre-queue. + * + * An event in the pre-queue is an event that we know about that + * has been sent to webkit, but that we haven't received back and + * enqueued into the normal touch queue yet. If webkit ever times + * out and we need to ignore currently missing events, we'll run + * events from the pre-queue to patch the holes. + * + * @param ted TouchEventData to pre-queue + */ + public void preQueueTouchEventData(TouchEventData ted) { + QueuedTouch newTouch = obtainQueuedTouch().set(ted); + if (mPreQueue == null) { + mPreQueue = newTouch; + } else { + QueuedTouch insertionPoint = mPreQueue; + while (insertionPoint.mNext != null && + insertionPoint.mNext.mSequence < newTouch.mSequence) { + insertionPoint = insertionPoint.mNext; + } + newTouch.mNext = insertionPoint.mNext; + insertionPoint.mNext = newTouch; + } } private void recycleQueuedTouch(QueuedTouch qd) { @@ -7252,6 +7316,11 @@ public class WebView extends AbsoluteLayout mTouchEventQueue = mTouchEventQueue.mNext; recycleQueuedTouch(recycleMe); } + while (mPreQueue != null) { + QueuedTouch recycleMe = mPreQueue; + mPreQueue = mPreQueue.mNext; + recycleQueuedTouch(recycleMe); + } } /** @@ -7274,6 +7343,28 @@ public class WebView extends AbsoluteLayout * @return true if the event was processed before returning, false if it was just enqueued. */ public boolean enqueueTouchEvent(TouchEventData ted) { + // Remove from the pre-queue if present + QueuedTouch preQueue = mPreQueue; + if (preQueue != null) { + // On exiting this block, preQueue is set to the pre-queued QueuedTouch object + // if it was present in the pre-queue, and removed from the pre-queue itself. + if (preQueue.mSequence == ted.mSequence) { + mPreQueue = preQueue.mNext; + } else { + QueuedTouch prev = preQueue; + preQueue = null; + while (prev.mNext != null) { + if (prev.mNext.mSequence == ted.mSequence) { + preQueue = prev.mNext; + prev.mNext = preQueue.mNext; + break; + } else { + prev = prev.mNext; + } + } + } + } + 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) + @@ -7285,23 +7376,24 @@ public class WebView extends AbsoluteLayout return false; } + // dropStaleGestures above might have fast-forwarded us to + // an event we have already. + runNextQueuedEvents(); + if (mLastHandledTouchSequence + 1 == ted.mSequence) { + if (preQueue != null) { + recycleQueuedTouch(preQueue); + preQueue = null; + } handleQueuedTouchEventData(ted); mLastHandledTouchSequence++; // Do we have any more? Run them if so. - QueuedTouch qd = mTouchEventQueue; - while (qd != null && qd.mSequence == mLastHandledTouchSequence + 1) { - handleQueuedTouch(qd); - QueuedTouch recycleMe = qd; - qd = qd.mNext; - recycleQueuedTouch(recycleMe); - mLastHandledTouchSequence++; - } - mTouchEventQueue = qd; + runNextQueuedEvents(); } else { - QueuedTouch qd = obtainQueuedTouch().set(ted); + // Reuse the pre-queued object if we had it. + QueuedTouch qd = preQueue != null ? preQueue : obtainQueuedTouch().set(ted); mTouchEventQueue = mTouchEventQueue == null ? qd : mTouchEventQueue.add(qd); } return true; @@ -7323,27 +7415,35 @@ public class WebView extends AbsoluteLayout return; } + // dropStaleGestures above might have fast-forwarded us to + // an event we have already. + runNextQueuedEvents(); + if (mLastHandledTouchSequence + 1 == sequence) { handleQueuedMotionEvent(ev); mLastHandledTouchSequence++; // Do we have any more? Run them if so. - QueuedTouch qd = mTouchEventQueue; - while (qd != null && qd.mSequence == mLastHandledTouchSequence + 1) { - handleQueuedTouch(qd); - QueuedTouch recycleMe = qd; - qd = qd.mNext; - recycleQueuedTouch(recycleMe); - mLastHandledTouchSequence++; - } - mTouchEventQueue = qd; + runNextQueuedEvents(); } else { QueuedTouch qd = obtainQueuedTouch().set(ev, sequence); mTouchEventQueue = mTouchEventQueue == null ? qd : mTouchEventQueue.add(qd); } } + private void runNextQueuedEvents() { + QueuedTouch qd = mTouchEventQueue; + while (qd != null && qd.mSequence == mLastHandledTouchSequence + 1) { + handleQueuedTouch(qd); + QueuedTouch recycleMe = qd; + qd = qd.mNext; + recycleQueuedTouch(recycleMe); + mLastHandledTouchSequence++; + } + mTouchEventQueue = qd; + } + 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 @@ -7363,13 +7463,16 @@ public class WebView extends AbsoluteLayout } // If we have a new down event and it's been a while since the last event - // we saw, just reset and keep going. + // we saw, catch up as best we can and keep going. if (ev != null && ev.getAction() == MotionEvent.ACTION_DOWN) { long eventTime = ev.getEventTime(); 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."); + "Catching up."); + runQueuedAndPreQueuedEvents(); + + // Drop leftovers that we truly don't have. QueuedTouch qd = mTouchEventQueue; while (qd != null && qd.mSequence < sequence) { QueuedTouch recycleMe = qd; @@ -7392,6 +7495,17 @@ public class WebView extends AbsoluteLayout mLastHandledTouchSequence = mIgnoreUntilSequence - 1; } + if (mPreQueue != null) { + // Drop stale prequeued events + QueuedTouch qd = mPreQueue; + while (qd != null && qd.mSequence < mIgnoreUntilSequence) { + QueuedTouch recycleMe = qd; + qd = qd.mNext; + recycleQueuedTouch(recycleMe); + } + mPreQueue = qd; + } + return sequence <= mLastHandledTouchSequence; } @@ -7641,6 +7755,7 @@ public class WebView extends AbsoluteLayout ted.mPoints[0].x, ted.mPoints[0].y, ted.mNativeLayerRect, null); ted.mSequence = mTouchEventQueue.nextTouchSequence(); + mTouchEventQueue.preQueueTouchEventData(ted); mWebViewCore.sendMessage(EventHub.TOUCH_EVENT, ted); } else if (mPreventDefault != PREVENT_DEFAULT_YES) { mTouchMode = TOUCH_DONE_MODE; |