Bug 1121353 - Implement SynthesizeNativeTouchPoint in the gonk widget to allow injecting touch events into APZ. r=mwu

This commit is contained in:
Kartikaya Gupta 2015-01-20 00:38:00 +01:00
parent a4a3c0a4d7
commit e116db3134
6 changed files with 101 additions and 14 deletions

View File

@ -664,8 +664,8 @@ interface nsIDOMWindowUtils : nsISupports {
* drag - msg1-n:TOUCH_CONTACT (moving), msgn+1:TOUCH_REMOVE
* hover drag - msg1-n:TOUCH_HOVER (moving), msgn+1:TOUCH_REMOVE
*
* Widget support: Windows 8.0+, Winrt/Win32. Other widgets will
* throw.
* Widget support: Windows 8.0+, Winrt/Win32. Gonk supports CONTACT, REMOVE,
* and CANCEL but no HOVER. Other widgets will throw.
*
* @param aPointerId The touch point id to create or update.
* @param aTouchState one or more of the touch states listed above

View File

@ -158,6 +158,17 @@ MultiTouchInput::ToWidgetMouseEvent(nsIWidget* aWidget) const
return event;
}
int32_t
MultiTouchInput::IndexOfTouch(int32_t aTouchIdentifier)
{
for (size_t i = 0; i < mTouches.Length(); i++) {
if (mTouches[i].mIdentifier == aTouchIdentifier) {
return (int32_t)i;
}
}
return -1;
}
// This conversion from WidgetMouseEvent to MultiTouchInput is needed because on
// the B2G emulator we can only receive mouse events, but we need to be able
// to pan correctly. To do this, we convert the events into a format that the

View File

@ -222,6 +222,10 @@ public:
WidgetTouchEvent ToWidgetTouchEvent(nsIWidget* aWidget) const;
WidgetMouseEvent ToWidgetMouseEvent(nsIWidget* aWidget) const;
// Return the index into mTouches of the SingleTouchData with the given
// identifier, or -1 if there is no such SingleTouchData.
int32_t IndexOfTouch(int32_t aTouchIdentifier);
// This conversion from WidgetMouseEvent to MultiTouchInput is needed because
// on the B2G emulator we can only receive mouse events, but we need to be
// able to pan correctly. To do this, we convert the events into a format that

View File

@ -224,19 +224,15 @@ Interpolate(int start, int end, TimeDuration aFrameDiff, TimeDuration aTouchDiff
static const SingleTouchData&
GetTouchByID(const SingleTouchData& aCurrentTouch, MultiTouchInput& aOtherTouch)
{
int32_t id = aCurrentTouch.mIdentifier;
for (size_t i = 0; i < aOtherTouch.mTouches.Length(); i++) {
SingleTouchData& touch = aOtherTouch.mTouches[i];
if (touch.mIdentifier == id) {
return touch;
}
int32_t index = aOtherTouch.IndexOfTouch(aCurrentTouch.mIdentifier);
if (index < 0) {
// We can have situations where a previous touch event had 2 fingers
// and we lift 1 finger off. In those cases, we won't find the touch event
// with given id, so just return the current touch, which will be resampled
// without modification and dispatched.
return aCurrentTouch;
}
// We can have situations where a previous touch event had 2 fingers
// and we lift 1 finger off. In those cases, we won't find the touch event
// with given id, so just return the current touch, which will be resampled
// without modification and dispatched.
return aCurrentTouch;
return aOtherTouch.mTouches[index];
}

View File

@ -300,6 +300,71 @@ nsWindow::DispatchTouchInputViaAPZ(MultiTouchInput& aInput)
}
}
nsresult
nsWindow::SynthesizeNativeTouchPoint(uint32_t aPointerId,
TouchPointerState aPointerState,
nsIntPoint aPointerScreenPoint,
double aPointerPressure,
uint32_t aPointerOrientation)
{
if (aPointerState == TOUCH_HOVER) {
return NS_ERROR_UNEXPECTED;
}
if (!mSynthesizedTouchInput) {
mSynthesizedTouchInput = new MultiTouchInput();
}
// We can't dispatch mSynthesizedTouchInput directly because (a) dispatching
// it might inadvertently modify it and (b) in the case of touchend or
// touchcancel events mSynthesizedTouchInput will hold the touches that are
// still down whereas the input dispatched needs to hold the removed
// touch(es). We use |inputToDispatch| for this purpose.
MultiTouchInput inputToDispatch;
inputToDispatch.mInputType = MULTITOUCH_INPUT;
int32_t index = mSynthesizedTouchInput->IndexOfTouch((int32_t)aPointerId);
if (aPointerState == TOUCH_CONTACT) {
if (index >= 0) {
// found an existing touch point, update it
SingleTouchData& point = mSynthesizedTouchInput->mTouches[index];
point.mScreenPoint = ScreenIntPoint::FromUntyped(aPointerScreenPoint);
point.mRotationAngle = (float)aPointerOrientation;
point.mForce = (float)aPointerPressure;
inputToDispatch.mType = MultiTouchInput::MULTITOUCH_MOVE;
} else {
// new touch point, add it
mSynthesizedTouchInput->mTouches.AppendElement(SingleTouchData(
(int32_t)aPointerId,
ScreenIntPoint::FromUntyped(aPointerScreenPoint),
ScreenSize(0, 0),
(float)aPointerOrientation,
(float)aPointerPressure));
inputToDispatch.mType = MultiTouchInput::MULTITOUCH_START;
}
inputToDispatch.mTouches = mSynthesizedTouchInput->mTouches;
} else {
MOZ_ASSERT(aPointerState == TOUCH_REMOVE || aPointerState == TOUCH_CANCEL);
// a touch point is being lifted, so remove it from the stored list
if (index >= 0) {
mSynthesizedTouchInput->mTouches.RemoveElementAt(index);
}
inputToDispatch.mType = (aPointerState == TOUCH_REMOVE
? MultiTouchInput::MULTITOUCH_END
: MultiTouchInput::MULTITOUCH_CANCEL);
inputToDispatch.mTouches.AppendElement(SingleTouchData(
(int32_t)aPointerId,
ScreenIntPoint::FromUntyped(aPointerScreenPoint),
ScreenSize(0, 0),
(float)aPointerOrientation,
(float)aPointerPressure));
}
DispatchTouchInputViaAPZ(inputToDispatch);
return NS_OK;
}
NS_IMETHODIMP
nsWindow::Create(nsIWidget *aParent,
void *aNativeParent,

View File

@ -90,6 +90,12 @@ public:
void DispatchTouchInputViaAPZ(mozilla::MultiTouchInput& aInput);
NS_IMETHOD DispatchEvent(mozilla::WidgetGUIEvent* aEvent,
nsEventStatus& aStatus);
virtual nsresult SynthesizeNativeTouchPoint(uint32_t aPointerId,
TouchPointerState aPointerState,
nsIntPoint aPointerScreenPoint,
double aPointerPressure,
uint32_t aPointerOrientation) MOZ_OVERRIDE;
NS_IMETHOD CaptureRollupEvents(nsIRollupListener *aListener,
bool aDoCapture)
{
@ -147,6 +153,11 @@ protected:
// Call this function when the users activity is the direct cause of an
// event (like a keypress or mouse click).
void UserActivity();
private:
// This is used by SynthesizeNativeTouchPoint to maintain state between
// multiple synthesized points
nsAutoPtr<mozilla::MultiTouchInput> mSynthesizedTouchInput;
};
#endif /* nsWindow_h */