diff --git a/aconfig/launcher_overview.aconfig b/aconfig/launcher_overview.aconfig index 5749c517d3..7b1ebeed8f 100644 --- a/aconfig/launcher_overview.aconfig +++ b/aconfig/launcher_overview.aconfig @@ -110,3 +110,13 @@ flag { description: "Enable wallpaper background for desktop tasks in overview." bug: "363257721" } + +flag { + name: "enable_show_enabled_shortcuts_in_accessibility_menu" + namespace: "launcher_overview" + description: "Enables showing the same shortcuts in the Task menu as well as the accessibility actions menu" + bug: "383662632" + metadata { + purpose: PURPOSE_BUGFIX + } +} diff --git a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java index a594e49445..deb06c98d8 100644 --- a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java +++ b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java @@ -42,6 +42,7 @@ import com.android.launcher3.popup.SystemShortcut; import com.android.launcher3.util.ResourceBasedOverride; import com.android.launcher3.views.ActivityContext; import com.android.launcher3.views.Snackbar; +import com.android.quickstep.task.thumbnail.TaskOverlayUiState; import com.android.quickstep.task.util.TaskOverlayHelper; import com.android.quickstep.util.RecentsOrientedState; import com.android.quickstep.views.DesktopTaskView; @@ -168,9 +169,32 @@ public class TaskOverlayFactory implements ResourceBasedOverride { : mTaskContainer.getThumbnailViewDeprecated().getThumbnail(); } - protected boolean isRealSnapshot() { - return enableRefactorTaskThumbnail() ? mHelper.getEnabledState().isRealSnapshot() - : mTaskContainer.getThumbnailViewDeprecated().isRealSnapshot(); + /** + * Returns whether the snapshot is real. If the device is locked for the user of the task, + * the snapshot used will be an app-theme generated snapshot instead of a real snapshot. + */ + public boolean isRealSnapshot() { + if (enableRefactorTaskThumbnail()) { + if (mHelper.getUiState() instanceof TaskOverlayUiState.Enabled) { + return mHelper.getEnabledState().isRealSnapshot(); + } else { + return false; + } + } + + return mTaskContainer.getThumbnailViewDeprecated().isRealSnapshot(); + } + + /** + * Returns whether the snapshot is rotated compared to the current task orientation. + */ + public boolean isThumbnailRotationDifferentFromTask() { + if (enableRefactorTaskThumbnail()) { + return mHelper.getThumbnailPositionState().isRotated(); + } + + return mTaskContainer.getThumbnailViewDeprecated() + .isThumbnailRotationDifferentFromTask(); } protected T getActionsView() { @@ -359,13 +383,10 @@ public class TaskOverlayFactory implements ResourceBasedOverride { private class ScreenshotSystemShortcut extends SystemShortcut { - private final RecentsViewContainer mContainer; - ScreenshotSystemShortcut(RecentsViewContainer container, ItemInfo itemInfo, View originalView) { super(R.drawable.ic_screenshot, R.string.action_screenshot, container, itemInfo, originalView); - mContainer = container; } @Override diff --git a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java index f92581e117..bc46ace741 100644 --- a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java +++ b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java @@ -20,7 +20,9 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS; import static android.view.Surface.ROTATION_0; +import static com.android.launcher3.Flags.enableGridOnlyOverview; import static com.android.launcher3.Flags.enableRefactorTaskThumbnail; +import static com.android.launcher3.Flags.enableShowEnabledShortcutsInAccessibilityMenu; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_CLOSE_APP_TAP; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SYSTEM_SHORTCUT_FREE_FORM_TAP; import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT; @@ -42,7 +44,6 @@ import android.window.SplashScreen; import androidx.annotation.Nullable; import com.android.launcher3.DeviceProfile; -import com.android.launcher3.Flags; import com.android.launcher3.R; import com.android.launcher3.logging.StatsLogManager.LauncherEvent; import com.android.launcher3.model.WellbeingModel; @@ -345,15 +346,20 @@ public interface TaskShortcutFactory { boolean isTaskSplitNotSupported = !task.isDockable || (intentFlags & FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) != 0; boolean hideForExistingMultiWindow = container.getDeviceProfile().isMultiWindowMode; - boolean isLargeTile = deviceProfile.isTablet && taskView.isLargeTile(); - boolean isTaskInExpectedScrollPosition = - recentsView.isTaskInExpectedScrollPosition(taskView); - if (notEnoughTasksToSplit || isTaskSplitNotSupported || hideForExistingMultiWindow - || (isLargeTile && isTaskInExpectedScrollPosition)) { + if (notEnoughTasksToSplit || isTaskSplitNotSupported || hideForExistingMultiWindow) { return null; } + if (!enableShowEnabledShortcutsInAccessibilityMenu()) { + boolean isLargeTile = deviceProfile.isTablet && taskView.isLargeTile(); + boolean isTaskInExpectedScrollPosition = + recentsView.isTaskInExpectedScrollPosition(taskView); + if (isLargeTile && isTaskInExpectedScrollPosition) { + return null; + } + } + return orientationHandler.getSplitPositionOptions(deviceProfile) .stream() .map((Function) option -> @@ -500,16 +506,23 @@ public interface TaskShortcutFactory { @Override public List getShortcuts(RecentsViewContainer container, TaskContainer taskContainer) { - boolean isTablet = container.getDeviceProfile().isTablet; - boolean isGridOnlyOverview = isTablet && Flags.enableGridOnlyOverview(); - // Extra conditions if it's not grid-only overview - if (!isGridOnlyOverview) { - RecentsOrientedState orientedState = taskContainer.getTaskView().getOrientedState(); - boolean isFakeLandscape = !orientedState.isRecentsActivityRotationAllowed() - && orientedState.getTouchRotation() != ROTATION_0; - if (!isFakeLandscape) { + if (enableShowEnabledShortcutsInAccessibilityMenu()) { + if (!taskContainer.getOverlay().isRealSnapshot()) { return null; } + } else { + boolean isTablet = container.getDeviceProfile().isTablet; + boolean isGridOnlyOverview = isTablet && enableGridOnlyOverview(); + // Extra conditions if it's not grid-only overview + if (!isGridOnlyOverview) { + RecentsOrientedState orientedState = taskContainer.getTaskView() + .getOrientedState(); + boolean isFakeLandscape = !orientedState.isRecentsActivityRotationAllowed() + && orientedState.getTouchRotation() != ROTATION_0; + if (!isFakeLandscape) { + return null; + } + } } SystemShortcut screenshotShortcut = taskContainer.getOverlay().getScreenshotShortcut( @@ -527,10 +540,39 @@ public interface TaskShortcutFactory { @Override public List getShortcuts(RecentsViewContainer container, TaskContainer taskContainer) { - boolean isTablet = container.getDeviceProfile().isTablet; - boolean isGridOnlyOverview = isTablet && Flags.enableGridOnlyOverview(); - if (!isGridOnlyOverview) { - return null; + if (enableShowEnabledShortcutsInAccessibilityMenu()) { + if (!taskContainer.getOverlay().isRealSnapshot()) { + return null; + } + + // Modal only works with grid size tiles with enableGridOnlyOverview enabled on + // tablets / foldables. With enableGridOnlyOverview off, for large tiles it works, + // but the tile needs to be in the center of Recents / Overview. + boolean isTablet = container.getDeviceProfile().isTablet; + RecentsView recentsView = container.getOverviewPanel(); + boolean isLargeTileInCenterOfOverview = taskContainer.getTaskView().isLargeTile() + && recentsView.isFocusedTaskInExpectedScrollPosition(); + if (isTablet + && !isLargeTileInCenterOfOverview + && !enableGridOnlyOverview()) { + return null; + } + + boolean isFakeLandscape = !taskContainer.getTaskView().getPagedOrientationHandler() + .isLayoutNaturalToLauncher(); + if (isFakeLandscape) { + return null; + } + + if (taskContainer.getOverlay().isThumbnailRotationDifferentFromTask()) { + return null; + } + } else { + boolean isTablet = container.getDeviceProfile().isTablet; + boolean isGridOnlyOverview = isTablet && enableGridOnlyOverview(); + if (!isGridOnlyOverview) { + return null; + } } SystemShortcut modalStateSystemShortcut = diff --git a/quickstep/src/com/android/quickstep/task/util/TaskOverlayHelper.kt b/quickstep/src/com/android/quickstep/task/util/TaskOverlayHelper.kt index f51660bd70..622663db0f 100644 --- a/quickstep/src/com/android/quickstep/task/util/TaskOverlayHelper.kt +++ b/quickstep/src/com/android/quickstep/task/util/TaskOverlayHelper.kt @@ -46,7 +46,7 @@ class TaskOverlayHelper(val task: Task, val overlay: TaskOverlayFactory.TaskOver private val recentsCoroutineScope: CoroutineScope = RecentsDependencies.get() private val dispatcherProvider: DispatcherProvider = RecentsDependencies.get() private lateinit var overlayInitializedScope: CoroutineScope - private var uiState: TaskOverlayUiState = Disabled + var uiState: TaskOverlayUiState = Disabled private lateinit var viewModel: TaskOverlayViewModel @@ -60,7 +60,7 @@ class TaskOverlayHelper(val task: Task, val overlay: TaskOverlayFactory.TaskOver fun getThumbnailMatrix() = getThumbnailPositionState().matrix - private fun getThumbnailPositionState() = + fun getThumbnailPositionState() = viewModel.getThumbnailPositionState( overlay.snapshotView.width, overlay.snapshotView.height, diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index 6b91df1b95..85310bc61c 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -1578,7 +1578,10 @@ public abstract class RecentsView< == getPagedOrientationHandler().getPrimaryScroll(this); } - private boolean isFocusedTaskInExpectedScrollPosition() { + /** + * Returns true if the focused TaskView is in expected scroll position. + */ + public boolean isFocusedTaskInExpectedScrollPosition() { TaskView focusedTask = getFocusedTaskView(); return focusedTask != null && isTaskInExpectedScrollPosition(focusedTask); } diff --git a/quickstep/src/com/android/quickstep/views/TaskThumbnailViewDeprecated.java b/quickstep/src/com/android/quickstep/views/TaskThumbnailViewDeprecated.java index 5ee5e10424..74d76e6432 100644 --- a/quickstep/src/com/android/quickstep/views/TaskThumbnailViewDeprecated.java +++ b/quickstep/src/com/android/quickstep/views/TaskThumbnailViewDeprecated.java @@ -412,7 +412,12 @@ public class TaskThumbnailViewDeprecated extends View implements ViewPool.Reusab thumbnailDataAspect, MAX_PCT_BEFORE_ASPECT_RATIOS_CONSIDERED_DIFFERENT); } - private boolean isThumbnailRotationDifferentFromTask() { + /** + * Returns whether or not the current thumbnail is a different orientation to the task. + *

+ * Used to disable modal state when screenshot doesn't match the device orientation. + */ + public boolean isThumbnailRotationDifferentFromTask() { RecentsView recents = mTaskView.getRecentsView(); if (recents == null || mThumbnailData == null) { return false;