зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1022719 - Ignore additional touches when in overscrolled state. r=kats
This commit is contained in:
Родитель
39d2cd0d1b
Коммит
e8a12a2e30
|
@ -40,6 +40,7 @@ static bool gPrintApzcTree = false;
|
|||
APZCTreeManager::APZCTreeManager()
|
||||
: mTreeLock("APZCTreeLock"),
|
||||
mInOverscrolledApzc(false),
|
||||
mRetainedTouchIdentifier(-1),
|
||||
mTouchCount(0),
|
||||
mApzcTreeLog("apzctree")
|
||||
{
|
||||
|
@ -379,6 +380,16 @@ APZCTreeManager::ReceiveInputEvent(const InputData& aEvent,
|
|||
case MULTITOUCH_INPUT: {
|
||||
const MultiTouchInput& multiTouchInput = aEvent.AsMultiTouchInput();
|
||||
if (multiTouchInput.mType == MultiTouchInput::MULTITOUCH_START) {
|
||||
// If we are in an overscrolled state and a second finger goes down,
|
||||
// ignore that second touch point completely. The touch-start for it is
|
||||
// dropped completely; subsequent touch events until the touch-end for it
|
||||
// will have this touch point filtered out.
|
||||
if (mApzcForInputBlock && mApzcForInputBlock->IsOverscrolled()) {
|
||||
if (mRetainedTouchIdentifier == -1) {
|
||||
mRetainedTouchIdentifier = mApzcForInputBlock->GetLastTouchIdentifier();
|
||||
}
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
// MULTITOUCH_START input contains all active touches of the current
|
||||
// session thus resetting mTouchCount.
|
||||
mTouchCount = multiTouchInput.mTouches.Length();
|
||||
|
@ -412,13 +423,43 @@ APZCTreeManager::ReceiveInputEvent(const InputData& aEvent,
|
|||
} else if (mApzcForInputBlock) {
|
||||
APZCTM_LOG("Re-using APZC %p as continuation of event block\n", mApzcForInputBlock.get());
|
||||
}
|
||||
|
||||
// If we receive a touch-cancel, it means all touches are finished, so we
|
||||
// can stop ignoring any that we were ignoring.
|
||||
if (multiTouchInput.mType == MultiTouchInput::MULTITOUCH_CANCEL) {
|
||||
mRetainedTouchIdentifier = -1;
|
||||
}
|
||||
|
||||
if (mApzcForInputBlock) {
|
||||
mApzcForInputBlock->GetGuid(aOutTargetGuid);
|
||||
// Use the cached transform to compute the point to send to the APZC.
|
||||
// This ensures that the sequence of touch points an APZC sees in an
|
||||
// input block are all in the same coordinate space.
|
||||
transformToApzc = mCachedTransformToApzcForInputBlock;
|
||||
|
||||
// Make a copy of the input event that we pass, with some modifications,
|
||||
// to the target APZC.
|
||||
MultiTouchInput inputForApzc(multiTouchInput);
|
||||
|
||||
// If we are currently ignoring any touch points, filter them out from
|
||||
// the set of touch points included in this event.
|
||||
if (mRetainedTouchIdentifier != -1) {
|
||||
for (size_t j = 0; j < inputForApzc.mTouches.Length(); ++j) {
|
||||
if (inputForApzc.mTouches[j].mIdentifier != mRetainedTouchIdentifier) {
|
||||
// TODO(botond): Once we get rid of ReceiveInputEvent(WidgetInputEvent),
|
||||
// the signature of this function will change to take the InputData
|
||||
// via non-const reference. We can then remove the touch point from
|
||||
// multiTouchInput rather than the copy (inputForApzc), so that
|
||||
// content doesn't get it either.
|
||||
inputForApzc.mTouches.RemoveElementAt(j);
|
||||
--j;
|
||||
}
|
||||
}
|
||||
if (inputForApzc.mTouches.IsEmpty()) {
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < inputForApzc.mTouches.Length(); i++) {
|
||||
ApplyTransform(&(inputForApzc.mTouches[i].mScreenPoint), transformToApzc);
|
||||
}
|
||||
|
@ -441,6 +482,7 @@ APZCTreeManager::ReceiveInputEvent(const InputData& aEvent,
|
|||
if (mTouchCount == 0) {
|
||||
mApzcForInputBlock = nullptr;
|
||||
mInOverscrolledApzc = false;
|
||||
mRetainedTouchIdentifier = -1;
|
||||
ClearOverscrollHandoffChain();
|
||||
}
|
||||
}
|
||||
|
@ -538,6 +580,16 @@ APZCTreeManager::ProcessTouchEvent(WidgetTouchEvent& aEvent,
|
|||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
if (aEvent.message == NS_TOUCH_START) {
|
||||
// If we are in an overscrolled state and a second finger goes down,
|
||||
// ignore that second touch point completely. The touch-start for it is
|
||||
// dropped completely; subsequent touch events until the touch-end for it
|
||||
// will have this touch point filtered out.
|
||||
if (mApzcForInputBlock && mApzcForInputBlock->IsOverscrolled()) {
|
||||
if (mRetainedTouchIdentifier == -1) {
|
||||
mRetainedTouchIdentifier = mApzcForInputBlock->GetLastTouchIdentifier();
|
||||
}
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
// NS_TOUCH_START event contains all active touches of the current
|
||||
// session thus resetting mTouchCount.
|
||||
mTouchCount = aEvent.touches.Length();
|
||||
|
@ -553,6 +605,28 @@ APZCTreeManager::ProcessTouchEvent(WidgetTouchEvent& aEvent,
|
|||
}
|
||||
}
|
||||
|
||||
// If we receive a touch-cancel, it means all touches are finished, so we
|
||||
// can stop ignoring any that we were ignoring.
|
||||
if (aEvent.message == NS_TOUCH_CANCEL) {
|
||||
mRetainedTouchIdentifier = -1;
|
||||
}
|
||||
|
||||
// If we are currently ignoring any touch points, filter them out from the
|
||||
// set of touch points included in this event. Note that we modify aEvent
|
||||
// itself, so that the touch points are also filtered out when the caller
|
||||
// passes the event on to content.
|
||||
if (mRetainedTouchIdentifier != -1) {
|
||||
for (size_t j = 0; j < aEvent.touches.Length(); ++j) {
|
||||
if (aEvent.touches[j]->Identifier() != mRetainedTouchIdentifier) {
|
||||
aEvent.touches.RemoveElementAt(j);
|
||||
--j;
|
||||
}
|
||||
}
|
||||
if (aEvent.touches.IsEmpty()) {
|
||||
return nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
}
|
||||
|
||||
if (mApzcForInputBlock) {
|
||||
mApzcForInputBlock->GetGuid(aOutTargetGuid);
|
||||
// For computing the input for the APZC, used the cached transform.
|
||||
|
@ -592,6 +666,7 @@ APZCTreeManager::ProcessTouchEvent(WidgetTouchEvent& aEvent,
|
|||
if (mTouchCount == 0) {
|
||||
mApzcForInputBlock = nullptr;
|
||||
mInOverscrolledApzc = false;
|
||||
mRetainedTouchIdentifier = -1;
|
||||
ClearOverscrollHandoffChain();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -377,6 +377,11 @@ private:
|
|||
* was inside an overscrolled APZC.
|
||||
*/
|
||||
bool mInOverscrolledApzc;
|
||||
/* Sometimes we want to ignore all touches except one. In such cases, this
|
||||
* is set to the identifier of the touch we are not ignoring; in other cases,
|
||||
* this is set to -1.
|
||||
*/
|
||||
int32_t mRetainedTouchIdentifier;
|
||||
/* The number of touch points we are tracking that are currently on the screen. */
|
||||
uint32_t mTouchCount;
|
||||
/* The transform from root screen coordinates into mApzcForInputBlock's
|
||||
|
|
|
@ -1842,6 +1842,11 @@ bool AsyncPanZoomController::IsPannable() const {
|
|||
return mX.CanScroll() || mY.CanScroll();
|
||||
}
|
||||
|
||||
int32_t AsyncPanZoomController::GetLastTouchIdentifier() const {
|
||||
nsRefPtr<GestureEventListener> listener = GetGestureEventListener();
|
||||
return listener ? listener->GetLastTouchIdentifier() : -1;
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::RequestContentRepaint() {
|
||||
RequestContentRepaint(mFrameMetrics);
|
||||
}
|
||||
|
|
|
@ -318,6 +318,13 @@ public:
|
|||
*/
|
||||
bool IsPannable() const;
|
||||
|
||||
/**
|
||||
* Returns the identifier of the touch in the last touch event processed by
|
||||
* this APZC. This should only be called when the last touch event contained
|
||||
* only one touch.
|
||||
*/
|
||||
int32_t GetLastTouchIdentifier() const;
|
||||
|
||||
protected:
|
||||
enum PanZoomState {
|
||||
NOTHING, /* no touch-start events received */
|
||||
|
|
|
@ -106,6 +106,16 @@ nsEventStatus GestureEventListener::HandleInputEvent(const MultiTouchInput& aEve
|
|||
return rv;
|
||||
}
|
||||
|
||||
int32_t GestureEventListener::GetLastTouchIdentifier() const
|
||||
{
|
||||
if (mTouches.Length() != 1) {
|
||||
NS_WARNING("GetLastTouchIdentifier() called when last touch event "
|
||||
"did not have one touch");
|
||||
}
|
||||
return mTouches.IsEmpty() ? -1 : mTouches[0].mIdentifier;
|
||||
}
|
||||
|
||||
|
||||
nsEventStatus GestureEventListener::HandleInputTouchSingleStart()
|
||||
{
|
||||
switch (mState) {
|
||||
|
|
|
@ -53,6 +53,13 @@ public:
|
|||
*/
|
||||
nsEventStatus HandleInputEvent(const MultiTouchInput& aEvent);
|
||||
|
||||
/**
|
||||
* Returns the identifier of the touch in the last touch event processed by
|
||||
* this GestureEventListener. This should only be called when the last touch
|
||||
* event contained only one touch.
|
||||
*/
|
||||
int32_t GetLastTouchIdentifier() const;
|
||||
|
||||
private:
|
||||
// Private destructor, to discourage deletion outside of Release():
|
||||
~GestureEventListener();
|
||||
|
|
Загрузка…
Ссылка в новой задаче