From 7861db93b43b6ab29b95fb7ccfb8837c10a3077b Mon Sep 17 00:00:00 2001 From: Hiroyuki Ikezoe Date: Thu, 20 Jun 2024 21:10:31 +0000 Subject: [PATCH] Bug 1895742 - Return HandledByContent for touches prevented by touch-action. r=botond,geckoview-reviewers,tthibaud, a=dmeehan Similar to what we did in bug 1785754, specifically in hg.mozilla.org/integration/autoland/rev/e05ed4cedf9f , but not eager cases. Differential Revision: https://phabricator.services.mozilla.com/D212487 --- gfx/layers/apz/src/AsyncPanZoomController.cpp | 2 +- gfx/layers/apz/src/AsyncPanZoomController.h | 2 +- gfx/layers/apz/src/InputQueue.cpp | 30 ++++++++++---- .../androidTest/assets/www/touch-action.html | 40 ++++++++++++++++--- .../geckoview/test/InputResultDetailTest.kt | 12 +++--- 5 files changed, 66 insertions(+), 20 deletions(-) diff --git a/gfx/layers/apz/src/AsyncPanZoomController.cpp b/gfx/layers/apz/src/AsyncPanZoomController.cpp index 46fcce043084..0730c971fe79 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.cpp +++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp @@ -876,7 +876,7 @@ AsyncPanZoomController::GetPinchLockMode() { } PointerEventsConsumableFlags AsyncPanZoomController::ArePointerEventsConsumable( - TouchBlockState* aBlock, const MultiTouchInput& aInput) { + TouchBlockState* aBlock, const MultiTouchInput& aInput) const { uint32_t touchPoints = aInput.mTouches.Length(); if (touchPoints == 0) { // Cant' do anything with zero touch points diff --git a/gfx/layers/apz/src/AsyncPanZoomController.h b/gfx/layers/apz/src/AsyncPanZoomController.h index fe1f8117dcf4..5153d394920c 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.h +++ b/gfx/layers/apz/src/AsyncPanZoomController.h @@ -1536,7 +1536,7 @@ class AsyncPanZoomController { * govern dynamic toolbar and pull-to-refresh behaviour). */ PointerEventsConsumableFlags ArePointerEventsConsumable( - TouchBlockState* aBlock, const MultiTouchInput& aInput); + TouchBlockState* aBlock, const MultiTouchInput& aInput) const; /** * Clear internal state relating to touch input handling. diff --git a/gfx/layers/apz/src/InputQueue.cpp b/gfx/layers/apz/src/InputQueue.cpp index 7f7fb1e16070..3039e56786a4 100644 --- a/gfx/layers/apz/src/InputQueue.cpp +++ b/gfx/layers/apz/src/InputQueue.cpp @@ -1007,10 +1007,11 @@ void InputQueue::SetBrowserGestureResponse(uint64_t aInputBlockId, ProcessQueue(); } -static APZHandledResult GetHandledResultFor( - const AsyncPanZoomController* aApzc, - const InputBlockState& aCurrentInputBlock, nsEventStatus aEagerStatus) { - if (aCurrentInputBlock.ShouldDropEvents()) { +static APZHandledResult GetHandledResultFor(const AsyncPanZoomController* aApzc, + InputBlockState* aCurrentInputBlock, + nsEventStatus aEagerStatus, + const InputData& aEvent) { + if (aCurrentInputBlock->ShouldDropEvents()) { return APZHandledResult{APZHandledPlace::HandledByContent, aApzc}; } @@ -1018,6 +1019,20 @@ static APZHandledResult GetHandledResultFor( return APZHandledResult{APZHandledPlace::HandledByContent, aApzc}; } + if (aEvent.mInputType == MULTITOUCH_INPUT) { + // If the event is a multi touch event and is disallowed by touch-action, + // treat it as if a touch event listener had preventDefault()-ed it. + PointerEventsConsumableFlags consumableFlags = + aApzc->ArePointerEventsConsumable(aCurrentInputBlock->AsTouchBlock(), + aEvent.AsMultiTouchInput()); + if (!consumableFlags.mAllowedByTouchAction) { + APZHandledResult result = + APZHandledResult{APZHandledPlace::HandledByContent, aApzc}; + result.mOverscrollDirections = ScrollDirections(); + return result; + } + } + if (aApzc->IsRootContent()) { // If the eager status was eIgnore, we would have returned an eager result // of Unhandled if there had been no event handler. Now that we know the @@ -1033,14 +1048,14 @@ static APZHandledResult GetHandledResultFor( } bool mayTriggerPullToRefresh = - aCurrentInputBlock.GetOverscrollHandoffChain() + aCurrentInputBlock->GetOverscrollHandoffChain() ->ScrollingUpWillTriggerPullToRefresh(aApzc); if (mayTriggerPullToRefresh) { return APZHandledResult{APZHandledPlace::Unhandled, aApzc, true}; } auto [willMoveDynamicToolbar, rootApzc] = - aCurrentInputBlock.GetOverscrollHandoffChain() + aCurrentInputBlock->GetOverscrollHandoffChain() ->ScrollingDownWillMoveDynamicToolbar(aApzc); if (!willMoveDynamicToolbar) { return APZHandledResult{APZHandledPlace::HandledByContent, aApzc}; @@ -1113,7 +1128,8 @@ bool InputQueue::ProcessQueue() { "\n", curBlock, curBlock->GetBlockId()); APZHandledResult handledResult = - GetHandledResultFor(target, *curBlock, it->second.mEagerStatus); + GetHandledResultFor(target, curBlock, it->second.mEagerStatus, + *(mQueuedInputs[0]->Input())); it->second.mCallback(curBlock->GetBlockId(), handledResult); // The callback is one-shot; discard it after calling it. mInputBlockCallbacks.erase(it); diff --git a/mobile/android/geckoview/src/androidTest/assets/www/touch-action.html b/mobile/android/geckoview/src/androidTest/assets/www/touch-action.html index bf315cfb7eed..b1d080596b7e 100644 --- a/mobile/android/geckoview/src/androidTest/assets/www/touch-action.html +++ b/mobile/android/geckoview/src/androidTest/assets/www/touch-action.html @@ -26,15 +26,43 @@