diff options
| author | 2011-04-05 11:14:27 -0700 | |
|---|---|---|
| committer | 2011-04-05 11:14:27 -0700 | |
| commit | 2bb59637caa71d7e05f7c94d3da425fbfd425ea7 (patch) | |
| tree | 6d7d7a522e8bf828568c4b75675341122c84936a | |
| parent | f0d2c1c4eb613130e34a4f377d8f82f935170873 (diff) | |
| parent | 030b38ffc21ef3962b31d5bac5170531293b6046 (diff) | |
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
| -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 a3ced9e1f2c1..57d61087b977 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;  |