From ca7df57c081b525b6b89ae2dbeef393863469824 Mon Sep 17 00:00:00 2001 From: Alex Chau Date: Fri, 13 Sep 2024 19:07:37 +0000 Subject: [PATCH] Reland "Separate desktop and fullscreen carousel" This reverts commit a555f4ca1b71a3120402e509d379e861aab226ef, and relands commit 9420ba75157bfd659571ee2ee1ae42ce9c0bbe12. - attachAlpha should only be reset in onRecycle, otherwise applyLoadPlan or moveRunningTaskToFront will unexpectedly reset it via resetViewTransforms. This fixes TaplTestsQuickstep.testQuickSwitchFromApp which assert all visible task must be on the left hand side of the screen during swipe up Fix: 353950224 Change-Id: If1c1524e435c8007844bcd51d8695a6d3b00450b --- .../quickstep/util/RecentsViewUtils.kt | 81 +++++++++++++--- .../android/quickstep/views/RecentsView.java | 93 ++++++++++++------- .../com/android/quickstep/views/TaskView.kt | 10 +- 3 files changed, 128 insertions(+), 56 deletions(-) diff --git a/quickstep/src/com/android/quickstep/util/RecentsViewUtils.kt b/quickstep/src/com/android/quickstep/util/RecentsViewUtils.kt index 595aa0077b..be1af64f02 100644 --- a/quickstep/src/com/android/quickstep/util/RecentsViewUtils.kt +++ b/quickstep/src/com/android/quickstep/util/RecentsViewUtils.kt @@ -28,9 +28,17 @@ import com.android.systemui.shared.recents.model.ThumbnailData * and extracted functions from RecentsView to facilitate the implementation of unit tests. */ class RecentsViewUtils { + /** Takes a screenshot of all [taskView] and return map of taskId to the screenshot */ + fun screenshotTasks( + taskView: TaskView, + recentsAnimationController: RecentsAnimationController, + ): Map = + taskView.taskContainers.associate { + it.task.key.id to recentsAnimationController.screenshotTask(it.task.key.id) + } /** - * Sort task groups to move desktop tasks to the end of the list. + * Sorts task groups to move desktop tasks to the end of the list. * * @param tasks List of group tasks to be sorted. * @return Sorted list of GroupTasks to be used in the RecentsView. @@ -40,6 +48,7 @@ class RecentsViewUtils { return otherTasks + desktopTasks } + /** Returns the expected index of the focus task. */ fun getFocusedTaskIndex(taskGroups: List): Int { // The focused task index is placed after the desktop tasks views. return if (enableLargeDesktopWindowingTile()) { @@ -49,12 +58,8 @@ class RecentsViewUtils { } } - /** - * Counts [TaskView]s that are [DesktopTaskView] instances. - * - * @param taskViews List of [TaskView]s - */ - fun getDesktopTaskViewCount(taskViews: List): Int = + /** Counts [TaskView]s that are [DesktopTaskView] instances. */ + fun getDesktopTaskViewCount(taskViews: Iterable): Int = taskViews.count { it is DesktopTaskView } /** Returns a list of all large TaskView Ids from [TaskView]s */ @@ -66,18 +71,64 @@ class RecentsViewUtils { * * @param taskViews List of [TaskView]s */ - fun getFirstLargeTaskView(taskViews: List): TaskView? = + fun getFirstLargeTaskView(taskViews: Iterable): TaskView? = taskViews.firstOrNull { it.isLargeTile } - fun screenshotTasks( - taskView: TaskView, - recentsAnimationController: RecentsAnimationController, - ): Map = - taskView.taskContainers.associate { - it.task.key.id to recentsAnimationController.screenshotTask(it.task.key.id) + /** Returns the last TaskView that should be displayed as a large tile. */ + fun getLastLargeTaskView(taskViews: Iterable): TaskView? = + taskViews.lastOrNull { it.isLargeTile } + + /** Returns the first [TaskView], with some tasks possibly hidden in the carousel. */ + fun getFirstTaskViewInCarousel( + nonRunningTaskCategoryHidden: Boolean, + taskViews: Iterable, + runningTaskView: TaskView?, + ): TaskView? = + taskViews.firstOrNull { + it.isVisibleInCarousel(runningTaskView, nonRunningTaskCategoryHidden) + } + + /** Returns the last [TaskView], with some tasks possibly hidden in the carousel. */ + fun getLastTaskViewInCarousel( + nonRunningTaskCategoryHidden: Boolean, + taskViews: Iterable, + runningTaskView: TaskView?, + ): TaskView? = + taskViews.lastOrNull { + it.isVisibleInCarousel(runningTaskView, nonRunningTaskCategoryHidden) } /** Returns the current list of [TaskView] children. */ - fun getTaskViews(taskViewCount: Int, requireTaskViewAt: (Int) -> TaskView): List = + fun getTaskViews(taskViewCount: Int, requireTaskViewAt: (Int) -> TaskView): Iterable = (0 until taskViewCount).map(requireTaskViewAt) + + /** Apply attachAlpha to all [TaskView] accordingly to different conditions. */ + fun applyAttachAlpha( + taskViews: Iterable, + runningTaskView: TaskView?, + runningTaskTileHidden: Boolean, + nonRunningTaskCategoryHidden: Boolean, + ) { + taskViews.forEach { taskView -> + val isVisible = + if (taskView == runningTaskView) !runningTaskTileHidden + else taskView.isVisibleInCarousel(runningTaskView, nonRunningTaskCategoryHidden) + taskView.attachAlpha = if (isVisible) 1f else 0f + } + } + + private fun TaskView.isVisibleInCarousel( + runningTaskView: TaskView?, + nonRunningTaskCategoryHidden: Boolean, + ): Boolean = + if (!nonRunningTaskCategoryHidden) true + else if (runningTaskView == null) true else getCategory() == runningTaskView.getCategory() + + private fun TaskView.getCategory(): TaskViewCategory = + if (this is DesktopTaskView) TaskViewCategory.DESKTOP else TaskViewCategory.FULL_SCREEN + + private enum class TaskViewCategory { + FULL_SCREEN, + DESKTOP, + } } diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index e37e036857..bb46a2c3ed 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -681,6 +681,7 @@ public abstract class RecentsView< protected int mRunningTaskViewId = -1; private int mTaskViewIdCount; protected boolean mRunningTaskTileHidden; + private boolean mNonRunningTaskCategoryHidden; @Nullable private Task[] mTmpRunningTasks; protected int mFocusedTaskViewId = INVALID_TASK_ID; @@ -2094,14 +2095,10 @@ public abstract class RecentsView< simulator.fullScreenProgress.value = 0; simulator.recentsViewScale.value = 1; }); - // Similar to setRunningTaskHidden below, reapply the state before runningTaskView is - // null. - if (!mRunningTaskShowScreenshot) { - setRunningTaskViewShowScreenshot(mRunningTaskShowScreenshot); - } - if (mRunningTaskTileHidden) { - setRunningTaskHidden(mRunningTaskTileHidden); - } + // Reapply runningTask related attributes as they might have been reset by + // resetViewTransforms(). + setRunningTaskViewShowScreenshot(mRunningTaskShowScreenshot); + applyAttachAlpha(); updateCurveProperties(); // Update the set of visible task's data @@ -2650,10 +2647,6 @@ public abstract class RecentsView< return getTaskViewFromTaskViewId(mFocusedTaskViewId); } - private @Nullable TaskView getFirstLargeTaskView() { - return mUtils.getFirstLargeTaskView(getTaskViews()); - } - @Nullable private TaskView getTaskViewFromTaskViewId(int taskViewId) { if (taskViewId == -1) { @@ -2749,7 +2742,10 @@ public abstract class RecentsView< showCurrentTask(mActiveGestureRunningTasks); setEnableFreeScroll(false); setEnableDrawingLiveTile(false); - setRunningTaskHidden(!shouldUpdateRunningTaskAlpha()); + setRunningTaskHidden(true); + if (enableLargeDesktopWindowingTile()) { + setNonRunningTaskCategoryHidden(true); + } setTaskIconScaledDown(true); } @@ -2888,6 +2884,9 @@ public abstract class RecentsView< setEnableDrawingLiveTile(mCurrentGestureEndTarget == GestureState.GestureEndTarget.RECENTS); Log.d(TAG, "onGestureAnimationEnd - mEnableDrawingLiveTile: " + mEnableDrawingLiveTile); setRunningTaskHidden(false); + if (enableLargeDesktopWindowingTile()) { + setNonRunningTaskCategoryHidden(false); + } animateUpTaskIconScale(); animateActionsViewIn(); @@ -3043,13 +3042,27 @@ public abstract class RecentsView< if (runningTask == null) { return; } - runningTask.setStableAlpha(isHidden ? 0 : mContentAlpha); + applyAttachAlpha(); if (!isHidden) { AccessibilityManagerCompat.sendCustomAccessibilityEvent( runningTask, AccessibilityEvent.TYPE_VIEW_FOCUSED, null); } } + /** + * Hides the tasks that has a different category (Fullscreen/Desktop) from the running task. + */ + public void setNonRunningTaskCategoryHidden(boolean isHidden) { + mNonRunningTaskCategoryHidden = isHidden; + updateMinAndMaxScrollX(); + applyAttachAlpha(); + } + + private void applyAttachAlpha() { + mUtils.applyAttachAlpha(getTaskViews(), getRunningTaskView(), mRunningTaskTileHidden, + mNonRunningTaskCategoryHidden); + } + private void setRunningTaskViewShowScreenshot(boolean showScreenshot) { setRunningTaskViewShowScreenshot(showScreenshot, /*updatedThumbnails=*/null); } @@ -4447,11 +4460,7 @@ public abstract class RecentsView< alpha = Utilities.boundToRange(alpha, 0, 1); mContentAlpha = alpha; - TaskView runningTaskView = getRunningTaskView(); for (TaskView taskView : getTaskViews()) { - if (runningTaskView != null && mRunningTaskTileHidden && taskView == runningTaskView) { - continue; - } taskView.setStableAlpha(alpha); } mClearAllButton.setContentAlpha(mContentAlpha); @@ -4564,7 +4573,7 @@ public abstract class RecentsView< /** * Returns the current list of [TaskView] children. */ - private List getTaskViews() { + private Iterable getTaskViews() { return mUtils.getTaskViews(getTaskViewCount(), this::requireTaskViewAt); } @@ -5794,26 +5803,42 @@ public abstract class RecentsView< } private int getFirstViewIndex() { - TaskView firstTaskView = mShowAsGridLastOnLayout ? getFirstLargeTaskView() : null; - return firstTaskView != null ? indexOfChild(firstTaskView) : 0; + final TaskView firstView; + if (mShowAsGridLastOnLayout) { + // For grid Overivew, it always start if a large tile (focused task or desktop task) if + // they exist, otherwise it start with the first task. + TaskView firstLargeTaskView = mUtils.getFirstLargeTaskView(getTaskViews()); + if (firstLargeTaskView != null) { + firstView = firstLargeTaskView; + } else { + firstView = getTaskViewAt(0); + } + } else { + firstView = mUtils.getFirstTaskViewInCarousel(mNonRunningTaskCategoryHidden, + getTaskViews(), getRunningTaskView()); + } + return indexOfChild(firstView); } private int getLastViewIndex() { + final View lastView; if (!mDisallowScrollToClearAll) { - return indexOfChild(mClearAllButton); + // When ClearAllButton is present, it always end with ClearAllButton. + lastView = mClearAllButton; + } else if (mShowAsGridLastOnLayout) { + // When ClearAllButton is absent, for the grid Overview, it always end with a grid task + // if they exist, otherwise it ends with a large tile (focused task or desktop task). + TaskView lastGridTaskView = getLastGridTaskView(); + if (lastGridTaskView != null) { + lastView = lastGridTaskView; + } else { + lastView = mUtils.getLastLargeTaskView(getTaskViews()); + } + } else { + lastView = mUtils.getLastTaskViewInCarousel(mNonRunningTaskCategoryHidden, + getTaskViews(), getRunningTaskView()); } - - if (!mShowAsGridLastOnLayout) { - return getTaskViewCount() - 1; - } - - TaskView lastGridTaskView = getLastGridTaskView(); - if (lastGridTaskView != null) { - return indexOfChild(lastGridTaskView); - } - - // Returns focus task if there are no grid tasks. - return indexOfChild(getFirstLargeTaskView()); + return indexOfChild(lastView); } /** diff --git a/quickstep/src/com/android/quickstep/views/TaskView.kt b/quickstep/src/com/android/quickstep/views/TaskView.kt index 291ccef258..2ed6ae66c8 100644 --- a/quickstep/src/com/android/quickstep/views/TaskView.kt +++ b/quickstep/src/com/android/quickstep/views/TaskView.kt @@ -82,7 +82,6 @@ import com.android.quickstep.TaskViewUtils import com.android.quickstep.orientation.RecentsPagedOrientationHandler import com.android.quickstep.recents.di.RecentsDependencies import com.android.quickstep.recents.di.get -import com.android.quickstep.task.thumbnail.TaskThumbnailView import com.android.quickstep.task.viewmodel.TaskViewModel import com.android.quickstep.util.ActiveGestureErrorDetector import com.android.quickstep.util.ActiveGestureLog @@ -397,7 +396,7 @@ constructor( } get() = taskViewAlpha.get(ALPHA_INDEX_STABLE).value - protected var attachAlpha + var attachAlpha set(value) { taskViewAlpha.get(ALPHA_INDEX_ATTACH).value = value } @@ -606,6 +605,7 @@ constructor( override fun onRecycle() { resetPersistentViewTransforms() + attachAlpha = 1f // Clear any references to the thumbnail (it will be re-read either from the cache or the // system on next bind) if (!enableRefactorTaskThumbnail()) { @@ -1587,10 +1587,7 @@ constructor( resetViewTransforms() } - fun getTaskContainerForTaskThumbnailView(taskThumbnailView: TaskThumbnailView): TaskContainer? = - taskContainers.firstOrNull { it.thumbnailView == taskThumbnailView } - - open fun resetViewTransforms() { + fun resetViewTransforms() { // fullscreenTranslation and accumulatedTranslation should not be reset, as // resetViewTransforms is called during QuickSwitch scrolling. dismissTranslationX = 0f @@ -1606,7 +1603,6 @@ constructor( } dismissScale = 1f translationZ = 0f - attachAlpha = 1f setIconScaleAndDim(1f) setColorTint(0f, 0) }