Bug 1194876. Reset the input state on an APZC if a new touch block targets a new APZC while there were touches still active. r=botond

--HG--
extra : commitid : LO0sHCo3M3F
This commit is contained in:
Kartikaya Gupta 2015-08-25 07:50:01 -04:00
Родитель d324c5c3c5
Коммит ffe3909665
5 изменённых файлов: 50 добавлений и 23 удалений

Просмотреть файл

@ -730,24 +730,7 @@ APZCTreeManager::ProcessTouchInput(MultiTouchInput& aInput,
}
mHitResultForInputBlock = HitNothing;
nsRefPtr<AsyncPanZoomController> apzc = GetTouchInputBlockAPZC(aInput, &mHitResultForInputBlock);
// XXX the following check assumes mHitResultForInputBlock == HitLayer
// (and that mApzcForInputBlock was the confirmed target of the previous
// input block). Eventually it would be better to move this into InputQueue
// and have it auto-generated when we start processing events in a new
// event block.
if (apzc != mApzcForInputBlock) {
// If we're moving to a different APZC as our input target, then send a cancel event
// to the old one so that it clears its internal state. Otherwise it could get left
// in the middle of a panning touch block (for example) and not clean up properly.
if (mApzcForInputBlock) {
MultiTouchInput cancel(MultiTouchInput::MULTITOUCH_CANCEL, 0, TimeStamp::Now(), 0);
mInputQueue->ReceiveInputEvent(mApzcForInputBlock,
/* aTargetConfirmed = */ true, cancel, nullptr);
}
mApzcForInputBlock = apzc;
}
mApzcForInputBlock = GetTouchInputBlockAPZC(aInput, &mHitResultForInputBlock);
} else if (mApzcForInputBlock) {
APZCTM_LOG("Re-using APZC %p as continuation of event block\n", mApzcForInputBlock.get());
}

Просмотреть файл

@ -151,6 +151,12 @@ CancelableBlockState::DispatchImmediate(const InputData& aEvent) const
{
MOZ_ASSERT(!HasEvents());
MOZ_ASSERT(GetTargetApzc());
DispatchEvent(aEvent);
}
void
CancelableBlockState::DispatchEvent(const InputData& aEvent) const
{
GetTargetApzc()->HandleInputEvent(aEvent, mTransformToApzc);
}
@ -273,7 +279,7 @@ WheelBlockState::HandleEvents()
TBS_LOG("%p returning first of %" PRIuSIZE " events\n", this, mEvents.Length());
ScrollWheelInput event = mEvents[0];
mEvents.RemoveElementAt(0);
GetTargetApzc()->HandleInputEvent(event, mTransformToApzc);
DispatchEvent(event);
}
}
@ -416,11 +422,12 @@ WheelBlockState::EndTransaction()
}
TouchBlockState::TouchBlockState(const nsRefPtr<AsyncPanZoomController>& aTargetApzc,
bool aTargetConfirmed)
bool aTargetConfirmed, TouchCounter& aCounter)
: CancelableBlockState(aTargetApzc, aTargetConfirmed)
, mAllowedTouchBehaviorSet(false)
, mDuringFastFling(false)
, mSingleTapOccurred(false)
, mTouchCounter(aCounter)
{
TBS_LOG("Creating %p\n", this);
}
@ -542,10 +549,18 @@ TouchBlockState::HandleEvents()
TBS_LOG("%p returning first of %" PRIuSIZE " events\n", this, mEvents.Length());
MultiTouchInput event = mEvents[0];
mEvents.RemoveElementAt(0);
GetTargetApzc()->HandleInputEvent(event, mTransformToApzc);
DispatchEvent(event);
}
}
void
TouchBlockState::DispatchEvent(const InputData& aEvent) const
{
MOZ_ASSERT(aEvent.mInputType == MULTITOUCH_INPUT);
mTouchCounter.Update(aEvent.AsMultiTouchInput());
CancelableBlockState::DispatchEvent(aEvent);
}
bool
TouchBlockState::TouchActionAllowsPinchZoom() const
{

Просмотреть файл

@ -117,6 +117,12 @@ public:
*/
void DispatchImmediate(const InputData& aEvent) const;
/**
* Dispatch the event to the target APZC. Mostly this is a hook for
* subclasses to do any per-event processing they need to.
*/
virtual void DispatchEvent(const InputData& aEvent) const;
/**
* @return true iff this block has received all the information needed
* to properly dispatch the events in the block.
@ -268,7 +274,7 @@ class TouchBlockState : public CancelableBlockState
{
public:
explicit TouchBlockState(const nsRefPtr<AsyncPanZoomController>& aTargetApzc,
bool aTargetConfirmed);
bool aTargetConfirmed, TouchCounter& aTouchCounter);
TouchBlockState *AsTouchBlock() override {
return this;
@ -344,6 +350,7 @@ public:
bool HasEvents() const override;
void DropEvents() override;
void HandleEvents() override;
void DispatchEvent(const InputData& aEvent) const override;
bool MustStayActive() override;
const char* Type() override;
@ -353,6 +360,8 @@ private:
bool mDuringFastFling;
bool mSingleTapOccurred;
nsTArray<MultiTouchInput> mEvents;
// A reference to the InputQueue's touch counter
TouchCounter& mTouchCounter;
};
} // namespace layers

Просмотреть файл

@ -64,6 +64,7 @@ InputQueue::MaybeHandleCurrentBlock(CancelableBlockState *block,
if (!target || block->IsDefaultPrevented()) {
return true;
}
UpdateActiveApzc(block->GetTargetApzc());
block->DispatchImmediate(aEvent);
return true;
}
@ -282,7 +283,8 @@ InputQueue::StartNewTouchBlock(const nsRefPtr<AsyncPanZoomController>& aTarget,
bool aTargetConfirmed,
bool aCopyPropertiesFromCurrent)
{
TouchBlockState* newBlock = new TouchBlockState(aTarget, aTargetConfirmed);
TouchBlockState* newBlock = new TouchBlockState(aTarget, aTargetConfirmed,
mTouchCounter);
if (aCopyPropertiesFromCurrent) {
newBlock->CopyPropertiesFrom(*CurrentTouchBlock());
}
@ -449,6 +451,7 @@ InputQueue::ProcessInputBlocks() {
curBlock->DropEvents();
target->ResetInputState();
} else {
UpdateActiveApzc(curBlock->GetTargetApzc());
curBlock->HandleEvents();
}
MOZ_ASSERT(!curBlock->HasEvents());
@ -468,12 +471,22 @@ InputQueue::ProcessInputBlocks() {
} while (!mInputBlockQueue.IsEmpty());
}
void
InputQueue::UpdateActiveApzc(const nsRefPtr<AsyncPanZoomController>& aNewActive) {
if (mLastActiveApzc && mLastActiveApzc != aNewActive
&& mTouchCounter.GetActiveTouchCount() > 0) {
mLastActiveApzc->ResetInputState();
}
mLastActiveApzc = aNewActive;
}
void
InputQueue::Clear()
{
APZThreadUtils::AssertOnControllerThread();
mInputBlockQueue.Clear();
mLastActiveApzc = nullptr;
}
} // namespace layers

Просмотреть файл

@ -147,11 +147,18 @@ private:
void ScheduleMainThreadTimeout(const nsRefPtr<AsyncPanZoomController>& aTarget, uint64_t aInputBlockId);
void MainThreadTimeout(const uint64_t& aInputBlockId);
void ProcessInputBlocks();
void UpdateActiveApzc(const nsRefPtr<AsyncPanZoomController>& aNewActive);
private:
// The queue of touch blocks that have not yet been fully processed.
// This member must only be accessed on the controller/UI thread.
nsTArray<UniquePtr<CancelableBlockState>> mInputBlockQueue;
// The APZC to which the last event was delivered
nsRefPtr<AsyncPanZoomController> mLastActiveApzc;
// Track touches so we know when to clear mLastActiveApzc
TouchCounter mTouchCounter;
};
} // namespace layers