diff --git a/quickstep/res/drawable/taskbar_overflow_icon.xml b/quickstep/res/drawable/taskbar_overflow_icon.xml
new file mode 100644
index 0000000000..b93a70e682
--- /dev/null
+++ b/quickstep/res/drawable/taskbar_overflow_icon.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
diff --git a/quickstep/res/layout/taskbar_overflow_button.xml b/quickstep/res/layout/taskbar_overflow_button.xml
new file mode 100644
index 0000000000..20104f257c
--- /dev/null
+++ b/quickstep/res/layout/taskbar_overflow_button.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
diff --git a/quickstep/res/values/strings.xml b/quickstep/res/values/strings.xml
index f72f3c5a20..008766b51b 100644
--- a/quickstep/res/values/strings.xml
+++ b/quickstep/res/values/strings.xml
@@ -320,6 +320,8 @@
Change navigation mode
Taskbar Divider
+
+ Taskbar Overflow
diff --git a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchView.java b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchView.java
index b4102a9fce..fc8204aa91 100644
--- a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchView.java
@@ -58,8 +58,12 @@ import java.util.List;
import java.util.Locale;
/**
- * View that allows quick switching between recent tasks through keyboard alt-tab and alt-shift-tab
- * commands.
+ * View that allows quick switching between recent tasks.
+ *
+ * Can be access via:
+ * - keyboard alt-tab
+ * - alt-shift-tab
+ * - taskbar overflow button
*/
public class KeyboardQuickSwitchView extends ConstraintLayout {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index b95c406b88..4f9310c6c4 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -29,6 +29,7 @@ import static com.android.launcher3.AbstractFloatingView.TYPE_ON_BOARD_POPUP;
import static com.android.launcher3.AbstractFloatingView.TYPE_REBIND_SAFE;
import static com.android.launcher3.AbstractFloatingView.TYPE_TASKBAR_OVERLAY_PROXY;
import static com.android.launcher3.Flags.enableCursorHoverStates;
+import static com.android.launcher3.Flags.taskbarOverflow;
import static com.android.launcher3.Utilities.calculateTextHeight;
import static com.android.launcher3.Utilities.isRunningInTestHarness;
import static com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_NAVBAR_UNIFICATION;
@@ -1221,6 +1222,11 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
RecentsView recents = taskbarUIController.getRecentsView();
boolean shouldCloseAllOpenViews = true;
Object tag = view.getTag();
+
+ if (taskbarOverflow()) {
+ mControllers.keyboardQuickSwitchController.closeQuickSwitchView(false);
+ }
+
if (tag instanceof GroupTask groupTask) {
handleGroupTaskLaunch(
groupTask,
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
index 0389a11019..2734137a29 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
@@ -46,6 +46,7 @@ import androidx.annotation.Nullable;
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.Flags;
import com.android.launcher3.Insettable;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
@@ -63,6 +64,7 @@ import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.LauncherBindableItemsContainer;
import com.android.launcher3.util.Themes;
import com.android.launcher3.views.ActivityContext;
+import com.android.launcher3.views.IconButtonView;
import com.android.quickstep.util.DesktopTask;
import com.android.quickstep.util.GroupTask;
import com.android.systemui.shared.recents.model.Task;
@@ -100,9 +102,12 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar
// Only non-null when device supports having an All Apps button.
@Nullable private final TaskbarAllAppsButtonContainer mAllAppsButtonContainer;
- // Only non-null when device supports having an All Apps button.
+ // Only non-null when device supports having a Divider button.
@Nullable private TaskbarDividerContainer mTaskbarDividerContainer;
+ // Only non-null when device supports having a Taskbar Overflow button.
+ @Nullable private IconButtonView mTaskbarOverflowView;
+
/**
* Whether the divider is between Hotseat icons and Recents,
* instead of between All Apps button and Hotseat.
@@ -171,6 +176,13 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar
mTaskbarDividerContainer = new TaskbarDividerContainer(context);
}
+ if (Flags.taskbarOverflow()) {
+ mTaskbarOverflowView = (IconButtonView) LayoutInflater.from(context)
+ .inflate(R.layout.taskbar_overflow_button, this, false);
+ mTaskbarOverflowView.setIconDrawable(
+ resources.getDrawable(R.drawable.taskbar_overflow_icon));
+ mTaskbarOverflowView.setPadding(mItemPadding, mItemPadding, mItemPadding, mItemPadding);
+ }
// TODO: Disable touch events on QSB otherwise it can crash.
mQsb = LayoutInflater.from(context).inflate(R.layout.search_container_hotseat, this, false);
}
@@ -263,6 +275,12 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar
if (mTaskbarDividerContainer != null && callbacks.supportsDividerLongPress()) {
mTaskbarDividerContainer.setUpCallbacks(callbacks);
}
+ if (mTaskbarOverflowView != null) {
+ mTaskbarOverflowView.setOnClickListener(
+ mControllerCallbacks.getOverflowOnClickListener());
+ mTaskbarOverflowView.setOnLongClickListener(
+ mControllerCallbacks.getOverflowOnLongClickListener());
+ }
}
private void removeAndRecycle(View view) {
@@ -290,6 +308,9 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar
removeView(mTaskbarDividerContainer);
}
}
+ if (mTaskbarOverflowView != null) {
+ removeView(mTaskbarOverflowView);
+ }
removeView(mQsb);
// Add Hotseat icons.
@@ -377,6 +398,9 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar
if (mTaskbarDividerContainer != null && !recentTasks.isEmpty()) {
addView(mTaskbarDividerContainer, nextViewIndex++);
mAddedDividerForRecents = true;
+ if (mTaskbarOverflowView != null) {
+ addView(mTaskbarOverflowView, nextViewIndex++);
+ }
}
// Add Recent/Running icons.
@@ -698,6 +722,14 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar
return mTaskbarDividerContainer;
}
+ /**
+ * Returns the taskbar overflow view in the taskbar.
+ */
+ @Nullable
+ public IconButtonView getTaskbarOverflowView() {
+ return mTaskbarOverflowView;
+ }
+
/**
* Returns whether the divider is between Hotseat icons and Recents,
* instead of between All Apps button and Hotseat.
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewCallbacks.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewCallbacks.java
index 5c8d439a13..d108d8c357 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewCallbacks.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewCallbacks.java
@@ -134,4 +134,25 @@ public class TaskbarViewCallbacks {
return Flags.enableBubbleBarInPersistentTaskBar()
&& mControllers.bubbleControllers.isPresent();
}
+
+ /** Returns on click listener for the taskbar overflow view. */
+ public View.OnClickListener getOverflowOnClickListener() {
+ return new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mControllers.keyboardQuickSwitchController.openQuickSwitchView();
+ }
+ };
+ }
+
+ /** Returns on long click listener for the taskbar overflow view. */
+ public View.OnLongClickListener getOverflowOnLongClickListener() {
+ return new View.OnLongClickListener() {
+ @Override
+ public boolean onLongClick(View v) {
+ mControllers.keyboardQuickSwitchController.openQuickSwitchView();
+ return true;
+ }
+ };
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
index 0a67ac2f1d..3a84915585 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
@@ -831,6 +831,7 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar
View child = mTaskbarView.getChildAt(i);
boolean isAllAppsButton = child == mTaskbarView.getAllAppsButtonContainer();
boolean isTaskbarDividerView = child == mTaskbarView.getTaskbarDividerViewContainer();
+ boolean isTaskbarOverflowView = child == mTaskbarView.getTaskbarOverflowView();
boolean isRecentTask = child.getTag() instanceof GroupTask;
// TODO(b/343522351): show recents on the home screen.
final boolean isRecentsInHotseat = false;
@@ -841,7 +842,8 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar
setter.setViewAlpha(child, 0, Interpolators.clampToProgress(LINEAR, 0.8f, 1f));
} else if ((isAllAppsButton && !FeatureFlags.enableAllAppsButtonInHotseat())
|| (isTaskbarDividerView && enableTaskbarPinning())
- || (isRecentTask && !isRecentsInHotseat)) {
+ || (isRecentTask && !isRecentsInHotseat)
+ || isTaskbarOverflowView) {
if (!isToHome
&& mIsHotseatIconOnTopWhenAligned
&& mIsStashed) {