Merge "Move DesktopTask to front of RecentsView (1/2)" into main

This commit is contained in:
Treehugger Robot
2024-08-21 18:38:34 +00:00
committed by Android (Google) Code Review
9 changed files with 211 additions and 84 deletions
+8
View File
@@ -31,3 +31,11 @@ flag {
purpose: PURPOSE_BUGFIX
}
}
flag {
name: "enable_large_desktop_windowing_tile"
namespace: "launcher_overview"
description: "Makes the desktop tiles larger and moves them to the front of the list in Overview."
bug: "353947137"
}
@@ -181,7 +181,7 @@ public abstract class TaskViewTouchController<CONTAINER extends Context & Recent
// - The task is snapped
mAllowGoingDown = i == mRecentsView.getCurrentPage()
&& DisplayController.getNavigationMode(mContainer).hasGestures
&& (!mRecentsView.showAsGrid() || mTaskBeingDragged.isFocusedTask())
&& (!mRecentsView.showAsGrid() || mTaskBeingDragged.isLargeTile())
&& mRecentsView.isTaskInExpectedScrollPosition(i);
directionsToDetectScroll = mAllowGoingDown ? DIRECTION_BOTH : upDirection;
@@ -310,7 +310,7 @@ public abstract class TaskViewTouchController<CONTAINER extends Context & Recent
// Set mOverrideVelocity to control task dismiss velocity in onDragEnd
int velocityDimenId = R.dimen.default_task_dismiss_drag_velocity;
if (mRecentsView.showAsGrid()) {
if (mTaskBeingDragged.isFocusedTask()) {
if (mTaskBeingDragged.isLargeTile()) {
velocityDimenId =
R.dimen.default_task_dismiss_drag_velocity_grid_focus_task;
} else {
@@ -315,12 +315,12 @@ public interface TaskShortcutFactory {
boolean isTaskSplitNotSupported = !task.isDockable ||
(intentFlags & FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) != 0;
boolean hideForExistingMultiWindow = container.getDeviceProfile().isMultiWindowMode;
boolean isFocusedTask = deviceProfile.isTablet && taskView.isFocusedTask();
boolean isLargeTile = deviceProfile.isTablet && taskView.isLargeTile();
boolean isTaskInExpectedScrollPosition =
recentsView.isTaskInExpectedScrollPosition(recentsView.indexOfChild(taskView));
if (notEnoughTasksToSplit || isTaskSplitNotSupported || hideForExistingMultiWindow
|| (isFocusedTask && isTaskInExpectedScrollPosition)) {
|| (isLargeTile && isTaskInExpectedScrollPosition)) {
return null;
}
@@ -340,11 +340,11 @@ public interface TaskShortcutFactory {
DeviceProfile deviceProfile = container.getDeviceProfile();
final TaskView taskView = taskContainer.getTaskView();
final RecentsView recentsView = taskView.getRecentsView();
boolean isLargeTileFocusedTask = deviceProfile.isTablet && taskView.isFocusedTask();
boolean isLargeTile = deviceProfile.isTablet && taskView.isLargeTile();
boolean isInExpectedScrollPosition =
recentsView.isTaskInExpectedScrollPosition(recentsView.indexOfChild(taskView));
boolean shouldShowActionsButtonInstead =
isLargeTileFocusedTask && isInExpectedScrollPosition;
isLargeTile && isInExpectedScrollPosition;
// No "save app pair" menu item if:
// - we are in 3p launcher
@@ -0,0 +1,71 @@
/*
* Copyright (C) 2024 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.quickstep.util
import com.android.launcher3.Flags.enableLargeDesktopWindowingTile
import com.android.quickstep.views.DesktopTaskView
import com.android.quickstep.views.TaskView
import com.android.quickstep.views.TaskViewType
/**
* Helper class for [com.android.quickstep.views.RecentsView]. This util class contains refactored
* and extracted functions from RecentsView to facilitate the implementation of unit tests.
*/
class RecentsViewUtils {
/**
* Sort 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.
*/
fun sortDesktopTasksToFront(tasks: List<GroupTask>): List<GroupTask> {
val (desktopTasks, otherTasks) = tasks.partition { it.taskViewType == TaskViewType.DESKTOP }
return otherTasks + desktopTasks
}
fun getFocusedTaskIndex(taskGroups: List<GroupTask>): Int {
// The focused task index is placed after the desktop tasks views.
return if (enableLargeDesktopWindowingTile()) {
taskGroups.count { it.taskViewType == TaskViewType.DESKTOP }
} else {
0
}
}
/**
* Counts [numChildren] that are [DesktopTaskView] instances.
*
* @param numChildren Quantity of children to transverse
* @param getTaskViewAt Function that provides a TaskView given an index
*/
fun getDesktopTaskViewCount(numChildren: Int, getTaskViewAt: (Int) -> TaskView?): Int =
(0 until numChildren).count { getTaskViewAt(it) is DesktopTaskView }
/**
* Returns the first TaskView that should be displayed as a large tile.
*
* @param numChildren Quantity of children to transverse
* @param getTaskViewAt Function that provides a TaskView given an index
*/
fun getFirstLargeTaskView(numChildren: Int, getTaskViewAt: (Int) -> TaskView?): TaskView? {
return (0 until numChildren).firstNotNullOfOrNull { index ->
val taskView = getTaskViewAt(index)
if (taskView?.isLargeTile == true) taskView else null
}
}
}
@@ -191,7 +191,7 @@ public final class DigitalWellBeingToast {
private @SplitBannerConfig int getSplitBannerConfig() {
if (mSplitBounds == null
|| !mContainer.getDeviceProfile().isTablet
|| mTaskView.isFocusedTask()) {
|| mTaskView.isLargeTile()) {
return SPLIT_BANNER_FULLSCREEN;
}
@@ -37,6 +37,7 @@ import static com.android.launcher3.AbstractFloatingView.getTopOpenViewWithType;
import static com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS;
import static com.android.launcher3.Flags.enableAdditionalHomeAnimations;
import static com.android.launcher3.Flags.enableGridOnlyOverview;
import static com.android.launcher3.Flags.enableLargeDesktopWindowingTile;
import static com.android.launcher3.Flags.enableRefactorTaskThumbnail;
import static com.android.launcher3.LauncherAnimUtils.SUCCESS_TRANSITION_PROGRESS;
import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
@@ -211,6 +212,7 @@ import com.android.quickstep.util.GroupTask;
import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.util.RecentsAtomicAnimationFactory;
import com.android.quickstep.util.RecentsOrientedState;
import com.android.quickstep.util.RecentsViewUtils;
import com.android.quickstep.util.SplitAnimationController.Companion.SplitAnimInitProps;
import com.android.quickstep.util.SplitAnimationTimings;
import com.android.quickstep.util.SplitSelectStateController;
@@ -254,8 +256,8 @@ import java.util.stream.Collectors;
* @param <CONTAINER_TYPE> : the container that should host recents view
* @param <STATE_TYPE> : the type of base state that will be used
*/
public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewContainer,
public abstract class RecentsView<
CONTAINER_TYPE extends Context & RecentsViewContainer,
STATE_TYPE extends BaseState<STATE_TYPE>> extends PagedView implements Insettable,
TaskThumbnailCache.HighResLoadingState.HighResLoadingStateChangedCallback,
TaskVisualsChangeListener {
@@ -656,7 +658,7 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo
protected boolean mRunningTaskTileHidden;
@Nullable
private Task[] mTmpRunningTasks;
protected int mFocusedTaskViewId = -1;
protected int mFocusedTaskViewId = INVALID_TASK_ID;
private boolean mTaskIconScaledDown = false;
private boolean mRunningTaskShowScreenshot = false;
@@ -813,7 +815,9 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo
private boolean mAnyTaskHasBeenDismissed;
private final RecentsViewModel mRecentsViewModel;
private final RecentsViewHelper mHelper;
private final RecentsViewModelHelper mHelper;
private final RecentsViewUtils mRecentsViewUtils = new RecentsViewUtils();
public RecentsView(Context context, @Nullable AttributeSet attrs, int defStyleAttr,
BaseContainerInterface sizeStrategy) {
@@ -835,7 +839,7 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo
recentsDependencies.inject(RecentTasksRepository.class),
recentsDependencies.inject(RecentsViewData.class)
);
mHelper = new RecentsViewHelper(mRecentsViewModel);
mHelper = new RecentsViewModelHelper(mRecentsViewModel);
recentsDependencies.provide(RecentsRotationStateRepository.class,
() -> new RecentsRotationStateRepositoryImpl(mOrientationState));
@@ -1685,10 +1689,10 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo
}
TaskView taskView = getTaskViewAt(mNextPage);
// Snap to fully visible focused task and clear all button.
boolean shouldSnapToFocusedTask = taskView != null && taskView.isFocusedTask()
boolean shouldSnapToLargeTask = taskView != null && taskView.isLargeTile()
&& isTaskViewFullyVisible(taskView);
boolean shouldSnapToClearAll = mNextPage == indexOfChild(mClearAllButton);
if (!shouldSnapToFocusedTask && !shouldSnapToClearAll) {
if (!shouldSnapToLargeTask && !shouldSnapToClearAll) {
return;
}
}
@@ -1748,7 +1752,9 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo
return;
}
if (mCurrentPage == 0) {
int frontIndex = enableLargeDesktopWindowingTile() ? getDesktopTaskViewCount() : 0;
if (mCurrentPage <= frontIndex) {
return;
}
@@ -1760,8 +1766,9 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo
removeView(runningTaskView);
mMovingTaskView = null;
runningTaskView.resetPersistentViewTransforms();
addView(runningTaskView, 0);
setCurrentPage(0);
addView(runningTaskView, frontIndex);
setCurrentPage(frontIndex);
updateTaskSize();
}
@@ -1779,7 +1786,8 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo
protected void applyLoadPlan(List<GroupTask> taskGroups) {
if (mPendingAnimation != null) {
mPendingAnimation.addEndListener(success -> applyLoadPlan(taskGroups));
final List<GroupTask> finalTaskGroups = taskGroups;
mPendingAnimation.addEndListener(success -> applyLoadPlan(finalTaskGroups));
return;
}
@@ -1824,7 +1832,7 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo
// Reset the focused task to avoiding initializing TaskViews layout as focused task during
// binding. The focused task view will be updated after all the TaskViews are bound.
mFocusedTaskViewId = INVALID_TASK_ID;
setFocusedTaskViewId(INVALID_TASK_ID);
// Removing views sets the currentPage to 0, so we save this and restore it after
// the new set of views are added
@@ -1847,6 +1855,11 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo
// Clear out desktop view if it is set
mDesktopTaskView = null;
// Move Desktop Tasks to the end of the list
if (enableLargeDesktopWindowingTile()) {
taskGroups = mRecentsViewUtils.sortDesktopTasksToFront(taskGroups);
}
// Add views as children based on whether it's grouped or single task. Looping through
// taskGroups backwards populates the thumbnail grid from least recent to most recent.
for (int i = taskGroups.size() - 1; i >= 0; i--) {
@@ -1900,11 +1913,14 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo
// Keep same previous focused task
TaskView newFocusedTaskView = getTaskViewByTaskIds(focusedTaskIds);
// If the list changed, maybe the focused task doesn't exist anymore
if (newFocusedTaskView == null && getTaskViewCount() > 0) {
newFocusedTaskView = getTaskViewAt(0);
int newFocusedTaskViewIndex = mRecentsViewUtils.getFocusedTaskIndex(taskGroups);
if (newFocusedTaskView == null && getTaskViewCount() > newFocusedTaskViewIndex) {
newFocusedTaskView = getTaskViewAt(newFocusedTaskViewIndex);
}
mFocusedTaskViewId = newFocusedTaskView != null && !enableGridOnlyOverview()
? newFocusedTaskView.getTaskViewId() : INVALID_TASK_ID;
setFocusedTaskViewId(newFocusedTaskView != null && !enableGridOnlyOverview()
? newFocusedTaskView.getTaskViewId() : INVALID_TASK_ID);
updateTaskSize();
updateChildTaskOrientations();
@@ -1944,8 +1960,8 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo
// Set the current page to the running task, but not if settling on new task.
if (hasAllValidTaskIds(runningTaskIds)) {
targetPage = indexOfChild(newRunningTaskView);
} else if (getTaskViewCount() > 0) {
targetPage = indexOfChild(requireTaskViewAt(0));
} else if (getTaskViewCount() > newFocusedTaskViewIndex) {
targetPage = indexOfChild(requireTaskViewAt(newFocusedTaskViewIndex));
}
}
if (targetPage != -1 && mCurrentPage != targetPage) {
@@ -1970,6 +1986,7 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo
// generally map to the same task.
mIgnoreResetTaskId = INVALID_TASK_ID;
}
resetTaskVisuals();
onTaskStackUpdated();
updateEnabledOverlays();
@@ -2010,14 +2027,13 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo
return taskViewCount;
}
public int getGroupedTaskViewCount() {
int groupViewCount = 0;
for (int i = 0; i < getChildCount(); i++) {
if (getChildAt(i) instanceof GroupedTaskView) {
groupViewCount++;
}
}
return groupViewCount;
/**
* Transverse RecentsView children to calculate the amount of DesktopTaskViews.
*
* @return Number of children that are instances of DesktopTaskView
*/
private int getDesktopTaskViewCount() {
return mRecentsViewUtils.getDesktopTaskViewCount(getChildCount(), this::getTaskViewAt);
}
/**
@@ -2549,7 +2565,7 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo
mCurrentPageScrollDiff = 0;
mIgnoreResetTaskId = -1;
mTaskListChangeId = -1;
mFocusedTaskViewId = -1;
setFocusedTaskViewId(INVALID_TASK_ID);
mAnyTaskHasBeenDismissed = false;
@@ -2621,6 +2637,10 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo
return getTaskViewFromTaskViewId(mFocusedTaskViewId);
}
private @Nullable TaskView getFirstLargeTaskView() {
return mRecentsViewUtils.getFirstLargeTaskView(getChildCount(), this::getTaskViewAt);
}
@Nullable
private TaskView getTaskViewFromTaskViewId(int taskViewId) {
if (taskViewId == -1) {
@@ -2882,6 +2902,7 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo
if (runningTasks.length == 0) {
return;
}
int runningTaskViewId = -1;
boolean needGroupTaskView = runningTasks.length > 1;
boolean needDesktopTask = hasDesktopTask(runningTasks);
@@ -2926,7 +2947,11 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo
boolean runningTaskTileHidden = mRunningTaskTileHidden;
setCurrentTask(runningTaskViewId);
mFocusedTaskViewId = enableGridOnlyOverview() ? INVALID_TASK_ID : runningTaskViewId;
boolean shouldFocusRunningTask = !(enableGridOnlyOverview()
&& (enableLargeDesktopWindowingTile()
|| getRunningTaskView() instanceof DesktopTaskView));
setFocusedTaskViewId(shouldFocusRunningTask ? runningTaskViewId : INVALID_TASK_ID);
runOnPageScrollsInitialized(() -> setCurrentPage(getRunningTaskIndex()));
setRunningTaskViewShowScreenshot(false);
setRunningTaskHidden(runningTaskTileHidden);
@@ -2978,6 +3003,10 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo
}
}
private void setFocusedTaskViewId(int viewId) {
mFocusedTaskViewId = viewId;
}
private int getTaskViewIdFromTaskId(int taskId) {
TaskView taskView = getTaskViewByTaskId(taskId);
return taskView != null ? taskView.getTaskViewId() : -1;
@@ -3077,8 +3106,9 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo
float[] gridTranslations = new float[taskCount];
int focusedTaskIndex = Integer.MAX_VALUE;
Set<Integer> largeTasksIndices = new HashSet<>();
int focusedTaskShift = 0;
int focusedTaskWidthAndSpacing = 0;
int largeTaskWidthAndSpacing = 0;
int snappedTaskRowWidth = 0;
int snappedPage = isKeyboardTaskFocusPending() ? mKeyboardTaskFocusIndex : getNextPage();
TaskView snappedTaskView = getTaskViewAt(snappedPage);
@@ -3095,12 +3125,11 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo
// Evenly distribute tasks between rows unless rearranging due to task dismissal, in
// which case keep tasks in their respective rows. For the running task, don't join
// the grid.
if (taskView.isFocusedTask()) {
boolean isLargeTile = taskView.isLargeTile();
if (isLargeTile) {
topRowWidth += taskWidthAndSpacing;
bottomRowWidth += taskWidthAndSpacing;
focusedTaskIndex = i;
focusedTaskWidthAndSpacing = taskWidthAndSpacing;
gridTranslations[i] += focusedTaskShift;
gridTranslations[i] += mIsRtl ? taskWidthAndSpacing : -taskWidthAndSpacing;
@@ -3108,6 +3137,12 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo
taskView.setGridTranslationY((mLastComputedTaskSize.height() + taskTopMargin
- taskView.getLayoutParams().height) / 2f);
if (taskView.getTaskViewId() == mFocusedTaskViewId) {
focusedTaskIndex = i;
}
largeTasksIndices.add(i);
largeTaskWidthAndSpacing = taskWidthAndSpacing;
if (taskView == snappedTaskView) {
// If focused task is snapped, the row width is just task width and spacing.
snappedTaskRowWidth = taskWidthAndSpacing;
@@ -3116,7 +3151,7 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo
if (i > focusedTaskIndex) {
// For tasks after the focused task, shift by focused task's width and spacing.
gridTranslations[i] +=
mIsRtl ? focusedTaskWidthAndSpacing : -focusedTaskWidthAndSpacing;
mIsRtl ? largeTaskWidthAndSpacing : -largeTaskWidthAndSpacing;
} else {
// For task before the focused task, accumulate the width and spacing to
// calculate the distance focused task need to shift.
@@ -3152,7 +3187,7 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo
// Move horizontally into empty space.
float widthOffset = 0;
for (int j = i - 1; !topSet.contains(j) && j >= 0; j--) {
if (j == focusedTaskIndex) {
if (largeTasksIndices.contains(j)) {
continue;
}
widthOffset += requireTaskViewAt(j).getLayoutParams().width + mPageSpacing;
@@ -3171,7 +3206,7 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo
// Move horizontally into empty space.
float widthOffset = 0;
for (int j = i - 1; !bottomSet.contains(j) && j >= 0; j--) {
if (j == focusedTaskIndex) {
if (largeTasksIndices.contains(j)) {
continue;
}
widthOffset += requireTaskViewAt(j).getLayoutParams().width + mPageSpacing;
@@ -3221,6 +3256,16 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo
// accordingly. Update longRowWidth if ClearAllButton has been moved.
float clearAllShortTotalWidthTranslation = 0;
int longRowWidth = Math.max(topRowWidth, bottomRowWidth);
// If Recents contains only large task sizes, it should only consider 1 large size
// for ClearAllButton translation. The space at the left side of the large task will be
// empty and it should be move ClearAllButton further away as well.
// TODO(b/359573248): Validate the translation for ClearAllButton for grid only.
boolean hasOnlyLargeTasks = taskCount == largeTasksIndices.size();
if (enableLargeDesktopWindowingTile() && hasOnlyLargeTasks) {
longRowWidth = largeTaskWidthAndSpacing;
}
if (longRowWidth < mLastComputedGridSize.width()) {
mClearAllShortTotalWidthTranslation =
(mIsRtl
@@ -3241,10 +3286,10 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo
float clearAllTotalTranslationX =
clearAllAccumulatedTranslation + clearAllShorterRowCompensation
+ clearAllShortTotalWidthTranslation + snappedTaskNonGridScrollAdjustment;
if (focusedTaskIndex < taskCount) {
if (!largeTasksIndices.isEmpty()) {
// Shift by focused task's width and spacing if a task is focused.
clearAllTotalTranslationX +=
mIsRtl ? focusedTaskWidthAndSpacing : -focusedTaskWidthAndSpacing;
mIsRtl ? largeTaskWidthAndSpacing : -largeTaskWidthAndSpacing;
}
// Make sure there are enough space between snapped page and ClearAllButton, for the case
@@ -3284,7 +3329,6 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo
mClearAllButton.setGridScrollOffset(
mIsRtl ? mLastComputedTaskSize.left - mLastComputedGridSize.left
: mLastComputedTaskSize.right - mLastComputedGridSize.right);
setGridProgress(mGridProgress);
}
@@ -3292,11 +3336,11 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo
if (taskView1 == null || taskView2 == null) {
return false;
}
int taskViewId1 = taskView1.getTaskViewId();
int taskViewId2 = taskView2.getTaskViewId();
if (taskViewId1 == mFocusedTaskViewId || taskViewId2 == mFocusedTaskViewId) {
if (taskView1.isLargeTile() || taskView2.isLargeTile()) {
return false;
}
int taskViewId1 = taskView1.getTaskViewId();
int taskViewId2 = taskView2.getTaskViewId();
return (mTopRowIdSet.contains(taskViewId1) && mTopRowIdSet.contains(taskViewId2)) || (
!mTopRowIdSet.contains(taskViewId1) && !mTopRowIdSet.contains(taskViewId2));
}
@@ -3549,11 +3593,11 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo
isStagingFocusedTask = true;
} else {
nextFocusedTaskFromTop =
mTopRowIdSet.size() > 0 && mTopRowIdSet.size() >= (taskCount - 1) / 2f;
!mTopRowIdSet.isEmpty() && mTopRowIdSet.size() >= (taskCount - 1) / 2f;
// Pick the next focused task from the preferred row.
for (int i = 0; i < taskCount; i++) {
TaskView taskView = requireTaskViewAt(i);
if (taskView == dismissedTaskView) {
if (taskView == dismissedTaskView || taskView.isLargeTile()) {
continue;
}
boolean isTopRow = mTopRowIdSet.contains(taskView.getTaskViewId());
@@ -4017,9 +4061,9 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo
} else {
// Update focus task and its size.
if (finalIsFocusedTaskDismissed && finalNextFocusedTaskView != null) {
mFocusedTaskViewId = enableGridOnlyOverview()
setFocusedTaskViewId(enableGridOnlyOverview()
? INVALID_TASK_ID
: finalNextFocusedTaskView.getTaskViewId();
: finalNextFocusedTaskView.getTaskViewId());
mTopRowIdSet.remove(mFocusedTaskViewId);
finalNextFocusedTaskView.animateIconScaleAndDimIntoView();
}
@@ -4162,8 +4206,9 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo
IntArray bottomArray = new IntArray(bottomRowIdArraySize);
int taskViewCount = getTaskViewCount();
for (int i = 0; i < taskViewCount; i++) {
int taskViewId = requireTaskViewAt(i).getTaskViewId();
if (!mTopRowIdSet.contains(taskViewId) && taskViewId != mFocusedTaskViewId) {
TaskView taskView = requireTaskViewAt(i);
int taskViewId = taskView.getTaskViewId();
if (!mTopRowIdSet.contains(taskViewId) && !taskView.isLargeTile()) {
bottomArray.add(taskViewId);
}
}
@@ -4269,6 +4314,7 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo
}
// Init task grid nav helper with top/bottom id arrays.
// TODO(b/361070854): Add keyboard navigation for all large tiles.
TaskGridNavHelper taskGridNavHelper = new TaskGridNavHelper(getTopRowIdArray(),
getBottomRowIdArray(), mFocusedTaskViewId);
@@ -4597,9 +4643,10 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo
? (runningTask == null ? INVALID_PAGE : indexOfChild(runningTask))
: mOffsetMidpointIndexOverride;
int modalMidpoint = getCurrentPage();
boolean isModalGridWithoutFocusedTask =
showAsGrid && enableGridOnlyOverview() && mTaskModalness > 0;
if (isModalGridWithoutFocusedTask) {
boolean shouldCalculateOffsetForAllTasks = showAsGrid
&& (enableGridOnlyOverview() || enableLargeDesktopWindowingTile())
&& mTaskModalness > 0;
if (shouldCalculateOffsetForAllTasks) {
modalMidpoint = indexOfChild(mSelectedTask);
}
@@ -4638,7 +4685,7 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo
: i < midpoint
? leftOffsetSize
: rightOffsetSize;
if (isModalGridWithoutFocusedTask) {
if (shouldCalculateOffsetForAllTasks) {
gridOffsetSize = getHorizontalOffsetSize(i, modalMidpoint, modalOffset);
gridOffsetSize = Math.abs(gridOffsetSize) * (i <= modalMidpoint ? 1 : -1);
}
@@ -5244,10 +5291,7 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo
float toScale = getMaxScaleForFullScreen();
boolean showAsGrid = showAsGrid();
boolean zoomInTaskView = showAsGrid
? ((taskView.isFocusedTask() && isTaskViewFullyVisible(taskView))
|| taskView instanceof DesktopTaskView)
: taskIndex == centerTaskIndex;
boolean zoomInTaskView = showAsGrid ? taskView.isLargeTile() : taskIndex == centerTaskIndex;
if (zoomInTaskView) {
anim.play(ObjectAnimator.ofFloat(this, RECENTS_SCALE_PROPERTY, toScale));
anim.play(ObjectAnimator.ofFloat(this, FULLSCREEN_PROGRESS, 1));
@@ -5728,8 +5772,8 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo
}
private int getFirstViewIndex() {
TaskView focusedTaskView = mShowAsGridLastOnLayout ? getFocusedTaskView() : null;
return focusedTaskView != null ? indexOfChild(focusedTaskView) : 0;
TaskView firstTaskView = mShowAsGridLastOnLayout ? getFirstLargeTaskView() : null;
return firstTaskView != null ? indexOfChild(firstTaskView) : 0;
}
private int getLastViewIndex() {
@@ -5747,7 +5791,7 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo
}
// Returns focus task if there are no grid tasks.
return indexOfChild(getFocusedTaskView());
return indexOfChild(getFirstLargeTaskView());
}
/**
@@ -5963,7 +6007,7 @@ public abstract class RecentsView<CONTAINER_TYPE extends Context & RecentsViewCo
public boolean isOnGridBottomRow(TaskView taskView) {
return showAsGrid()
&& !mTopRowIdSet.contains(taskView.getTaskViewId())
&& taskView.getTaskViewId() != mFocusedTaskViewId;
&& !taskView.isLargeTile();
}
public Consumer<MotionEvent> getEventDispatcher(float navbarRotation) {
@@ -27,8 +27,8 @@ import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
/** Helper for [RecentsView] to interact with coroutine. */
class RecentsViewHelper(private val recentsViewModel: RecentsViewModel) {
/** Helper for [RecentsView] to interact with the [RecentsViewModel]. */
class RecentsViewModelHelper(private val recentsViewModel: RecentsViewModel) {
private lateinit var viewAttachedScope: CoroutineScope
fun onAttachedToWindow() {
@@ -43,7 +43,7 @@ class RecentsViewHelper(private val recentsViewModel: RecentsViewModel) {
fun switchToScreenshot(
taskView: TaskView,
recentsAnimationController: RecentsAnimationController,
onFinishRunnable: Runnable
onFinishRunnable: Runnable,
) {
val updatedThumbnails =
taskView.taskContainers.associate {
@@ -55,7 +55,7 @@ class RecentsViewHelper(private val recentsViewModel: RecentsViewModel) {
fun switchToScreenshot(
taskView: TaskView,
updatedThumbnails: Map<Int, ThumbnailData>?,
onFinishRunnable: Runnable
onFinishRunnable: Runnable,
) {
// Update recentsViewModel and apply the thumbnailOverride ASAP, before waiting inside
// viewAttachedScope.
@@ -99,7 +99,7 @@ class TaskMenuViewWithArrow<T> : ArrowPopup<T> where T : RecentsViewContainer, T
private var optionMeasuredHeight = 0
private val arrowHorizontalPadding: Int
get() =
if (taskView.isFocusedTask)
if (taskView.isLargeTile)
resources.getDimensionPixelSize(R.dimen.task_menu_horizontal_padding)
else 0
@@ -49,6 +49,7 @@ import com.android.launcher3.Flags.enableCursorHoverStates
import com.android.launcher3.Flags.enableFocusOutline
import com.android.launcher3.Flags.enableGridOnlyOverview
import com.android.launcher3.Flags.enableHoverOfChildElementsInTaskview
import com.android.launcher3.Flags.enableLargeDesktopWindowingTile
import com.android.launcher3.Flags.enableOverviewIconMenu
import com.android.launcher3.Flags.enableRefactorTaskThumbnail
import com.android.launcher3.R
@@ -108,7 +109,7 @@ constructor(
defStyleRes: Int = 0,
focusBorderAnimator: BorderAnimator? = null,
hoverBorderAnimator: BorderAnimator? = null,
type: TaskViewType = TaskViewType.SINGLE
private val type: TaskViewType = TaskViewType.SINGLE,
) : FrameLayout(context, attrs), ViewPool.Reusable {
/**
* Used in conjunction with [onTaskListVisibilityChanged], providing more granularity on which
@@ -133,13 +134,15 @@ constructor(
val isGridTask: Boolean
/** Returns whether the task is part of overview grid and not being focused. */
get() = container.deviceProfile.isTablet && !isFocusedTask
get() = container.deviceProfile.isTablet && !isLargeTile
val isRunningTask: Boolean
get() = this === recentsView?.runningTaskView
val isFocusedTask: Boolean
get() = this === recentsView?.focusedTaskView
val isLargeTile: Boolean
get() =
this == recentsView?.focusedTaskView ||
(enableLargeDesktopWindowingTile() && type == TaskViewType.DESKTOP)
val taskCornerRadius: Float
get() = currentFullscreenParams.cornerRadius
@@ -521,7 +524,7 @@ constructor(
public override fun onFocusChanged(
gainFocus: Boolean,
direction: Int,
previouslyFocusedRect: Rect?
previouslyFocusedRect: Rect?,
) {
super.onFocusChanged(gainFocus, direction, previouslyFocusedRect)
if (borderEnabled) {
@@ -682,7 +685,7 @@ constructor(
open fun bind(
task: Task,
orientedState: RecentsOrientedState,
taskOverlayFactory: TaskOverlayFactory
taskOverlayFactory: TaskOverlayFactory,
) {
cancelPendingLoadTasks()
@@ -707,7 +710,7 @@ constructor(
@IdRes iconViewId: Int,
@IdRes showWindowViewId: Int,
@StagePosition stagePosition: Int,
taskOverlayFactory: TaskOverlayFactory
taskOverlayFactory: TaskOverlayFactory,
): TaskContainer {
val thumbnailViewDeprecated: TaskThumbnailViewDeprecated = findViewById(thumbnailViewId)!!
val snapshotView =
@@ -777,7 +780,7 @@ constructor(
open fun updateTaskSize(
lastComputedTaskSize: Rect,
lastComputedGridTaskSize: Rect,
lastComputedCarouselTaskSize: Rect
lastComputedCarouselTaskSize: Rect,
) {
val thumbnailPadding = container.deviceProfile.overviewTaskThumbnailTopMarginPx
val taskWidth = lastComputedTaskSize.width()
@@ -789,9 +792,10 @@ constructor(
if (container.deviceProfile.isTablet) {
val boxWidth: Int
val boxHeight: Int
if (isFocusedTask) {
// Task will be focused and should use focused task size. Use focusTaskRatio
// that is associated with the original orientation of the focused task.
// Focused task and Desktop tasks should use focusTaskRatio that is associated
// with the original orientation of the focused task.
if (isLargeTile) {
boxWidth = taskWidth
boxHeight = taskHeight
} else {
@@ -1334,7 +1338,7 @@ constructor(
private fun computeAndSetIconTouchDelegate(
view: TaskViewIcon,
tempCenterCoordinates: FloatArray,
transformingTouchDelegate: TransformingTouchDelegate
transformingTouchDelegate: TransformingTouchDelegate,
) {
val viewHalfWidth = view.width / 2f
val viewHalfHeight = view.height / 2f