commit 3d47ff163f96446022a701b74611d10d16920c94 parent a52ae7f8463026fc79ee76622fe5eb4cfd94c0f8 Author: Cristina Horotan <chorotan@mozilla.com> Date: Sat, 4 Oct 2025 02:00:30 +0300 Revert "Bug 1917726 - Don't force-expand toolbars during gestures that resemble a scroll up gesture. r=mstange,android-reviewers,petru" for causing build components build bustage at EngineViewScrollingBehaviorTest This reverts commit 8685eaf79f2039aea2de6afbb592daea1f126bac. Diffstat:
2 files changed, 48 insertions(+), 5 deletions(-)
diff --git a/mobile/android/android-components/components/ui/widgets/src/main/java/mozilla/components/ui/widgets/behavior/EngineViewScrollingBehavior.kt b/mobile/android/android-components/components/ui/widgets/src/main/java/mozilla/components/ui/widgets/behavior/EngineViewScrollingBehavior.kt @@ -96,7 +96,7 @@ class EngineViewScrollingBehavior( type: Int, ): Boolean { return if (dynamicScrollView != null) { - startNestedScroll(axes, type) + startNestedScroll(axes, type, child) } else { return false // not interested in subsequent scroll events } @@ -172,6 +172,12 @@ class EngineViewScrollingBehavior( dynamicScrollView?.let { view -> if (shouldScroll && startedScroll) { yTranslator.translate(view, distance) + } else if (engineView?.getInputResultDetail()?.isTouchHandlingUnknown() == false) { + // Force expand the view if the user scrolled up, it is not already expanded and + // an animation to expand it is not already in progress, + // otherwise the user could get stuck in a state where they cannot show the view + // See https://github.com/mozilla-mobile/android-components/issues/7101 + yTranslator.forceExpandIfNotAlready(view, distance) } } } @@ -204,12 +210,18 @@ class EngineViewScrollingBehavior( ) @VisibleForTesting - internal fun startNestedScroll(axes: Int, type: Int): Boolean { + internal fun startNestedScroll(axes: Int, type: Int, view: View): Boolean { return if (shouldScroll && axes == ViewCompat.SCROLL_AXIS_VERTICAL) { startedScroll = true shouldSnapAfterScroll = type == ViewCompat.TYPE_TOUCH yTranslator.cancelInProgressTranslation() true + } else if (engineView?.getInputResultDetail()?.isTouchUnhandled() == true) { + // Force expand the view if event is unhandled, otherwise user could get stuck in a + // state where they cannot show the view + yTranslator.cancelInProgressTranslation() + yTranslator.expandWithAnimation(view) + false } else { false } diff --git a/mobile/android/android-components/components/ui/widgets/src/test/java/mozilla/components/ui/widgets/behavior/EngineViewScrollingBehaviorTest.kt b/mobile/android/android-components/components/ui/widgets/src/test/java/mozilla/components/ui/widgets/behavior/EngineViewScrollingBehaviorTest.kt @@ -15,6 +15,7 @@ import androidx.core.view.ViewCompat import androidx.test.ext.junit.runners.AndroidJUnit4 import mozilla.components.concept.engine.EngineSession import mozilla.components.concept.engine.EngineView +import mozilla.components.concept.engine.INPUT_UNHANDLED import mozilla.components.concept.engine.InputResultDetail import mozilla.components.concept.engine.selection.SelectionActionDelegate import mozilla.components.support.test.any @@ -50,7 +51,7 @@ class EngineViewScrollingBehaviorTest { type = ViewCompat.TYPE_TOUCH, ) assertFalse(acceptsNestedScroll) - verify(behavior, never()).startNestedScroll(anyInt(), anyInt()) + verify(behavior, never()).startNestedScroll(anyInt(), anyInt(), any()) behavior.dynamicScrollView = mock() acceptsNestedScroll = behavior.onStartNestedScroll( @@ -62,7 +63,7 @@ class EngineViewScrollingBehaviorTest { type = ViewCompat.TYPE_TOUCH, ) assertTrue(acceptsNestedScroll) - verify(behavior).startNestedScroll(anyInt(), anyInt()) + verify(behavior).startNestedScroll(anyInt(), anyInt(), any()) } @Test @@ -75,6 +76,7 @@ class EngineViewScrollingBehaviorTest { val acceptsNestedScroll = behavior.startNestedScroll( axes = ViewCompat.SCROLL_AXIS_VERTICAL, type = ViewCompat.TYPE_TOUCH, + view = mock(), ) assertTrue(acceptsNestedScroll) @@ -89,12 +91,14 @@ class EngineViewScrollingBehaviorTest { var acceptsNestedScroll = behavior.startNestedScroll( axes = ViewCompat.SCROLL_AXIS_VERTICAL, type = ViewCompat.TYPE_TOUCH, + view = mock(), ) assertTrue(acceptsNestedScroll) acceptsNestedScroll = behavior.startNestedScroll( axes = ViewCompat.SCROLL_AXIS_HORIZONTAL, type = ViewCompat.TYPE_TOUCH, + view = mock(), ) assertFalse(acceptsNestedScroll) } @@ -114,6 +118,7 @@ class EngineViewScrollingBehaviorTest { val acceptsNestedScroll = behavior.startNestedScroll( axes = ViewCompat.SCROLL_AXIS_VERTICAL, type = ViewCompat.TYPE_TOUCH, + view = mock(), ) verify(yTranslator).cancelInProgressTranslation() @@ -165,7 +170,7 @@ class EngineViewScrollingBehaviorTest { type = inputType, ) - verify(behavior).startNestedScroll(axes, inputType) + verify(behavior).startNestedScroll(axes, inputType, view) } @Test @@ -468,6 +473,32 @@ class EngineViewScrollingBehaviorTest { } @Test + fun `Behavior will forceExpand when scrolling up and !shouldScroll if the touch was handled in the browser`() { + val behavior = spy(EngineViewScrollingBehavior(testContext, null, ViewPosition.BOTTOM)) + val yTranslator: ViewYTranslator = mock() + behavior.yTranslator = yTranslator + behavior.initGesturesDetector(behavior.createGestureDetector()) + val view: View = spy(View(testContext, null, 0)) + behavior.dynamicScrollView = view + val engineView: EngineView = mock() + behavior.engineView = engineView + val handledTouchInput = InputResultDetail.newInstance().copy(INPUT_UNHANDLED) + doReturn(handledTouchInput).`when`(engineView).getInputResultDetail() + + doReturn(100).`when`(view).height + doReturn(100f).`when`(view).translationY + + val downEvent = TestUtils.getMotionEvent(ACTION_DOWN, 0f, 0f) + val moveEvent = TestUtils.getMotionEvent(ACTION_MOVE, 0f, 30f, downEvent) + + behavior.onInterceptTouchEvent(mock(), mock(), downEvent) + behavior.onInterceptTouchEvent(mock(), mock(), moveEvent) + + verify(behavior).tryToScrollVertically(-30f) + verify(yTranslator).forceExpandIfNotAlready(view, -30f) + } + + @Test fun `Behavior will not forceExpand when scrolling up and !shouldScroll if the touch was not yet handled in the browser`() { val behavior = spy(EngineViewScrollingBehavior(testContext, null, ViewPosition.BOTTOM)) val yTranslator: ViewYTranslator = mock()