diff --git a/dom/ipc/PBrowser.ipdl b/dom/ipc/PBrowser.ipdl index 3f7c1501219a..69c90d3feb1e 100644 --- a/dom/ipc/PBrowser.ipdl +++ b/dom/ipc/PBrowser.ipdl @@ -375,7 +375,7 @@ parent: * batched and only processed for panning and zooming if content does not * preventDefault. */ - ContentReceivedTouch(ScrollableLayerGuid aGuid, bool aPreventDefault); + ContentReceivedTouch(ScrollableLayerGuid aGuid, uint64_t aInputBlockId, bool aPreventDefault); /** * Updates the zoom constraints for a scrollable frame in this tab. @@ -436,7 +436,7 @@ child: AcknowledgeScrollUpdate(ViewID aScrollId, uint32_t aScrollGeneration); HandleDoubleTap(CSSPoint point, ScrollableLayerGuid aGuid); HandleSingleTap(CSSPoint point, ScrollableLayerGuid aGuid); - HandleLongTap(CSSPoint point, ScrollableLayerGuid aGuid); + HandleLongTap(CSSPoint point, ScrollableLayerGuid aGuid, uint64_t aInputBlockId); HandleLongTapUp(CSSPoint point, ScrollableLayerGuid aGuid); NotifyAPZStateChange(ViewID aViewId, APZStateChange aChange, int aArg); @@ -462,10 +462,10 @@ child: RealMouseEvent(WidgetMouseEvent event); RealKeyEvent(WidgetKeyboardEvent event, MaybeNativeKeyBinding keyBinding); MouseWheelEvent(WidgetWheelEvent event); - RealTouchEvent(WidgetTouchEvent aEvent, ScrollableLayerGuid aGuid); + RealTouchEvent(WidgetTouchEvent aEvent, ScrollableLayerGuid aGuid, uint64_t aInputBlockId); // We use a separate message for touchmove events only to apply // compression to them. - RealTouchMoveEvent(WidgetTouchEvent aEvent, ScrollableLayerGuid aGuid) compress; + RealTouchMoveEvent(WidgetTouchEvent aEvent, ScrollableLayerGuid aGuid, uint64_t aInputBlockId) compress; /** * @see nsIDOMWindowUtils sendKeyEvent. diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index 93552e64c8b5..d19863a53eb9 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -826,6 +826,7 @@ TabChild::TabChild(nsIContentChild* aManager, , mOrientation(eScreenOrientation_PortraitPrimary) , mUpdateHitRegion(false) , mPendingTouchPreventedResponse(false) + , mPendingTouchPreventedBlockId(0) , mTouchEndCancelled(false) , mEndTouchIsClick(false) , mIgnoreKeyPressEvent(false) @@ -1511,7 +1512,7 @@ TabChild::SendPendingTouchPreventedResponse(bool aPreventDefault, { if (mPendingTouchPreventedResponse) { MOZ_ASSERT(aGuid == mPendingTouchPreventedGuid); - SendContentReceivedTouch(mPendingTouchPreventedGuid, aPreventDefault); + SendContentReceivedTouch(mPendingTouchPreventedGuid, mPendingTouchPreventedBlockId, aPreventDefault); mPendingTouchPreventedResponse = false; } } @@ -1961,7 +1962,7 @@ TabChild::FireSingleTapEvent(LayoutDevicePoint aPoint) } bool -TabChild::RecvHandleLongTap(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid) +TabChild::RecvHandleLongTap(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid, const uint64_t& aInputBlockId) { TABC_LOG("Handling long tap at %s with %p %p\n", Stringify(aPoint).c_str(), mGlobal.get(), mTabChildGlobal.get()); @@ -1991,7 +1992,7 @@ TabChild::RecvHandleLongTap(const CSSPoint& aPoint, const ScrollableLayerGuid& a TABC_LOG("MOZLONGTAP event handled: %d\n", eventHandled); } - SendContentReceivedTouch(aGuid, eventHandled); + SendContentReceivedTouch(aGuid, aInputBlockId, eventHandled); return true; } @@ -2260,7 +2261,8 @@ TabChild::CancelTapTracking() bool TabChild::RecvRealTouchEvent(const WidgetTouchEvent& aEvent, - const ScrollableLayerGuid& aGuid) + const ScrollableLayerGuid& aGuid, + const uint64_t& aInputBlockId) { TABC_LOG("Receiving touch event of type %d\n", aEvent.message); @@ -2289,14 +2291,15 @@ TabChild::RecvRealTouchEvent(const WidgetTouchEvent& aEvent, if (mPendingTouchPreventedResponse) { // We can enter here if we get two TOUCH_STARTs in a row and didn't // respond to the first one. Respond to it now. - SendContentReceivedTouch(mPendingTouchPreventedGuid, false); + SendContentReceivedTouch(mPendingTouchPreventedGuid, mPendingTouchPreventedBlockId, false); mPendingTouchPreventedResponse = false; } if (isTouchPrevented) { - SendContentReceivedTouch(aGuid, isTouchPrevented); + SendContentReceivedTouch(aGuid, aInputBlockId, isTouchPrevented); } else { mPendingTouchPreventedResponse = true; mPendingTouchPreventedGuid = aGuid; + mPendingTouchPreventedBlockId = aInputBlockId; } break; } @@ -2324,9 +2327,10 @@ TabChild::RecvRealTouchEvent(const WidgetTouchEvent& aEvent, bool TabChild::RecvRealTouchMoveEvent(const WidgetTouchEvent& aEvent, - const ScrollableLayerGuid& aGuid) + const ScrollableLayerGuid& aGuid, + const uint64_t& aInputBlockId) { - return RecvRealTouchEvent(aEvent, aGuid); + return RecvRealTouchEvent(aEvent, aGuid, aInputBlockId); } void diff --git a/dom/ipc/TabChild.h b/dom/ipc/TabChild.h index 3e2bc25a1c29..4bf5852a4ef0 100644 --- a/dom/ipc/TabChild.h +++ b/dom/ipc/TabChild.h @@ -324,7 +324,8 @@ public: virtual bool RecvHandleSingleTap(const CSSPoint& aPoint, const mozilla::layers::ScrollableLayerGuid& aGuid) MOZ_OVERRIDE; virtual bool RecvHandleLongTap(const CSSPoint& aPoint, - const mozilla::layers::ScrollableLayerGuid& aGuid) MOZ_OVERRIDE; + const mozilla::layers::ScrollableLayerGuid& aGuid, + const uint64_t& aInputBlockId) MOZ_OVERRIDE; virtual bool RecvHandleLongTapUp(const CSSPoint& aPoint, const mozilla::layers::ScrollableLayerGuid& aGuid) MOZ_OVERRIDE; virtual bool RecvNotifyAPZStateChange(const ViewID& aViewId, @@ -344,9 +345,11 @@ public: const MaybeNativeKeyBinding& aBindings) MOZ_OVERRIDE; virtual bool RecvMouseWheelEvent(const mozilla::WidgetWheelEvent& event) MOZ_OVERRIDE; virtual bool RecvRealTouchEvent(const WidgetTouchEvent& aEvent, - const ScrollableLayerGuid& aGuid) MOZ_OVERRIDE; + const ScrollableLayerGuid& aGuid, + const uint64_t& aInputBlockId) MOZ_OVERRIDE; virtual bool RecvRealTouchMoveEvent(const WidgetTouchEvent& aEvent, - const ScrollableLayerGuid& aGuid) MOZ_OVERRIDE; + const ScrollableLayerGuid& aGuid, + const uint64_t& aInputBlockId) MOZ_OVERRIDE; virtual bool RecvKeyEvent(const nsString& aType, const int32_t& aKeyCode, const int32_t& aCharCode, @@ -597,6 +600,7 @@ private: bool mUpdateHitRegion; bool mPendingTouchPreventedResponse; ScrollableLayerGuid mPendingTouchPreventedGuid; + uint64_t mPendingTouchPreventedBlockId; void FireSingleTapEvent(LayoutDevicePoint aPoint); bool mTouchEndCancelled; diff --git a/dom/ipc/TabParent.cpp b/dom/ipc/TabParent.cpp index dc5206a6f5d8..7092154ec688 100644 --- a/dom/ipc/TabParent.cpp +++ b/dom/ipc/TabParent.cpp @@ -644,10 +644,11 @@ void TabParent::HandleSingleTap(const CSSPoint& aPoint, void TabParent::HandleLongTap(const CSSPoint& aPoint, int32_t aModifiers, - const ScrollableLayerGuid &aGuid) + const ScrollableLayerGuid &aGuid, + uint64_t aInputBlockId) { if (!mIsDestroyed) { - unused << SendHandleLongTap(aPoint, aGuid); + unused << SendHandleLongTap(aPoint, aGuid, aInputBlockId); } } @@ -877,7 +878,7 @@ bool TabParent::SendRealMouseEvent(WidgetMouseEvent& event) if (mIsDestroyed) { return false; } - nsEventStatus status = MaybeForwardEventToRenderFrame(event, nullptr); + nsEventStatus status = MaybeForwardEventToRenderFrame(event, nullptr, nullptr); if (status == nsEventStatus_eConsumeNoDefault || !MapEventCoordinatesForChildProcess(&event)) { return false; @@ -913,13 +914,13 @@ bool TabParent::SendHandleSingleTap(const CSSPoint& aPoint, const ScrollableLaye return PBrowserParent::SendHandleSingleTap(AdjustTapToChildWidget(aPoint), aGuid); } -bool TabParent::SendHandleLongTap(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid) +bool TabParent::SendHandleLongTap(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid, const uint64_t& aInputBlockId) { if (mIsDestroyed) { return false; } - return PBrowserParent::SendHandleLongTap(AdjustTapToChildWidget(aPoint), aGuid); + return PBrowserParent::SendHandleLongTap(AdjustTapToChildWidget(aPoint), aGuid, aInputBlockId); } bool TabParent::SendHandleLongTapUp(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid) @@ -945,7 +946,7 @@ bool TabParent::SendMouseWheelEvent(WidgetWheelEvent& event) if (mIsDestroyed) { return false; } - nsEventStatus status = MaybeForwardEventToRenderFrame(event, nullptr); + nsEventStatus status = MaybeForwardEventToRenderFrame(event, nullptr, nullptr); if (status == nsEventStatus_eConsumeNoDefault || !MapEventCoordinatesForChildProcess(&event)) { return false; @@ -999,7 +1000,7 @@ bool TabParent::SendRealKeyEvent(WidgetKeyboardEvent& event) if (mIsDestroyed) { return false; } - MaybeForwardEventToRenderFrame(event, nullptr); + MaybeForwardEventToRenderFrame(event, nullptr, nullptr); if (!MapEventCoordinatesForChildProcess(&event)) { return false; } @@ -1067,7 +1068,8 @@ bool TabParent::SendRealTouchEvent(WidgetTouchEvent& event) } ScrollableLayerGuid guid; - nsEventStatus status = MaybeForwardEventToRenderFrame(event, &guid); + uint64_t blockId; + nsEventStatus status = MaybeForwardEventToRenderFrame(event, &guid, &blockId); if (status == nsEventStatus_eConsumeNoDefault || mIsDestroyed) { return false; @@ -1076,8 +1078,8 @@ bool TabParent::SendRealTouchEvent(WidgetTouchEvent& event) MapEventCoordinatesForChildProcess(mChildProcessOffsetAtTouchStart, &event); return (event.message == NS_TOUCH_MOVE) ? - PBrowserParent::SendRealTouchMoveEvent(event, guid) : - PBrowserParent::SendRealTouchEvent(event, guid); + PBrowserParent::SendRealTouchMoveEvent(event, guid, blockId) : + PBrowserParent::SendRealTouchEvent(event, guid, blockId); } /*static*/ TabParent* @@ -2010,10 +2012,11 @@ TabParent::UseAsyncPanZoom() nsEventStatus TabParent::MaybeForwardEventToRenderFrame(WidgetInputEvent& aEvent, - ScrollableLayerGuid* aOutTargetGuid) + ScrollableLayerGuid* aOutTargetGuid, + uint64_t* aOutInputBlockId) { if (RenderFrameParent* rfp = GetRenderFrame()) { - return rfp->NotifyInputEvent(aEvent, aOutTargetGuid); + return rfp->NotifyInputEvent(aEvent, aOutTargetGuid, aOutInputBlockId); } return nsEventStatus_eIgnore; } @@ -2067,10 +2070,11 @@ TabParent::RecvUpdateZoomConstraints(const uint32_t& aPresShellId, bool TabParent::RecvContentReceivedTouch(const ScrollableLayerGuid& aGuid, + const uint64_t& aInputBlockId, const bool& aPreventDefault) { if (RenderFrameParent* rfp = GetRenderFrame()) { - rfp->ContentReceivedTouch(aGuid, aPreventDefault); + rfp->ContentReceivedTouch(aGuid, aInputBlockId, aPreventDefault); } return true; } diff --git a/dom/ipc/TabParent.h b/dom/ipc/TabParent.h index 015cee334bfb..e178b26bc20b 100644 --- a/dom/ipc/TabParent.h +++ b/dom/ipc/TabParent.h @@ -210,6 +210,7 @@ public: const bool& aIsRoot, const ZoomConstraints& aConstraints) MOZ_OVERRIDE; virtual bool RecvContentReceivedTouch(const ScrollableLayerGuid& aGuid, + const uint64_t& aInputBlockId, const bool& aPreventDefault) MOZ_OVERRIDE; virtual PColorPickerParent* @@ -233,7 +234,8 @@ public: const ScrollableLayerGuid& aGuid); void HandleLongTap(const CSSPoint& aPoint, int32_t aModifiers, - const ScrollableLayerGuid& aGuid); + const ScrollableLayerGuid& aGuid, + uint64_t aInputBlockId); void HandleLongTapUp(const CSSPoint& aPoint, int32_t aModifiers, const ScrollableLayerGuid& aGuid); @@ -261,7 +263,7 @@ public: bool SendRealKeyEvent(mozilla::WidgetKeyboardEvent& event); bool SendRealTouchEvent(WidgetTouchEvent& event); bool SendHandleSingleTap(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid); - bool SendHandleLongTap(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid); + bool SendHandleLongTap(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid, const uint64_t& aInputBlockId); bool SendHandleLongTapUp(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid); bool SendHandleDoubleTap(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid); @@ -423,8 +425,12 @@ private: // |aOutTargetGuid| will contain the identifier // of the APZC instance that handled the event. aOutTargetGuid may be // null. + // |aOutInputBlockId| will contain the identifier of the input block + // that this event was added to, if there was one. aOutInputBlockId may + // be null. nsEventStatus MaybeForwardEventToRenderFrame(WidgetInputEvent& aEvent, - ScrollableLayerGuid* aOutTargetGuid); + ScrollableLayerGuid* aOutTargetGuid, + uint64_t* aOutInputBlockId); // The offset for the child process which is sampled at touch start. This // means that the touch events are relative to where the frame was at the // start of the touch. We need to look for a better solution to this diff --git a/gfx/layers/apz/public/GeckoContentController.h b/gfx/layers/apz/public/GeckoContentController.h index 125774a9c1cf..4456b5885053 100644 --- a/gfx/layers/apz/public/GeckoContentController.h +++ b/gfx/layers/apz/public/GeckoContentController.h @@ -62,7 +62,8 @@ public: */ virtual void HandleLongTap(const CSSPoint& aPoint, int32_t aModifiers, - const ScrollableLayerGuid& aGuid) = 0; + const ScrollableLayerGuid& aGuid, + uint64_t aInputBlockId) = 0; /** * Requests handling of releasing a long tap. |aPoint| is in CSS pixels, diff --git a/gfx/layers/apz/src/APZCTreeManager.cpp b/gfx/layers/apz/src/APZCTreeManager.cpp index 18c02471883c..30c2de067790 100644 --- a/gfx/layers/apz/src/APZCTreeManager.cpp +++ b/gfx/layers/apz/src/APZCTreeManager.cpp @@ -7,6 +7,7 @@ #include "AsyncPanZoomController.h" #include "Compositor.h" // for Compositor #include "CompositorParent.h" // for CompositorParent, etc +#include "InputBlockState.h" // for InputBlockState #include "InputData.h" // for InputData, etc #include "Layers.h" // for Layer, etc #include "mozilla/dom/Touch.h" // for Touch @@ -110,11 +111,12 @@ APZCTreeManager::GetAllowedTouchBehavior(WidgetInputEvent* aEvent, void APZCTreeManager::SetAllowedTouchBehavior(const ScrollableLayerGuid& aGuid, + uint64_t aInputBlockId, const nsTArray &aValues) { nsRefPtr apzc = GetTargetAPZC(aGuid); if (apzc) { - apzc->SetAllowedTouchBehavior(aValues); + apzc->SetAllowedTouchBehavior(aInputBlockId, aValues); } } @@ -517,15 +519,21 @@ TransformScreenToGecko(T* aPoint, AsyncPanZoomController* aApzc, APZCTreeManager nsEventStatus APZCTreeManager::ReceiveInputEvent(InputData& aEvent, - ScrollableLayerGuid* aOutTargetGuid) + ScrollableLayerGuid* aOutTargetGuid, + uint64_t* aOutInputBlockId) { + // Initialize aOutInputBlockId to a sane value, and then later we overwrite + // it if the input event goes into a block. + if (aOutInputBlockId) { + *aOutInputBlockId = InputBlockState::NO_BLOCK_ID; + } nsEventStatus result = nsEventStatus_eIgnore; Matrix4x4 transformToApzc; bool inOverscrolledApzc = false; switch (aEvent.mInputType) { case MULTITOUCH_INPUT: { MultiTouchInput& touchInput = aEvent.AsMultiTouchInput(); - result = ProcessTouchInput(touchInput, aOutTargetGuid); + result = ProcessTouchInput(touchInput, aOutTargetGuid, aOutInputBlockId); break; } case PANGESTURE_INPUT: { PanGestureInput& panInput = aEvent.AsPanGestureInput(); @@ -538,7 +546,7 @@ APZCTreeManager::ReceiveInputEvent(InputData& aEvent, PanGestureInput inputForApzc(panInput); transformToApzc = GetScreenToApzcTransform(apzc); ApplyTransform(&(inputForApzc.mPanStartPoint), transformToApzc); - result = apzc->ReceiveInputEvent(inputForApzc); + result = apzc->ReceiveInputEvent(inputForApzc, aOutInputBlockId); // Update the out-parameters so they are what the caller expects. apzc->GetGuid(aOutTargetGuid); @@ -556,7 +564,7 @@ APZCTreeManager::ReceiveInputEvent(InputData& aEvent, PinchGestureInput inputForApzc(pinchInput); transformToApzc = GetScreenToApzcTransform(apzc); ApplyTransform(&(inputForApzc.mFocusPoint), transformToApzc); - result = apzc->ReceiveInputEvent(inputForApzc); + result = apzc->ReceiveInputEvent(inputForApzc, aOutInputBlockId); // Update the out-parameters so they are what the caller expects. apzc->GetGuid(aOutTargetGuid); @@ -574,7 +582,7 @@ APZCTreeManager::ReceiveInputEvent(InputData& aEvent, TapGestureInput inputForApzc(tapInput); transformToApzc = GetScreenToApzcTransform(apzc); ApplyTransform(&(inputForApzc.mPoint), transformToApzc); - result = apzc->ReceiveInputEvent(inputForApzc); + result = apzc->ReceiveInputEvent(inputForApzc, aOutInputBlockId); // Update the out-parameters so they are what the caller expects. apzc->GetGuid(aOutTargetGuid); @@ -628,7 +636,8 @@ APZCTreeManager::GetTouchInputBlockAPZC(const MultiTouchInput& aEvent, nsEventStatus APZCTreeManager::ProcessTouchInput(MultiTouchInput& aInput, - ScrollableLayerGuid* aOutTargetGuid) + ScrollableLayerGuid* aOutTargetGuid, + uint64_t* aOutInputBlockId) { if (aInput.mType == MultiTouchInput::MULTITOUCH_START) { // If we are in an overscrolled state and a second finger goes down, @@ -653,7 +662,7 @@ APZCTreeManager::ProcessTouchInput(MultiTouchInput& aInput, // in the middle of a panning touch block (for example) and not clean up properly. if (mApzcForInputBlock) { MultiTouchInput cancel(MultiTouchInput::MULTITOUCH_CANCEL, 0, TimeStamp::Now(), 0); - mApzcForInputBlock->ReceiveInputEvent(cancel); + mApzcForInputBlock->ReceiveInputEvent(cancel, nullptr); } mApzcForInputBlock = apzc; } @@ -702,7 +711,7 @@ APZCTreeManager::ProcessTouchInput(MultiTouchInput& aInput, for (size_t i = 0; i < inputForApzc.mTouches.Length(); i++) { ApplyTransform(&(inputForApzc.mTouches[i].mScreenPoint), transformToApzc); } - result = mApzcForInputBlock->ReceiveInputEvent(inputForApzc); + result = mApzcForInputBlock->ReceiveInputEvent(inputForApzc, aOutInputBlockId); // For computing the event to pass back to Gecko, use the up-to-date transforms. // This ensures that transformToApzc and transformToGecko are in sync @@ -757,7 +766,8 @@ APZCTreeManager::TransformCoordinateToGecko(const ScreenIntPoint& aPoint, nsEventStatus APZCTreeManager::ProcessEvent(WidgetInputEvent& aEvent, - ScrollableLayerGuid* aOutTargetGuid) + ScrollableLayerGuid* aOutTargetGuid, + uint64_t* aOutInputBlockId) { MOZ_ASSERT(NS_IsMainThread()); nsEventStatus result = nsEventStatus_eIgnore; @@ -782,7 +792,8 @@ APZCTreeManager::ProcessEvent(WidgetInputEvent& aEvent, nsEventStatus APZCTreeManager::ReceiveInputEvent(WidgetInputEvent& aEvent, - ScrollableLayerGuid* aOutTargetGuid) + ScrollableLayerGuid* aOutTargetGuid, + uint64_t* aOutInputBlockId) { // This function will be removed as part of bug 930939. // In general it is preferable to use the version of ReceiveInputEvent @@ -790,11 +801,17 @@ APZCTreeManager::ReceiveInputEvent(WidgetInputEvent& aEvent, MOZ_ASSERT(NS_IsMainThread()); + // Initialize aOutInputBlockId to a sane value, and then later we overwrite + // it if the input event goes into a block. + if (aOutInputBlockId) { + *aOutInputBlockId = InputBlockState::NO_BLOCK_ID; + } + switch (aEvent.mClass) { case eTouchEventClass: { WidgetTouchEvent& touchEvent = *aEvent.AsTouchEvent(); MultiTouchInput touchInput(touchEvent); - nsEventStatus result = ProcessTouchInput(touchInput, aOutTargetGuid); + nsEventStatus result = ProcessTouchInput(touchInput, aOutTargetGuid, aOutInputBlockId); // touchInput was modified in-place to possibly remove some // touch points (if we are overscrolled), and the coordinates were // modified using the APZ untransform. We need to copy these changes @@ -807,7 +824,7 @@ APZCTreeManager::ReceiveInputEvent(WidgetInputEvent& aEvent, return result; } default: { - return ProcessEvent(aEvent, aOutTargetGuid); + return ProcessEvent(aEvent, aOutTargetGuid, aOutInputBlockId); } } } @@ -824,11 +841,12 @@ APZCTreeManager::ZoomToRect(const ScrollableLayerGuid& aGuid, void APZCTreeManager::ContentReceivedTouch(const ScrollableLayerGuid& aGuid, + uint64_t aInputBlockId, bool aPreventDefault) { nsRefPtr apzc = GetTargetAPZC(aGuid); if (apzc) { - apzc->ContentReceivedTouch(aPreventDefault); + apzc->ContentReceivedTouch(aInputBlockId, aPreventDefault); } } diff --git a/gfx/layers/apz/src/APZCTreeManager.h b/gfx/layers/apz/src/APZCTreeManager.h index 405c0e833af4..ea52174c9fa7 100644 --- a/gfx/layers/apz/src/APZCTreeManager.h +++ b/gfx/layers/apz/src/APZCTreeManager.h @@ -159,9 +159,12 @@ public: * @param aEvent input event object; is modified in-place * @param aOutTargetGuid returns the guid of the apzc this event was * delivered to. May be null. + * @param aOutInputBlockId returns the id of the input block that this event + * was added to, if that was the case. May be null. */ nsEventStatus ReceiveInputEvent(InputData& aEvent, - ScrollableLayerGuid* aOutTargetGuid); + ScrollableLayerGuid* aOutTargetGuid, + uint64_t* aOutInputBlockId); /** * WidgetInputEvent handler. Transforms |aEvent| (which is assumed to be an @@ -175,13 +178,11 @@ public: * NOTE: On unix, mouse events are treated as touch and are forwarded * to the appropriate apz as such. * - * @param aEvent input event object; is modified in-place - * @param aOutTargetGuid returns the guid of the apzc this event was - * delivered to. May be null. - * @return See documentation for other ReceiveInputEvent above. + * See documentation for other ReceiveInputEvent above. */ nsEventStatus ReceiveInputEvent(WidgetInputEvent& aEvent, - ScrollableLayerGuid* aOutTargetGuid); + ScrollableLayerGuid* aOutTargetGuid, + uint64_t* aOutInputBlockId); /** * A helper for transforming coordinates to gecko coordinate space. @@ -207,6 +208,7 @@ public: * queue will be discarded. */ void ContentReceivedTouch(const ScrollableLayerGuid& aGuid, + uint64_t aInputBlockId, bool aPreventDefault); /** @@ -266,12 +268,15 @@ public: nsTArray& aOutValues); /** - * Sets allowed touch behavior values for current touch-session for specific apzc (determined by guid). - * Should be invoked by the widget. Each value of the aValues arrays corresponds to the different - * touch point that is currently active. - * Must be called after receiving the TOUCH_START event that starts the touch-session. + * Sets allowed touch behavior values for current touch-session for specific + * apzc and input block (determined by aGuid and aInputBlock). + * Should be invoked by the widget. Each value of the aValues arrays + * corresponds to the different touch point that is currently active. + * Must be called after receiving the TOUCH_START event that starts the + * touch-session. */ void SetAllowedTouchBehavior(const ScrollableLayerGuid& aGuid, + uint64_t aInputBlockId, const nsTArray& aValues); /** @@ -383,9 +388,11 @@ private: already_AddRefed GetTouchInputBlockAPZC(const MultiTouchInput& aEvent, bool* aOutInOverscrolledApzc); nsEventStatus ProcessTouchInput(MultiTouchInput& aInput, - ScrollableLayerGuid* aOutTargetGuid); + ScrollableLayerGuid* aOutTargetGuid, + uint64_t* aOutInputBlockId); nsEventStatus ProcessEvent(WidgetInputEvent& inputEvent, - ScrollableLayerGuid* aOutTargetGuid); + ScrollableLayerGuid* aOutTargetGuid, + uint64_t* aOutInputBlockId); void UpdateZoomConstraintsRecursively(AsyncPanZoomController* aApzc, const ZoomConstraints& aConstraints); void FlushRepaintsRecursively(AsyncPanZoomController* aApzc); diff --git a/gfx/layers/apz/src/AsyncPanZoomController.cpp b/gfx/layers/apz/src/AsyncPanZoomController.cpp index 1348c8a7153e..32f136144878 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.cpp +++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp @@ -1013,8 +1013,8 @@ AsyncPanZoomController::ArePointerEventsConsumable(TouchBlockState* aBlock, uint return true; } -nsEventStatus AsyncPanZoomController::ReceiveInputEvent(const InputData& aEvent) { - return GetInputQueue()->ReceiveInputEvent(this, aEvent); +nsEventStatus AsyncPanZoomController::ReceiveInputEvent(const InputData& aEvent, uint64_t* aOutInputBlockId) { + return GetInputQueue()->ReceiveInputEvent(this, aEvent, aOutInputBlockId); } nsEventStatus AsyncPanZoomController::HandleInputEvent(const InputData& aEvent) { @@ -1579,8 +1579,8 @@ nsEventStatus AsyncPanZoomController::OnLongPress(const TapGestureInput& aEvent) int32_t modifiers = WidgetModifiersToDOMModifiers(aEvent.modifiers); CSSPoint geckoScreenPoint; if (ConvertToGecko(aEvent.mPoint, &geckoScreenPoint)) { - GetInputQueue()->InjectNewTouchBlock(this); - controller->HandleLongTap(geckoScreenPoint, modifiers, GetGuid()); + uint64_t blockId = GetInputQueue()->InjectNewTouchBlock(this); + controller->HandleLongTap(geckoScreenPoint, modifiers, GetGuid(), blockId); return nsEventStatus_eConsumeNoDefault; } } @@ -2855,13 +2855,13 @@ void AsyncPanZoomController::ZoomToRect(CSSRect aRect) { } void -AsyncPanZoomController::ContentReceivedTouch(bool aPreventDefault) { - GetInputQueue()->ContentReceivedTouch(aPreventDefault); +AsyncPanZoomController::ContentReceivedTouch(uint64_t aInputBlockId, bool aPreventDefault) { + GetInputQueue()->ContentReceivedTouch(aInputBlockId, aPreventDefault); } void -AsyncPanZoomController::SetAllowedTouchBehavior(const nsTArray& aBehaviors) { - GetInputQueue()->SetAllowedTouchBehavior(aBehaviors); +AsyncPanZoomController::SetAllowedTouchBehavior(uint64_t aInputBlockId, const nsTArray& aBehaviors) { + GetInputQueue()->SetAllowedTouchBehavior(aInputBlockId, aBehaviors); } bool diff --git a/gfx/layers/apz/src/AsyncPanZoomController.h b/gfx/layers/apz/src/AsyncPanZoomController.h index c6da481ed2a4..84ffe22ee622 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.h +++ b/gfx/layers/apz/src/AsyncPanZoomController.h @@ -122,7 +122,7 @@ public: * See the documentation on APZCTreeManager::ReceiveInputEvent for info on * return values from this function. */ - nsEventStatus ReceiveInputEvent(const InputData& aEvent); + nsEventStatus ReceiveInputEvent(const InputData& aEvent, uint64_t* aOutInputBlockId); /** * Kicks an animation to zoom to a rect. This may be either a zoom out or zoom @@ -776,12 +776,12 @@ public: /** * See InputQueue::ContentReceivedTouch */ - void ContentReceivedTouch(bool aPreventDefault); + void ContentReceivedTouch(uint64_t aInputBlockId, bool aPreventDefault); /** * See InputQueue::SetAllowedTouchBehavior */ - void SetAllowedTouchBehavior(const nsTArray& aBehaviors); + void SetAllowedTouchBehavior(uint64_t aInputBlockId, const nsTArray& aBehaviors); /** * Flush a repaint request if one is needed, without throttling it with the diff --git a/gfx/layers/apz/src/InputBlockState.cpp b/gfx/layers/apz/src/InputBlockState.cpp index 10c52be04fc0..333ee2a3e074 100644 --- a/gfx/layers/apz/src/InputBlockState.cpp +++ b/gfx/layers/apz/src/InputBlockState.cpp @@ -15,8 +15,11 @@ namespace mozilla { namespace layers { +static uint64_t sBlockCounter = InputBlockState::NO_BLOCK_ID + 1; + InputBlockState::InputBlockState(const nsRefPtr& aTargetApzc) : mTargetApzc(aTargetApzc) + , mBlockId(sBlockCounter++) { // We should never be constructed with a nullptr target. MOZ_ASSERT(mTargetApzc); @@ -35,6 +38,12 @@ InputBlockState::GetOverscrollHandoffChain() const return mOverscrollHandoffChain; } +uint64_t +InputBlockState::GetBlockId() const +{ + return mBlockId; +} + TouchBlockState::TouchBlockState(const nsRefPtr& aTargetApzc) : InputBlockState(aTargetApzc) , mAllowedTouchBehaviorSet(false) diff --git a/gfx/layers/apz/src/InputBlockState.h b/gfx/layers/apz/src/InputBlockState.h index a9ae12328def..d796a3712ca1 100644 --- a/gfx/layers/apz/src/InputBlockState.h +++ b/gfx/layers/apz/src/InputBlockState.h @@ -23,14 +23,17 @@ class OverscrollHandoffChain; class InputBlockState { public: + static const uint64_t NO_BLOCK_ID = 0; + explicit InputBlockState(const nsRefPtr& aTargetApzc); const nsRefPtr& GetTargetApzc() const; const nsRefPtr& GetOverscrollHandoffChain() const; - + uint64_t GetBlockId() const; private: nsRefPtr mTargetApzc; nsRefPtr mOverscrollHandoffChain; + const uint64_t mBlockId; }; /** diff --git a/gfx/layers/apz/src/InputQueue.cpp b/gfx/layers/apz/src/InputQueue.cpp index eea586602d52..8d35a531645c 100644 --- a/gfx/layers/apz/src/InputQueue.cpp +++ b/gfx/layers/apz/src/InputQueue.cpp @@ -18,7 +18,6 @@ namespace mozilla { namespace layers { InputQueue::InputQueue() - : mTouchBlockBalance(0) { } @@ -27,7 +26,7 @@ InputQueue::~InputQueue() { } nsEventStatus -InputQueue::ReceiveInputEvent(const nsRefPtr& aTarget, const InputData& aEvent) { +InputQueue::ReceiveInputEvent(const nsRefPtr& aTarget, const InputData& aEvent, uint64_t* aOutInputBlockId) { AsyncPanZoomController::AssertOnControllerThread(); if (aEvent.mInputType != MULTITOUCH_INPUT) { @@ -60,13 +59,12 @@ InputQueue::ReceiveInputEvent(const nsRefPtr& aTarget, c if (aTarget->NeedToWaitForContent()) { // Content may intercept the touch events and prevent-default them. So we schedule // a timeout to give content time to do that. - ScheduleContentResponseTimeout(aTarget); + ScheduleContentResponseTimeout(aTarget, block->GetBlockId()); } else { // Content won't prevent-default this, so we can just pretend like we scheduled // a timeout and it expired. Note that we will still receive a ContentReceivedTouch // callback for this block, and so we need to make sure we adjust the touch balance. INPQ_LOG("%p not waiting for content response on block %p\n", this, block); - mTouchBlockBalance++; block->TimeoutContentResponse(); } } else if (mTouchBlockQueue.IsEmpty()) { @@ -80,6 +78,9 @@ InputQueue::ReceiveInputEvent(const nsRefPtr& aTarget, c if (!block) { return nsEventStatus_eIgnore; } + if (aOutInputBlockId) { + *aOutInputBlockId = block->GetBlockId(); + } nsEventStatus result = aTarget->ArePointerEventsConsumable(block, aEvent.AsMultiTouchInput().mTouches.Length()) ? nsEventStatus_eConsumeDoDefault @@ -100,11 +101,14 @@ InputQueue::ReceiveInputEvent(const nsRefPtr& aTarget, c return result; } -void +uint64_t InputQueue::InjectNewTouchBlock(AsyncPanZoomController* aTarget) { - StartNewTouchBlock(aTarget, true); - ScheduleContentResponseTimeout(aTarget); + TouchBlockState* block = StartNewTouchBlock(aTarget, true); + INPQ_LOG("%p injecting new touch block with id %llu and target %p\n", + this, block->GetBlockId(), aTarget); + ScheduleContentResponseTimeout(aTarget, block->GetBlockId()); + return block->GetBlockId(); } TouchBlockState* @@ -147,76 +151,63 @@ InputQueue::HasReadyTouchBlock() const } void -InputQueue::ScheduleContentResponseTimeout(const nsRefPtr& aTarget) { +InputQueue::ScheduleContentResponseTimeout(const nsRefPtr& aTarget, uint64_t aInputBlockId) { INPQ_LOG("%p scheduling content response timeout for target %p\n", this, aTarget.get()); aTarget->PostDelayedTask( - NewRunnableMethod(this, &InputQueue::ContentResponseTimeout), + NewRunnableMethod(this, &InputQueue::ContentResponseTimeout, aInputBlockId), gfxPrefs::APZContentResponseTimeout()); } void -InputQueue::ContentResponseTimeout() { +InputQueue::ContentResponseTimeout(const uint64_t& aInputBlockId) { AsyncPanZoomController::AssertOnControllerThread(); - mTouchBlockBalance++; - INPQ_LOG("%p got a content response timeout; balance %d\n", this, mTouchBlockBalance); - if (mTouchBlockBalance > 0) { - // Find the first touch block in the queue that hasn't already received - // the content response timeout callback, and notify it. - bool found = false; - for (size_t i = 0; i < mTouchBlockQueue.Length(); i++) { - if (mTouchBlockQueue[i]->TimeoutContentResponse()) { - found = true; - break; - } - } - if (found) { - ProcessPendingInputBlocks(); - } else { - NS_WARNING("INPQ received more ContentResponseTimeout calls than it has unprocessed touch blocks\n"); - } - } -} - -void -InputQueue::ContentReceivedTouch(bool aPreventDefault) { - AsyncPanZoomController::AssertOnControllerThread(); - - mTouchBlockBalance--; - INPQ_LOG("%p got a content response; balance %d\n", this, mTouchBlockBalance); - if (mTouchBlockBalance < 0) { - // Find the first touch block in the queue that hasn't already received - // its response from content, and notify it. - bool found = false; - for (size_t i = 0; i < mTouchBlockQueue.Length(); i++) { - if (mTouchBlockQueue[i]->SetContentResponse(aPreventDefault)) { - found = true; - break; - } - } - if (found) { - ProcessPendingInputBlocks(); - } else { - NS_WARNING("INPQ received more ContentReceivedTouch calls than it has unprocessed touch blocks\n"); - } - } -} - -void -InputQueue::SetAllowedTouchBehavior(const nsTArray& aBehaviors) { - AsyncPanZoomController::AssertOnControllerThread(); - - bool found = false; + INPQ_LOG("%p got a content response timeout; block=%llu\n", this, aInputBlockId); + bool success = false; for (size_t i = 0; i < mTouchBlockQueue.Length(); i++) { - if (mTouchBlockQueue[i]->SetAllowedTouchBehaviors(aBehaviors)) { - found = true; + if (mTouchBlockQueue[i]->GetBlockId() == aInputBlockId) { + success = mTouchBlockQueue[i]->TimeoutContentResponse(); break; } } - if (found) { + if (success) { + ProcessPendingInputBlocks(); + } +} + +void +InputQueue::ContentReceivedTouch(uint64_t aInputBlockId, bool aPreventDefault) { + AsyncPanZoomController::AssertOnControllerThread(); + + INPQ_LOG("%p got a content response; block=%llu\n", this, aInputBlockId); + bool success = false; + for (size_t i = 0; i < mTouchBlockQueue.Length(); i++) { + if (mTouchBlockQueue[i]->GetBlockId() == aInputBlockId) { + success = mTouchBlockQueue[i]->SetContentResponse(aPreventDefault); + break; + } + } + if (success) { + ProcessPendingInputBlocks(); + } +} + +void +InputQueue::SetAllowedTouchBehavior(uint64_t aInputBlockId, const nsTArray& aBehaviors) { + AsyncPanZoomController::AssertOnControllerThread(); + + INPQ_LOG("%p got allowed touch behaviours; block=%llu\n", this, aInputBlockId); + bool success = false; + for (size_t i = 0; i < mTouchBlockQueue.Length(); i++) { + if (mTouchBlockQueue[i]->GetBlockId() == aInputBlockId) { + success = mTouchBlockQueue[i]->SetAllowedTouchBehaviors(aBehaviors); + break; + } + } + if (success) { ProcessPendingInputBlocks(); } else { - NS_WARNING("INPQ received more SetAllowedTouchBehavior calls than it has unprocessed touch blocks\n"); + NS_WARNING("INPQ received useless SetAllowedTouchBehavior"); } } diff --git a/gfx/layers/apz/src/InputQueue.h b/gfx/layers/apz/src/InputQueue.h index cb37c49cc56d..43e0bad81eb2 100644 --- a/gfx/layers/apz/src/InputQueue.h +++ b/gfx/layers/apz/src/InputQueue.h @@ -39,35 +39,31 @@ public: * Notifies the InputQueue of a new incoming input event. The APZC that the * input event was targeted to should be provided in the |aTarget| parameter. * See the documentation on APZCTreeManager::ReceiveInputEvent for info on - * return values from this function. + * return values from this function, including |aOutInputBlockId|. */ - nsEventStatus ReceiveInputEvent(const nsRefPtr& aTarget, const InputData& aEvent); + nsEventStatus ReceiveInputEvent(const nsRefPtr& aTarget, const InputData& aEvent, uint64_t* aOutInputBlockId); /** * This function should be invoked to notify the InputQueue when web content - * decides whether or not it wants to cancel a block of events. This - * automatically gets applied to the next block of events that has not yet - * been responded to. This function MUST be invoked exactly once for each - * touch block, after the touch-start event that creates the block is sent to - * ReceiveInputEvent. + * decides whether or not it wants to cancel a block of events. The block + * id to which this applies should be provided in |aInputBlockId|. */ - void ContentReceivedTouch(bool aPreventDefault); + void ContentReceivedTouch(uint64_t aInputBlockId, bool aPreventDefault); /** * This function should be invoked to notify the InputQueue of the touch- - * action properties for the different touch points in an input block. This - * automatically gets applied to the next block of events that has not yet - * received a touch behaviour notification. This function MUST be invoked - * exactly once for each touch block, after the touch-start event that creates - * the block is sent to ReceiveInputEvent. If touch-action is not enabled on - * the platform, this function does nothing and need not be called. + * action properties for the different touch points in an input block. The + * input block this applies to should be specified by the |aInputBlockId| + * parameter. If touch-action is not enabled on the platform, this function + * does nothing and need not be called. */ - void SetAllowedTouchBehavior(const nsTArray& aBehaviors); + void SetAllowedTouchBehavior(uint64_t aInputBlockId, const nsTArray& aBehaviors); /** * Adds a new touch block at the end of the input queue that has the same * allowed touch behaviour flags as the the touch block currently being * processed. This should only be called when processing of a touch block - * triggers the creation of a new touch block. + * triggers the creation of a new touch block. Returns the input block id + * of the the newly-created block. */ - void InjectNewTouchBlock(AsyncPanZoomController* aTarget); + uint64_t InjectNewTouchBlock(AsyncPanZoomController* aTarget); /** * Returns the touch block at the head of the queue. */ @@ -81,64 +77,14 @@ public: private: ~InputQueue(); TouchBlockState* StartNewTouchBlock(const nsRefPtr& aTarget, bool aCopyAllowedTouchBehaviorFromCurrent); - void ScheduleContentResponseTimeout(const nsRefPtr& aTarget); - void ContentResponseTimeout(); + void ScheduleContentResponseTimeout(const nsRefPtr& aTarget, uint64_t aInputBlockId); + void ContentResponseTimeout(const uint64_t& aInputBlockId); void ProcessPendingInputBlocks(); private: // The queue of touch blocks that have not yet been processed. // This member must only be accessed on the controller/UI thread. nsTArray> mTouchBlockQueue; - - // This variable requires some explanation. Strap yourself in. - // - // For each block of events, we do two things: (1) send the events to gecko and expect - // exactly one call to ContentReceivedTouch in return, and (2) kick off a timeout - // that triggers in case we don't hear from web content in a timely fashion. - // Since events are constantly coming in, we need to be able to handle more than one - // block of input events sitting in the queue. - // - // There are ordering restrictions on events that we can take advantage of, and that - // we need to abide by. Blocks of events in the queue will always be in the order that - // the user generated them. Responses we get from content will be in the same order as - // as the blocks of events in the queue. The timeout callbacks that have been posted - // will also fire in the same order as the blocks of events in the queue. - // HOWEVER, we may get multiple responses from content interleaved with multiple - // timeout expirations, and that interleaving is not predictable. - // - // Therefore, we need to make sure that for each block of events, we process the queued - // events exactly once, either when we get the response from content, or when the - // timeout expires (whichever happens first). There is no way to associate the timeout - // or response from content with a particular block of events other than via ordering. - // - // So, what we do to accomplish this is to track a "touch block balance", which is the - // number of timeout expirations that have fired, minus the number of content responses - // that have been received. (Think "balance" as in teeter-totter balance). This - // value is: - // - zero when we are in a state where the next content response we expect to receive - // and the next timeout expiration we expect to fire both correspond to the next - // unprocessed block of events in the queue. - // - negative when we are in a state where we have received more content responses than - // timeout expirations. This means that the next content repsonse we receive will - // correspond to the first unprocessed block, but the next n timeout expirations need - // to be ignored as they are for blocks we have already processed. (n is the absolute - // value of the balance.) - // - positive when we are in a state where we have received more timeout expirations - // than content responses. This means that the next timeout expiration that we will - // receive will correspond to the first unprocessed block, but the next n content - // responses need to be ignored as they are for blocks we have already processed. - // (n is the absolute value of the balance.) - // - // Note that each touch block internally carries flags that indicate whether or not it - // has received a content response and/or timeout expiration. However, we cannot rely - // on that alone to deliver these notifications to the right input block, because - // once an input block has been processed, it can potentially be removed from the queue. - // Therefore the information in that block is lost. An alternative approach would - // be to keep around those blocks until they have received both the content response - // and timeout expiration, but that involves a higher level of memory usage. - // - // This member must only be accessed on the controller/UI thread. - int32_t mTouchBlockBalance; }; } diff --git a/gfx/tests/gtest/TestAsyncPanZoomController.cpp b/gfx/tests/gtest/TestAsyncPanZoomController.cpp index 2dd9453fae07..7d66701990c6 100644 --- a/gfx/tests/gtest/TestAsyncPanZoomController.cpp +++ b/gfx/tests/gtest/TestAsyncPanZoomController.cpp @@ -62,7 +62,7 @@ public: MOCK_METHOD2(AcknowledgeScrollUpdate, void(const FrameMetrics::ViewID&, const uint32_t& aScrollGeneration)); MOCK_METHOD3(HandleDoubleTap, void(const CSSPoint&, int32_t, const ScrollableLayerGuid&)); MOCK_METHOD3(HandleSingleTap, void(const CSSPoint&, int32_t, const ScrollableLayerGuid&)); - MOCK_METHOD3(HandleLongTap, void(const CSSPoint&, int32_t, const ScrollableLayerGuid&)); + MOCK_METHOD4(HandleLongTap, void(const CSSPoint&, int32_t, const ScrollableLayerGuid&, uint64_t)); MOCK_METHOD3(HandleLongTapUp, void(const CSSPoint&, int32_t, const ScrollableLayerGuid&)); MOCK_METHOD3(SendAsyncScrollDOMEvent, void(bool aIsRoot, const CSSRect &aContentRect, const CSSSize &aScrollableSize)); MOCK_METHOD2(PostDelayedTask, void(Task* aTask, int aDelayMs)); @@ -243,11 +243,11 @@ public: }; static nsEventStatus -ApzcDown(AsyncPanZoomController* apzc, int aX, int aY, int aTime) +ApzcDown(AsyncPanZoomController* apzc, int aX, int aY, int aTime, uint64_t* aOutInputBlockId = nullptr) { MultiTouchInput mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_START, aTime, TimeStamp(), 0); mti.mTouches.AppendElement(SingleTouchData(0, ScreenIntPoint(aX, aY), ScreenSize(0, 0), 0, 0)); - return apzc->ReceiveInputEvent(mti); + return apzc->ReceiveInputEvent(mti, aOutInputBlockId); } static nsEventStatus @@ -255,7 +255,7 @@ ApzcUp(AsyncPanZoomController* apzc, int aX, int aY, int aTime) { MultiTouchInput mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_END, aTime, TimeStamp(), 0); mti.mTouches.AppendElement(SingleTouchData(0, ScreenIntPoint(aX, aY), ScreenSize(0, 0), 0, 0)); - return apzc->ReceiveInputEvent(mti); + return apzc->ReceiveInputEvent(mti, nullptr); } static void @@ -289,13 +289,21 @@ ApzcPan(AsyncPanZoomController* aApzc, int aTouchEndY, bool aKeepFingerDown = false, nsTArray* aAllowedTouchBehaviors = nullptr, - nsEventStatus (*aOutEventStatuses)[4] = nullptr) + nsEventStatus (*aOutEventStatuses)[4] = nullptr, + uint64_t* aOutInputBlockId = nullptr) { const int TIME_BETWEEN_TOUCH_EVENT = 100; const int OVERCOME_TOUCH_TOLERANCE = 100; + // Even if the caller doesn't care about the block id, we need it to set the + // allowed touch behaviour below, so make sure aOutInputBlockId is non-null. + uint64_t blockId; + if (!aOutInputBlockId) { + aOutInputBlockId = &blockId; + } + // Make sure the move is large enough to not be handled as a tap - nsEventStatus status = ApzcDown(aApzc, 10, aTouchStartY + OVERCOME_TOUCH_TOLERANCE, aTime); + nsEventStatus status = ApzcDown(aApzc, 10, aTouchStartY + OVERCOME_TOUCH_TOLERANCE, aTime, aOutInputBlockId); if (aOutEventStatuses) { (*aOutEventStatuses)[0] = status; } @@ -304,12 +312,12 @@ ApzcPan(AsyncPanZoomController* aApzc, // Allowed touch behaviours must be set after sending touch-start. if (gfxPrefs::TouchActionEnabled() && aAllowedTouchBehaviors) { - aApzc->SetAllowedTouchBehavior(*aAllowedTouchBehaviors); + aApzc->SetAllowedTouchBehavior(*aOutInputBlockId, *aAllowedTouchBehaviors); } MultiTouchInput mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_MOVE, aTime, TimeStamp(), 0); mti.mTouches.AppendElement(SingleTouchData(0, ScreenIntPoint(10, aTouchStartY), ScreenSize(0, 0), 0, 0)); - status = aApzc->ReceiveInputEvent(mti); + status = aApzc->ReceiveInputEvent(mti, nullptr); if (aOutEventStatuses) { (*aOutEventStatuses)[1] = status; } @@ -318,7 +326,7 @@ ApzcPan(AsyncPanZoomController* aApzc, mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_MOVE, aTime, TimeStamp(), 0); mti.mTouches.AppendElement(SingleTouchData(0, ScreenIntPoint(10, aTouchEndY), ScreenSize(0, 0), 0, 0)); - status = aApzc->ReceiveInputEvent(mti); + status = aApzc->ReceiveInputEvent(mti, nullptr); if (aOutEventStatuses) { (*aOutEventStatuses)[2] = status; } @@ -347,10 +355,11 @@ ApzcPanAndCheckStatus(AsyncPanZoomController* aApzc, int aTouchStartY, int aTouchEndY, bool aExpectConsumed, - nsTArray* aAllowedTouchBehaviors) + nsTArray* aAllowedTouchBehaviors, + uint64_t* aOutInputBlockId = nullptr) { nsEventStatus statuses[4]; // down, move, move, up - ApzcPan(aApzc, aTime, aTouchStartY, aTouchEndY, false, aAllowedTouchBehaviors, &statuses); + ApzcPan(aApzc, aTime, aTouchStartY, aTouchEndY, false, aAllowedTouchBehaviors, &statuses, aOutInputBlockId); EXPECT_EQ(nsEventStatus_eConsumeDoDefault, statuses[0]); @@ -368,9 +377,10 @@ static void ApzcPanNoFling(AsyncPanZoomController* aApzc, int& aTime, int aTouchStartY, - int aTouchEndY) + int aTouchEndY, + uint64_t* aOutInputBlockId = nullptr) { - ApzcPan(aApzc, aTime, aTouchStartY, aTouchEndY); + ApzcPan(aApzc, aTime, aTouchStartY, aTouchEndY, false, nullptr, nullptr, aOutInputBlockId); aApzc->CancelAnimation(); } @@ -424,29 +434,37 @@ ApzcPinchWithTouchInput(AsyncPanZoomController* aApzc, int aFocusX, int aFocusY, float aScale, int& inputId, nsTArray* aAllowedTouchBehaviors = nullptr, - nsEventStatus (*aOutEventStatuses)[4] = nullptr) + nsEventStatus (*aOutEventStatuses)[4] = nullptr, + uint64_t* aOutInputBlockId = nullptr) { // Having pinch coordinates in float type may cause problems with high-precision scale values // since SingleTouchData accepts integer value. But for trivial tests it should be ok. float pinchLength = 100.0; float pinchLengthScaled = pinchLength * aScale; + // Even if the caller doesn't care about the block id, we need it to set the + // allowed touch behaviour below, so make sure aOutInputBlockId is non-null. + uint64_t blockId; + if (!aOutInputBlockId) { + aOutInputBlockId = &blockId; + } + MultiTouchInput mtiStart = MultiTouchInput(MultiTouchInput::MULTITOUCH_START, 0, TimeStamp(), 0); mtiStart.mTouches.AppendElement(SingleTouchData(inputId, ScreenIntPoint(aFocusX, aFocusY), ScreenSize(0, 0), 0, 0)); mtiStart.mTouches.AppendElement(SingleTouchData(inputId + 1, ScreenIntPoint(aFocusX, aFocusY), ScreenSize(0, 0), 0, 0)); - nsEventStatus status = aApzc->ReceiveInputEvent(mtiStart); + nsEventStatus status = aApzc->ReceiveInputEvent(mtiStart, aOutInputBlockId); if (aOutEventStatuses) { (*aOutEventStatuses)[0] = status; } if (gfxPrefs::TouchActionEnabled() && aAllowedTouchBehaviors) { - aApzc->SetAllowedTouchBehavior(*aAllowedTouchBehaviors); + aApzc->SetAllowedTouchBehavior(*aOutInputBlockId, *aAllowedTouchBehaviors); } MultiTouchInput mtiMove1 = MultiTouchInput(MultiTouchInput::MULTITOUCH_MOVE, 0, TimeStamp(), 0); mtiMove1.mTouches.AppendElement(SingleTouchData(inputId, ScreenIntPoint(aFocusX - pinchLength, aFocusY), ScreenSize(0, 0), 0, 0)); mtiMove1.mTouches.AppendElement(SingleTouchData(inputId + 1, ScreenIntPoint(aFocusX + pinchLength, aFocusY), ScreenSize(0, 0), 0, 0)); - status = aApzc->ReceiveInputEvent(mtiMove1); + status = aApzc->ReceiveInputEvent(mtiMove1, nullptr); if (aOutEventStatuses) { (*aOutEventStatuses)[1] = status; } @@ -454,7 +472,7 @@ ApzcPinchWithTouchInput(AsyncPanZoomController* aApzc, MultiTouchInput mtiMove2 = MultiTouchInput(MultiTouchInput::MULTITOUCH_MOVE, 0, TimeStamp(), 0); mtiMove2.mTouches.AppendElement(SingleTouchData(inputId, ScreenIntPoint(aFocusX - pinchLengthScaled, aFocusY), ScreenSize(0, 0), 0, 0)); mtiMove2.mTouches.AppendElement(SingleTouchData(inputId + 1, ScreenIntPoint(aFocusX + pinchLengthScaled, aFocusY), ScreenSize(0, 0), 0, 0)); - status = aApzc->ReceiveInputEvent(mtiMove2); + status = aApzc->ReceiveInputEvent(mtiMove2, nullptr); if (aOutEventStatuses) { (*aOutEventStatuses)[2] = status; } @@ -462,7 +480,7 @@ ApzcPinchWithTouchInput(AsyncPanZoomController* aApzc, MultiTouchInput mtiEnd = MultiTouchInput(MultiTouchInput::MULTITOUCH_END, 0, TimeStamp(), 0); mtiEnd.mTouches.AppendElement(SingleTouchData(inputId, ScreenIntPoint(aFocusX - pinchLengthScaled, aFocusY), ScreenSize(0, 0), 0, 0)); mtiEnd.mTouches.AppendElement(SingleTouchData(inputId + 1, ScreenIntPoint(aFocusX + pinchLengthScaled, aFocusY), ScreenSize(0, 0), 0, 0)); - status = aApzc->ReceiveInputEvent(mtiEnd); + status = aApzc->ReceiveInputEvent(mtiEnd, nullptr); if (aOutEventStatuses) { (*aOutEventStatuses)[3] = status; } @@ -618,10 +636,11 @@ TEST_F(APZCPinchGestureDetectorTester, Pinch_PreventDefault) { MakeApzcZoomable(); int touchInputId = 0; - ApzcPinchWithTouchInput(apzc, 250, 300, 1.25, touchInputId); + uint64_t blockId = 0; + ApzcPinchWithTouchInput(apzc, 250, 300, 1.25, touchInputId, nullptr, nullptr, &blockId); // Send the prevent-default notification for the touch block - apzc->ContentReceivedTouch(true); + apzc->ContentReceivedTouch(blockId, true); // Run all pending tasks (this should include at least the // prevent-default timer). @@ -822,15 +841,16 @@ protected: int touchEnd = 10; ScreenPoint pointOut; ViewTransform viewTransformOut; + uint64_t blockId = 0; // Pan down nsTArray allowedTouchBehaviors; allowedTouchBehaviors.AppendElement(mozilla::layers::AllowedTouchBehavior::VERTICAL_PAN); - ApzcPanAndCheckStatus(apzc, time, touchStart, touchEnd, true, &allowedTouchBehaviors); + ApzcPanAndCheckStatus(apzc, time, touchStart, touchEnd, true, &allowedTouchBehaviors, &blockId); // Send the signal that content has handled and preventDefaulted the touch // events. This flushes the event queue. - apzc->ContentReceivedTouch(true); + apzc->ContentReceivedTouch(blockId, true); // Run all pending tasks (this should include at least the // prevent-default timer). EXPECT_LE(1, mcc->RunThroughDelayedTasks()); @@ -1110,10 +1130,11 @@ protected: int time = 0; int touchStart = 50; int touchEnd = 10; + uint64_t blockId = 0; // Start the fling down. - ApzcPan(apzc, time, touchStart, touchEnd); - apzc->ContentReceivedTouch(false); + ApzcPan(apzc, time, touchStart, touchEnd, false, nullptr, nullptr, &blockId); + apzc->ContentReceivedTouch(blockId, false); while (mcc->RunThroughDelayedTasks()); // Sample the fling a couple of times to ensure it's going. @@ -1124,7 +1145,7 @@ protected: EXPECT_GT(finalPoint.y, point.y); // Now we put our finger down to stop the fling - ApzcDown(apzc, 10, 10, time); + ApzcDown(apzc, 10, 10, time, &blockId); // Re-sample to make sure it hasn't moved apzc->SampleContentTransformForFrame(testStartTime + TimeDuration::FromMilliseconds(30), &viewTransform, point); @@ -1133,7 +1154,7 @@ protected: // respond to the touchdown that stopped the fling. // even if we do a prevent-default on it, the animation should remain stopped. - apzc->ContentReceivedTouch(aPreventDefault); + apzc->ContentReceivedTouch(blockId, aPreventDefault); while (mcc->RunThroughDelayedTasks()); // Verify the page hasn't moved @@ -1211,18 +1232,19 @@ protected: MakeApzcUnzoomable(); int time = 0; + uint64_t blockId = 0; - nsEventStatus status = ApzcDown(apzc, 10, 10, time); + nsEventStatus status = ApzcDown(apzc, 10, 10, time, &blockId); EXPECT_EQ(nsEventStatus_eConsumeDoDefault, status); if (gfxPrefs::TouchActionEnabled()) { // SetAllowedTouchBehavior() must be called after sending touch-start. nsTArray allowedTouchBehaviors; allowedTouchBehaviors.AppendElement(aBehavior); - apzc->SetAllowedTouchBehavior(allowedTouchBehaviors); + apzc->SetAllowedTouchBehavior(blockId, allowedTouchBehaviors); } // Have content "respond" to the touchstart - apzc->ContentReceivedTouch(false); + apzc->ContentReceivedTouch(blockId, false); MockFunction check; @@ -1230,7 +1252,8 @@ protected: InSequence s; EXPECT_CALL(check, Call("preHandleLongTap")); - EXPECT_CALL(*mcc, HandleLongTap(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(1); + blockId++; + EXPECT_CALL(*mcc, HandleLongTap(CSSPoint(10, 10), 0, apzc->GetGuid(), blockId)).Times(1); EXPECT_CALL(check, Call("postHandleLongTap")); EXPECT_CALL(check, Call("preHandleLongTapUp")); @@ -1254,7 +1277,7 @@ protected: // in the queue. Deal with those here. We do the content response first // with preventDefault=false, and then we run the timeout task which // "loses the race" and does nothing. - apzc->ContentReceivedTouch(false); + apzc->ContentReceivedTouch(blockId, false); mcc->CheckHasDelayedTask(); mcc->RunDelayedTask(); @@ -1281,17 +1304,18 @@ protected: touchEndY = 50; int time = 0; - nsEventStatus status = ApzcDown(apzc, touchX, touchStartY, time); + uint64_t blockId = 0; + nsEventStatus status = ApzcDown(apzc, touchX, touchStartY, time, &blockId); EXPECT_EQ(nsEventStatus_eConsumeDoDefault, status); if (gfxPrefs::TouchActionEnabled()) { // SetAllowedTouchBehavior() must be called after sending touch-start. nsTArray allowedTouchBehaviors; allowedTouchBehaviors.AppendElement(aBehavior); - apzc->SetAllowedTouchBehavior(allowedTouchBehaviors); + apzc->SetAllowedTouchBehavior(blockId, allowedTouchBehaviors); } // Have content "respond" to the touchstart - apzc->ContentReceivedTouch(false); + apzc->ContentReceivedTouch(blockId, false); MockFunction check; @@ -1299,7 +1323,8 @@ protected: InSequence s; EXPECT_CALL(check, Call("preHandleLongTap")); - EXPECT_CALL(*mcc, HandleLongTap(CSSPoint(touchX, touchStartY), 0, apzc->GetGuid())).Times(1); + blockId++; + EXPECT_CALL(*mcc, HandleLongTap(CSSPoint(touchX, touchStartY), 0, apzc->GetGuid(), blockId)).Times(1); EXPECT_CALL(check, Call("postHandleLongTap")); } @@ -1318,7 +1343,7 @@ protected: // Send the signal that content has handled the long-tap, and then run // the timeout task (it will be a no-op because the content "wins" the // race. This takes the place of the "contextmenu" event. - apzc->ContentReceivedTouch(true); + apzc->ContentReceivedTouch(blockId, true); mcc->CheckHasDelayedTask(); mcc->RunDelayedTask(); @@ -1326,7 +1351,7 @@ protected: MultiTouchInput mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_MOVE, time, TimeStamp(), 0); mti.mTouches.AppendElement(SingleTouchData(0, ScreenIntPoint(touchX, touchEndY), ScreenSize(0, 0), 0, 0)); - status = apzc->ReceiveInputEvent(mti); + status = apzc->ReceiveInputEvent(mti, nullptr); EXPECT_EQ(nsEventStatus_eConsumeDoDefault, status); EXPECT_CALL(*mcc, HandleLongTapUp(CSSPoint(touchX, touchEndY), 0, apzc->GetGuid())).Times(0); @@ -1368,22 +1393,30 @@ TEST_F(APZCLongPressTester, LongPressPreventDefaultWithTouchAction) { static void ApzcDoubleTap(AsyncPanZoomController* aApzc, int aX, int aY, int& aTime, - nsEventStatus (*aOutEventStatuses)[4] = nullptr) + nsEventStatus (*aOutEventStatuses)[4] = nullptr, + uint64_t (*aOutInputBlockIds)[2] = nullptr) { - nsEventStatus status = ApzcDown(aApzc, aX, aY, aTime); + uint64_t blockId; + nsEventStatus status = ApzcDown(aApzc, aX, aY, aTime, &blockId); if (aOutEventStatuses) { (*aOutEventStatuses)[0] = status; } + if (aOutInputBlockIds) { + (*aOutInputBlockIds)[0] = blockId; + } aTime += 10; status = ApzcUp(aApzc, aX, aY, aTime); if (aOutEventStatuses) { (*aOutEventStatuses)[1] = status; } aTime += 10; - status = ApzcDown(aApzc, aX, aY, aTime); + status = ApzcDown(aApzc, aX, aY, aTime, &blockId); if (aOutEventStatuses) { (*aOutEventStatuses)[2] = status; } + if (aOutInputBlockIds) { + (*aOutInputBlockIds)[1] = blockId; + } aTime += 10; status = ApzcUp(aApzc, aX, aY, aTime); if (aOutEventStatuses) { @@ -1392,10 +1425,10 @@ ApzcDoubleTap(AsyncPanZoomController* aApzc, int aX, int aY, int& aTime, } static void -ApzcDoubleTapAndCheckStatus(AsyncPanZoomController* aApzc, int aX, int aY, int& aTime) +ApzcDoubleTapAndCheckStatus(AsyncPanZoomController* aApzc, int aX, int aY, int& aTime, uint64_t (*aOutInputBlockIds)[2] = nullptr) { nsEventStatus statuses[4]; - ApzcDoubleTap(aApzc, aX, aY, aTime, &statuses); + ApzcDoubleTap(aApzc, aX, aY, aTime, &statuses, aOutInputBlockIds); EXPECT_EQ(nsEventStatus_eConsumeDoDefault, statuses[0]); EXPECT_EQ(nsEventStatus_eConsumeDoDefault, statuses[1]); EXPECT_EQ(nsEventStatus_eConsumeDoDefault, statuses[2]); @@ -1410,11 +1443,12 @@ TEST_F(APZCGestureDetectorTester, DoubleTap) { EXPECT_CALL(*mcc, HandleDoubleTap(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(1); int time = 0; - ApzcDoubleTapAndCheckStatus(apzc, 10, 10, time); + uint64_t blockIds[2]; + ApzcDoubleTapAndCheckStatus(apzc, 10, 10, time, &blockIds); // responses to the two touchstarts - apzc->ContentReceivedTouch(false); - apzc->ContentReceivedTouch(false); + apzc->ContentReceivedTouch(blockIds[0], false); + apzc->ContentReceivedTouch(blockIds[1], false); while (mcc->RunThroughDelayedTasks()); @@ -1429,11 +1463,12 @@ TEST_F(APZCGestureDetectorTester, DoubleTapNotZoomable) { EXPECT_CALL(*mcc, HandleDoubleTap(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(0); int time = 0; - ApzcDoubleTapAndCheckStatus(apzc, 10, 10, time); + uint64_t blockIds[2]; + ApzcDoubleTapAndCheckStatus(apzc, 10, 10, time, &blockIds); // responses to the two touchstarts - apzc->ContentReceivedTouch(false); - apzc->ContentReceivedTouch(false); + apzc->ContentReceivedTouch(blockIds[0], false); + apzc->ContentReceivedTouch(blockIds[1], false); while (mcc->RunThroughDelayedTasks()); @@ -1448,11 +1483,12 @@ TEST_F(APZCGestureDetectorTester, DoubleTapPreventDefaultFirstOnly) { EXPECT_CALL(*mcc, HandleDoubleTap(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(0); int time = 0; - ApzcDoubleTapAndCheckStatus(apzc, 10, 10, time); + uint64_t blockIds[2]; + ApzcDoubleTapAndCheckStatus(apzc, 10, 10, time, &blockIds); // responses to the two touchstarts - apzc->ContentReceivedTouch(true); - apzc->ContentReceivedTouch(false); + apzc->ContentReceivedTouch(blockIds[0], true); + apzc->ContentReceivedTouch(blockIds[1], false); while (mcc->RunThroughDelayedTasks()); @@ -1467,11 +1503,13 @@ TEST_F(APZCGestureDetectorTester, DoubleTapPreventDefaultBoth) { EXPECT_CALL(*mcc, HandleDoubleTap(CSSPoint(10, 10), 0, apzc->GetGuid())).Times(0); int time = 0; - ApzcDoubleTapAndCheckStatus(apzc, 10, 10, time); + uint64_t blockIds[2]; + ApzcDoubleTapAndCheckStatus(apzc, 10, 10, time, &blockIds); +printf_stderr("blockids %llu %llu\n", blockIds[0], blockIds[1]); // responses to the two touchstarts - apzc->ContentReceivedTouch(true); - apzc->ContentReceivedTouch(true); + apzc->ContentReceivedTouch(blockIds[0], true); + apzc->ContentReceivedTouch(blockIds[1], true); while (mcc->RunThroughDelayedTasks()); @@ -1493,12 +1531,12 @@ TEST_F(APZCGestureDetectorTester, TapFollowedByPinch) { mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_START, time, TimeStamp(), 0); mti.mTouches.AppendElement(SingleTouchData(inputId, ScreenIntPoint(20, 20), ScreenSize(0, 0), 0, 0)); mti.mTouches.AppendElement(SingleTouchData(inputId + 1, ScreenIntPoint(10, 10), ScreenSize(0, 0), 0, 0)); - apzc->ReceiveInputEvent(mti); + apzc->ReceiveInputEvent(mti, nullptr); mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_END, time, TimeStamp(), 0); mti.mTouches.AppendElement(SingleTouchData(inputId, ScreenIntPoint(20, 20), ScreenSize(0, 0), 0, 0)); mti.mTouches.AppendElement(SingleTouchData(inputId + 1, ScreenIntPoint(10, 10), ScreenSize(0, 0), 0, 0)); - apzc->ReceiveInputEvent(mti); + apzc->ReceiveInputEvent(mti, nullptr); while (mcc->RunThroughDelayedTasks()); @@ -1517,17 +1555,17 @@ TEST_F(APZCGestureDetectorTester, TapFollowedByMultipleTouches) { MultiTouchInput mti; mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_START, time, TimeStamp(), 0); mti.mTouches.AppendElement(SingleTouchData(inputId, ScreenIntPoint(20, 20), ScreenSize(0, 0), 0, 0)); - apzc->ReceiveInputEvent(mti); + apzc->ReceiveInputEvent(mti, nullptr); mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_START, time, TimeStamp(), 0); mti.mTouches.AppendElement(SingleTouchData(inputId, ScreenIntPoint(20, 20), ScreenSize(0, 0), 0, 0)); mti.mTouches.AppendElement(SingleTouchData(inputId + 1, ScreenIntPoint(10, 10), ScreenSize(0, 0), 0, 0)); - apzc->ReceiveInputEvent(mti); + apzc->ReceiveInputEvent(mti, nullptr); mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_END, time, TimeStamp(), 0); mti.mTouches.AppendElement(SingleTouchData(inputId, ScreenIntPoint(20, 20), ScreenSize(0, 0), 0, 0)); mti.mTouches.AppendElement(SingleTouchData(inputId + 1, ScreenIntPoint(10, 10), ScreenSize(0, 0), 0, 0)); - apzc->ReceiveInputEvent(mti); + apzc->ReceiveInputEvent(mti, nullptr); while (mcc->RunThroughDelayedTasks()); @@ -1636,26 +1674,26 @@ ApzctmPan(APZCTreeManager* aTreeManager, // Make sure the move is large enough to not be handled as a tap MultiTouchInput mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_START, aTime, TimeStamp(), 0); mti.mTouches.AppendElement(SingleTouchData(0, ScreenIntPoint(10, aTouchStartY), ScreenSize(0, 0), 0, 0)); - aTreeManager->ReceiveInputEvent(mti, nullptr); + aTreeManager->ReceiveInputEvent(mti, nullptr, nullptr); aTime += TIME_BETWEEN_TOUCH_EVENT; mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_MOVE, aTime, TimeStamp(), 0); mti.mTouches.AppendElement(SingleTouchData(0, ScreenIntPoint(10, aTouchStartY + OVERCOME_TOUCH_TOLERANCE), ScreenSize(0, 0), 0, 0)); - aTreeManager->ReceiveInputEvent(mti, nullptr); + aTreeManager->ReceiveInputEvent(mti, nullptr, nullptr); aTime += TIME_BETWEEN_TOUCH_EVENT; mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_MOVE, aTime, TimeStamp(), 0); mti.mTouches.AppendElement(SingleTouchData(0, ScreenIntPoint(10, aTouchEndY), ScreenSize(0, 0), 0, 0)); - aTreeManager->ReceiveInputEvent(mti, nullptr); + aTreeManager->ReceiveInputEvent(mti, nullptr, nullptr); aTime += TIME_BETWEEN_TOUCH_EVENT; if (!aKeepFingerDown) { mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_END, aTime, TimeStamp(), 0); mti.mTouches.AppendElement(SingleTouchData(0, ScreenIntPoint(10, aTouchEndY), ScreenSize(0, 0), 0, 0)); - aTreeManager->ReceiveInputEvent(mti, nullptr); + aTreeManager->ReceiveInputEvent(mti, nullptr, nullptr); } aTime += TIME_BETWEEN_TOUCH_EVENT; @@ -2048,13 +2086,13 @@ TEST_F(APZHitTestingTester, TestRepaintFlushOnNewInputBlock) { MultiTouchInput mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_START, time, TimeStamp(), 0); mti.mTouches.AppendElement(SingleTouchData(0, touchPoint, ScreenSize(0, 0), 0, 0)); - EXPECT_EQ(nsEventStatus_eConsumeDoDefault, manager->ReceiveInputEvent(mti, nullptr)); + EXPECT_EQ(nsEventStatus_eConsumeDoDefault, manager->ReceiveInputEvent(mti, nullptr, nullptr)); EXPECT_EQ(touchPoint, mti.mTouches[0].mScreenPoint); check.Call("post-first-touch-start"); // Send a touchend to clear state mti.mType = MultiTouchInput::MULTITOUCH_END; - manager->ReceiveInputEvent(mti, nullptr); + manager->ReceiveInputEvent(mti, nullptr, nullptr); AsyncPanZoomController::SetFrameTime(testStartTime + TimeDuration::FromMilliseconds(1000)); @@ -2071,12 +2109,12 @@ TEST_F(APZHitTestingTester, TestRepaintFlushOnNewInputBlock) { // Ensure that a touch start again doesn't get untransformed by flushing // a repaint mti.mType = MultiTouchInput::MULTITOUCH_START; - EXPECT_EQ(nsEventStatus_eConsumeDoDefault, manager->ReceiveInputEvent(mti, nullptr)); + EXPECT_EQ(nsEventStatus_eConsumeDoDefault, manager->ReceiveInputEvent(mti, nullptr, nullptr)); EXPECT_EQ(touchPoint, mti.mTouches[0].mScreenPoint); check.Call("post-second-touch-start"); mti.mType = MultiTouchInput::MULTITOUCH_END; - EXPECT_EQ(nsEventStatus_eConsumeDoDefault, manager->ReceiveInputEvent(mti, nullptr)); + EXPECT_EQ(nsEventStatus_eConsumeDoDefault, manager->ReceiveInputEvent(mti, nullptr, nullptr)); EXPECT_EQ(touchPoint, mti.mTouches[0].mScreenPoint); mcc->RunThroughDelayedTasks(); @@ -2180,10 +2218,11 @@ TEST_F(APZOverscrollHandoffTester, DeferredInputEventProcessing) { // Queue input events for a pan. int time = 0; - ApzcPanNoFling(childApzc, time, 90, 30); + uint64_t blockId = 0; + ApzcPanNoFling(childApzc, time, 90, 30, &blockId); // Allow the pan to be processed. - childApzc->ContentReceivedTouch(false); + childApzc->ContentReceivedTouch(blockId, false); // Make sure overscroll was handed off correctly. EXPECT_EQ(50, childApzc->GetFrameMetrics().GetScrollOffset().y); @@ -2207,7 +2246,8 @@ TEST_F(APZOverscrollHandoffTester, LayerStructureChangesWhileEventsArePending) { // Queue input events for a pan. int time = 0; - ApzcPanNoFling(childApzc, time, 90, 30); + uint64_t blockId = 0; + ApzcPanNoFling(childApzc, time, 90, 30, &blockId); // Modify the APZC tree to insert a new APZC 'middle' into the handoff chain // between the child and the root. @@ -2217,10 +2257,11 @@ TEST_F(APZOverscrollHandoffTester, LayerStructureChangesWhileEventsArePending) { TestAsyncPanZoomController* middleApzc = ApzcOf(middle); // Queue input events for another pan. - ApzcPanNoFling(childApzc, time, 30, 90); + uint64_t secondBlockId = 0; + ApzcPanNoFling(childApzc, time, 30, 90, &secondBlockId); // Allow the first pan to be processed. - childApzc->ContentReceivedTouch(false); + childApzc->ContentReceivedTouch(blockId, false); // Make sure things have scrolled according to the handoff chain in // place at the time the touch-start of the first pan was queued. @@ -2229,7 +2270,7 @@ TEST_F(APZOverscrollHandoffTester, LayerStructureChangesWhileEventsArePending) { EXPECT_EQ(0, middleApzc->GetFrameMetrics().GetScrollOffset().y); // Allow the second pan to be processed. - childApzc->ContentReceivedTouch(false); + childApzc->ContentReceivedTouch(secondBlockId, false); // Make sure things have scrolled according to the handoff chain in // place at the time the touch-start of the second pan was queued. @@ -2259,12 +2300,12 @@ TEST_F(APZOverscrollHandoffTester, StuckInOverscroll_Bug1073250) { // Use the same touch identifier for the first touch (0) as ApzctmPan(). (A bit hacky.) secondFingerDown.mTouches.AppendElement(SingleTouchData(0, ScreenIntPoint(10, 40), ScreenSize(0, 0), 0, 0)); secondFingerDown.mTouches.AppendElement(SingleTouchData(1, ScreenIntPoint(30, 20), ScreenSize(0, 0), 0, 0)); - manager->ReceiveInputEvent(secondFingerDown, nullptr); + manager->ReceiveInputEvent(secondFingerDown, nullptr, nullptr); // Release the fingers. MultiTouchInput fingersUp = secondFingerDown; fingersUp.mType = MultiTouchInput::MULTITOUCH_END; - manager->ReceiveInputEvent(fingersUp, nullptr); + manager->ReceiveInputEvent(fingersUp, nullptr, nullptr); // Allow any animations to run their course. child->AdvanceAnimationsUntilEnd(testStartTime); diff --git a/layout/ipc/RenderFrameParent.cpp b/layout/ipc/RenderFrameParent.cpp index 860665cfee80..6d6ae82c2c88 100644 --- a/layout/ipc/RenderFrameParent.cpp +++ b/layout/ipc/RenderFrameParent.cpp @@ -154,7 +154,8 @@ public: virtual void HandleLongTap(const CSSPoint& aPoint, int32_t aModifiers, - const ScrollableLayerGuid& aGuid) MOZ_OVERRIDE + const ScrollableLayerGuid& aGuid, + uint64_t aInputBlockId) MOZ_OVERRIDE { if (MessageLoop::current() != mUILoop) { // We have to send this message from the "UI thread" (main @@ -162,12 +163,12 @@ public: mUILoop->PostTask( FROM_HERE, NewRunnableMethod(this, &RemoteContentController::HandleLongTap, - aPoint, aModifiers, aGuid)); + aPoint, aModifiers, aGuid, aInputBlockId)); return; } if (mRenderFrame) { TabParent* browser = static_cast(mRenderFrame->Manager()); - browser->HandleLongTap(aPoint, aModifiers, aGuid); + browser->HandleLongTap(aPoint, aModifiers, aGuid, aInputBlockId); } } @@ -416,10 +417,12 @@ RenderFrameParent::OwnerContentChanged(nsIContent* aContent) nsEventStatus RenderFrameParent::NotifyInputEvent(WidgetInputEvent& aEvent, - ScrollableLayerGuid* aOutTargetGuid) + ScrollableLayerGuid* aOutTargetGuid, + uint64_t* aOutInputBlockId) { if (GetApzcTreeManager()) { - return GetApzcTreeManager()->ReceiveInputEvent(aEvent, aOutTargetGuid); + return GetApzcTreeManager()->ReceiveInputEvent( + aEvent, aOutTargetGuid, aOutInputBlockId); } return nsEventStatus_eIgnore; } @@ -528,6 +531,7 @@ RenderFrameParent::ZoomToRect(uint32_t aPresShellId, ViewID aViewId, void RenderFrameParent::ContentReceivedTouch(const ScrollableLayerGuid& aGuid, + uint64_t aInputBlockId, bool aPreventDefault) { if (aGuid.mLayersId != mLayersId) { @@ -536,7 +540,7 @@ RenderFrameParent::ContentReceivedTouch(const ScrollableLayerGuid& aGuid, return; } if (GetApzcTreeManager()) { - GetApzcTreeManager()->ContentReceivedTouch(aGuid, aPreventDefault); + GetApzcTreeManager()->ContentReceivedTouch(aGuid, aInputBlockId, aPreventDefault); } } diff --git a/layout/ipc/RenderFrameParent.h b/layout/ipc/RenderFrameParent.h index f53cd1ad770a..6022c6f67f14 100644 --- a/layout/ipc/RenderFrameParent.h +++ b/layout/ipc/RenderFrameParent.h @@ -88,13 +88,18 @@ public: * @param aOutTargetGuid An out-parameter that will contain the identifier * of the APZC instance that handled the event, if one was found. This * argument may be null. + * @param aOutInputBlockId An out-parameter that will contain the identifier + * of the input block that this event was added to, if there was on. + * This argument may be null. */ nsEventStatus NotifyInputEvent(WidgetInputEvent& aEvent, - ScrollableLayerGuid* aOutTargetGuid); + ScrollableLayerGuid* aOutTargetGuid, + uint64_t* aOutInputBlockId); void ZoomToRect(uint32_t aPresShellId, ViewID aViewId, const CSSRect& aRect); void ContentReceivedTouch(const ScrollableLayerGuid& aGuid, + uint64_t aInputBlockId, bool aPreventDefault); void UpdateZoomConstraints(uint32_t aPresShellId, diff --git a/widget/android/APZCCallbackHandler.cpp b/widget/android/APZCCallbackHandler.cpp index 219df1824318..08ee7ddd0e34 100644 --- a/widget/android/APZCCallbackHandler.cpp +++ b/widget/android/APZCCallbackHandler.cpp @@ -37,6 +37,7 @@ APZCCallbackHandler::SetNativePanZoomController(jobject obj) void APZCCallbackHandler::NotifyDefaultPrevented(const ScrollableLayerGuid& aGuid, + uint64_t aInputBlockId, bool aDefaultPrevented) { if (!AndroidBridge::IsJavaUiThread()) { @@ -45,14 +46,14 @@ APZCCallbackHandler::NotifyDefaultPrevented(const ScrollableLayerGuid& aGuid, // have to throw it onto the other thread. AndroidBridge::Bridge()->PostTaskToUiThread(NewRunnableMethod( this, &APZCCallbackHandler::NotifyDefaultPrevented, - aGuid, aDefaultPrevented), 0); + aGuid, aInputBlockId, aDefaultPrevented), 0); return; } MOZ_ASSERT(AndroidBridge::IsJavaUiThread()); APZCTreeManager* controller = nsWindow::GetAPZCTreeManager(); if (controller) { - controller->ContentReceivedTouch(aGuid, aDefaultPrevented); + controller->ContentReceivedTouch(aGuid, aInputBlockId, aDefaultPrevented); } } @@ -137,7 +138,8 @@ APZCCallbackHandler::HandleSingleTap(const CSSPoint& aPoint, void APZCCallbackHandler::HandleLongTap(const CSSPoint& aPoint, int32_t aModifiers, - const mozilla::layers::ScrollableLayerGuid& aGuid) + const mozilla::layers::ScrollableLayerGuid& aGuid, + uint64_t aInputBlockId) { // TODO send content response back to APZC CSSIntPoint point = RoundedToInt(aPoint); diff --git a/widget/android/APZCCallbackHandler.h b/widget/android/APZCCallbackHandler.h index 08144dce4409..b347cf48c001 100644 --- a/widget/android/APZCCallbackHandler.h +++ b/widget/android/APZCCallbackHandler.h @@ -38,7 +38,7 @@ public: } NativePanZoomController* SetNativePanZoomController(jobject obj); - void NotifyDefaultPrevented(const mozilla::layers::ScrollableLayerGuid& aGuid, bool aDefaultPrevented); + void NotifyDefaultPrevented(const mozilla::layers::ScrollableLayerGuid& aGuid, uint64_t aInputBlockId, bool aDefaultPrevented); public: // GeckoContentController methods void RequestContentRepaint(const mozilla::layers::FrameMetrics& aFrameMetrics) MOZ_OVERRIDE; @@ -49,7 +49,8 @@ public: // GeckoContentController methods void HandleSingleTap(const mozilla::CSSPoint& aPoint, int32_t aModifiers, const mozilla::layers::ScrollableLayerGuid& aGuid) MOZ_OVERRIDE; void HandleLongTap(const mozilla::CSSPoint& aPoint, int32_t aModifiers, - const mozilla::layers::ScrollableLayerGuid& aGuid) MOZ_OVERRIDE; + const mozilla::layers::ScrollableLayerGuid& aGuid, + uint64_t aInputBlockId) MOZ_OVERRIDE; void HandleLongTapUp(const mozilla::CSSPoint& aPoint, int32_t aModifiers, const mozilla::layers::ScrollableLayerGuid& aGuid) MOZ_OVERRIDE; void SendAsyncScrollDOMEvent(bool aIsRoot, const mozilla::CSSRect& aContentRect, diff --git a/widget/android/AndroidJNI.cpp b/widget/android/AndroidJNI.cpp index bad1765a294b..b0e40e009f96 100644 --- a/widget/android/AndroidJNI.cpp +++ b/widget/android/AndroidJNI.cpp @@ -924,9 +924,10 @@ Java_org_mozilla_gecko_gfx_NativePanZoomController_handleTouchEvent(JNIEnv* env, } ScrollableLayerGuid guid; - nsEventStatus status = controller->ReceiveInputEvent(input, &guid); + uint64_t blockId; + nsEventStatus status = controller->ReceiveInputEvent(input, &guid, &blockId); if (status != nsEventStatus_eConsumeNoDefault) { - nsAppShell::gAppShell->PostEvent(AndroidGeckoEvent::MakeApzInputEvent(input, guid)); + nsAppShell::gAppShell->PostEvent(AndroidGeckoEvent::MakeApzInputEvent(input, guid, blockId)); } return true; } diff --git a/widget/android/AndroidJavaWrappers.cpp b/widget/android/AndroidJavaWrappers.cpp index b37761122205..3a3ad60b56f9 100644 --- a/widget/android/AndroidJavaWrappers.cpp +++ b/widget/android/AndroidJavaWrappers.cpp @@ -690,6 +690,13 @@ AndroidGeckoEvent::ApzGuid() return mApzGuid; } +uint64_t +AndroidGeckoEvent::ApzInputBlockId() +{ + MOZ_ASSERT(Type() == APZ_INPUT_EVENT); + return mApzInputBlockId; +} + WidgetTouchEvent AndroidGeckoEvent::MakeTouchEvent(nsIWidget* widget) { diff --git a/widget/android/AndroidJavaWrappers.h b/widget/android/AndroidJavaWrappers.h index e2e7dc6e4aea..e9e43b76f927 100644 --- a/widget/android/AndroidJavaWrappers.h +++ b/widget/android/AndroidJavaWrappers.h @@ -487,11 +487,12 @@ public: return event; } - static AndroidGeckoEvent* MakeApzInputEvent(const MultiTouchInput& aInput, const mozilla::layers::ScrollableLayerGuid& aGuid) { + static AndroidGeckoEvent* MakeApzInputEvent(const MultiTouchInput& aInput, const mozilla::layers::ScrollableLayerGuid& aGuid, uint64_t aInputBlockId) { AndroidGeckoEvent* event = new AndroidGeckoEvent(); event->Init(APZ_INPUT_EVENT); event->mApzInput = aInput; event->mApzGuid = aGuid; + event->mApzInputBlockId = aInputBlockId; return event; } @@ -560,6 +561,7 @@ public: void UnionRect(nsIntRect const& aRect); nsIObserver *Observer() { return mObserver; } mozilla::layers::ScrollableLayerGuid ApzGuid(); + uint64_t ApzInputBlockId(); protected: int mAction; @@ -602,6 +604,7 @@ protected: nsTArray mPrefNames; MultiTouchInput mApzInput; mozilla::layers::ScrollableLayerGuid mApzGuid; + uint64_t mApzInputBlockId; AutoGlobalWrappedJavaObject mObject; void ReadIntArray(nsTArray &aVals, diff --git a/widget/android/nsWindow.cpp b/widget/android/nsWindow.cpp index 5d7e25296a45..620bd8522d6b 100644 --- a/widget/android/nsWindow.cpp +++ b/widget/android/nsWindow.cpp @@ -1096,7 +1096,7 @@ bool nsWindow::OnMultitouchEvent(AndroidGeckoEvent *ae) // previous block should not be default-prevented bool defaultPrevented = isDownEvent ? false : preventDefaultActions; if (ae->Type() == AndroidGeckoEvent::APZ_INPUT_EVENT) { - mozilla::widget::android::APZCCallbackHandler::GetInstance()->NotifyDefaultPrevented(ae->ApzGuid(), defaultPrevented); + mozilla::widget::android::APZCCallbackHandler::GetInstance()->NotifyDefaultPrevented(ae->ApzGuid(), ae->ApzInputBlockId(), defaultPrevented); } else { mozilla::widget::android::GeckoAppShell::NotifyDefaultPrevented(defaultPrevented); } @@ -1109,7 +1109,7 @@ bool nsWindow::OnMultitouchEvent(AndroidGeckoEvent *ae) if (isDownEvent) { if (preventDefaultActions) { if (ae->Type() == AndroidGeckoEvent::APZ_INPUT_EVENT) { - mozilla::widget::android::APZCCallbackHandler::GetInstance()->NotifyDefaultPrevented(ae->ApzGuid(), true); + mozilla::widget::android::APZCCallbackHandler::GetInstance()->NotifyDefaultPrevented(ae->ApzGuid(), ae->ApzInputBlockId(), true); } else { mozilla::widget::android::GeckoAppShell::NotifyDefaultPrevented(true); } diff --git a/widget/cocoa/nsChildView.mm b/widget/cocoa/nsChildView.mm index f74a078a25d3..2a09ca7b6a84 100644 --- a/widget/cocoa/nsChildView.mm +++ b/widget/cocoa/nsChildView.mm @@ -428,7 +428,8 @@ public: virtual void HandleSingleTap(const mozilla::CSSPoint& aPoint, int32_t aModifiers, const ScrollableLayerGuid& aGuid) MOZ_OVERRIDE {} virtual void HandleLongTap(const mozilla::CSSPoint& aPoint, int32_t aModifiers, - const ScrollableLayerGuid& aGuid) MOZ_OVERRIDE {} + const ScrollableLayerGuid& aGuid, + uint64_t aInputBlockId) MOZ_OVERRIDE {} virtual void HandleLongTapUp(const CSSPoint& aPoint, int32_t aModifiers, const ScrollableLayerGuid& aGuid) MOZ_OVERRIDE {} virtual void SendAsyncScrollDOMEvent(bool aIsRoot, const mozilla::CSSRect &aContentRect, @@ -5374,13 +5375,13 @@ static int32_t RoundUp(double aDouble) if (phase == NSEventPhaseMayBegin) { PanGestureInput panInput(PanGestureInput::PANGESTURE_MAYSTART, eventTime, eventTimeStamp, location, ScreenPoint(0, 0), 0); - apzctm->ReceiveInputEvent(panInput, &guid); + apzctm->ReceiveInputEvent(panInput, &guid, nullptr); return; } if (phase == NSEventPhaseCancelled) { PanGestureInput panInput(PanGestureInput::PANGESTURE_CANCELLED, eventTime, eventTimeStamp, location, ScreenPoint(0, 0), 0); - apzctm->ReceiveInputEvent(panInput, &guid); + apzctm->ReceiveInputEvent(panInput, &guid, nullptr); return; } @@ -5397,34 +5398,34 @@ static int32_t RoundUp(double aDouble) if (phase == NSEventPhaseBegan || isLegacyScroll) { PanGestureInput panInput(PanGestureInput::PANGESTURE_START, eventTime, eventTimeStamp, location, ScreenPoint(0, 0), 0); - apzctm->ReceiveInputEvent(panInput, &guid); + apzctm->ReceiveInputEvent(panInput, &guid, nullptr); } if (momentumPhase == NSEventPhaseNone && delta != ScreenPoint(0, 0)) { PanGestureInput panInput(PanGestureInput::PANGESTURE_PAN, eventTime, eventTimeStamp, location, delta, 0); - apzctm->ReceiveInputEvent(panInput, &guid); + apzctm->ReceiveInputEvent(panInput, &guid, nullptr); } if (phase == NSEventPhaseEnded || isLegacyScroll) { PanGestureInput panInput(PanGestureInput::PANGESTURE_END, eventTime, eventTimeStamp, location, ScreenPoint(0, 0), 0); - apzctm->ReceiveInputEvent(panInput, &guid); + apzctm->ReceiveInputEvent(panInput, &guid, nullptr); } // Any device that can dispatch momentum events supports all three momentum phases. if (momentumPhase == NSEventPhaseBegan) { PanGestureInput panInput(PanGestureInput::PANGESTURE_MOMENTUMSTART, eventTime, eventTimeStamp, location, ScreenPoint(0, 0), 0); - apzctm->ReceiveInputEvent(panInput, &guid); + apzctm->ReceiveInputEvent(panInput, &guid, nullptr); } if (momentumPhase == NSEventPhaseChanged && delta != ScreenPoint(0, 0)) { PanGestureInput panInput(PanGestureInput::PANGESTURE_MOMENTUMPAN, eventTime, eventTimeStamp, location, delta, 0); - apzctm->ReceiveInputEvent(panInput, &guid); + apzctm->ReceiveInputEvent(panInput, &guid, nullptr); } if (momentumPhase == NSEventPhaseEnded) { PanGestureInput panInput(PanGestureInput::PANGESTURE_MOMENTUMEND, eventTime, eventTimeStamp, location, ScreenPoint(0, 0), 0); - apzctm->ReceiveInputEvent(panInput, &guid); + apzctm->ReceiveInputEvent(panInput, &guid, nullptr); } } } diff --git a/widget/gonk/ParentProcessController.h b/widget/gonk/ParentProcessController.h index 6d1349cb5f3e..7c4c9faeb71c 100644 --- a/widget/gonk/ParentProcessController.h +++ b/widget/gonk/ParentProcessController.h @@ -31,7 +31,8 @@ public: const ScrollableLayerGuid& aGuid) MOZ_OVERRIDE {} virtual void HandleLongTap(const CSSPoint& aPoint, int32_t aModifiers, - const ScrollableLayerGuid& aGuid) MOZ_OVERRIDE {} + const ScrollableLayerGuid& aGuid, + uint64_t aInputBlockId) MOZ_OVERRIDE {} virtual void HandleLongTapUp(const CSSPoint& aPoint, int32_t aModifiers, const ScrollableLayerGuid& aGuid) MOZ_OVERRIDE {} diff --git a/widget/windows/winrt/APZController.cpp b/widget/windows/winrt/APZController.cpp index 7e1843d9ec56..f8adc1742171 100644 --- a/widget/windows/winrt/APZController.cpp +++ b/widget/windows/winrt/APZController.cpp @@ -86,12 +86,12 @@ APZController::SetPendingResponseFlusher(APZPendingResponseFlusher* aFlusher) } void -APZController::ContentReceivedTouch(const ScrollableLayerGuid& aGuid, bool aPreventDefault) +APZController::ContentReceivedTouch(const ScrollableLayerGuid& aGuid, const uint64_t aInputBlockId, bool aPreventDefault) { if (!sAPZC) { return; } - sAPZC->ContentReceivedTouch(aGuid, aPreventDefault); + sAPZC->ContentReceivedTouch(aGuid, aInputBlockId, aPreventDefault); } bool @@ -115,14 +115,15 @@ APZController::TransformCoordinateToGecko(const ScreenIntPoint& aPoint, nsEventStatus APZController::ReceiveInputEvent(WidgetInputEvent* aEvent, - ScrollableLayerGuid* aOutTargetGuid) + ScrollableLayerGuid* aOutTargetGuid, + uint64_t* aOutInputBlockId) { MOZ_ASSERT(aEvent); if (!sAPZC) { return nsEventStatus_eIgnore; } - return sAPZC->ReceiveInputEvent(*aEvent->AsInputEvent(), aOutTargetGuid); + return sAPZC->ReceiveInputEvent(*aEvent->AsInputEvent(), aOutTargetGuid, aOutInputBlockId); } // APZC sends us this request when we need to update the display port on @@ -214,12 +215,13 @@ APZController::HandleSingleTap(const CSSPoint& aPoint, void APZController::HandleLongTap(const CSSPoint& aPoint, int32_t aModifiers, - const ScrollableLayerGuid& aGuid) + const ScrollableLayerGuid& aGuid, + uint64_t aInputBlockId) { if (mFlusher) { mFlusher->FlushPendingContentResponse(); } - ContentReceivedTouch(aGuid, false); + ContentReceivedTouch(aGuid, aInputBlockId, false); } void diff --git a/widget/windows/winrt/APZController.h b/widget/windows/winrt/APZController.h index da9510a05c40..b7771fd8fb3a 100644 --- a/widget/windows/winrt/APZController.h +++ b/widget/windows/winrt/APZController.h @@ -46,7 +46,8 @@ public: const mozilla::layers::ScrollableLayerGuid& aGuid); virtual void HandleLongTap(const mozilla::CSSPoint& aPoint, int32_t aModifiers, - const mozilla::layers::ScrollableLayerGuid& aGuid); + const mozilla::layers::ScrollableLayerGuid& aGuid, + uint64_t aInputBlockId); virtual void HandleLongTapUp(const mozilla::CSSPoint& aPoint, int32_t aModifiers, const mozilla::layers::ScrollableLayerGuid& aGuid); @@ -62,9 +63,10 @@ public: bool HitTestAPZC(mozilla::ScreenIntPoint& aPoint); void TransformCoordinateToGecko(const mozilla::ScreenIntPoint& aPoint, LayoutDeviceIntPoint* aRefPointOut); - void ContentReceivedTouch(const ScrollableLayerGuid& aGuid, bool aPreventDefault); + void ContentReceivedTouch(const ScrollableLayerGuid& aGuid, uint64_t aInputBlockId, bool aPreventDefault); nsEventStatus ReceiveInputEvent(mozilla::WidgetInputEvent* aEvent, - ScrollableLayerGuid* aOutTargetGuid); + ScrollableLayerGuid* aOutTargetGuid, + uint64_t* aOutInputBlockId); public: // todo: make this a member variable as prep for multiple views diff --git a/widget/windows/winrt/MetroInput.cpp b/widget/windows/winrt/MetroInput.cpp index 8e7bde5fde90..ae28a8c66fa3 100644 --- a/widget/windows/winrt/MetroInput.cpp +++ b/widget/windows/winrt/MetroInput.cpp @@ -266,7 +266,8 @@ MetroInput::MetroInput(MetroWidget* aWidget, UI::Core::ICoreWindow* aWindow) : mWidget(aWidget), mNonApzTargetForTouch(false), - mWindow(aWindow) + mWindow(aWindow), + mInputBlockId(0) { LogFunction(); NS_ASSERTION(aWidget, "Attempted to create MetroInput for null widget!"); @@ -1215,7 +1216,7 @@ MetroInput::HandleTouchStartEvent(WidgetTouchEvent* aEvent) WidgetTouchEvent transformedEvent(*aEvent); DUMP_TOUCH_IDS("APZC(1)", aEvent); - nsEventStatus result = mWidget->ApzReceiveInputEvent(&transformedEvent, &mTargetAPZCGuid); + nsEventStatus result = mWidget->ApzReceiveInputEvent(&transformedEvent, &mTargetAPZCGuid, &mInputBlockId); if (result == nsEventStatus_eConsumeNoDefault) { // The APZ said: throw this event away entirely. CancelGesture(); @@ -1235,7 +1236,7 @@ MetroInput::HandleTouchStartEvent(WidgetTouchEvent* aEvent) // action values from. E.g. for zooming we're taking parent apzc of a few ones // that were touched but touch behaviors would be taken from childs. DUMP_ALLOWED_TOUCH_BEHAVIOR(touchBehaviors); - mWidget->ApzcSetAllowedTouchBehavior(mTargetAPZCGuid, touchBehaviors); + mWidget->ApzcSetAllowedTouchBehavior(mTargetAPZCGuid, mInputBlockId, touchBehaviors); } // Pass the event on to content @@ -1245,7 +1246,7 @@ MetroInput::HandleTouchStartEvent(WidgetTouchEvent* aEvent) if (nsEventStatus_eConsumeNoDefault == contentStatus) { // Content consumed the event, so we need to notify the APZ // to not do anything with this touch block. - mWidget->ApzContentConsumingTouch(mTargetAPZCGuid); + mWidget->ApzContentConsumingTouch(mTargetAPZCGuid, mInputBlockId); mCancelable = false; // Also cancel the gesture detection. @@ -1259,7 +1260,7 @@ MetroInput::HandleFirstTouchMoveEvent(WidgetTouchEvent* aEvent) // If the APZ is using this block, pass the event to it. WidgetTouchEvent transformedEvent(*aEvent); DUMP_TOUCH_IDS("APZC(2)", aEvent); - nsEventStatus apzcStatus = mWidget->ApzReceiveInputEvent(&transformedEvent, &mTargetAPZCGuid); + nsEventStatus apzcStatus = mWidget->ApzReceiveInputEvent(&transformedEvent, &mTargetAPZCGuid, &mInputBlockId); if (apzcStatus == nsEventStatus_eConsumeNoDefault) { // The APZ said: throw this event away entirely. CancelGesture(); @@ -1289,9 +1290,9 @@ MetroInput::HandleFirstTouchMoveEvent(WidgetTouchEvent* aEvent) // Let the apz know if content wants to consume touch events. if (mCancelable) { if (nsEventStatus_eConsumeNoDefault == contentStatus) { - mWidget->ApzContentConsumingTouch(mTargetAPZCGuid); + mWidget->ApzContentConsumingTouch(mTargetAPZCGuid, mInputBlockId); } else { - mWidget->ApzContentIgnoringTouch(mTargetAPZCGuid); + mWidget->ApzContentIgnoringTouch(mTargetAPZCGuid, mInputBlockId); if (apzcStatus == nsEventStatus_eConsumeDoDefault) { SendPointerCancelToContent(transformedEvent); } @@ -1327,7 +1328,7 @@ MetroInput::SendPendingResponseToApz() // If this is called, content has missed its chance to consume this event block // so we should notify the APZ that content is ignoring this touch block. if (mCancelable) { - mWidget->ApzContentIgnoringTouch(mTargetAPZCGuid); + mWidget->ApzContentIgnoringTouch(mTargetAPZCGuid, mInputBlockId); mCancelable = false; return true; } @@ -1373,6 +1374,7 @@ MetroInput::DeliverNextQueuedTouchEvent() mCancelable = true; mTargetAPZCGuid = ScrollableLayerGuid(); + mInputBlockId = 0; } // Test for non-apz vs. apz target. To do this we only use the first touch @@ -1424,7 +1426,7 @@ MetroInput::DeliverNextQueuedTouchEvent() // Normal processing of events. Send it to the APZ first for handling and // untransformation. then pass the untransformed event to content. DUMP_TOUCH_IDS("APZC(3)", event); - status = mWidget->ApzReceiveInputEvent(event, nullptr); + status = mWidget->ApzReceiveInputEvent(event, nullptr, nullptr); if (status == nsEventStatus_eConsumeNoDefault) { CancelGesture(); return; diff --git a/widget/windows/winrt/MetroInput.h b/widget/windows/winrt/MetroInput.h index 3b33e6d927e1..9e00039b097b 100644 --- a/widget/windows/winrt/MetroInput.h +++ b/widget/windows/winrt/MetroInput.h @@ -286,6 +286,7 @@ private: nsDeque mInputEventQueue; mozilla::layers::ScrollableLayerGuid mTargetAPZCGuid; + uint64_t mInputBlockId; static nsEventStatus sThrowawayStatus; }; diff --git a/widget/windows/winrt/MetroWidget.cpp b/widget/windows/winrt/MetroWidget.cpp index bb200fdf9098..324528fd5123 100644 --- a/widget/windows/winrt/MetroWidget.cpp +++ b/widget/windows/winrt/MetroWidget.cpp @@ -1074,33 +1074,34 @@ MetroWidget::ApzcGetAllowedTouchBehavior(WidgetInputEvent* aTransformedEvent, void MetroWidget::ApzcSetAllowedTouchBehavior(const ScrollableLayerGuid& aGuid, + uint64_t aInputBlockId, nsTArray& aBehaviors) { LogFunction(); if (!APZController::sAPZC) { return; } - APZController::sAPZC->SetAllowedTouchBehavior(aGuid, aBehaviors); + APZController::sAPZC->SetAllowedTouchBehavior(aGuid, aInputBlockId, aBehaviors); } void -MetroWidget::ApzContentConsumingTouch(const ScrollableLayerGuid& aGuid) +MetroWidget::ApzContentConsumingTouch(const ScrollableLayerGuid& aGuid, uint64_t aInputBlockId) { LogFunction(); if (!mController) { return; } - mController->ContentReceivedTouch(aGuid, true); + mController->ContentReceivedTouch(aGuid, aInputBlockId, true); } void -MetroWidget::ApzContentIgnoringTouch(const ScrollableLayerGuid& aGuid) +MetroWidget::ApzContentIgnoringTouch(const ScrollableLayerGuid& aGuid, uint64_t aInputBlockId) { LogFunction(); if (!mController) { return; } - mController->ContentReceivedTouch(aGuid, false); + mController->ContentReceivedTouch(aGuid, aInputBlockId, false); } bool @@ -1124,14 +1125,15 @@ MetroWidget::ApzTransformGeckoCoordinate(const ScreenIntPoint& aPoint, nsEventStatus MetroWidget::ApzReceiveInputEvent(WidgetInputEvent* aEvent, - ScrollableLayerGuid* aOutTargetGuid) + ScrollableLayerGuid* aOutTargetGuid, + uint64_t* aOutInputBlockId) { MOZ_ASSERT(aEvent); if (!mController) { return nsEventStatus_eIgnore; } - return mController->ReceiveInputEvent(aEvent, aOutTargetGuid); + return mController->ReceiveInputEvent(aEvent, aOutTargetGuid, aOutInputBlockId); } void diff --git a/widget/windows/winrt/MetroWidget.h b/widget/windows/winrt/MetroWidget.h index 3c4e63456921..29843d7a5261 100644 --- a/widget/windows/winrt/MetroWidget.h +++ b/widget/windows/winrt/MetroWidget.h @@ -209,7 +209,7 @@ public: // apzc controller related api void ApzcGetAllowedTouchBehavior(mozilla::WidgetInputEvent* aTransformedEvent, nsTArray& aOutBehaviors); - void ApzcSetAllowedTouchBehavior(const ScrollableLayerGuid& aGuid, nsTArray& aBehaviors); + void ApzcSetAllowedTouchBehavior(const ScrollableLayerGuid& aGuid, uint64_t aInputBlockId, nsTArray& aBehaviors); // Hit test a point to see if an apzc would consume input there bool ApzHitTest(mozilla::ScreenIntPoint& pt); @@ -218,11 +218,12 @@ public: 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); + void ApzContentConsumingTouch(const ScrollableLayerGuid& aGuid, uint64_t aInputBlockId); + void ApzContentIgnoringTouch(const ScrollableLayerGuid& aGuid, uint64_t aInputBlockId); // Input handling nsEventStatus ApzReceiveInputEvent(mozilla::WidgetInputEvent* aEvent, - ScrollableLayerGuid* aOutTargetGuid); + ScrollableLayerGuid* aOutTargetGuid, + uint64_t* aOutInputBlockId); // Callback for the APZController void SetApzPendingResponseFlusher(APZPendingResponseFlusher* aFlusher);