diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java b/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java index 44f220bb76a0b..4ecda542ca362 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java +++ b/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java @@ -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. */ diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java index b75a91e8c42bc..e4da8b3699142 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java @@ -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); } /** diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java index 13c8403ab0abd..0fc45ed8951c0 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java @@ -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 && diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java index 19b3c943ae657..1fa73c6ef61cc 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java @@ -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; } diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java index ee0de1ad05dfd..3cdb1fb27854c 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java @@ -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); }