Bug 931504 - Fire touchcancel to content for every touch point the apz consumes. r=tabraldes

This commit is contained in:
Jim Mathies 2013-10-29 20:51:00 -05:00
parent 10f67f2dba
commit 7f75a05c86
2 changed files with 31 additions and 15 deletions

View File

@ -487,7 +487,7 @@ MetroInput::OnPointerPressed(UI::Core::ICoreWindow* aSender,
mTouchMoveDefaultPrevented = false; mTouchMoveDefaultPrevented = false;
mIsFirstTouchMove = true; mIsFirstTouchMove = true;
mCancelable = true; mCancelable = true;
mTouchCancelSent = false; mCanceledIds.Clear();
InitTouchEventTouchList(touchEvent); InitTouchEventTouchList(touchEvent);
DispatchAsyncTouchEventWithCallback(touchEvent, &MetroInput::OnPointerPressedCallback); DispatchAsyncTouchEventWithCallback(touchEvent, &MetroInput::OnPointerPressedCallback);
} else { } else {
@ -1217,6 +1217,10 @@ MetroInput::DeliverNextQueuedTouchEvent()
* a touchcancel to content and do not deliver any additional events there. * a touchcancel to content and do not deliver any additional events there.
* (If the apz is doing something with the events we can save ourselves * (If the apz is doing something with the events we can save ourselves
* the overhead of delivering dom events.) * the overhead of delivering dom events.)
*
* Notes:
* - never rely on the contents of mTouches here, since this is a delayed
* callback. mTouches will likely have been modified.
*/ */
// Test for chrome vs. content target. To do this we only use the first touch // Test for chrome vs. content target. To do this we only use the first touch
@ -1247,10 +1251,7 @@ MetroInput::DeliverNextQueuedTouchEvent()
WidgetTouchEvent transformedEvent(*event); WidgetTouchEvent transformedEvent(*event);
status = mWidget->ApzReceiveInputEvent(event, &transformedEvent); status = mWidget->ApzReceiveInputEvent(event, &transformedEvent);
if (!mCancelable && status == nsEventStatus_eConsumeNoDefault) { if (!mCancelable && status == nsEventStatus_eConsumeNoDefault) {
if (!mTouchCancelSent) { DispatchTouchCancel(event);
mTouchCancelSent = true;
DispatchTouchCancel();
}
return status; return status;
} }
@ -1261,16 +1262,31 @@ MetroInput::DeliverNextQueuedTouchEvent()
} }
void void
MetroInput::DispatchTouchCancel() MetroInput::DispatchTouchCancel(WidgetTouchEvent* aEvent)
{ {
LogFunction(); MOZ_ASSERT(aEvent);
// From the spec: The touch point or points that were removed must be // Send a touchcancel for each pointer id we have a corresponding start
// included in the changedTouches attribute of the TouchEvent, and must // for. Note we can't rely on mTouches here since touchends remove points
// not be included in the touches and targetTouches attributes. // from it. The only time we end up in here is if the apz is consuming
// (We are 'removing' all touch points that have been sent to content // events, so this array shouldn't be very large.
// thus far.)
WidgetTouchEvent touchEvent(true, NS_TOUCH_CANCEL, mWidget.Get()); WidgetTouchEvent touchEvent(true, NS_TOUCH_CANCEL, mWidget.Get());
InitTouchEventTouchList(&touchEvent); nsTArray< nsRefPtr<dom::Touch> >& touches = aEvent->touches;
for (uint32_t i = 0; i < touches.Length(); ++i) {
dom::Touch* touch = touches[i];
if (!touch) {
continue;
}
int32_t id = touch->Identifier();
if (mCanceledIds.Contains(id)) {
continue;
}
mCanceledIds.AppendElement(id);
touchEvent.touches.AppendElement(touch);
}
if (!touchEvent.touches.Length()) {
return;
}
mWidget->DispatchEvent(&touchEvent, sThrowawayStatus); mWidget->DispatchEvent(&touchEvent, sThrowawayStatus);
} }

View File

@ -211,7 +211,7 @@ private:
bool mTouchMoveDefaultPrevented; bool mTouchMoveDefaultPrevented;
bool mIsFirstTouchMove; bool mIsFirstTouchMove;
bool mCancelable; bool mCancelable;
bool mTouchCancelSent; nsTArray<uint32_t> mCanceledIds;
// In the old Win32 way of doing things, we would receive a WM_TOUCH event // In the old Win32 way of doing things, we would receive a WM_TOUCH event
// that told us the state of every touchpoint on the touch surface. If // that told us the state of every touchpoint on the touch surface. If
@ -287,7 +287,7 @@ private:
// Sync event dispatching // Sync event dispatching
void DispatchEventIgnoreStatus(WidgetGUIEvent* aEvent); void DispatchEventIgnoreStatus(WidgetGUIEvent* aEvent);
void DispatchTouchCancel(); void DispatchTouchCancel(WidgetTouchEvent* aEvent);
nsDeque mInputEventQueue; nsDeque mInputEventQueue;
static nsEventStatus sThrowawayStatus; static nsEventStatus sThrowawayStatus;