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

Commit 0e529667 authored by Fabian Kozynski's avatar Fabian Kozynski Committed by Android (Google) Code Review
Browse files

Merge "Fix scrim clipping" into main

parents 0afb8b77 80aa374d
Loading
Loading
Loading
Loading
+64 −27
Original line number Diff line number Diff line
@@ -118,6 +118,7 @@ import com.android.systemui.keyboard.shortcut.ui.composable.InteractionsConfig
import com.android.systemui.keyboard.shortcut.ui.composable.ProvideShortcutHelperIndication
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.lifecycle.setSnapshotBinding
import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.media.controls.ui.view.MediaHost
import com.android.systemui.plugins.qs.QS
import com.android.systemui.plugins.qs.QSContainerController
@@ -132,6 +133,7 @@ import com.android.systemui.qs.composefragment.ui.toEditMode
import com.android.systemui.qs.composefragment.viewmodel.QSFragmentComposeViewModel
import com.android.systemui.qs.flags.QSComposeFragment
import com.android.systemui.qs.footer.ui.compose.FooterActions
import com.android.systemui.qs.panels.shared.model.QSFragmentComposeClippingTableLog
import com.android.systemui.qs.panels.ui.compose.EditMode
import com.android.systemui.qs.panels.ui.compose.QuickQuickSettings
import com.android.systemui.qs.panels.ui.compose.TileGrid
@@ -163,6 +165,7 @@ class QSFragmentCompose
@Inject
constructor(
    private val qsFragmentComposeViewModelFactory: QSFragmentComposeViewModel.Factory,
    @QSFragmentComposeClippingTableLog private val qsClippingTableLogBuffer: TableLogBuffer,
    private val dumpManager: DumpManager,
) : LifecycleFragment(), QS, Dumpable {

@@ -183,8 +186,12 @@ constructor(
    // Inside object for namespacing
    private val notificationScrimClippingParams =
        object {
            var isEnabled by mutableStateOf(false)
            var params by mutableStateOf(NotificationScrimClipParams())
            var clipData by mutableStateOf(false to NotificationScrimClipParams())
            private val isEnabled
                get() = clipData.first

            private val params
                get() = clipData.second

            fun dump(pw: IndentingPrintWriter) {
                pw.printSection("NotificationScrimClippingParams") {
@@ -241,12 +248,12 @@ constructor(
        val frame =
            FrameLayoutTouchPassthrough(
                context,
                { notificationScrimClippingParams.isEnabled },
                snapshotFlow { notificationScrimClippingParams.params },
                snapshotFlow { notificationScrimClippingParams.clipData },
                // 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 },
                viewModel::emitMotionEventForFalsingSwipeNested,
                qsClippingTableLogBuffer,
            )
        frame.addView(
            composeView,
@@ -520,8 +527,8 @@ constructor(
        visible: Boolean,
        fullWidth: Boolean,
    ) {
        notificationScrimClippingParams.isEnabled = visible
        notificationScrimClippingParams.params =
        notificationScrimClippingParams.clipData =
            visible to
                NotificationScrimClipParams(
                    top,
                    bottom,
@@ -1056,17 +1063,15 @@ private const val EDIT_MODE_TIME_MILLIS = 500
 */
private class FrameLayoutTouchPassthrough(
    context: Context,
    private val clippingEnabledProvider: () -> Boolean,
    private val clippingParams: Flow<NotificationScrimClipParams>,
    private val clippingData: Flow<Pair<Boolean, NotificationScrimClipParams>>,
    private val canScrollForwardQs: () -> Boolean,
    private val emitMotionEventForFalsing: () -> Unit,
    private val logBuffer: TableLogBuffer,
) : FrameLayout(context) {

    init {
        repeatWhenAttached {
            repeatOnLifecycle(Lifecycle.State.STARTED) {
                clippingParams.collect { currentClipParams = it }
            }
            repeatOnLifecycle(Lifecycle.State.STARTED) { clippingData.collect { clipData = it } }
        }
    }

@@ -1074,33 +1079,53 @@ private class FrameLayoutTouchPassthrough(
    private var lastWidth = -1
        set(value) {
            if (field != value) {
                logBuffer.logChange(columnName = COL_WIDTH, value = value, isInitial = false)
                field = value
                updateClippingPath()
            }
        }

    private var currentClipParams = NotificationScrimClipParams()
    // [first] is enabled and [second] is the clipping params
    private var clipData = false to NotificationScrimClipParams()
        set(value) {
            if (field != value) {
                logBuffer.logDiffs(
                    columnPrefix = PREFIX_PARAMS,
                    prevVal = field.second,
                    newVal = value.second,
                )
                if (field.first != value.first) {
                    logBuffer.logChange(
                        columnName = COL_CLIP_ENABLED,
                        value = value.first,
                        isInitial = false,
                    )
                }
                field = value
                updateClippingPath()
            }
        }

    private val clipEnabled
        get() = clipData.first

    private val clipParams
        get() = clipData.second

    private fun updateClippingPath() {
        currentClippingPath.rewind()
        if (clippingEnabledProvider()) {
            val right = width + currentClipParams.rightInset
            val left = -currentClipParams.leftInset
            val top = currentClipParams.top
            val bottom = currentClipParams.bottom
        if (clipEnabled) {
            val right = width + clipParams.rightInset
            val left = -clipParams.leftInset
            val top = clipParams.top
            val bottom = clipParams.bottom
            currentClippingPath.addRoundRect(
                left.toFloat(),
                top.toFloat(),
                right.toFloat(),
                bottom.toFloat(),
                currentClipParams.radius.toFloat(),
                currentClipParams.radius.toFloat(),
                clipParams.radius.toFloat(),
                clipParams.radius.toFloat(),
                Path.Direction.CW,
            )
        }
@@ -1114,7 +1139,12 @@ private class FrameLayoutTouchPassthrough(

    override fun dispatchDraw(canvas: Canvas) {
        if (!currentClippingPath.isEmpty) {
            logBuffer.logChange(columnName = COL_CLIP_APPLIED, value = true, isInitial = false)
            canvas.translate(0f, -translationY)
            canvas.clipOutPath(currentClippingPath)
            canvas.translate(0f, translationY)
        } else {
            logBuffer.logChange(columnName = COL_CLIP_APPLIED, value = false, isInitial = false)
        }
        super.dispatchDraw(canvas)
    }
@@ -1125,7 +1155,7 @@ private class FrameLayoutTouchPassthrough(
        child: View?,
        outLocalPoint: PointF?,
    ): Boolean {
        return if (clippingEnabledProvider() && y + translationY > currentClipParams.top) {
        return if (clipEnabled && y + translationY > clipParams.top) {
            false
        } else {
            super.isTransformedTouchPointInView(x, y, child, outLocalPoint)
@@ -1187,6 +1217,13 @@ private class FrameLayoutTouchPassthrough(
        }
        return super.onInterceptTouchEvent(ev)
    }

    private companion object {
        const val COL_CLIP_ENABLED = "enabled"
        const val COL_CLIP_APPLIED = "applied"
        const val COL_WIDTH = "width"
        const val PREFIX_PARAMS = "params"
    }
}

private fun Modifier.gesturesDisabled(disabled: Boolean) =
+38 −1
Original line number Diff line number Diff line
@@ -16,6 +16,9 @@

package com.android.systemui.qs.composefragment.ui

import com.android.systemui.log.table.Diffable
import com.android.systemui.log.table.TableRowLogger

/** Params for [notificationScrimClip]. */
data class NotificationScrimClipParams(
    val top: Int = 0,
@@ -23,4 +26,38 @@ data class NotificationScrimClipParams(
    val leftInset: Int = 0,
    val rightInset: Int = 0,
    val radius: Int = 0,
)
) : Diffable<NotificationScrimClipParams> {
    override fun logDiffs(prevVal: NotificationScrimClipParams, row: TableRowLogger) {
        if (top != prevVal.top) {
            row.logChange(Columns.COL_TOP, top)
        }
        if (bottom != prevVal.bottom) {
            row.logChange(Columns.COL_BOTTOM, bottom)
        }
        if (leftInset != prevVal.leftInset) {
            row.logChange(Columns.COL_LEFT_INSET, leftInset)
        }
        if (rightInset != prevVal.rightInset) {
            row.logChange(Columns.COL_RIGHT_INSET, rightInset)
        }
        if (radius != prevVal.radius) {
            row.logChange(Columns.COL_RADIUS, radius)
        }
    }

    override fun logFull(row: TableRowLogger) {
        row.logChange(Columns.COL_TOP, top)
        row.logChange(Columns.COL_BOTTOM, bottom)
        row.logChange(Columns.COL_LEFT_INSET, leftInset)
        row.logChange(Columns.COL_RIGHT_INSET, rightInset)
        row.logChange(Columns.COL_RADIUS, radius)
    }
}

private object Columns {
    const val COL_TOP = "top"
    const val COL_BOTTOM = "bottom"
    const val COL_LEFT_INSET = "left_inset"
    const val COL_RIGHT_INSET = "right_inset"
    const val COL_RADIUS = "radius"
}
+10 −0
Original line number Diff line number Diff line
@@ -20,6 +20,8 @@ import com.android.systemui.CoreStartable
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.log.LogBuffer
import com.android.systemui.log.LogBufferFactory
import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.log.table.TableLogBufferFactory
import com.android.systemui.qs.panels.data.repository.DefaultLargeTilesRepository
import com.android.systemui.qs.panels.data.repository.DefaultLargeTilesRepositoryImpl
import com.android.systemui.qs.panels.domain.interactor.EditTilesResetInteractor
@@ -29,6 +31,7 @@ import com.android.systemui.qs.panels.shared.model.GridLayoutType
import com.android.systemui.qs.panels.shared.model.InfiniteGridLayoutType
import com.android.systemui.qs.panels.shared.model.PaginatedGridLayoutType
import com.android.systemui.qs.panels.shared.model.PanelsLog
import com.android.systemui.qs.panels.shared.model.QSFragmentComposeClippingTableLog
import com.android.systemui.qs.panels.ui.compose.GridLayout
import com.android.systemui.qs.panels.ui.compose.PaginatableGridLayout
import com.android.systemui.qs.panels.ui.compose.PaginatedGridLayout
@@ -74,6 +77,13 @@ interface PanelsModule {
            return factory.create("PanelsLog", 50)
        }

        @Provides
        @SysUISingleton
        @QSFragmentComposeClippingTableLog
        fun providesQSFragmentComposeClippingLog(factory: TableLogBufferFactory): TableLogBuffer {
            return factory.create("QSFragmentComposeClippingTableLog", 100)
        }

        @Provides
        @IntoSet
        fun provideGridLayout(gridLayout: InfiniteGridLayout): Pair<GridLayoutType, GridLayout> {
+24 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.qs.panels.shared.model

import javax.inject.Qualifier

@Qualifier
@MustBeDocumented
@Retention(AnnotationRetention.RUNTIME)
annotation class QSFragmentComposeClippingTableLog