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

Commit 5e2a4186 authored by András Kurucz's avatar András Kurucz Committed by Android (Google) Code Review
Browse files

Merge "[Flexiglass] Disable NSSL OverScroller" into main

parents ee700ffe a17508d7
Loading
Loading
Loading
Loading
+92 −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.statusbar.notification.stack

/** A no-operation implementation of the [OverScrollerInterface] interface. */
class NoOpOverScroller : OverScrollerInterface {

    override fun abortAnimation() {
        // No-op
    }

    override fun computeScrollOffset(): Boolean {
        return false
    }

    override fun fling(
        startX: Int,
        startY: Int,
        velocityX: Int,
        velocityY: Int,
        minX: Int,
        maxX: Int,
        minY: Int,
        maxY: Int,
    ) {
        // No-op
    }

    override fun fling(
        startX: Int,
        startY: Int,
        velocityX: Int,
        velocityY: Int,
        minX: Int,
        maxX: Int,
        minY: Int,
        maxY: Int,
        overX: Int,
        overY: Int,
    ) {
        // No-op
    }

    override fun forceFinished(finished: Boolean) {
        // No-op
    }

    override fun getCurrVelocity(): Float {
        return 0.0f
    }

    override fun getCurrX(): Int {
        return 0
    }

    override fun getCurrY(): Int {
        return 0
    }

    override fun isFinished(): Boolean {
        return true
    }

    override fun springBack(
        startX: Int,
        startY: Int,
        minX: Int,
        maxX: Int,
        minY: Int,
        maxY: Int,
    ): Boolean {
        return false
    }

    override fun startScroll(startX: Int, startY: Int, dx: Int, dy: Int) {
        // No-op
    }
}
+4 −2
Original line number Diff line number Diff line
@@ -187,7 +187,7 @@ public class NotificationStackScrollLayout
    private int mMaxLayoutHeight;

    private VelocityTracker mVelocityTracker;
    private OverScroller mScroller;
    private OverScrollerInterface mScroller;

    private Runnable mFinishScrollingCallback;
    private int mTouchSlop;
@@ -886,7 +886,9 @@ public class NotificationStackScrollLayout

    void initView(Context context, NotificationSwipeHelper swipeHelper,
                  NotificationStackSizeCalculator notificationStackSizeCalculator) {
        mScroller = new OverScroller(getContext());
        mScroller = !SceneContainerFlag.isEnabled()
                ? OverScrollerWrapper.wrap(new OverScroller(getContext()))
                : new NoOpOverScroller();
        mSwipeHelper = swipeHelper;
        mNotificationStackSizeCalculator = notificationStackSizeCalculator;

+159 −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.statusbar.notification.stack

/**
 * Interface defining the contract for an OverScroller. This handles scrolling and flinging with
 * overscroll support.
 */
interface OverScrollerInterface {
    /**
     * Stops the animation. Contrary to {@link #forceFinished(boolean)}, aborting the animation
     * causes the scroller to move to the final x and y positions.
     */
    fun abortAnimation()

    /**
     * Call this when you want to know the new location. If it returns true, the animation is not
     * yet finished.
     *
     * @return True if the animation is not yet finished.
     */
    fun computeScrollOffset(): Boolean

    /**
     * Start scrolling based on a fling gesture. The distance travelled will depend on the initial
     * velocity of the fling.
     *
     * @param startX Starting point of the scroll (X)
     * @param startY Starting point of the scroll (Y)
     * @param velocityX Initial velocity of the fling (X) measured in pixels per second.
     * @param velocityY Initial velocity of the fling (Y) measured in pixels per second
     * @param minX Minimum X value. The scroller will not scroll beyond this point.
     * @param maxX Maximum X value. The scroller will not scroll beyond this point.
     * @param minY Minimum Y value. The scroller will not scroll beyond this point.
     * @param maxY Maximum Y value. The scroller will not scroll beyond this point.
     */
    fun fling(
        startX: Int,
        startY: Int,
        velocityX: Int,
        velocityY: Int,
        minX: Int,
        maxX: Int,
        minY: Int,
        maxY: Int,
    )

    /**
     * Start scrolling based on a fling gesture. The distance travelled will depend on the initial
     * velocity of the fling.
     *
     * @param startX Starting point of the scroll (X)
     * @param startY Starting point of the scroll (Y)
     * @param velocityX Initial velocity of the fling (X) measured in pixels per second.
     * @param velocityY Initial velocity of the fling (Y) measured in pixels per second
     * @param minX Minimum X value. The scroller will not scroll beyond this point.
     * @param maxX Maximum X value. The scroller will not scroll beyond this point.
     * @param minY Minimum Y value. The scroller will not scroll beyond this point.
     * @param maxY Maximum Y value. The scroller will not scroll beyond this point.
     * @param overX Overfling range. If > 0, horizontal overfling in either direction will be
     *   possible.
     * @param overY Overfling range. If > 0, vertical overfling in either direction will be
     *   possible.
     */
    fun fling(
        startX: Int,
        startY: Int,
        velocityX: Int,
        velocityY: Int,
        minX: Int,
        maxX: Int,
        minY: Int,
        maxY: Int,
        overX: Int,
        overY: Int,
    )

    /**
     * Force the finished field to a particular value.
     *
     * @param finished The new finished value.
     */
    fun forceFinished(finished: Boolean)

    /**
     * Returns the current velocity.
     *
     * @return The original velocity less the deceleration. Result may be negative.
     */
    fun getCurrVelocity(): Float

    /**
     * Returns the current X offset in the scroll.
     *
     * @return The new X offset as an absolute distance from the origin.
     */
    fun getCurrX(): Int

    /**
     * Returns the current Y offset in the scroll.
     *
     * @return The new Y offset as an absolute distance from the origin.
     */
    fun getCurrY(): Int

    // getSplineFlingDistance was package-private, typically not in public interface
    // fun getSplineFlingDistance(velocity: Int): Double

    /**
     * Returns whether the scroller has finished scrolling.
     *
     * @return True if the scroller has finished scrolling, false otherwise.
     */
    fun isFinished(): Boolean

    // setInterpolator was package-private
    // fun setInterpolator(interpolator: Interpolator?)

    /**
     * Call this when you want to 'spring back' into a valid range.
     *
     * @param startX Starting X coordinate
     * @param startY Starting Y coordinate
     * @param minX Minimum X value
     * @param maxX Maximum X value
     * @param minY Minimum Y value
     * @param maxY Maximum Y value
     * @return true if a springback animation is started, false if already in range.
     */
    fun springBack(startX: Int, startY: Int, minX: Int, maxX: Int, minY: Int, maxY: Int): Boolean

    /**
     * Start scrolling by providing a starting point and the distance to travel. The scroll will use
     * the default value of 250 milliseconds for the duration.
     *
     * @param startX Starting horizontal scroll offset in pixels. Positive numbers will scroll the
     *   content to the left.
     * @param startY Starting vertical scroll offset in pixels. Positive numbers will scroll the
     *   content up.
     * @param dx Horizontal distance to travel. Positive numbers will scroll the content to the
     *   left.
     * @param dy Vertical distance to travel. Positive numbers will scroll the content up.
     */
    fun startScroll(startX: Int, startY: Int, dx: Int, dy: Int)
}
+98 −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.statusbar.notification.stack

import android.widget.OverScroller

class OverScrollerWrapper(private val delegate: OverScroller) : OverScrollerInterface {

    companion object {
        @JvmStatic
        fun wrap(delegate: OverScroller): OverScrollerWrapper = OverScrollerWrapper(delegate)
    }

    override fun abortAnimation() {
        delegate.abortAnimation()
    }

    override fun computeScrollOffset(): Boolean {
        return delegate.computeScrollOffset()
    }

    override fun fling(
        startX: Int,
        startY: Int,
        velocityX: Int,
        velocityY: Int,
        minX: Int,
        maxX: Int,
        minY: Int,
        maxY: Int,
    ) {
        delegate.fling(startX, startY, velocityX, velocityY, minX, maxX, minY, maxY)
    }

    override fun fling(
        startX: Int,
        startY: Int,
        velocityX: Int,
        velocityY: Int,
        minX: Int,
        maxX: Int,
        minY: Int,
        maxY: Int,
        overX: Int,
        overY: Int,
    ) {
        delegate.fling(startX, startY, velocityX, velocityY, minX, maxX, minY, maxY, overX, overY)
    }

    override fun forceFinished(finished: Boolean) {
        delegate.forceFinished(finished)
    }

    override fun getCurrVelocity(): Float {
        return delegate.currVelocity
    }

    override fun getCurrX(): Int {
        return delegate.currX
    }

    override fun getCurrY(): Int {
        return delegate.currY
    }

    override fun isFinished(): Boolean {
        return delegate.isFinished
    }

    override fun springBack(
        startX: Int,
        startY: Int,
        minX: Int,
        maxX: Int,
        minY: Int,
        maxY: Int,
    ): Boolean {
        return delegate.springBack(startX, startY, minX, maxX, minY, maxY)
    }

    override fun startScroll(startX: Int, startY: Int, dx: Int, dy: Int) {
        delegate.startScroll(startX, startY, dx, dy)
    }
}