Merge "Migrate ENABLE_SPLIT_FROM_FULLSCREEN_WITH_KEYBOARD_SHORTCUTS to aconfig" into main
diff --git a/quickstep/res/layout/overview_actions_container.xml b/quickstep/res/layout/overview_actions_container.xml
index 0fda0bf..fe517fa 100644
--- a/quickstep/res/layout/overview_actions_container.xml
+++ b/quickstep/res/layout/overview_actions_container.xml
@@ -31,7 +31,7 @@
android:layout_height="1dp"
android:layout_weight="1" />
- <Button
+ <com.android.quickstep.views.ScreenshotActionButton
android:id="@+id/action_screenshot"
style="@style/OverviewActionButton"
android:layout_width="wrap_content"
@@ -40,17 +40,12 @@
android:text="@string/action_screenshot"
android:theme="@style/ThemeControlHighlightWorkspaceColor" />
- <Space
- android:id="@+id/action_split_space"
- android:layout_width="@dimen/overview_actions_button_spacing"
- android:layout_height="1dp"
- android:visibility="gone" />
-
- <Button
+ <com.android.quickstep.views.SplitActionButton
android:id="@+id/action_split"
style="@style/OverviewActionButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:layout_marginStart="@dimen/overview_actions_button_spacing"
android:text="@string/action_split"
android:theme="@style/ThemeControlHighlightWorkspaceColor"
android:visibility="gone" />
diff --git a/quickstep/src/com/android/quickstep/views/ActionButton.kt b/quickstep/src/com/android/quickstep/views/ActionButton.kt
new file mode 100644
index 0000000..5c004cc
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/views/ActionButton.kt
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2023 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.views
+
+import android.content.Context
+import android.util.AttributeSet
+import android.widget.Button
+
+/**
+ * A button on the Overview Actions Bar. Custom logic for hiding/showing each button type is handled
+ * in the respective subclass.
+ */
+open class ActionButton : Button {
+ private var mHiddenFlags = 0
+
+ constructor(context: Context) : super(context)
+ constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
+ constructor(
+ context: Context,
+ attrs: AttributeSet?,
+ defStyleAttr: Int
+ ) : super(context, attrs, defStyleAttr)
+
+ /**
+ * Updates the proper flags to indicate whether the button should be hidden.
+ *
+ * @param flag The flag to update.
+ * @param enable Whether to enable the hidden flag: True will cause view to be hidden.
+ */
+ protected fun updateHiddenFlags(flag: Int, enable: Boolean) {
+ if (enable) {
+ mHiddenFlags = mHiddenFlags or flag
+ } else {
+ mHiddenFlags = mHiddenFlags and flag.inv()
+ }
+ val shouldBeVisible = mHiddenFlags == 0
+ this.visibility = if (shouldBeVisible) VISIBLE else GONE
+ }
+
+ /** Show/hide the button when the focused task is a single/pair. */
+ open fun updateForMultipleTasks(hasMultipleTasks: Boolean) {
+ // overridden in subclass, or else don't do anything
+ }
+
+ /** Show/hide the button depending on if the device is a tablet. */
+ open fun updateForTablet(isTablet: Boolean) {
+ // overridden in subclass, or else don't do anything
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
index 7f1d619..8692e4e 100644
--- a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
+++ b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
@@ -22,7 +22,6 @@
import android.util.AttributeSet;
import android.view.View;
import android.view.View.OnClickListener;
-import android.widget.Button;
import android.widget.FrameLayout;
import androidx.annotation.IntDef;
@@ -41,6 +40,8 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.List;
/**
* View for showing action buttons in Overview
@@ -89,14 +90,11 @@
private static final int INDEX_SCROLL_ALPHA = 5;
private static final int NUM_ALPHAS = 6;
- public @interface SplitButtonHiddenFlags { }
- public static final int FLAG_IS_NOT_TABLET = 1 << 0;
-
- public @interface SplitButtonDisabledFlags { }
- public static final int FLAG_SINGLE_TASK = 1 << 0;
-
private MultiValueAlpha mMultiValueAlpha;
- private Button mSplitButton;
+
+ private List<ActionButton> mActionButtons = new ArrayList<>();
+ private ScreenshotActionButton mScreenshotButton;
+ private SplitActionButton mSplitButton;
@ActionsHiddenFlags
private int mHiddenFlags;
@@ -104,12 +102,6 @@
@ActionsDisabledFlags
protected int mDisabledFlags;
- @SplitButtonHiddenFlags
- private int mSplitButtonHiddenFlags;
-
- @SplitButtonDisabledFlags
- private int mSplitButtonDisabledFlags;
-
@Nullable
protected T mCallbacks;
@@ -135,9 +127,12 @@
mMultiValueAlpha = new MultiValueAlpha(findViewById(R.id.action_buttons), NUM_ALPHAS);
mMultiValueAlpha.setUpdateVisibility(true);
- findViewById(R.id.action_screenshot).setOnClickListener(this);
+ mScreenshotButton = findViewById(R.id.action_screenshot);
+ mScreenshotButton.setOnClickListener(this);
+ mActionButtons.add(mScreenshotButton);
mSplitButton = findViewById(R.id.action_split);
mSplitButton.setOnClickListener(this);
+ mActionButtons.add(mSplitButton);
}
/**
@@ -201,40 +196,28 @@
}
boolean isEnabled = (mDisabledFlags & ~DISABLED_ROTATED) == 0;
LayoutUtils.setViewEnabled(this, isEnabled);
- updateSplitButtonEnabledState();
}
/**
- * Updates the proper flags to indicate whether the "Split screen" button should be hidden.
- *
- * @param flag The flag to update.
- * @param enable Whether to enable the hidden flag: True will cause view to be hidden.
+ * Updates flags to hide and show actions buttons when a grouped task (split screen) is focused.
+ * @param isGroupedTask True if the focused task is a grouped task.
*/
- public void updateSplitButtonHiddenFlags(@SplitButtonHiddenFlags int flag, boolean enable) {
- if (enable) {
- mSplitButtonHiddenFlags |= flag;
- } else {
- mSplitButtonHiddenFlags &= ~flag;
+ public void updateForGroupedTask(boolean isGroupedTask) {
+ for (ActionButton button : mActionButtons) {
+ // Update flags to show/hide buttons.
+ button.updateForMultipleTasks(isGroupedTask);
}
- if (mSplitButton == null) return;
- boolean shouldBeVisible = mSplitButtonHiddenFlags == 0;
- mSplitButton.setVisibility(shouldBeVisible ? VISIBLE : GONE);
- findViewById(R.id.action_split_space).setVisibility(shouldBeVisible ? VISIBLE : GONE);
}
/**
- * Updates the proper flags to indicate whether the "Split screen" button should be disabled.
- *
- * @param flag The flag to update.
- * @param enable Whether to enable the disable flag: True will cause view to be disabled.
+ * Updates flags to hide and show actions buttons depending on if the device is a tablet.
+ * @param isTablet True if the current device is a tablet.
*/
- public void updateSplitButtonDisabledFlags(@SplitButtonDisabledFlags int flag, boolean enable) {
- if (enable) {
- mSplitButtonDisabledFlags |= flag;
- } else {
- mSplitButtonDisabledFlags &= ~flag;
+ public void updateForTablet(boolean isTablet) {
+ for (ActionButton button : mActionButtons) {
+ // Update flags to show/hide buttons.
+ button.updateForTablet(isTablet);
}
- updateSplitButtonEnabledState();
}
public MultiProperty getContentAlpha() {
@@ -312,18 +295,4 @@
(dp.isLandscape ? R.drawable.ic_split_horizontal : R.drawable.ic_split_vertical),
0, 0, 0);
}
-
- /**
- * Enables/disables the "Split" button based on the status of mSplitButtonDisabledFlags and
- * mDisabledFlags.
- */
- private void updateSplitButtonEnabledState() {
- if (mSplitButton == null) {
- return;
- }
- boolean isParentEnabled = (mDisabledFlags & ~DISABLED_ROTATED) == 0;
- boolean shouldBeEnabled = mSplitButtonDisabledFlags == 0 && isParentEnabled;
- mSplitButton.setEnabled(shouldBeEnabled);
- }
-
}
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 7972999..6a275e6 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -20,7 +20,6 @@
import static android.view.Surface.ROTATION_0;
import static android.view.View.MeasureSpec.EXACTLY;
import static android.view.View.MeasureSpec.makeMeasureSpec;
-
import static com.android.app.animation.Interpolators.ACCELERATE;
import static com.android.app.animation.Interpolators.ACCELERATE_0_75;
import static com.android.app.animation.Interpolators.ACCELERATE_DECELERATE;
@@ -34,6 +33,7 @@
import static com.android.launcher3.AbstractFloatingView.TYPE_TASK_MENU;
import static com.android.launcher3.AbstractFloatingView.getTopOpenViewWithType;
import static com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS;
+import static com.android.launcher3.Flags.enableGridOnlyOverview;
import static com.android.launcher3.LauncherAnimUtils.SUCCESS_TRANSITION_PROGRESS;
import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
@@ -42,7 +42,6 @@
import static com.android.launcher3.Utilities.mapToRange;
import static com.android.launcher3.Utilities.squaredHypot;
import static com.android.launcher3.Utilities.squaredTouchSlop;
-import static com.android.launcher3.Flags.enableGridOnlyOverview;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_OVERVIEW_ACTIONS_SPLIT;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_CLEAR_ALL;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_DISMISS_SWIPE_UP;
@@ -57,8 +56,6 @@
import static com.android.quickstep.util.LogUtils.splitFailureMessage;
import static com.android.quickstep.views.ClearAllButton.DISMISS_ALPHA;
import static com.android.quickstep.views.DesktopTaskView.isDesktopModeSupported;
-import static com.android.quickstep.views.OverviewActionsView.FLAG_IS_NOT_TABLET;
-import static com.android.quickstep.views.OverviewActionsView.FLAG_SINGLE_TASK;
import static com.android.quickstep.views.OverviewActionsView.HIDDEN_ACTIONS_IN_MENU;
import static com.android.quickstep.views.OverviewActionsView.HIDDEN_DESKTOP;
import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NON_ZERO_ROTATION;
@@ -3927,18 +3924,23 @@
}
/**
- * Hides all overview actions if current page is for split apps, shows otherwise
- * If actions are showing, we only show split option if
+ * Hides all overview actions if user is halfway through split selection, shows otherwise.
+ * We only show split option if:
+ * * Focused view is a single app
* * Device is large screen
- * * There are at least 2 tasks to invoke split
*/
private void updateCurrentTaskActionsVisibility() {
- boolean isCurrentSplit = getCurrentPageTaskView() instanceof GroupedTaskView;
- mActionsView.updateHiddenFlags(HIDDEN_SPLIT_SCREEN, isCurrentSplit);
+ boolean isGroupedTask = getCurrentPageTaskView() != null
+ && getCurrentPageTaskView().containsMultipleTasks();
+ // Update flags to see if entire actions bar should be hidden.
+ mActionsView.updateHiddenFlags(HIDDEN_SPLIT_SCREEN, isGroupedTask);
mActionsView.updateHiddenFlags(HIDDEN_SPLIT_SELECT_ACTIVE, isSplitSelectionActive());
- mActionsView.updateSplitButtonHiddenFlags(FLAG_IS_NOT_TABLET,
- !mActivity.getDeviceProfile().isTablet);
- mActionsView.updateSplitButtonDisabledFlags(FLAG_SINGLE_TASK, /*enable=*/ false);
+ // Update flags to see if actions bar should show buttons for a single task or a pair of
+ // tasks.
+ mActionsView.updateForGroupedTask(isGroupedTask);
+ // Update flags to see if split button should be hidden.
+ mActionsView.updateForTablet(mActivity.getDeviceProfile().isTablet);
+
if (isDesktopModeSupported()) {
boolean isCurrentDesktop = getCurrentPageTaskView() instanceof DesktopTaskView;
mActionsView.updateHiddenFlags(HIDDEN_DESKTOP, isCurrentDesktop);
diff --git a/quickstep/src/com/android/quickstep/views/ScreenshotActionButton.kt b/quickstep/src/com/android/quickstep/views/ScreenshotActionButton.kt
new file mode 100644
index 0000000..9cb48b8
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/views/ScreenshotActionButton.kt
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2023 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.views
+
+import android.content.Context
+import android.util.AttributeSet
+
+/** A button on the Overview Actions Bar for screenshotting the focused app. */
+class ScreenshotActionButton : ActionButton {
+ companion object {
+ const val FLAG_MULTIPLE_TASKS_HIDE_SCREENSHOT = 1 shl 0
+ }
+
+ constructor(context: Context) : super(context)
+ constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
+ constructor(
+ context: Context,
+ attrs: AttributeSet?,
+ defStyleAttr: Int
+ ) : super(context, attrs, defStyleAttr)
+
+ /** Show/hide the button when the focused task is a single/pair. */
+ override fun updateForMultipleTasks(hasMultipleTasks: Boolean) {
+ // Hidden for multiple tasks
+ updateHiddenFlags(FLAG_MULTIPLE_TASKS_HIDE_SCREENSHOT, hasMultipleTasks)
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/views/SplitActionButton.kt b/quickstep/src/com/android/quickstep/views/SplitActionButton.kt
new file mode 100644
index 0000000..88d1a77
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/views/SplitActionButton.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2023 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.views
+
+import android.content.Context
+import android.util.AttributeSet
+
+/** A button on the Overview Actions Bar for initiating split screen. */
+class SplitActionButton : ActionButton {
+ companion object {
+ const val FLAG_IS_NOT_TABLET_HIDE_SPLIT = 1 shl 0
+ const val FLAG_MULTIPLE_TASKS_HIDE_SPLIT = 1 shl 1
+ }
+
+ constructor(context: Context) : super(context)
+ constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
+ constructor(
+ context: Context,
+ attrs: AttributeSet?,
+ defStyleAttr: Int
+ ) : super(context, attrs, defStyleAttr)
+
+ /** Show/hide the button when the focused task is a single/pair. */
+ override fun updateForMultipleTasks(hasMultipleTasks: Boolean) {
+ // Hidden for multiple tasks
+ updateHiddenFlags(FLAG_MULTIPLE_TASKS_HIDE_SPLIT, hasMultipleTasks)
+ }
+
+ /** Show/hide the button depending on if the device is a tablet. */
+ override fun updateForTablet(isTablet: Boolean) {
+ // Hidden for non-tablets
+ updateHiddenFlags(FLAG_IS_NOT_TABLET_HIDE_SPLIT, !isTablet)
+ }
+}
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
index ff8537b..0966350 100644
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
+++ b/quickstep/tests/src/com/android/quickstep/TaplTestsQuickstep.java
@@ -103,6 +103,7 @@
@Test
@NavigationModeSwitch
@PortraitLandscape
+ @PlatinumTest(focusArea = "launcher")
public void testWorkspaceSwitchToAllApps() {
assertNotNull("switchToAllApps() returned null",
mLauncher.getWorkspace().switchToAllApps());
@@ -179,6 +180,7 @@
@Test
@NavigationModeSwitch
@PortraitLandscape
+ @PlatinumTest(focusArea = "launcher")
public void testOverviewActions() throws Exception {
assumeFalse("Skipping Overview Actions tests for grid only overview",
mLauncher.isTablet() && mLauncher.isGridOnlyOverviewEnabled());
@@ -215,6 +217,7 @@
@NavigationModeSwitch
@PortraitLandscape
@ScreenRecord // b/238461765
+ @PlatinumTest(focusArea = "launcher")
public void testSwitchToOverview() throws Exception {
startTestAppsWithCheck();
assertNotNull("Workspace.switchToOverview() returned null",
@@ -240,6 +243,7 @@
@Test
@NavigationModeSwitch
@PortraitLandscape
+ @PlatinumTest(focusArea = "launcher")
public void testBackground() throws Exception {
startAppFast(CALCULATOR_APP_PACKAGE);
final LaunchedAppState launchedAppState = getAndAssertLaunchedApp();
@@ -266,6 +270,7 @@
@Test
@NavigationModeSwitch
@PortraitLandscape
+ @PlatinumTest(focusArea = "launcher")
public void testQuickSwitchFromApp() throws Exception {
startTestActivity(2);
startTestActivity(3);
@@ -295,6 +300,7 @@
@Test
@ScreenRecord // b/242163205
+ @PlatinumTest(focusArea = "launcher")
@TaskbarModeSwitch(mode = PERSISTENT)
public void testQuickSwitchToPreviousAppForTablet() throws Exception {
assumeTrue(mLauncher.isTablet());
@@ -321,6 +327,7 @@
@Test
@NavigationModeSwitch
@PortraitLandscape
+ @PlatinumTest(focusArea = "launcher")
public void testQuickSwitchFromHome() throws Exception {
startTestActivity(2);
mLauncher.goHome().quickSwitchToPreviousApp();