Bug 918273 - Add an apzc tree manager helper for translating device to gecko coordinate space, and use it when sending events to the dom in cases where content is consuming touch. r=kats

This commit is contained in:
Jim Mathies 2013-11-10 10:43:18 -06:00
parent 4b7c1d4e1c
commit 719c8ac7d1
8 changed files with 95 additions and 22 deletions

View File

@ -398,6 +398,24 @@ APZCTreeManager::ProcessTouchEvent(const WidgetTouchEvent& aEvent,
return ret;
}
void
APZCTreeManager::TransformCoordinateToGecko(const ScreenIntPoint& aPoint,
LayoutDeviceIntPoint* aOutTransformedPoint)
{
MOZ_ASSERT(aOutTransformedPoint);
nsRefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(aPoint);
if (apzc && aOutTransformedPoint) {
gfx3DMatrix transformToApzc;
gfx3DMatrix transformToGecko;
GetInputTransforms(apzc, transformToApzc, transformToGecko);
gfx3DMatrix outTransform = transformToApzc * transformToGecko;
aOutTransformedPoint->x = aPoint.x;
aOutTransformedPoint->y = aPoint.y;
ApplyTransform(aOutTransformedPoint, outTransform);
}
}
nsEventStatus
APZCTreeManager::ProcessMouseEvent(const WidgetMouseEvent& aEvent,
ScrollableLayerGuid* aOutTargetGuid,
@ -579,7 +597,7 @@ APZCTreeManager::HandleOverscroll(AsyncPanZoomController* aChild, ScreenPoint aS
}
bool
APZCTreeManager::HitTestAPZC(const ScreenPoint& aPoint)
APZCTreeManager::HitTestAPZC(const ScreenIntPoint& aPoint)
{
MonitorAutoLock lock(mTreeLock);
nsRefPtr<AsyncPanZoomController> target;

View File

@ -190,6 +190,15 @@ public:
nsEventStatus ReceiveInputEvent(WidgetInputEvent& aEvent,
ScrollableLayerGuid* aOutTargetGuid);
/**
* A helper for transforming coordinates to gecko coordinate space.
*
* @param aPoint point to transform
* @param aOutTransformedPoint resulting transformed point
*/
void TransformCoordinateToGecko(const ScreenIntPoint& aPoint,
LayoutDeviceIntPoint* aOutTransformedPoint);
/**
* Updates the composition bounds, i.e. the dimensions of the final size of
* the frame this is tied to during composition onto, in device pixels. In
@ -254,7 +263,7 @@ public:
/**
* Tests if a screen point intersect an apz in the tree.
*/
bool HitTestAPZC(const ScreenPoint& aPoint);
bool HitTestAPZC(const ScreenIntPoint& aPoint);
/**
* Set the dpi value used by all AsyncPanZoomControllers.

View File

@ -174,12 +174,22 @@ APZController::ContentReceivedTouch(const ScrollableLayerGuid& aGuid, bool aPrev
}
bool
APZController::HitTestAPZC(ScreenPoint& pt)
APZController::HitTestAPZC(ScreenIntPoint& aPoint)
{
if (!sAPZC) {
return false;
}
return sAPZC->HitTestAPZC(pt);
return sAPZC->HitTestAPZC(aPoint);
}
void
APZController::TransformCoordinateToGecko(const ScreenIntPoint& aPoint,
LayoutDeviceIntPoint* aRefPointOut)
{
if (!sAPZC || !aRefPointOut) {
return;
}
sAPZC->TransformCoordinateToGecko(aPoint, aRefPointOut);
}
nsEventStatus

View File

@ -38,7 +38,9 @@ public:
void SetWidgetListener(nsIWidgetListener* aWidgetListener);
void UpdateScrollOffset(const mozilla::layers::ScrollableLayerGuid& aScrollLayerId, CSSIntPoint& aScrollOffset);
bool HitTestAPZC(mozilla::ScreenPoint& pt);
bool HitTestAPZC(mozilla::ScreenIntPoint& aPoint);
void TransformCoordinateToGecko(const mozilla::ScreenIntPoint& aPoint,
LayoutDeviceIntPoint* aRefPointOut);
void ContentReceivedTouch(const ScrollableLayerGuid& aGuid, bool aPreventDefault);
nsEventStatus ReceiveInputEvent(mozilla::WidgetInputEvent* aEvent,
ScrollableLayerGuid* aOutTargetGuid);

View File

@ -668,19 +668,35 @@ MetroInput::TransformRefPoint(const Foundation::Point& aPosition, LayoutDeviceIn
{
// If this event is destined for content we need to transform our ref point through
// the apz so that zoom can be accounted for.
LayoutDeviceIntPoint pt = LayoutDeviceIntPoint::FromUntyped(MetroUtils::LogToPhys(aPosition));
aRefPointOut = pt;
aRefPointOut = LayoutDeviceIntPoint::FromUntyped(MetroUtils::LogToPhys(aPosition));
ScreenIntPoint spt;
spt.x = aRefPointOut.x;
spt.y = aRefPointOut.y;
// This is currently a general contained rect hit test, it may produce a false positive for
// overlay chrome elements.
bool apzIntersect = mWidget->ApzHitTest(mozilla::ScreenPoint(pt.x, pt.y));
if (apzIntersect && HitTestChrome(pt)) {
bool apzIntersect = mWidget->ApzHitTest(spt);
if (apzIntersect && HitTestChrome(aRefPointOut)) {
return;
}
WidgetMouseEvent event(true, NS_MOUSE_MOVE, mWidget.Get(),
WidgetMouseEvent::eReal, WidgetMouseEvent::eNormal);
event.refPoint = aRefPointOut;
mWidget->ApzReceiveInputEvent(&event, nullptr);
aRefPointOut = event.refPoint;
mWidget->ApzTransformGeckoCoordinate(spt, &aRefPointOut);
}
void
MetroInput::TransformTouchEvent(WidgetTouchEvent* aEvent)
{
nsTArray< nsRefPtr<dom::Touch> >& touches = aEvent->touches;
for (uint32_t i = 0; i < touches.Length(); ++i) {
dom::Touch* touch = touches[i];
if (touch) {
LayoutDeviceIntPoint lpt;
ScreenIntPoint spt;
spt.x = touch->mRefPoint.x;
spt.y = touch->mRefPoint.y;
mWidget->ApzTransformGeckoCoordinate(spt, &lpt);
touch->mRefPoint.x = lpt.x;
touch->mRefPoint.y = lpt.y;
}
}
}
void
@ -1115,7 +1131,7 @@ MetroInput::DeliverNextQueuedTouchEvent()
if (mCancelable && event->message == NS_TOUCH_START) {
nsRefPtr<Touch> touch = event->touches[0];
LayoutDeviceIntPoint pt = LayoutDeviceIntPoint::FromUntyped(touch->mRefPoint);
bool apzIntersect = mWidget->ApzHitTest(mozilla::ScreenPoint(pt.x, pt.y));
bool apzIntersect = mWidget->ApzHitTest(mozilla::ScreenIntPoint(pt.x, pt.y));
mChromeHitTestCacheForTouch = (apzIntersect && HitTestChrome(pt));
}
@ -1172,11 +1188,14 @@ MetroInput::DeliverNextQueuedTouchEvent()
return;
}
// Forward event data to apz. Even if content is consuming input, we still
// need APZC to transform the coordinates. It won't actually react to the
// event if ContentReceivedTouch was called previously.
DUMP_TOUCH_IDS("APZC(2)", event);
status = mWidget->ApzReceiveInputEvent(event, nullptr);
// If content is consuming touch, we need to transform event coords
// through the apzc before sending. Otherwise send the event to apzc.
if (mContentConsumingTouch) {
TransformTouchEvent(event);
} else {
DUMP_TOUCH_IDS("APZC(2)", event);
status = mWidget->ApzReceiveInputEvent(event, nullptr);
}
// If content called preventDefault on touchstart or first touchmove send
// the event to content only.

View File

@ -171,6 +171,7 @@ private:
// Event processing helpers. See function definitions for more info.
void TransformRefPoint(const Point& aPosition,
LayoutDeviceIntPoint& aRefPointOut);
void TransformTouchEvent(WidgetTouchEvent* aEvent);
void OnPointerNonTouch(IPointerPoint* aPoint);
void AddPointerMoveDataToRecognizer(IPointerEventArgs* aArgs);
void InitGeckoMouseEventFromPointerPoint(WidgetMouseEvent* aEvent,

View File

@ -993,7 +993,7 @@ MetroWidget::ApzContentIgnoringTouch(const ScrollableLayerGuid& aGuid)
}
bool
MetroWidget::ApzHitTest(ScreenPoint& pt)
MetroWidget::ApzHitTest(ScreenIntPoint& pt)
{
if (!mController) {
return false;
@ -1001,6 +1001,16 @@ MetroWidget::ApzHitTest(ScreenPoint& pt)
return mController->HitTestAPZC(pt);
}
void
MetroWidget::ApzTransformGeckoCoordinate(const ScreenIntPoint& aPoint,
LayoutDeviceIntPoint* aRefPointOut)
{
if (!mController) {
return;
}
mController->TransformCoordinateToGecko(aPoint, aRefPointOut);
}
nsEventStatus
MetroWidget::ApzReceiveInputEvent(WidgetInputEvent* aEvent,
ScrollableLayerGuid* aOutTargetGuid)

View File

@ -202,7 +202,11 @@ public:
// apzc controller related api
// Hit test a point to see if an apzc would consume input there
bool ApzHitTest(mozilla::ScreenPoint& pt);
bool ApzHitTest(mozilla::ScreenIntPoint& pt);
// Transforms a coord so that it properly targets gecko content based
// on apzc transforms currently applied.
void ApzTransformGeckoCoordinate(const mozilla::ScreenIntPoint& pt,
mozilla::LayoutDeviceIntPoint* aRefPointOut);
// send ContentRecievedTouch calls to the apz with appropriate preventDefault params
void ApzContentConsumingTouch(const ScrollableLayerGuid& aGuid);
void ApzContentIgnoringTouch(const ScrollableLayerGuid& aGuid);