Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 80615b00 authored by Adam Powell's avatar Adam Powell
Browse files

Fix bug 4080407 - Browser stuck after scrolling- page stops responding

Account for gaps in touch queue sequence numbering when we flush out
canceled events from webcore's queue. Add a 2-second timeout to auto-flush
old events when a new gesture begins.

Change-Id: I764a7fcd673b3afb629055b001e9346f5b959dba
parent 0837fde9
Loading
Loading
Loading
Loading
+59 −0
Original line number Diff line number Diff line
@@ -6019,6 +6019,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];
@@ -7157,11 +7158,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;
@@ -7172,6 +7177,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;
@@ -7187,6 +7199,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;
@@ -7213,6 +7226,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);

@@ -7245,6 +7267,9 @@ public class WebView extends AbsoluteLayout
         */
        public void enqueueTouchEvent(MotionEvent ev) {
            final long sequence = nextTouchSequence();

            dropStaleGestures(ev, sequence);

            if (mLastHandledTouchSequence + 1 == sequence) {
                handleQueuedMotionEvent(ev);

@@ -7266,6 +7291,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);