From a90a5cba08fdf6c0ceb95101c275108a152a3aed Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 12 Jun 2024 07:35:37 +0200 Subject: Merging upstream version 127.0. Signed-off-by: Daniel Baumann --- gfx/layers/apz/src/AsyncPanZoomController.cpp | 10 ++ gfx/layers/apz/src/FocusState.cpp | 1 + gfx/layers/apz/src/InputBlockState.h | 4 +- gfx/layers/apz/src/InputQueue.cpp | 14 +- gfx/layers/apz/test/gtest/TestGestureDetector.cpp | 100 ++++++++++++++ .../mochitest/helper_doubletap_zoom_textarea.html | 6 + .../mochitest/helper_scroll_over_subframe.html | 146 +++++++++++++++++++++ .../helper_scroll_over_subframe_child.html | 29 ++++ .../test/mochitest/test_group_double_tap_zoom.html | 2 +- .../test/mochitest/test_group_pointerevents.html | 9 +- .../apz/test/mochitest/test_group_wheelevents.html | 11 ++ 11 files changed, 320 insertions(+), 12 deletions(-) create mode 100644 gfx/layers/apz/test/mochitest/helper_scroll_over_subframe.html create mode 100644 gfx/layers/apz/test/mochitest/helper_scroll_over_subframe_child.html (limited to 'gfx/layers/apz') diff --git a/gfx/layers/apz/src/AsyncPanZoomController.cpp b/gfx/layers/apz/src/AsyncPanZoomController.cpp index a070340421..84b4a95b9e 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.cpp +++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp @@ -1988,6 +1988,10 @@ ParentLayerPoint AsyncPanZoomController::GetScrollWheelDelta( // Apply user-set multipliers. delta.x *= aMultiplierX; delta.y *= aMultiplierY; + APZC_LOGV( + "user-multiplied delta is %s (deltaType %d, line size %s, page size %s)", + ToString(delta).c_str(), (int)aEvent.mDeltaType, + ToString(scrollAmount).c_str(), ToString(pageScrollSize).c_str()); // For the conditions under which we allow system scroll overrides, see // WidgetWheelEvent::OverriddenDelta{X,Y}. @@ -1999,6 +2003,7 @@ ParentLayerPoint AsyncPanZoomController::GetScrollWheelDelta( aEvent.mAllowToOverrideSystemScrollSpeed) { delta.x = WidgetWheelEvent::ComputeOverriddenDelta(delta.x, false); delta.y = WidgetWheelEvent::ComputeOverriddenDelta(delta.y, true); + APZC_LOGV("overridden delta is %s", ToString(delta).c_str()); } // If this is a line scroll, and this event was part of a scroll series, then @@ -2258,6 +2263,8 @@ bool AsyncPanZoomController::AllowOneTouchPinch() const { // Return whether or not the underlying layer can be scrolled on either axis. bool AsyncPanZoomController::CanScroll(const InputData& aEvent) const { ParentLayerPoint delta = GetDeltaForEvent(aEvent); + APZC_LOGV_DETAIL("CanScroll: event delta is %s", this, + ToString(delta).c_str()); if (!delta.x && !delta.y) { return false; } @@ -2330,6 +2337,9 @@ bool AsyncPanZoomController::CanScrollWithWheel( disregardedDirection != Some(ScrollDirection::eVertical)) { return true; } + APZC_LOGV_FM(Metrics(), + "cannot scroll with wheel (disregarded direction is %s)", + ToString(disregardedDirection).c_str()); return false; } diff --git a/gfx/layers/apz/src/FocusState.cpp b/gfx/layers/apz/src/FocusState.cpp index 0230676e7e..84bf0b4570 100644 --- a/gfx/layers/apz/src/FocusState.cpp +++ b/gfx/layers/apz/src/FocusState.cpp @@ -7,6 +7,7 @@ #include "FocusState.h" #include "mozilla/Logging.h" +#include "mozilla/IntegerPrintfMacros.h" #include "mozilla/layers/APZThreadUtils.h" static mozilla::LazyLogModule sApzFstLog("apz.focusstate"); diff --git a/gfx/layers/apz/src/InputBlockState.h b/gfx/layers/apz/src/InputBlockState.h index d65b1cb57b..d27e7ead27 100644 --- a/gfx/layers/apz/src/InputBlockState.h +++ b/gfx/layers/apz/src/InputBlockState.h @@ -501,9 +501,9 @@ class TouchBlockState : public CancelableBlockState { mIsWaitingLongTapResult = false; } - void SetWaitingLongTapResult() { + void SetWaitingLongTapResult(bool aResult) { MOZ_ASSERT(!mForLongTap); - mIsWaitingLongTapResult = true; + mIsWaitingLongTapResult = aResult; } bool IsWaitingLongTapResult() const { return mIsWaitingLongTapResult; } diff --git a/gfx/layers/apz/src/InputQueue.cpp b/gfx/layers/apz/src/InputQueue.cpp index 8ad75a9794..78b70fddf4 100644 --- a/gfx/layers/apz/src/InputQueue.cpp +++ b/gfx/layers/apz/src/InputQueue.cpp @@ -204,8 +204,8 @@ APZEventResult InputQueue::ReceiveTouchInput( } else { // If all following conditions are met, we need to wait for a content // response (again); - // 1) this is the first event bailing out from in-slop state after a - // long-tap event has been fired + // 1) this is the first touch-move event bailing out from in-slop state + // after a long-tap event has been fired // 2) there's any APZ-aware event listeners // 3) the event block hasn't yet been prevented // @@ -216,7 +216,7 @@ APZEventResult InputQueue::ReceiveTouchInput( // until a long-tap event happens, then if the user started moving their // finger, we have to wait for a content response twice, one is for // `touchstart` and one is for `touchmove`. - if (wasInSlop && + if (wasInSlop && aEvent.mType == MultiTouchInput::MULTITOUCH_MOVE && (block->WasLongTapProcessed() || block->IsWaitingLongTapResult()) && !block->IsTargetOriginallyConfirmed() && !block->ShouldDropEvents()) { INPQ_LOG( @@ -637,6 +637,12 @@ uint64_t InputQueue::InjectNewTouchBlock(AsyncPanZoomController* aTarget) { TouchBlockState* InputQueue::StartNewTouchBlock( const RefPtr& aTarget, TargetConfirmationFlags aFlags) { + if (mPrevActiveTouchBlock && mActiveTouchBlock && + mActiveTouchBlock->ForLongTap()) { + mPrevActiveTouchBlock->SetWaitingLongTapResult(false); + mPrevActiveTouchBlock = nullptr; + } + TouchBlockState* newBlock = new TouchBlockState(aTarget, aFlags, mTouchCounter); @@ -664,7 +670,7 @@ TouchBlockState* InputQueue::StartNewTouchBlockForLongTap( // touch block because if the long-tap event response prevents us from // scrolling we must stop processing any subsequent touch-move events in the // same block. - currentBlock->SetWaitingLongTapResult(); + currentBlock->SetWaitingLongTapResult(true); // We need to keep the current block alive, it will be used once after this // new touch block for long-tap was processed. diff --git a/gfx/layers/apz/test/gtest/TestGestureDetector.cpp b/gfx/layers/apz/test/gtest/TestGestureDetector.cpp index 8256667d6b..f5024e8208 100644 --- a/gfx/layers/apz/test/gtest/TestGestureDetector.cpp +++ b/gfx/layers/apz/test/gtest/TestGestureDetector.cpp @@ -10,6 +10,7 @@ #include "APZCBasicTester.h" #include "APZTestCommon.h" #include "InputUtils.h" +#include "apz/src/InputBlockState.h" #include "mozilla/StaticPrefs_apz.h" // Note: There are additional tests that test gesture detection behaviour @@ -553,6 +554,83 @@ class APZCLongPressTester : public APZCGestureDetectorTester { apzc->AssertStateIsReset(); } + + // Tests a scenario that after a long-press event happened the original touch + // block initiated by a touch-start event and the touch block initiated by a + // long-tap event have been discarded when a new touch-start event happens. + void DoLongPressDiscardTouchBlockTest(bool aWithTouchMove) { + // Set apz.content_response_timeout > ui.click_hold_context_menus.delay and + // apz.touch_start_tolerance explicitly to match Android preferences. + SCOPED_GFX_PREF_INT("apz.content_response_timeout", 60); + SCOPED_GFX_PREF_INT("ui.click_hold_context_menus.delay", 30); + SCOPED_GFX_PREF_FLOAT("apz.touch_start_tolerance", 0.06); + + MockFunction check; + { + InSequence s; + EXPECT_CALL(check, Call("pre long-tap dispatch")); + EXPECT_CALL(*mcc, HandleTap(TapType::eLongTap, LayoutDevicePoint(10, 10), + 0, apzc->GetGuid(), _, _)) + .Times(1); + EXPECT_CALL(check, Call("post long-tap dispatch")); + + // If a touch-move happens while long-tap is happening, there's no + // eLongTapUp event. + if (!aWithTouchMove) { + EXPECT_CALL(*mcc, + HandleTap(TapType::eLongTapUp, LayoutDevicePoint(10, 20), 0, + apzc->GetGuid(), _, _)) + .Times(1); + } + EXPECT_CALL(*mcc, HandleTap(TapType::eLongTap, LayoutDevicePoint(10, 10), + 0, apzc->GetGuid(), _, _)) + .Times(1); + } + + // Keep touching for a while to trigger a long tap event. + uint64_t firstTouchBlockId = + TouchDown(apzc, ScreenIntPoint(10, 10), mcc->Time()).mInputBlockId; + TouchBlockState* firstTouchBlock = + tm->GetInputQueue()->GetCurrentTouchBlock(); + EXPECT_NE(firstTouchBlock, nullptr); + EXPECT_EQ(tm->GetInputQueue()->GetBlockForId(firstTouchBlockId), + firstTouchBlock); + + // Wait for a long tap. + check.Call("pre long-tap dispatch"); + mcc->AdvanceByMillis(30); + check.Call("post long-tap dispatch"); + + // Now the current touch block is not the first touch block, it should be + // a new touch block for the long tap event. + TouchBlockState* secondTouchBlock = + tm->GetInputQueue()->GetCurrentTouchBlock(); + EXPECT_NE(secondTouchBlock, firstTouchBlock); + EXPECT_TRUE(secondTouchBlock->ForLongTap()); + uint64_t secondTouchBlockId = secondTouchBlock->GetBlockId(); + + if (aWithTouchMove) { + mcc->AdvanceByMillis(10); + TouchMove(apzc, ScreenIntPoint(10, 20), mcc->Time()); + } + + // Finish the first touch block. + mcc->AdvanceByMillis(10); + TouchUp(apzc, ScreenIntPoint(10, 20), mcc->Time()); + + // And start a new touch block. + mcc->AdvanceByMillis(10); + uint64_t newTouchBlockId = + TouchDown(apzc, ScreenIntPoint(10, 10), mcc->Time()).mInputBlockId; + + mcc->AdvanceByMillis(10); + // Now the original touch block and the touch block for long-tap should have + // been discarded from the input queue. + EXPECT_EQ(tm->GetInputQueue()->GetBlockForId(firstTouchBlockId), nullptr); + EXPECT_EQ(tm->GetInputQueue()->GetBlockForId(secondTouchBlockId), nullptr); + EXPECT_EQ(tm->GetInputQueue()->GetBlockForId(newTouchBlockId), + tm->GetInputQueue()->GetCurrentBlock()); + } }; TEST_F(APZCLongPressTester, LongPress) { @@ -563,6 +641,28 @@ TEST_F(APZCLongPressTester, LongPressPreventDefault) { DoLongPressPreventDefaultTest(kDefaultTouchBehavior); } +TEST_F(APZCLongPressTester, LongPressDiscardBlock) { + DoLongPressDiscardTouchBlockTest(true /* with touch-move */); +} + +// Similar to above LongPressDiscardBlock but APZ is waiting for responses from +// the content. +TEST_F(APZCLongPressTester, LongPressDiscardBlock2) { + MakeApzcWaitForMainThread(); + DoLongPressDiscardTouchBlockTest(true /* with touch-move */); +} + +// Similar to above LongPressDiscardBlock/LongPressDiscardBlock2 without +// touch-move events. +TEST_F(APZCLongPressTester, LongPressDiscardBlock3) { + DoLongPressDiscardTouchBlockTest(false /* without touch-move */); +} + +TEST_F(APZCLongPressTester, LongPressDiscardBlock4) { + MakeApzcWaitForMainThread(); + DoLongPressDiscardTouchBlockTest(false /* without touch-move */); +} + TEST_F(APZCGestureDetectorTester, DoubleTap) { MakeApzcWaitForMainThread(); MakeApzcZoomable(); diff --git a/gfx/layers/apz/test/mochitest/helper_doubletap_zoom_textarea.html b/gfx/layers/apz/test/mochitest/helper_doubletap_zoom_textarea.html index 99616d9834..762e1cef69 100644 --- a/gfx/layers/apz/test/mochitest/helper_doubletap_zoom_textarea.html +++ b/gfx/layers/apz/test/mochitest/helper_doubletap_zoom_textarea.html @@ -7,6 +7,12 @@ + + + + + + + +
+ + + + diff --git a/gfx/layers/apz/test/mochitest/helper_scroll_over_subframe_child.html b/gfx/layers/apz/test/mochitest/helper_scroll_over_subframe_child.html new file mode 100644 index 0000000000..48f03a51d9 --- /dev/null +++ b/gfx/layers/apz/test/mochitest/helper_scroll_over_subframe_child.html @@ -0,0 +1,29 @@ + + + + + + + + + +
+
+ + + diff --git a/gfx/layers/apz/test/mochitest/test_group_double_tap_zoom.html b/gfx/layers/apz/test/mochitest/test_group_double_tap_zoom.html index fe4a0784a9..c1e0351ccb 100644 --- a/gfx/layers/apz/test/mochitest/test_group_double_tap_zoom.html +++ b/gfx/layers/apz/test/mochitest/test_group_double_tap_zoom.html @@ -24,12 +24,12 @@ var logging_and_doubletap_prefs = [ var subtests = [ {"file": "helper_doubletap_zoom.html", "prefs": doubletap_prefs}, {"file": "helper_doubletap_zoom_img.html", "prefs": doubletap_prefs}, - {"file": "helper_doubletap_zoom_textarea.html", "prefs": doubletap_prefs}, {"file": "helper_doubletap_zoom_horizontal_center.html", "prefs": doubletap_prefs}, {"file": "helper_doubletap_zoom_bug1702464.html", "prefs": doubletap_prefs}, {"file": "helper_doubletap_zoom_large_overflow.html", "prefs": doubletap_prefs}, {"file": "helper_doubletap_zoom_fixedpos.html", "prefs": logging_and_doubletap_prefs}, {"file": "helper_doubletap_zoom_tallwide.html", "prefs": doubletap_prefs}, + {"file": "helper_doubletap_zoom_textarea.html", "prefs": doubletap_prefs}, ]; if (getPlatform() == "mac") { diff --git a/gfx/layers/apz/test/mochitest/test_group_pointerevents.html b/gfx/layers/apz/test/mochitest/test_group_pointerevents.html index 9ec03edd59..8bc0690bfc 100644 --- a/gfx/layers/apz/test/mochitest/test_group_pointerevents.html +++ b/gfx/layers/apz/test/mochitest/test_group_pointerevents.html @@ -24,14 +24,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1285070 {"file": "helper_bug1682170_pointercancel_on_touchaction_pinchzoom.html", "prefs": touch_action_prefs}, {"file": "helper_bug1719855_pointercancel_on_touchmove_after_contextmenu_prevented.html"}, + {"file": "helper_bug1285070.html"}, + {"file": "helper_bug1299195.html", "prefs": [["dom.meta-viewport.enabled", isMac]]}, ]; + if (getPlatform() != "android") { // Bug 1858610: these subtests are flaky on Android. - subtests.push( - {"file": "helper_bug1285070.html"}, - {"file": "helper_bug1299195.html", "prefs": [["dom.meta-viewport.enabled", isMac]]}, - {"file": "helper_bug1502010_unconsumed_pan.html"} - ) + subtests.push({"file": "helper_bug1502010_unconsumed_pan.html"}); } if (isApzEnabled()) { diff --git a/gfx/layers/apz/test/mochitest/test_group_wheelevents.html b/gfx/layers/apz/test/mochitest/test_group_wheelevents.html index 42ce15a247..93746b9f6f 100644 --- a/gfx/layers/apz/test/mochitest/test_group_wheelevents.html +++ b/gfx/layers/apz/test/mochitest/test_group_wheelevents.html @@ -20,6 +20,13 @@ var prefs = [ ["mousewheel.transaction.timeout", 0], ]; +var wheel_transaction_prefs = [ + ["dom.event.wheel-event-groups.enabled", true], + ["mousewheel.transaction.timeout", 10000], + ["apz.test.mac.synth_wheel_input", true], + ...getSmoothScrollPrefs("wheel"), +]; + // For helper_scroll_over_scrollbar, we need to set a pref to force // layerization of the scrollbar track to reproduce the bug being fixed. // Otherwise, the bug only manifests with overlay scrollbars on macOS, @@ -48,6 +55,10 @@ var subtests = [ prefs: [["general.smoothScroll", false], ["apz.test.mac.synth_wheel_input", true]]}, {"file": "helper_scroll_anchoring_on_wheel.html", prefs: smoothness_prefs}, + {"file": "helper_scroll_over_subframe.html?scroll=wheel", prefs: wheel_transaction_prefs}, + {"file": "helper_scroll_over_subframe.html?oop=true&scroll=wheel", prefs: wheel_transaction_prefs}, + {"file": "helper_scroll_over_subframe.html?scroll=pan", prefs: wheel_transaction_prefs}, + {"file": "helper_scroll_over_subframe.html?oop=true&scroll=pan", prefs: wheel_transaction_prefs}, ]; subtests.push(...buildRelativeScrollSmoothnessVariants("wheel", ["scrollBy", "scrollTo", "scrollTop"])); -- cgit v1.2.3