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

Commit da8d2285 authored by Winson's avatar Winson Committed by Winson Chung
Browse files

Fixing issue with scrolling tasks upwards

- When scrolling the stack away from the task overrides, we should 
  actually lock the stack scroll and instead apply the changes in scroll
  to the override tasks.

Bug: 27376567
Change-Id: Idd1874ab0f6f5eb273bf6e9623b84277961f4291
parent e1b1ce77
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Trace;
import android.util.ArraySet;
import android.util.IntProperty;
import android.util.Property;
@@ -260,6 +261,14 @@ public class Utilities {
        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, res.getDisplayMetrics());
    }

    /**
     * Adds a trace event for debugging.
     */
    public static void addTraceEvent(String event) {
        Trace.traceBegin(Trace.TRACE_TAG_VIEW, event);
        Trace.traceEnd(Trace.TRACE_TAG_VIEW);
    }

    /**
     * Returns a lightweight dump of a rect.
     */
+26 −12
Original line number Diff line number Diff line
@@ -23,13 +23,13 @@ import android.content.res.Resources;
import android.graphics.Path;
import android.graphics.Rect;
import android.util.ArraySet;
import android.util.MutableFloat;
import android.util.SparseArray;
import android.util.SparseIntArray;
import android.view.ViewDebug;

import com.android.systemui.R;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsActivity;
import com.android.systemui.recents.RecentsActivityLaunchState;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.RecentsDebugFlags;
@@ -628,22 +628,24 @@ public class TaskStackLayoutAlgorithm {

    /**
     * Updates this stack when a scroll happens.
     *
     */
    public void updateFocusStateOnScroll(float stackScroll, float deltaScroll) {
        if (deltaScroll == 0f) {
            return;
    public float updateFocusStateOnScroll(float lastTargetStackScroll, float targetStackScroll,
            float lastStackScroll) {
        if (targetStackScroll == lastStackScroll) {
            return targetStackScroll;
        }

        float deltaScroll = targetStackScroll - lastStackScroll;
        float deltaTargetScroll = targetStackScroll - lastTargetStackScroll;
        float newScroll = targetStackScroll;
        mUnfocusedRange.offset(targetStackScroll);
        for (int i = mTaskIndexOverrideMap.size() - 1; i >= 0; i--) {
            int taskId = mTaskIndexOverrideMap.keyAt(i);
            float x = mTaskIndexMap.get(taskId);
            float overrideX = mTaskIndexOverrideMap.get(taskId, 0f);
            float newOverrideX = overrideX + deltaScroll;
            mUnfocusedRange.offset(stackScroll);
            boolean outOfBounds = mUnfocusedRange.getNormalizedX(newOverrideX) < 0f ||
                    mUnfocusedRange.getNormalizedX(newOverrideX) > 1f;
            if (outOfBounds || (overrideX >= x && x >= newOverrideX) ||
                    (overrideX <= x && x <= newOverrideX)) {
            if (isInvalidOverrideX(x, overrideX, newOverrideX)) {
                // Remove the override once we reach the original task index
                mTaskIndexOverrideMap.removeAt(i);
            } else if ((overrideX >= x && deltaScroll <= 0f) ||
@@ -652,11 +654,23 @@ public class TaskStackLayoutAlgorithm {
                mTaskIndexOverrideMap.put(taskId, newOverrideX);
            } else {
                // Scrolling override x away from x, we should still move the scroll towards x
                float deltaX = overrideX - x;
                newOverrideX = Math.signum(deltaX) * (Math.abs(deltaX) - Math.abs(deltaScroll));
                mTaskIndexOverrideMap.put(taskId, x + newOverrideX);
                newScroll = lastStackScroll;
                newOverrideX = overrideX - deltaTargetScroll;
                if (isInvalidOverrideX(x, overrideX, newOverrideX)) {
                    mTaskIndexOverrideMap.removeAt(i);
                } else{
                    mTaskIndexOverrideMap.put(taskId, newOverrideX);
                }
            }
        }
        return newScroll;
    }

    private boolean isInvalidOverrideX(float x, float overrideX, float newOverrideX) {
        boolean outOfBounds = mUnfocusedRange.getNormalizedX(newOverrideX) < 0f ||
                mUnfocusedRange.getNormalizedX(newOverrideX) > 1f;
        return outOfBounds || (overrideX >= x && x >= newOverrideX) ||
                (overrideX <= x && x <= newOverrideX);
    }

    /**
+0 −1
Original line number Diff line number Diff line
@@ -1618,7 +1618,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
        if (animation != null) {
            relayoutTaskViewsOnNextFrame(animation);
        }
        mLayoutAlgorithm.updateFocusStateOnScroll(curScroll, curScroll - prevScroll);

        if (mEnterAnimationComplete) {
            if (prevScroll > SHOW_STACK_ACTION_BUTTON_SCROLL_THRESHOLD &&
+29 −9
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.animation.ObjectAnimator;
import android.content.Context;
import android.util.FloatProperty;
import android.util.Log;
import android.util.MutableFloat;
import android.util.Property;
import android.view.ViewDebug;
import android.widget.OverScroller;
@@ -66,6 +67,8 @@ public class TaskStackViewScroller {

    @ViewDebug.ExportedProperty(category="recents")
    float mStackScrollP;
    @ViewDebug.ExportedProperty(category="recents")
    float mLastDeltaP = 0f;
    float mFlingDownScrollP;
    int mFlingDownY;

@@ -84,6 +87,11 @@ public class TaskStackViewScroller {
    /** Resets the task scroller. */
    void reset() {
        mStackScrollP = 0f;
        mLastDeltaP = 0f;
    }

    void resetDeltaScroll() {
        mLastDeltaP = 0f;
    }

    /** Gets the current stack scroll */
@@ -98,15 +106,28 @@ public class TaskStackViewScroller {
        setStackScroll(s, AnimationProps.IMMEDIATE);
    }

    /**
     * Sets the current stack scroll immediately, and returns the difference between the target
     * scroll and the actual scroll after accounting for the effect on the focus state.
     */
    public float setDeltaStackScroll(float downP, float deltaP) {
        float targetScroll = downP + deltaP;
        float newScroll = mLayoutAlgorithm.updateFocusStateOnScroll(downP + mLastDeltaP, targetScroll,
                mStackScrollP);
        setStackScroll(newScroll, AnimationProps.IMMEDIATE);
        mLastDeltaP = deltaP;
        return newScroll - targetScroll;
    }

    /**
     * Sets the current stack scroll, but indicates to the callback the preferred animation to
     * update to this new scroll.
     */
    public void setStackScroll(float s, AnimationProps animation) {
        float prevStackScroll = mStackScrollP;
        mStackScrollP = s;
    public void setStackScroll(float newScroll, AnimationProps animation) {
        float prevScroll = mStackScrollP;
        mStackScrollP = newScroll;
        if (mCb != null) {
            mCb.onStackScrollChanged(prevStackScroll, mStackScrollP, animation);
            mCb.onStackScrollChanged(prevScroll, mStackScrollP, animation);
        }
    }

@@ -115,9 +136,9 @@ public class TaskStackViewScroller {
     * @return whether the stack progress changed.
     */
    public boolean setStackScrollToInitialState() {
        float prevStackScrollP = mStackScrollP;
        float prevScroll = mStackScrollP;
        setStackScroll(mLayoutAlgorithm.mInitialScrollP);
        return Float.compare(prevStackScrollP, mStackScrollP) != 0;
        return Float.compare(prevScroll, mStackScrollP) != 0;
    }

    /**
@@ -227,10 +248,9 @@ public class TaskStackViewScroller {
    boolean computeScroll() {
        if (mScroller.computeScrollOffset()) {
            float deltaP = mLayoutAlgorithm.getDeltaPForY(mFlingDownY, mScroller.getCurrY());
            float scroll = mFlingDownScrollP + deltaP;
            setStackScroll(scroll);
            mFlingDownScrollP += setDeltaStackScroll(mFlingDownScrollP, deltaP);
            if (DEBUG) {
                Log.d(TAG, "computeScroll: " + scroll);
                Log.d(TAG, "computeScroll: " + (mFlingDownScrollP + deltaP));
            }
            return true;
        }
+8 −5
Original line number Diff line number Diff line
@@ -200,6 +200,7 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
                // Stop the current scroll if it is still flinging
                mScroller.stopScroller();
                mScroller.stopBoundScrollAnimation();
                mScroller.resetDeltaScroll();
                Utilities.cancelAnimationWithoutCallbacks(mScrollFlingAnimator);

                // Finish any existing task animations from the delete
@@ -223,6 +224,7 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
                mDownY = (int) ev.getY(index);
                mLastY = mDownY;
                mDownScrollP = mScroller.getStackScroll();
                mScroller.resetDeltaScroll();
                mVelocityTracker.addMovement(ev);
                break;
            }
@@ -256,20 +258,21 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
                    // If we just move linearly on the screen, then that would map to 1/arclength
                    // of the curve, so just move the scroll proportional to that
                    float deltaP = layoutAlgorithm.getDeltaPForY(mDownY, y);
                    float curScrollP = mDownScrollP + deltaP;

                    // Modulate the overscroll to prevent users from pulling the stack too far
                    float minScrollP = layoutAlgorithm.mMinScrollP;
                    float maxScrollP = layoutAlgorithm.mMaxScrollP;
                    float curScrollP = mDownScrollP + deltaP;
                    if (curScrollP < minScrollP || curScrollP > maxScrollP) {
                        float clampedScrollP = Utilities.clamp(curScrollP, minScrollP, maxScrollP);
                        float overscrollP = (curScrollP - clampedScrollP);
                        float overscrollX = Math.abs(overscrollP) / MAX_OVERSCROLL;
                        curScrollP = clampedScrollP + (Math.signum(overscrollP) *
                                (OVERSCROLL_INTERP.getInterpolation(overscrollX) * MAX_OVERSCROLL));
                        float interpX = OVERSCROLL_INTERP.getInterpolation(overscrollX);
                        curScrollP = clampedScrollP + Math.signum(overscrollP) *
                                (interpX * MAX_OVERSCROLL);
                    }

                    mScroller.setStackScroll(curScrollP);
                    mDownScrollP += mScroller.setDeltaStackScroll(mDownScrollP,
                            curScrollP - mDownScrollP);
                    mStackViewScrolledEvent.updateY(y - mLastY);
                    EventBus.getDefault().send(mStackViewScrolledEvent);
                }