Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dd20e046 authored by Fabián Kozynski's avatar Fabián Kozynski
Browse files

Properly intercept touches

We were using the view's canScrollX methods, instead of getting the
values from the actual scrollable in Compose.

Also, only intercept touches that are more vertical than horizontal.

Test: manual, more touches accepted + edit mode scrolls
Fixes: 400438156
Flag: com.android.systemui.qs_ui_refactor_compose_fragment
Change-Id: If8e310b49b1218a07cf8b10359e660fdc23b6256
parent 5f7fe743
Loading
Loading
Loading
Loading
+33 −9
Original line number Diff line number Diff line
@@ -244,6 +244,19 @@ constructor(
                }
            }

        val canScrollQs =
            object : CanScrollQs {
                override fun forward(): Boolean {
                    return (scrollState.canScrollForward && viewModel.isQsFullyExpanded) ||
                        isCustomizing
                }

                override fun backward(): Boolean {
                    return (scrollState.canScrollBackward && viewModel.isQsFullyExpanded) ||
                        isCustomizing
                }
            }

        val frame =
            FrameLayoutTouchPassthrough(
                context,
@@ -251,7 +264,7 @@ constructor(
                snapshotFlow { notificationScrimClippingParams.params },
                // Only allow scrolling when we are fully expanded. That way, we don't intercept
                // swipes in lockscreen (when somehow QS is receiving touches).
                { (scrollState.canScrollForward && viewModel.isQsFullyExpanded) || isCustomizing },
                canScrollQs,
                viewModel::emitMotionEventForFalsingSwipeNested,
            )
        frame.addView(
@@ -1080,7 +1093,7 @@ private class FrameLayoutTouchPassthrough(
    context: Context,
    private val clippingEnabledProvider: () -> Boolean,
    private val clippingParams: Flow<NotificationScrimClipParams>,
    private val canScrollForwardQs: () -> Boolean,
    private val canScrollQs: CanScrollQs,
    private val emitMotionEventForFalsing: () -> Unit,
) : FrameLayout(context) {

@@ -1156,6 +1169,7 @@ private class FrameLayoutTouchPassthrough(

    val touchSlop = ViewConfiguration.get(context).scaledTouchSlop
    var downY = 0f
    var downX = 0f
    var preventingIntercept = false

    override fun onTouchEvent(event: MotionEvent): Boolean {
@@ -1163,11 +1177,11 @@ private class FrameLayoutTouchPassthrough(
        when (action) {
            MotionEvent.ACTION_DOWN -> {
                preventingIntercept = false
                if (canScrollVertically(1)) {
                if (canScrollQs.forward()) {
                    // If we can scroll down, make sure we're not intercepted by the parent
                    preventingIntercept = true
                    parent?.requestDisallowInterceptTouchEvent(true)
                } else if (!canScrollVertically(-1)) {
                } else if (!canScrollQs.backward()) {
                    // Don't pass on the touch to the view, because scrolling will unconditionally
                    // disallow interception even if we can't scroll.
                    // if a user can't scroll at all, we should never listen to the touch.
@@ -1191,18 +1205,22 @@ private class FrameLayoutTouchPassthrough(
            MotionEvent.ACTION_DOWN -> {
                preventingIntercept = false
                // If we can scroll down, make sure none of our parents intercepts us.
                if (canScrollForwardQs()) {
                if (canScrollQs.forward()) {
                    preventingIntercept = true
                    parent?.requestDisallowInterceptTouchEvent(true)
                }
                downY = ev.y
                downX = ev.x
            }

            MotionEvent.ACTION_MOVE -> {
                val y = ev.y.toInt()
                val yDiff: Float = y - downY
                if (yDiff < -touchSlop && !canScrollForwardQs()) {
                    // Intercept touches that are overscrolling.
                val y = ev.y
                val x = ev.x
                val yDiff = y - downY
                val xDiff = x - downX
                val collapsing = yDiff < -touchSlop && !canScrollQs.forward()
                val vertical = Math.abs(xDiff) < Math.abs(yDiff)
                if (collapsing && vertical) {
                    return true
                }
            }
@@ -1211,6 +1229,12 @@ private class FrameLayoutTouchPassthrough(
    }
}

private interface CanScrollQs {
    fun forward(): Boolean

    fun backward(): Boolean
}

private fun Modifier.gesturesDisabled(disabled: Boolean) =
    if (disabled) {
        pointerInput(Unit) {