From 843a881e7c70eef58246da24f8f226e72396b401 Mon Sep 17 00:00:00 2001 From: Alex Chau Date: Fri, 14 Mar 2025 16:52:05 +0000 Subject: [PATCH] Update scale on TaskView instead for select mode - Avoid zooming in RecentsView in Select mode, instead zoom in the selected TaskView only to avoid changing RecentsView's scale and pivot, otherwise when doing home gesture in Select mode RecentseView zoom will be distorted - Set taskModalness on all TaskViews, so they can fade out while entering Select mode, this avoid janky transitionig of non-selected TaskView appearing during hoem gesture - Keep overviewGridEnabled true until transitioning out of a RecentsView visible state, so showAsGrid() remains true and the Overview grid won't deform midway through animating - When leaving Select mode to RecentsView invisible state (e.g. Home), leave taskModalness 1 until the last frame so selected TaskView remains zoomed in until RecentsView is invisible Fix: 322818393 Test: OverviewTaskSelectImageTest Test: Repeat with combination of default/fallback, live/static tile, handheld/tablet 1) Swipe up from Overview 2) Swipe up from Select to go Home 3) Backc/cross button to exit Select to Overview Flag: com.android.launcher3.enable_grid_only_overview Change-Id: I8fec62315cbd404502852654772edb1d695f1ec6 --- .../uioverrides/RecentsViewStateController.kt | 7 +- .../states/OverviewModalTaskState.java | 7 +- .../FallbackRecentsStateController.java | 5 +- .../fallback/FallbackRecentsView.java | 15 +++- .../quickstep/fallback/RecentsState.java | 4 ++ .../quickstep/views/LauncherRecentsView.java | 15 +++- .../android/quickstep/views/RecentsView.java | 55 ++++++++------- .../quickstep/views/RecentsViewUtils.kt | 45 ++++++++++++ .../com/android/quickstep/views/TaskView.kt | 70 ++++++++++++++----- 9 files changed, 175 insertions(+), 48 deletions(-) diff --git a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.kt b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.kt index 23dc81d4e6..c9f791c6ee 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.kt +++ b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.kt @@ -21,6 +21,7 @@ import com.android.app.animation.Interpolators.FINAL_FRAME import com.android.app.animation.Interpolators.INSTANT import com.android.app.animation.Interpolators.LINEAR import com.android.launcher3.Flags.enableDesktopExplodedView +import com.android.launcher3.Flags.enableGridOnlyOverview import com.android.launcher3.Flags.enableLargeDesktopWindowingTile import com.android.launcher3.LauncherState import com.android.launcher3.anim.AnimatedFloat @@ -143,7 +144,11 @@ class RecentsViewStateController(private val launcher: QuickstepLauncher) : recentsView, TASK_MODALNESS, toState.overviewModalness, - config.getInterpolator(ANIM_OVERVIEW_MODAL, LINEAR), + config.getInterpolator( + ANIM_OVERVIEW_MODAL, + if (enableGridOnlyOverview() && !toState.isRecentsViewVisible) FINAL_FRAME + else LINEAR, + ), ) val fromState = launcher.stateManager.state diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java index 0c0b4fd203..ae82f82c01 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java +++ b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java @@ -15,11 +15,11 @@ */ package com.android.launcher3.uioverrides.states; +import static com.android.launcher3.Flags.enableGridOnlyOverview; import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_OVERVIEW; import android.graphics.Rect; -import com.android.launcher3.Flags; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherState; import com.android.launcher3.views.ActivityContext; @@ -50,6 +50,9 @@ public class OverviewModalTaskState extends OverviewState { @Override public float[] getOverviewScaleAndOffset(Launcher launcher) { + if (enableGridOnlyOverview()) { + return super.getOverviewScaleAndOffset(launcher); + } return getOverviewScaleAndOffsetForModalState(launcher.getOverviewPanel()); } @@ -65,7 +68,7 @@ public class OverviewModalTaskState extends OverviewState { @Override public boolean isTaskbarStashed(Launcher launcher) { - if (Flags.enableGridOnlyOverview()) { + if (enableGridOnlyOverview()) { return true; } return super.isTaskbarStashed(launcher); diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java index 554cea262f..7db1813a90 100644 --- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java +++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java @@ -19,6 +19,7 @@ import static com.android.app.animation.Interpolators.FINAL_FRAME; import static com.android.app.animation.Interpolators.INSTANT; import static com.android.app.animation.Interpolators.LINEAR; import static com.android.launcher3.Flags.enableDesktopExplodedView; +import static com.android.launcher3.Flags.enableGridOnlyOverview; import static com.android.launcher3.Flags.enableLargeDesktopWindowingTile; import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_MODAL; import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE; @@ -118,7 +119,9 @@ public class FallbackRecentsStateController implements StateHandler { @Override public float[] getOverviewScaleAndOffset(RecentsViewContainer container) { + if (enableGridOnlyOverview()) { + return super.getOverviewScaleAndOffset(container); + } return getOverviewScaleAndOffsetForModalState(container.getOverviewPanel()); } } diff --git a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java index 74de2aca7b..c1282b945a 100644 --- a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java +++ b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java @@ -18,6 +18,7 @@ package com.android.quickstep.views; import static android.app.ActivityTaskManager.INVALID_TASK_ID; import static android.window.DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_WALLPAPER_ACTIVITY; +import static com.android.launcher3.Flags.enableGridOnlyOverview; import static com.android.launcher3.LauncherState.CLEAR_ALL_BUTTON; import static com.android.launcher3.LauncherState.ADD_DESK_BUTTON; import static com.android.launcher3.LauncherState.NORMAL; @@ -151,7 +152,14 @@ public class LauncherRecentsView extends RecentsView> CONTENT_ALPHA = @@ -534,7 +534,6 @@ public abstract class RecentsView< protected final Rect mLastComputedTaskSize = new Rect(); protected final Rect mLastComputedGridSize = new Rect(); protected final Rect mLastComputedGridTaskSize = new Rect(); - private TaskView mSelectedTask = null; // How much a task that is directly offscreen will be pushed out due to RecentsView scale/pivot. @Nullable protected Float mLastComputedTaskStartPushOutDistance = null; @@ -2418,21 +2417,28 @@ public abstract class RecentsView< } /** - * Sets the last TaskView selected. + * Returns the currently selected TaskView in Select mode. + */ + @Nullable + public TaskView getSelectedTaskView() { + return mUtils.getSelectedTaskView(); + } + + /** + * Sets the selected TaskView in Select mode. */ public void setSelectedTask(int lastSelectedTaskId) { - mSelectedTask = getTaskViewByTaskId(lastSelectedTaskId); + mUtils.setSelectedTaskView(getTaskViewByTaskId(lastSelectedTaskId)); } /** * Returns the bounds of the task selected to enter modal state. */ public Rect getSelectedTaskBounds() { - if (mSelectedTask == null) { - return enableGridOnlyOverview() && mContainer.getDeviceProfile().isTablet - ? mLastComputedGridTaskSize : mLastComputedTaskSize; + if (getSelectedTaskView() == null) { + return mLastComputedTaskSize; } - return getTaskBounds(mSelectedTask); + return getTaskBounds(getSelectedTaskView()); } /** @@ -2448,7 +2454,7 @@ public abstract class RecentsView< return deviceProfile.overviewTaskThumbnailTopMarginPx / 2.0f; } - private Rect getTaskBounds(TaskView taskView) { + protected Rect getTaskBounds(TaskView taskView) { int selectedPage = indexOfChild(taskView); int primaryScroll = getPagedOrientationHandler().getPrimaryScroll(this); int selectedPageScroll = getScrollForPage(selectedPage); @@ -5011,15 +5017,8 @@ public abstract class RecentsView< } private void updatePivots() { - if (mOverviewSelectEnabled) { - if (enableGridOnlyOverview()) { - getModalTaskSize(mTempRect); - Rect selectedTaskPosition = getSelectedTaskBounds(); - Utilities.getPivotsForScalingRectToRect(mTempRect, selectedTaskPosition, - mTempPointF); - } else { - mTempPointF.set(mLastComputedTaskSize.centerX(), mLastComputedTaskSize.bottom); - } + if (mOverviewSelectEnabled && !enableGridOnlyOverview()) { + mTempPointF.set(mLastComputedTaskSize.centerX(), mLastComputedTaskSize.bottom); } else { mTempRect.set(mLastComputedTaskSize); getPagedViewOrientedState().getFullScreenScaleAndPivot(mTempRect, @@ -5065,7 +5064,7 @@ public abstract class RecentsView< && (enableGridOnlyOverview() || enableLargeDesktopWindowingTile()) && mTaskModalness > 0; if (shouldCalculateOffsetForAllTasks) { - modalMidpoint = indexOfChild(mSelectedTask); + modalMidpoint = indexOfChild(getSelectedTaskView()); } float midpointOffsetSize = 0; @@ -5273,7 +5272,7 @@ public abstract class RecentsView< */ private float getVerticalOffsetSize(TaskView taskView, float offsetProgress) { if (offsetProgress == 0 || !(showAsGrid() && enableGridOnlyOverview()) - || mSelectedTask == null) { + || getSelectedTaskView() == null) { // Don't bother calculating everything below if we won't offset vertically. return 0; } @@ -5281,7 +5280,7 @@ public abstract class RecentsView< // First, get the position of the task relative to the top row. Rect taskPosition = getTaskBounds(taskView); - boolean isSelectedTaskTopRow = mTopRowIdSet.contains(mSelectedTask.getTaskViewId()); + boolean isSelectedTaskTopRow = mTopRowIdSet.contains(getSelectedTaskView().getTaskViewId()); boolean isChildTopRow = mTopRowIdSet.contains(taskView.getTaskViewId()); // Whether the task should be shifted to the top. boolean isTopShift = !isSelectedTaskTopRow && isChildTopRow; @@ -5335,8 +5334,8 @@ public abstract class RecentsView< * Resets the visuals when exit modal state. */ public void resetModalVisuals() { - if (mSelectedTask != null) { - mSelectedTask.taskContainers.forEach( + if (getSelectedTaskView() != null) { + getSelectedTaskView().taskContainers.forEach( taskContainer -> taskContainer.getOverlay().resetModalVisuals()); } } @@ -6717,8 +6716,14 @@ public abstract class RecentsView< private void setTaskModalness(float modalness) { mTaskModalness = modalness; updatePageOffsets(); - if (mSelectedTask != null) { - mSelectedTask.setModalness(modalness); + if (getSelectedTaskView() != null) { + if (enableGridOnlyOverview()) { + for (TaskView taskView : getTaskViews()) { + taskView.setModalness(modalness); + } + } else { + getSelectedTaskView().setModalness(modalness); + } } else if (getCurrentPageTaskView() != null) { getCurrentPageTaskView().setModalness(modalness); } diff --git a/quickstep/src/com/android/quickstep/views/RecentsViewUtils.kt b/quickstep/src/com/android/quickstep/views/RecentsViewUtils.kt index 9c35913841..51a5d0f0d6 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsViewUtils.kt +++ b/quickstep/src/com/android/quickstep/views/RecentsViewUtils.kt @@ -16,6 +16,7 @@ package com.android.quickstep.views +import android.graphics.PointF import android.graphics.Rect import android.util.FloatProperty import android.view.KeyEvent @@ -25,9 +26,11 @@ import android.view.View.LAYOUT_DIRECTION_RTL import androidx.core.view.children import com.android.launcher3.AbstractFloatingView.TYPE_TASK_MENU import com.android.launcher3.AbstractFloatingView.getTopOpenViewWithType +import com.android.launcher3.Flags.enableGridOnlyOverview import com.android.launcher3.Flags.enableLargeDesktopWindowingTile import com.android.launcher3.Flags.enableOverviewIconMenu import com.android.launcher3.Flags.enableSeparateExternalDisplayTasks +import com.android.launcher3.Utilities.getPivotsForScalingRectToRect import com.android.launcher3.statehandlers.DesktopVisibilityController import com.android.launcher3.statehandlers.DesktopVisibilityController.Companion.INACTIVE_DESK_ID import com.android.launcher3.util.IntArray @@ -38,6 +41,7 @@ import com.android.quickstep.util.isExternalDisplay import com.android.quickstep.views.RecentsView.RUNNING_TASK_ATTACH_ALPHA import com.android.systemui.shared.recents.model.ThumbnailData import java.util.function.BiConsumer +import kotlin.math.min import kotlin.reflect.KMutableProperty1 /** @@ -393,6 +397,47 @@ class RecentsViewUtils(private val recentsView: RecentsView<*, *>) { taskViews.filterIsInstance().forEach { it.explodeProgress = field } } + var selectedTaskView: TaskView? = null + set(newValue) { + val oldValue = field + field = newValue + if (oldValue != newValue) { + onSelectedTaskViewUpdated(oldValue, newValue) + } + } + + private fun onSelectedTaskViewUpdated( + oldSelectedTaskView: TaskView?, + newSelectedTaskView: TaskView?, + ) { + if (!enableGridOnlyOverview()) return + with(recentsView) { + oldSelectedTaskView?.modalScale = 1f + oldSelectedTaskView?.modalPivot = null + + if (newSelectedTaskView == null) return + + val modalTaskBounds = mTempRect + getModalTaskSize(modalTaskBounds) + val selectedTaskBounds = getTaskBounds(newSelectedTaskView) + + // Map bounds to selectedTaskView's coordinate system. + modalTaskBounds.offset(-selectedTaskBounds.left, -selectedTaskBounds.top) + selectedTaskBounds.offset(-selectedTaskBounds.left, -selectedTaskBounds.top) + + val modalScale = + min( + (modalTaskBounds.height().toFloat() / selectedTaskBounds.height()), + (modalTaskBounds.width().toFloat() / selectedTaskBounds.width()), + ) + val modalPivot = PointF() + getPivotsForScalingRectToRect(modalTaskBounds, selectedTaskBounds, modalPivot) + + newSelectedTaskView.modalScale = modalScale + newSelectedTaskView.modalPivot = modalPivot + } + } + companion object { class RecentsViewFloatProperty( private val utilsProperty: KMutableProperty1 diff --git a/quickstep/src/com/android/quickstep/views/TaskView.kt b/quickstep/src/com/android/quickstep/views/TaskView.kt index 3d1643cefe..3835e48a9e 100644 --- a/quickstep/src/com/android/quickstep/views/TaskView.kt +++ b/quickstep/src/com/android/quickstep/views/TaskView.kt @@ -33,6 +33,7 @@ import android.util.Log import android.view.Display import android.view.MotionEvent import android.view.View +import android.view.View.OnClickListener import android.view.ViewGroup import android.view.ViewStub import android.view.accessibility.AccessibilityNodeInfo @@ -147,6 +148,9 @@ constructor( val isRunningTask: Boolean get() = this === recentsView?.runningTaskView + private val isSelectedTask: Boolean + get() = this === recentsView?.selectedTaskView + open val displayId: Int get() = taskContainers.firstOrNull()?.task.displayId @@ -337,6 +341,12 @@ constructor( onModalnessUpdated(field) } + var modalPivot: PointF? = null + set(value) { + field = value + updatePivots() + } + var splitSplashAlpha = 0f set(value) { field = value @@ -361,6 +371,12 @@ constructor( applyScale() } + var modalScale = 1f + set(value) { + field = value + applyScale() + } + private var dismissTranslationX = 0f set(value) { field = value @@ -446,9 +462,10 @@ constructor( } private val taskViewAlpha = MultiValueAlpha(this, Alpha.entries.size) - protected var stableAlpha by MultiPropertyDelegate(taskViewAlpha, Alpha.STABLE) - var attachAlpha by MultiPropertyDelegate(taskViewAlpha, Alpha.ATTACH) - var splitAlpha by MultiPropertyDelegate(taskViewAlpha, Alpha.SPLIT) + protected var stableAlpha by MultiPropertyDelegate(taskViewAlpha, Alpha.Stable) + var attachAlpha by MultiPropertyDelegate(taskViewAlpha, Alpha.Attach) + var splitAlpha by MultiPropertyDelegate(taskViewAlpha, Alpha.Split) + private var modalAlpha by MultiPropertyDelegate(taskViewAlpha, Alpha.Modal) protected var shouldShowScreenshot = false get() = !isRunningTask || field @@ -628,14 +645,7 @@ constructor( override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) { super.onLayout(changed, left, top, right, bottom) - val thumbnailTopMargin = container.deviceProfile.overviewTaskThumbnailTopMarginPx - if (container.deviceProfile.isTablet) { - pivotX = (if (layoutDirection == LAYOUT_DIRECTION_RTL) 0 else right - left).toFloat() - pivotY = thumbnailTopMargin.toFloat() - } else { - pivotX = (right - left) * 0.5f - pivotY = thumbnailTopMargin + (height - thumbnailTopMargin) * 0.5f - } + updatePivots() systemGestureExclusionRects = SYSTEM_GESTURE_EXCLUSION_RECT.onEach { it.right = width @@ -646,6 +656,24 @@ constructor( } } + private fun updatePivots() { + val modalPivot = modalPivot + if (modalPivot != null) { + pivotX = modalPivot.x + pivotY = modalPivot.y + } else { + val thumbnailTopMargin = container.deviceProfile.overviewTaskThumbnailTopMarginPx + if (container.deviceProfile.isTablet) { + pivotX = + (if (layoutDirection == LAYOUT_DIRECTION_RTL) 0 else right - left).toFloat() + pivotY = thumbnailTopMargin.toFloat() + } else { + pivotX = (right - left) * 0.5f + pivotY = thumbnailTopMargin + (height - thumbnailTopMargin) * 0.5f + } + } + } + override fun onRecycle() { resetPersistentViewTransforms() @@ -653,6 +681,9 @@ constructor( attachAlpha = 1f splitAlpha = 1f splitSplashAlpha = 0f + modalAlpha = 1f + modalScale = 1f + modalPivot = null taskThumbnailSplashAlpha = 0f // Clear any references to the thumbnail (it will be re-read either from the cache or the // system on next bind) @@ -1286,7 +1317,7 @@ constructor( targets.apps, targets.wallpapers, targets.nonApps, - true /* launcherClosing */, + true, /* launcherClosing */ recentsView.stateManager, recentsView, recentsView.depthController, @@ -1722,7 +1753,7 @@ constructor( fun getSizeAdjustment(fullscreenEnabled: Boolean) = if (fullscreenEnabled) nonGridScale else 1f private fun applyScale() { - val scale = persistentScale * dismissScale + val scale = persistentScale * dismissScale * Utilities.mapRange(modalness, 1f, modalScale) scaleX = scale scaleY = scale updateFullscreenParams() @@ -1784,9 +1815,13 @@ constructor( private fun onModalnessUpdated(modalness: Float) { isClickable = modalness == 0f taskContainers.forEach { - it.iconView.setModalAlpha(1 - modalness) + it.iconView.setModalAlpha(1f - modalness) it.digitalWellBeingToast?.bannerOffsetPercentage = modalness } + if (enableGridOnlyOverview()) { + modalAlpha = if (isSelectedTask) 1f else (1f - modalness) + applyScale() + } } fun resetPersistentViewTransforms() { @@ -1842,9 +1877,10 @@ constructor( private const val TAG = "TaskView" private enum class Alpha { - STABLE, - ATTACH, - SPLIT, + Stable, + Attach, + Split, + Modal, } private enum class SettledProgress {