зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
d324c5c3c5
Коммит
ffe3909665
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче