From 8449555fb02105fcc4a44f2974cc157d1e2730f7 Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Mon, 9 Mar 2015 12:46:04 -0400 Subject: [PATCH] Bug 1140578 - Prevent resampling moves across non-move touch events. r=mchang --- widget/gonk/GeckoTouchDispatcher.cpp | 37 +++++++++++++++++++++++++++- widget/gonk/GeckoTouchDispatcher.h | 2 ++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/widget/gonk/GeckoTouchDispatcher.cpp b/widget/gonk/GeckoTouchDispatcher.cpp index 2963dd95f71f..efde013f2481 100644 --- a/widget/gonk/GeckoTouchDispatcher.cpp +++ b/widget/gonk/GeckoTouchDispatcher.cpp @@ -64,6 +64,7 @@ GeckoTouchDispatcher::GetInstance() GeckoTouchDispatcher::GeckoTouchDispatcher() : mTouchQueueLock("GeckoTouchDispatcher::mTouchQueueLock") , mHavePendingTouchMoves(false) + , mInflightNonMoveEvents(0) , mTouchEventsFiltered(false) { // Since GeckoTouchDispatcher is initialized when input is initialized @@ -112,6 +113,16 @@ GeckoTouchDispatcher::NotifyTouch(MultiTouchInput& aTouch, TimeStamp aEventTime) if (aTouch.mType == MultiTouchInput::MULTITOUCH_MOVE) { MutexAutoLock lock(mTouchQueueLock); + if (mInflightNonMoveEvents > 0) { + // If we have any pending non-move events, we shouldn't resample the + // move events because we might end up dispatching events out of order. + // Instead, fall back to a non-resampling in-order dispatch until we're + // done processing the non-move events. + layers::APZThreadUtils::RunOnControllerThread(NewRunnableMethod( + this, &GeckoTouchDispatcher::DispatchTouchEvent, aTouch)); + return; + } + mTouchMoveEvents.push_back(aTouch); mHavePendingTouchMoves = true; if (mResamplingEnabled) { @@ -121,8 +132,32 @@ GeckoTouchDispatcher::NotifyTouch(MultiTouchInput& aTouch, TimeStamp aEventTime) layers::APZThreadUtils::RunOnControllerThread(NewRunnableMethod( this, &GeckoTouchDispatcher::DispatchTouchMoveEvents, TimeStamp::Now())); } else { + if (mResamplingEnabled) { + MutexAutoLock lock(mTouchQueueLock); + mInflightNonMoveEvents++; + } layers::APZThreadUtils::RunOnControllerThread(NewRunnableMethod( - this, &GeckoTouchDispatcher::DispatchTouchEvent, aTouch)); + this, &GeckoTouchDispatcher::DispatchTouchNonMoveEvent, aTouch)); + } +} + +void +GeckoTouchDispatcher::DispatchTouchNonMoveEvent(MultiTouchInput aInput) +{ + layers::APZThreadUtils::AssertOnControllerThread(); + + if (mResamplingEnabled) { + // Flush pending touch move events, if there are any + // (DispatchTouchMoveEvents will check the mHavePendingTouchMoves flag and + // bail out if there's nothing to be done). + NotifyVsync(TimeStamp::Now()); + } + DispatchTouchEvent(aInput); + + if (mResamplingEnabled) { + MutexAutoLock lock(mTouchQueueLock); + mInflightNonMoveEvents--; + MOZ_ASSERT(mInflightNonMoveEvents >= 0); } } diff --git a/widget/gonk/GeckoTouchDispatcher.h b/widget/gonk/GeckoTouchDispatcher.h index 60973087f096..ef5e8aba90ba 100644 --- a/widget/gonk/GeckoTouchDispatcher.h +++ b/widget/gonk/GeckoTouchDispatcher.h @@ -49,6 +49,7 @@ public: static GeckoTouchDispatcher* GetInstance(); void NotifyTouch(MultiTouchInput& aTouch, TimeStamp aEventTime); void DispatchTouchEvent(MultiTouchInput aMultiTouch); + void DispatchTouchNonMoveEvent(MultiTouchInput aInput); void DispatchTouchMoveEvents(TimeStamp aVsyncTime); void NotifyVsync(TimeStamp aVsyncTimestamp); void SetCompositorVsyncObserver(layers::CompositorVsyncObserver* aObserver); @@ -65,6 +66,7 @@ private: Mutex mTouchQueueLock; std::vector mTouchMoveEvents; bool mHavePendingTouchMoves; + int mInflightNonMoveEvents; // end stuff protected by mTouchQueueLock bool mResamplingEnabled;