From 9e2e275653248f9fc2094354587f8fc9cc2bcbe8 Mon Sep 17 00:00:00 2001 From: Maksim Lebedev Date: Wed, 25 Mar 2015 12:20:20 -0400 Subject: [PATCH] Bug 1143655 - Add sending NS_TOUCH_CANCEL event. r=kats --- dom/ipc/TabChild.cpp | 3 ++- gfx/layers/apz/util/APZEventState.cpp | 27 ++++++++++++++++++++++++--- gfx/layers/apz/util/APZEventState.h | 5 +++-- gfx/thebes/gfxPrefs.h | 1 + widget/gonk/nsWindow.cpp | 24 ++++++++++++++---------- widget/gonk/nsWindow.h | 3 ++- widget/nsBaseWidget.cpp | 7 ++++--- widget/nsBaseWidget.h | 3 ++- 8 files changed, 52 insertions(+), 21 deletions(-) diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index 224f16126a1e..2a18d1a8da5b 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -2392,7 +2392,8 @@ TabChild::RecvRealTouchEvent(const WidgetTouchEvent& aEvent, return true; } - mAPZEventState->ProcessTouchEvent(localEvent, aGuid, aInputBlockId); + mAPZEventState->ProcessTouchEvent(localEvent, aGuid, aInputBlockId, + nsEventStatus_eIgnore); return true; } diff --git a/gfx/layers/apz/util/APZEventState.cpp b/gfx/layers/apz/util/APZEventState.cpp index 23bb09071047..425a9f5d068c 100644 --- a/gfx/layers/apz/util/APZEventState.cpp +++ b/gfx/layers/apz/util/APZEventState.cpp @@ -236,7 +236,8 @@ APZEventState::ProcessLongTap(const nsCOMPtr& aUtils, void APZEventState::ProcessTouchEvent(const WidgetTouchEvent& aEvent, const ScrollableLayerGuid& aGuid, - uint64_t aInputBlockId) + uint64_t aInputBlockId, + nsEventStatus aApzResponse) { if (aEvent.message == NS_TOUCH_START && aEvent.touches.Length() > 0) { mActiveElementManager->SetTargetElement(aEvent.touches[0]->GetTarget()); @@ -244,6 +245,7 @@ APZEventState::ProcessTouchEvent(const WidgetTouchEvent& aEvent, bool isTouchPrevented = TouchManager::gPreventMouseEvents || aEvent.mFlags.mMultipleActionsPrevented; + bool sentContentResponse = false; switch (aEvent.message) { case NS_TOUCH_START: { mTouchEndCancelled = false; @@ -252,10 +254,12 @@ APZEventState::ProcessTouchEvent(const WidgetTouchEvent& aEvent, // respond to the first one. Respond to it now. mContentReceivedInputBlockCallback->Run(mPendingTouchPreventedGuid, mPendingTouchPreventedBlockId, false); + sentContentResponse = true; mPendingTouchPreventedResponse = false; } if (isTouchPrevented) { mContentReceivedInputBlockCallback->Run(aGuid, aInputBlockId, isTouchPrevented); + sentContentResponse = true; } else { mPendingTouchPreventedResponse = true; mPendingTouchPreventedGuid = aGuid; @@ -274,13 +278,28 @@ APZEventState::ProcessTouchEvent(const WidgetTouchEvent& aEvent, mActiveElementManager->HandleTouchEndEvent(mEndTouchIsClick); // fall through case NS_TOUCH_MOVE: { - SendPendingTouchPreventedResponse(isTouchPrevented, aGuid); + sentContentResponse = SendPendingTouchPreventedResponse(isTouchPrevented, aGuid); break; } default: NS_WARNING("Unknown touch event type"); } + + if (sentContentResponse && + aApzResponse == nsEventStatus_eConsumeDoDefault && + gfxPrefs::PointerEventsEnabled()) { + WidgetTouchEvent cancelEvent(aEvent); + cancelEvent.message = NS_TOUCH_CANCEL; + cancelEvent.mFlags.mCancelable = false; // message != NS_TOUCH_CANCEL; + for (uint32_t i = 0; i < cancelEvent.touches.Length(); ++i) { + if (mozilla::dom::Touch* touch = cancelEvent.touches[i]) { + touch->convertToPointer = true; + } + } + nsEventStatus status; + cancelEvent.widget->DispatchEvent(&cancelEvent, status); + } } void @@ -364,7 +383,7 @@ APZEventState::ProcessAPZStateChange(const nsCOMPtr& aDocument, } } -void +bool APZEventState::SendPendingTouchPreventedResponse(bool aPreventDefault, const ScrollableLayerGuid& aGuid) { @@ -373,7 +392,9 @@ APZEventState::SendPendingTouchPreventedResponse(bool aPreventDefault, mContentReceivedInputBlockCallback->Run(mPendingTouchPreventedGuid, mPendingTouchPreventedBlockId, aPreventDefault); mPendingTouchPreventedResponse = false; + return true; } + return false; } already_AddRefed diff --git a/gfx/layers/apz/util/APZEventState.h b/gfx/layers/apz/util/APZEventState.h index 2b1e79295732..e94aa62e1139 100644 --- a/gfx/layers/apz/util/APZEventState.h +++ b/gfx/layers/apz/util/APZEventState.h @@ -61,7 +61,8 @@ public: float aPresShellResolution); void ProcessTouchEvent(const WidgetTouchEvent& aEvent, const ScrollableLayerGuid& aGuid, - uint64_t aInputBlockId); + uint64_t aInputBlockId, + nsEventStatus aApzResponse); void ProcessWheelEvent(const WidgetWheelEvent& aEvent, const ScrollableLayerGuid& aGuid, uint64_t aInputBlockId); @@ -71,7 +72,7 @@ public: int aArg); private: ~APZEventState(); - void SendPendingTouchPreventedResponse(bool aPreventDefault, + bool SendPendingTouchPreventedResponse(bool aPreventDefault, const ScrollableLayerGuid& aGuid); already_AddRefed GetWidget() const; private: diff --git a/gfx/thebes/gfxPrefs.h b/gfx/thebes/gfxPrefs.h index 308400f9012b..7598b75a95ca 100644 --- a/gfx/thebes/gfxPrefs.h +++ b/gfx/thebes/gfxPrefs.h @@ -186,6 +186,7 @@ private: DECL_GFX_PREF(Once, "dom.vr.enabled", VREnabled, bool, false); DECL_GFX_PREF(Once, "dom.vr.add-test-devices", VRAddTestDevices, int32_t, 1); + DECL_GFX_PREF(Live, "dom.w3c_pointer_events.enabled", PointerEventsEnabled, bool, false); DECL_GFX_PREF(Once, "gfx.android.rgb16.force", AndroidRGB16Force, bool, false); #if defined(ANDROID) diff --git a/widget/gonk/nsWindow.cpp b/widget/gonk/nsWindow.cpp index ff2be4f1de0d..e50a40184893 100644 --- a/widget/gonk/nsWindow.cpp +++ b/widget/gonk/nsWindow.cpp @@ -259,15 +259,17 @@ class DispatchTouchInputOnMainThread : public nsRunnable public: DispatchTouchInputOnMainThread(const MultiTouchInput& aInput, const ScrollableLayerGuid& aGuid, - const uint64_t& aInputBlockId) + const uint64_t& aInputBlockId, + nsEventStatus aApzResponse) : mInput(aInput) , mGuid(aGuid) , mInputBlockId(aInputBlockId) + , mApzResponse(aApzResponse) {} NS_IMETHOD Run() { if (gFocusedWindow) { - gFocusedWindow->DispatchTouchEventForAPZ(mInput, mGuid, mInputBlockId); + gFocusedWindow->DispatchTouchEventForAPZ(mInput, mGuid, mInputBlockId, mApzResponse); } return NS_OK; } @@ -276,6 +278,7 @@ private: MultiTouchInput mInput; ScrollableLayerGuid mGuid; uint64_t mInputBlockId; + nsEventStatus mApzResponse; }; void @@ -292,9 +295,9 @@ nsWindow::DispatchTouchInputViaAPZ(MultiTouchInput& aInput) // First send it through the APZ code mozilla::layers::ScrollableLayerGuid guid; uint64_t inputBlockId; - nsEventStatus rv = mAPZC->ReceiveInputEvent(aInput, &guid, &inputBlockId); + nsEventStatus result = mAPZC->ReceiveInputEvent(aInput, &guid, &inputBlockId); // If the APZ says to drop it, then we drop it - if (rv == nsEventStatus_eConsumeNoDefault) { + if (result == nsEventStatus_eConsumeNoDefault) { return; } @@ -303,13 +306,14 @@ nsWindow::DispatchTouchInputViaAPZ(MultiTouchInput& aInput) // refcounting is not threadsafe. Instead we just use the gFocusedWindow // static ptr inside the task. NS_DispatchToMainThread(new DispatchTouchInputOnMainThread( - aInput, guid, inputBlockId)); + aInput, guid, inputBlockId, result)); } void nsWindow::DispatchTouchEventForAPZ(const MultiTouchInput& aInput, const ScrollableLayerGuid& aGuid, - const uint64_t aInputBlockId) + const uint64_t aInputBlockId, + nsEventStatus aApzResponse) { MOZ_ASSERT(NS_IsMainThread()); UserActivity(); @@ -318,10 +322,10 @@ nsWindow::DispatchTouchEventForAPZ(const MultiTouchInput& aInput, WidgetTouchEvent event = aInput.ToWidgetTouchEvent(this); // Dispatch the event into the gecko root process for "normal" flow. - // The event might get sent to a child process, but if it doesn't we need to - // notify the APZ of various things. All of that happens in - // ProcessUntransformedAPZEvent - ProcessUntransformedAPZEvent(&event, aGuid, aInputBlockId); + // The event might get sent to a child process, + // but if it doesn't we need to notify the APZ of various things. + // All of that happens in ProcessUntransformedAPZEvent + ProcessUntransformedAPZEvent(&event, aGuid, aInputBlockId, aApzResponse); } class DispatchTouchInputOnControllerThread : public Task diff --git a/widget/gonk/nsWindow.h b/widget/gonk/nsWindow.h index 43c9fc92b582..8b3b38e6a34a 100644 --- a/widget/gonk/nsWindow.h +++ b/widget/gonk/nsWindow.h @@ -90,7 +90,8 @@ public: void DispatchTouchInputViaAPZ(mozilla::MultiTouchInput& aInput); void DispatchTouchEventForAPZ(const mozilla::MultiTouchInput& aInput, const ScrollableLayerGuid& aGuid, - const uint64_t aInputBlockId); + const uint64_t aInputBlockId, + nsEventStatus aApzResponse); NS_IMETHOD DispatchEvent(mozilla::WidgetGUIEvent* aEvent, nsEventStatus& aStatus); virtual nsresult SynthesizeNativeTouchPoint(uint32_t aPointerId, diff --git a/widget/nsBaseWidget.cpp b/widget/nsBaseWidget.cpp index d37725fa0140..bcd2ce14dde5 100644 --- a/widget/nsBaseWidget.cpp +++ b/widget/nsBaseWidget.cpp @@ -993,7 +993,8 @@ void nsBaseWidget::ConfigureAPZCTreeManager() nsEventStatus nsBaseWidget::ProcessUntransformedAPZEvent(WidgetInputEvent* aEvent, const ScrollableLayerGuid& aGuid, - uint64_t aInputBlockId) + uint64_t aInputBlockId, + nsEventStatus aApzResponse) { MOZ_ASSERT(NS_IsMainThread()); InputAPZContext context(aGuid, aInputBlockId); @@ -1026,7 +1027,7 @@ nsBaseWidget::ProcessUntransformedAPZEvent(WidgetInputEvent* aEvent, APZCCallbackHelper::SendSetTargetAPZCNotification(this, GetDocument(), *aEvent, aGuid, aInputBlockId, mSetTargetAPZCCallback); } - mAPZEventState->ProcessTouchEvent(*touchEvent, aGuid, aInputBlockId); + mAPZEventState->ProcessTouchEvent(*touchEvent, aGuid, aInputBlockId, aApzResponse); } else if (WidgetWheelEvent* wheelEvent = aEvent->AsWheelEvent()) { APZCCallbackHelper::SendSetTargetAPZCNotification(this, GetDocument(), *aEvent, aGuid, aInputBlockId, mSetTargetAPZCCallback); @@ -1063,7 +1064,7 @@ nsBaseWidget::DispatchAPZAwareEvent(WidgetInputEvent* aEvent) if (result == nsEventStatus_eConsumeNoDefault) { return result; } - return ProcessUntransformedAPZEvent(aEvent, guid, inputBlockId); + return ProcessUntransformedAPZEvent(aEvent, guid, inputBlockId, result); } nsEventStatus status; diff --git a/widget/nsBaseWidget.h b/widget/nsBaseWidget.h index a2b232647164..3a2a0000c298 100644 --- a/widget/nsBaseWidget.h +++ b/widget/nsBaseWidget.h @@ -336,7 +336,8 @@ protected: // Dispatch an event that has already been routed through APZ. nsEventStatus ProcessUntransformedAPZEvent(mozilla::WidgetInputEvent* aEvent, const ScrollableLayerGuid& aGuid, - uint64_t aInputBlockId); + uint64_t aInputBlockId, + nsEventStatus aApzResponse); const nsIntRegion RegionFromArray(const nsTArray& aRects); void ArrayFromRegion(const nsIntRegion& aRegion, nsTArray& aRects);