Merge "Move DesktopTask to front of RecentsView (1/2)" into main
This commit is contained in:
committed by
Android (Google) Code Review
commit
cbd92ce7e4
@@ -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"
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -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) {
|
||||
|
||||
+4
-4
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user