From f4cf80ea739d92bb86408f77ee7483e49d0e6e37 Mon Sep 17 00:00:00 2001 From: Alex Chau Date: Wed, 7 Apr 2021 15:38:34 +0100 Subject: [PATCH] Handle swipe up after quick switch in overview grid - If swipe up after task launches, move the task to be the first and focused it - If swipe up before task launches, make sure the task can be sanpped to by moving ClearAllButton further away - Before snapping to page on swipe up, make sure scroll calculation is up to date and consider the target gesture state - Removed home task special casing in fallback recents, as the snapped page logic handles invariant scroll generically - Invoke reset when launching home in fallback recents Bug: 175939487 Fixes: 184262404 Fixes: 185468049 Test: Manual Change-Id: I5a6c581f15cd62748cfe6c77342d959f4dd1bfaf --- .../android/quickstep/AbsSwipeUpHandler.java | 3 + .../fallback/FallbackRecentsView.java | 19 +- .../quickstep/views/ClearAllButton.java | 6 +- .../android/quickstep/views/RecentsView.java | 291 +++++++++++------- .../com/android/quickstep/views/TaskView.java | 29 +- 5 files changed, 225 insertions(+), 123 deletions(-) diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java index 2a903eb9fc..654f5de5d1 100644 --- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java +++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java @@ -968,6 +968,9 @@ public abstract class AbsSwipeUpHandler, if (mRecentsView != null) { int nearestPage = mRecentsView.getDestinationPage(); boolean isScrolling = false; + // Update page scroll before snapping to page to make sure we snapped to the + // position calculated with target gesture in mind. + mRecentsView.updateScrollSynchronously(); if (mRecentsView.getNextPage() != nearestPage) { // We shouldn't really scroll to the next page when swiping up to recents. // Only allow settling on the next page if it's nearest to the center. diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java index 854a140d71..4d4b6e1467 100644 --- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java +++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java @@ -17,6 +17,7 @@ package com.android.quickstep.fallback; import static com.android.quickstep.GestureState.GestureEndTarget.RECENTS; import static com.android.quickstep.fallback.RecentsState.DEFAULT; +import static com.android.quickstep.fallback.RecentsState.HOME; import static com.android.quickstep.fallback.RecentsState.MODAL_TASK; import android.annotation.TargetApi; @@ -97,6 +98,15 @@ public class FallbackRecentsView extends RecentsView= start && taskStart <= end) || (taskEnd >= start && taskEnd <= end); @@ -1199,16 +1199,8 @@ public abstract class RecentsView focusedTaskIndex) { + // For tasks after the focused task, shift by focused task's width and spacing. + gridTranslations[i] += + mIsRtl ? focusedTaskWidthAndSpacing : -focusedTaskWidthAndSpacing; + } else { + // For task before the focused task, accumulate the width and spacing to + // calculate the distance focused task need to shift. + focusedTaskShift += mIsRtl ? taskWidthAndSpacing : -taskWidthAndSpacing; } + boolean isTopRow = isTaskDismissal ? mTopIdSet.contains(taskView.getTask().key.id) + : topRowWidth <= bottomRowWidth; + if (isTopRow) { + gridTranslations[i] += topAccumulatedTranslationX; + topRowWidth += taskWidthAndSpacing; + topSet.add(i); + mTopIdSet.add(taskView.getTask().key.id); - float gridTranslationX = mIsRtl ? widthOffset : -widthOffset; - gridTranslations[i] += gridTranslationX; - bottomAccumulatedTranslationX += gridTranslationX; + taskView.setGridTranslationY(taskGridVerticalDiff); + + // Move horizontally into empty space. + float widthOffset = 0; + for (int j = i - 1; !topSet.contains(j) && j >= 0; j--) { + if (j == focusedTaskIndex) { + continue; + } + widthOffset += getTaskViewAt(j).getLayoutParams().width + mPageSpacing; + } + + float gridTranslationX = mIsRtl ? widthOffset : -widthOffset; + gridTranslations[i] += gridTranslationX; + topAccumulatedTranslationX += gridTranslationX; + } else { + gridTranslations[i] += bottomAccumulatedTranslationX; + bottomRowWidth += taskWidthAndSpacing; + bottomSet.add(i); + + // Move into bottom row. + taskView.setGridTranslationY(heightOffset + taskGridVerticalDiff); + + // Move horizontally into empty space. + float widthOffset = 0; + for (int j = i - 1; !bottomSet.contains(j) && j >= 0; j--) { + if (j == focusedTaskIndex) { + continue; + } + widthOffset += getTaskViewAt(j).getLayoutParams().width + mPageSpacing; + } + + float gridTranslationX = mIsRtl ? widthOffset : -widthOffset; + gridTranslations[i] += gridTranslationX; + bottomAccumulatedTranslationX += gridTranslationX; + } + if (taskView == snappedTaskView) { + snappedTaskRowWidth = isTopRow ? topRowWidth : bottomRowWidth; + } } } - // We need to maintain first non-home task's grid translation at 0, now shift translation - // of all the TaskViews to achieve that. - for (int i = firstNonHomeTaskIndex; i < taskCount; i++) { + // We need to maintain snapped task's page scroll invariant between quick switch and + // overview, so we sure snapped task's grid translation is 0, and add a non-fullscreen + // translationX that is the same as snapped task's full scroll adjustment. + float snappedTaskFullscreenScrollAdjustment = 0; + float snappedTaskGridTranslationX = 0; + if (snappedTaskView != null) { + snappedTaskFullscreenScrollAdjustment = snappedTaskView.getScrollAdjustment( + /*fullscreenEnabled=*/true, /*gridEnabled=*/false); + snappedTaskGridTranslationX = gridTranslations[snappedPage - mTaskViewStartIndex]; + } + + + for (int i = 0; i < taskCount; i++) { TaskView taskView = getTaskViewAt(i); - taskView.setGridTranslationX( - gridTranslations[i] - gridTranslations[firstNonHomeTaskIndex]); + taskView.setGridTranslationX(gridTranslations[i] - snappedTaskGridTranslationX); + taskView.setNonFullscreenTranslationX(snappedTaskFullscreenScrollAdjustment); } // Use the accumulated translation of the longer row. @@ -1866,7 +1908,7 @@ public abstract class RecentsView 0) { - if (mIsRtl && mDisallowScrollToClearAll) { - // We aren't showing the clear all button, - // so use the leftmost task as the min scroll. - return getScrollForPage(indexOfChild(getTaskViewAt(getTaskViewCount() - 1))); + if (mIsRtl) { + // If we aren't showing the clear all button, use the rightmost task as the min + // scroll. + return getScrollForPage(mDisallowScrollToClearAll ? indexOfChild( + getTaskViewAt(getTaskViewCount() - 1)) : indexOfChild(mClearAllButton)); + } else { + TaskView focusedTaskView = showAsGrid() ? getFocusedTaskView() : null; + return getScrollForPage(focusedTaskView != null ? indexOfChild(focusedTaskView) + : mTaskViewStartIndex); } - return getLeftMostChildScroll(); } return super.computeMinScroll(); } - /** - * Returns page scroll of the left most child. - */ - public int getLeftMostChildScroll() { - return getScrollForPage(mIsRtl ? indexOfChild(mClearAllButton) : mTaskViewStartIndex); - } - @Override protected int computeMaxScroll() { if (getTaskViewCount() > 0) { - if (!mIsRtl && mDisallowScrollToClearAll) { - // We aren't showing the clear all button, - // so use the rightmost task as the min scroll. - return getScrollForPage(indexOfChild(getTaskViewAt(getTaskViewCount() - 1))); + if (mIsRtl) { + TaskView focusedTaskView = showAsGrid() ? getFocusedTaskView() : null; + return getScrollForPage(focusedTaskView != null ? indexOfChild(focusedTaskView) + : mTaskViewStartIndex); + } else { + // If we aren't showing the clear all button, use the leftmost task as the min + // scroll. + return getScrollForPage(mDisallowScrollToClearAll ? indexOfChild( + getTaskViewAt(getTaskViewCount() - 1)) : indexOfChild(mClearAllButton)); } - return getScrollForPage(mIsRtl ? mTaskViewStartIndex : indexOfChild(mClearAllButton)); } return super.computeMaxScroll(); } + /** + * Returns page scroll of ClearAllButton. + */ + public int getClearAllScroll() { + return getScrollForPage(indexOfChild(mClearAllButton)); + } + @Override protected boolean getPageScrolls(int[] outPageScrolls, boolean layoutChildren, ComputePageScrollsLogic scrollLogic) { boolean pageScrollChanged = super.getPageScrolls(outPageScrolls, layoutChildren, scrollLogic); + boolean showAsFullscreen = showAsFullscreen(); + boolean showAsGrid = showAsGrid(); // Align ClearAllButton to the left (RTL) or right (non-RTL), which is different from other // TaskViews. This must be called after laying out ClearAllButton. @@ -3028,11 +3101,10 @@ public abstract class RecentsView