Merge changes I34983821,I175e4282 into main

* changes:
  Initial overflow compatibility with layout transition.
  Migrate layout transition flag to DesktopModeFlag version.
diff --git a/aconfig/launcher.aconfig b/aconfig/launcher.aconfig
index c564594..a87e290 100644
--- a/aconfig/launcher.aconfig
+++ b/aconfig/launcher.aconfig
@@ -518,13 +518,6 @@
 }
 
 flag {
-    name: "taskbar_recents_layout_transition"
-    namespace: "launcher"
-    description: "Enable Taskbar LayoutTransition for Recent Apps"
-    bug: "343521765"
-}
-
-flag {
     name: "enable_pinning_app_with_context_menu"
     namespace: "launcher"
     description: "Add options to pin/unpin to taskbar to app context menus."
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
index e589c87..573bc1d 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
@@ -16,11 +16,11 @@
 package com.android.launcher3.taskbar;
 
 import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED;
+import static android.window.DesktopModeFlags.ENABLE_TASKBAR_RECENTS_LAYOUT_TRANSITION;
 
 import static com.android.launcher3.BubbleTextView.DISPLAY_TASKBAR;
 import static com.android.launcher3.Flags.enableCursorHoverStates;
 import static com.android.launcher3.Flags.enableRecentsInTaskbar;
-import static com.android.launcher3.Flags.taskbarRecentsLayoutTransition;
 import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APP_PAIR;
 import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_FOLDER;
 import static com.android.launcher3.config.FeatureFlags.enableTaskbarPinning;
@@ -70,7 +70,6 @@
 import com.android.systemui.shared.recents.model.Task;
 import com.android.wm.shell.shared.bubbles.BubbleBarLocation;
 
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
@@ -135,6 +134,7 @@
     private final int mNumStaticViews;
 
     private Set<GroupTask> mPrevRecentTasks = Collections.emptySet();
+    private Set<GroupTask> mPrevOverflowTasks = Collections.emptySet();
 
     public TaskbarView(@NonNull Context context) {
         this(context, null);
@@ -201,8 +201,10 @@
         // TODO: Disable touch events on QSB otherwise it can crash.
         mQsb = LayoutInflater.from(context).inflate(R.layout.search_container_hotseat, this, false);
 
-        mNumStaticViews = taskbarRecentsLayoutTransition() && !mActivityContext.isPhoneMode()
-                ? addStaticViews() : 0;
+        mNumStaticViews =
+                ENABLE_TASKBAR_RECENTS_LAYOUT_TRANSITION.isTrue() && !mActivityContext.isPhoneMode()
+                        ? addStaticViews()
+                        : 0;
     }
 
     /**
@@ -399,7 +401,7 @@
         // TODO(b/343289567 and b/316004172): support app pairs and desktop mode.
         recentTasks = recentTasks.stream().filter(it -> it instanceof SingleTask).toList();
 
-        if (taskbarRecentsLayoutTransition()) {
+        if (ENABLE_TASKBAR_RECENTS_LAYOUT_TRANSITION.isTrue()) {
             updateItemsWithLayoutTransition(hotseatItemInfos, recentTasks);
         } else {
             updateItemsWithoutLayoutTransition(hotseatItemInfos, recentTasks);
@@ -429,7 +431,7 @@
             mAddedDividerForRecents = true;
         }
 
-        updateRecents(recentTasks);
+        updateRecents(recentTasks, hotseatItemInfos.length);
 
         addView(mAllAppsButtonContainer, mIsRtl ? hotseatItemInfos.length : 0);
 
@@ -458,7 +460,7 @@
 
         // Update left section.
         if (mIsRtl) {
-            updateRecents(recentTasks.reversed());
+            updateRecents(recentTasks.reversed(), hotseatItemInfos.length);
         } else {
             updateHotseatItems(hotseatItemInfos);
         }
@@ -473,7 +475,7 @@
         if (mIsRtl) {
             updateHotseatItems(hotseatItemInfos);
         } else {
-            updateRecents(recentTasks);
+            updateRecents(recentTasks, hotseatItemInfos.length);
         }
 
         // Recents divider takes priority.
@@ -604,47 +606,59 @@
         }
     }
 
-    private void updateRecents(List<GroupTask> recentTasks) {
-        // At this point, the all apps button has not been added as a child view, but needs to be
-        // accounted for when comparing current icon count to max number of icons.
-        int nonTaskIconsToBeAdded = 1;
-
+    private void updateRecents(List<GroupTask> recentTasks, int hotseatSize) {
         boolean supportsOverflow = Flags.taskbarOverflow() && recentTasks.size() > 1;
         int overflowSize = 0;
-        if (supportsOverflow) {
-            mIdealNumIcons = mNextViewIndex + recentTasks.size() + nonTaskIconsToBeAdded;
+        boolean hasOverflow = false;
+        if (supportsOverflow && mTaskbarOverflowView != null) {
+            // Need to account for All Apps and the divider. If we need to have an overflow, we will
+            // have a divider for recents.
+            final int nonTaskIconsToBeAdded = 2;
+            mIdealNumIcons = hotseatSize + recentTasks.size() + nonTaskIconsToBeAdded;
             overflowSize = mIdealNumIcons - mMaxNumIcons;
+            hasOverflow = overflowSize > 0;
 
-            if (overflowSize > 0 && mTaskbarOverflowView != null) {
+            if (!ENABLE_TASKBAR_RECENTS_LAYOUT_TRANSITION.isTrue() && hasOverflow) {
                 addView(mTaskbarOverflowView, mNextViewIndex++);
-            } else if (mTaskbarOverflowView != null) {
+            } else if (ENABLE_TASKBAR_RECENTS_LAYOUT_TRANSITION.isTrue()) {
+                // RTL case is handled after we add the recent icons, because the button needs to
+                // then be to the right of them.
+                if (hasOverflow && !mIsRtl) {
+                    if (mPrevOverflowTasks.isEmpty()) addView(mTaskbarOverflowView, mNextViewIndex);
+                    // NOTE: If overflow already existed, assume the overflow view is already
+                    // at the correct position.
+                    mNextViewIndex++;
+                } else if (!hasOverflow && !mPrevOverflowTasks.isEmpty()) {
+                    removeView(mTaskbarOverflowView);
+                    mTaskbarOverflowView.clearItems();
+                }
+            } else {
                 mTaskbarOverflowView.clearItems();
             }
         }
 
-        List<Task> overflownTasks = null;
         // An extra item needs to be added to overflow button to account for the space taken up by
         // the overflow button.
         final int itemsToAddToOverflow =
-                (overflowSize > 0) ? Math.min(overflowSize + 1, recentTasks.size()) : 0;
-        if (overflowSize > 0) {
-            overflownTasks = new ArrayList<>(itemsToAddToOverflow);
+                hasOverflow ? Math.min(overflowSize + 1, recentTasks.size()) : 0;
+        final Set<GroupTask> overflownRecentsSet;
+        if (hasOverflow && mTaskbarOverflowView != null) {
+            final int startIndex = mIsRtl ? recentTasks.size() - itemsToAddToOverflow : 0;
+            final int endIndex = mIsRtl ? recentTasks.size() : itemsToAddToOverflow;
+            final List<GroupTask> overflownRecents = recentTasks.subList(startIndex, endIndex);
+            mTaskbarOverflowView.setItems(
+                    overflownRecents.stream().map(t -> ((SingleTask) t).getTask()).toList());
+            overflownRecentsSet = new ArraySet<>(overflownRecents);
+        } else {
+            overflownRecentsSet = Collections.emptySet();
         }
 
         // Add Recent/Running icons.
         final Set<GroupTask> recentTasksSet = new ArraySet<>(recentTasks);
-        for (GroupTask task : recentTasks) {
-            if (mTaskbarOverflowView != null && overflownTasks != null
-                    && overflownTasks.size() < itemsToAddToOverflow
-                    && task instanceof SingleTask singleTask) {
-                // TODO(b/343289567 and b/316004172): support app pairs and desktop mode.
-                overflownTasks.add(singleTask.getTask());
-                if (overflownTasks.size() == itemsToAddToOverflow) {
-                    mTaskbarOverflowView.setItems(overflownTasks);
-                }
-                continue;
-            }
-
+        final int startIndex = mIsRtl ? 0 : itemsToAddToOverflow;
+        final int endIndex =
+                mIsRtl ? recentTasks.size() - itemsToAddToOverflow : recentTasks.size();
+        for (GroupTask task : recentTasks.subList(startIndex, endIndex)) {
             // Replace any Recent views with the appropriate type if it's not already that type.
             final int expectedLayoutResId;
             boolean isCollection = false;
@@ -663,17 +677,19 @@
 
             View recentIcon = null;
             // If a task is new, we should not reuse a view so that it animates in when it is added.
-            final boolean canReuseView = !taskbarRecentsLayoutTransition()
-                    || mPrevRecentTasks.contains(task);
+            final boolean canReuseView = !ENABLE_TASKBAR_RECENTS_LAYOUT_TRANSITION.isTrue()
+                    || (mPrevRecentTasks.contains(task) && !mPrevOverflowTasks.contains(task));
             while (canReuseView && isNextViewInSection(GroupTask.class)) {
                 recentIcon = getChildAt(mNextViewIndex);
+                GroupTask tag = (GroupTask) recentIcon.getTag();
 
                 // see if the view can be reused
                 if ((recentIcon.getSourceLayoutResId() != expectedLayoutResId)
-                        || (isCollection && (recentIcon.getTag() != task))
+                        || (isCollection && tag != task)
                         // Remove view corresponding to removed task so that it animates out.
-                        || (taskbarRecentsLayoutTransition()
-                                && !recentTasksSet.contains(recentIcon.getTag()))) {
+                        || (ENABLE_TASKBAR_RECENTS_LAYOUT_TRANSITION.isTrue()
+                                && (!recentTasksSet.contains(tag)
+                                        || overflownRecentsSet.contains(tag)))) {
                     removeAndRecycle(recentIcon);
                     recentIcon = null;
                 } else {
@@ -704,7 +720,15 @@
             removeAndRecycle(getChildAt(mNextViewIndex));
         }
 
+        if (ENABLE_TASKBAR_RECENTS_LAYOUT_TRANSITION.isTrue() && mIsRtl && hasOverflow) {
+            if (mPrevOverflowTasks.isEmpty()) {
+                addView(mTaskbarOverflowView, mNextViewIndex);
+            }
+            mNextViewIndex++;
+        }
+
         mPrevRecentTasks = recentTasksSet;
+        mPrevOverflowTasks = overflownRecentsSet;
     }
 
     private boolean isNextViewInSection(Class<?> tagClass) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewCallbacks.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewCallbacks.java
index 066d4df..dcb9fbf 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewCallbacks.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewCallbacks.java
@@ -16,7 +16,8 @@
 
 package com.android.launcher3.taskbar;
 
-import static com.android.launcher3.Flags.taskbarRecentsLayoutTransition;
+import static android.window.DesktopModeFlags.ENABLE_TASKBAR_RECENTS_LAYOUT_TRANSITION;
+
 import static com.android.launcher3.config.FeatureFlags.enableTaskbarPinning;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_ALLAPPS_BUTTON_LONG_PRESS;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_ALLAPPS_BUTTON_TAP;
@@ -123,7 +124,7 @@
 
     /** Callback invoked before Taskbar icons are laid out. */
     void onPreLayoutChildren() {
-        if (enableTaskbarPinning() && taskbarRecentsLayoutTransition()) {
+        if (enableTaskbarPinning() && ENABLE_TASKBAR_RECENTS_LAYOUT_TRANSITION.isTrue()) {
             mControllers.taskbarViewController.updateTaskbarIconTranslationXForPinning();
         }
     }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
index 6ae13d4..7f980aa 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
@@ -19,13 +19,13 @@
 import static android.animation.LayoutTransition.CHANGE_APPEARING;
 import static android.animation.LayoutTransition.CHANGE_DISAPPEARING;
 import static android.animation.LayoutTransition.DISAPPEARING;
+import static android.window.DesktopModeFlags.ENABLE_TASKBAR_RECENTS_LAYOUT_TRANSITION;
 
 import static com.android.app.animation.Interpolators.EMPHASIZED;
 import static com.android.app.animation.Interpolators.FINAL_FRAME;
 import static com.android.app.animation.Interpolators.LINEAR;
 import static com.android.launcher3.Flags.enableScalingRevealHomeAnimation;
 import static com.android.launcher3.Flags.taskbarOverflow;
-import static com.android.launcher3.Flags.taskbarRecentsLayoutTransition;
 import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
 import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
 import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
@@ -189,7 +189,7 @@
 
     private final View.OnLayoutChangeListener mTaskbarViewLayoutChangeListener =
             (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
-                if (!taskbarRecentsLayoutTransition()) {
+                if (!ENABLE_TASKBAR_RECENTS_LAYOUT_TRANSITION.isTrue()) {
                     // update shiftX is handled with the animation at the end of the method
                     updateTaskbarIconTranslationXForPinning(/* updateShiftXForBubbleBar = */ false);
                 }
@@ -1206,7 +1206,8 @@
     /** Called when there's a change in running apps to update the UI. */
     public void commitRunningAppsToUI() {
         mModelCallbacks.commitRunningAppsToUI();
-        if (taskbarRecentsLayoutTransition() && mTaskbarView.getLayoutTransition() == null) {
+        if (ENABLE_TASKBAR_RECENTS_LAYOUT_TRANSITION.isTrue()
+                && mTaskbarView.getLayoutTransition() == null) {
             // Set up after the first commit so that the initial recents do not animate (janky).
             mTaskbarView.setLayoutTransition(createLayoutTransitionForRunningApps());
         }
diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarViewTest.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarViewTest.kt
index 44d31c4..24ed81f 100644
--- a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarViewTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarViewTest.kt
@@ -19,7 +19,6 @@
 import android.platform.test.flag.junit.FlagsParameterization
 import android.platform.test.flag.junit.FlagsParameterization.allCombinationsOf
 import android.platform.test.flag.junit.SetFlagsRule
-import com.android.launcher3.Flags.FLAG_TASKBAR_RECENTS_LAYOUT_TRANSITION
 import com.android.launcher3.R
 import com.android.launcher3.taskbar.TaskbarControllerTestUtil.runOnMainSync
 import com.android.launcher3.taskbar.TaskbarIconType.ALL_APPS
@@ -34,6 +33,7 @@
 import com.android.launcher3.taskbar.rules.TaskbarUnitTestRule.ForceRtl
 import com.android.launcher3.taskbar.rules.TaskbarWindowSandboxContext
 import com.android.launcher3.util.LauncherMultivalentJUnit.Companion.isRunningInRobolectric
+import com.android.window.flags.Flags.FLAG_ENABLE_TASKBAR_RECENTS_LAYOUT_TRANSITION
 import org.junit.Before
 import org.junit.Rule
 import org.junit.Test
@@ -54,7 +54,7 @@
                 } else {
                     listOf("onDevice") // Unused.
                 }
-            val flags = allCombinationsOf(FLAG_TASKBAR_RECENTS_LAYOUT_TRANSITION)
+            val flags = allCombinationsOf(FLAG_ENABLE_TASKBAR_RECENTS_LAYOUT_TRANSITION)
             return devices.flatMap { d -> flags.map { f -> arrayOf(d, f) } } // Cartesian product.
         }
     }
diff --git a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarViewWithLayoutTransitionTest.kt b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarViewWithLayoutTransitionTest.kt
index ac1572e..2df4fab 100644
--- a/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarViewWithLayoutTransitionTest.kt
+++ b/quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/TaskbarViewWithLayoutTransitionTest.kt
@@ -19,13 +19,14 @@
 import android.platform.test.annotations.EnableFlags
 import android.platform.test.flag.junit.SetFlagsRule
 import android.view.View
-import com.android.launcher3.Flags.FLAG_TASKBAR_RECENTS_LAYOUT_TRANSITION
+import com.android.launcher3.Flags.FLAG_TASKBAR_OVERFLOW
 import com.android.launcher3.R
 import com.android.launcher3.statehandlers.DesktopVisibilityController
 import com.android.launcher3.taskbar.TaskbarControllerTestUtil.runOnMainSync
 import com.android.launcher3.taskbar.TaskbarIconType.ALL_APPS
 import com.android.launcher3.taskbar.TaskbarIconType.DIVIDER
 import com.android.launcher3.taskbar.TaskbarIconType.HOTSEAT
+import com.android.launcher3.taskbar.TaskbarIconType.OVERFLOW
 import com.android.launcher3.taskbar.TaskbarIconType.RECENT
 import com.android.launcher3.taskbar.TaskbarViewTestUtil.assertThat
 import com.android.launcher3.taskbar.TaskbarViewTestUtil.createHotseatItems
@@ -35,6 +36,7 @@
 import com.android.launcher3.taskbar.rules.TaskbarWindowSandboxContext
 import com.android.launcher3.util.LauncherMultivalentJUnit
 import com.android.launcher3.util.LauncherMultivalentJUnit.EmulatedDevices
+import com.android.window.flags.Flags.FLAG_ENABLE_TASKBAR_RECENTS_LAYOUT_TRANSITION
 import com.google.common.truth.Truth.assertThat
 import org.junit.Before
 import org.junit.Rule
@@ -44,7 +46,7 @@
 
 @RunWith(LauncherMultivalentJUnit::class)
 @EmulatedDevices(["pixelFoldable2023", "pixelTablet2023"])
-@EnableFlags(FLAG_TASKBAR_RECENTS_LAYOUT_TRANSITION)
+@EnableFlags(FLAG_ENABLE_TASKBAR_RECENTS_LAYOUT_TRANSITION, FLAG_TASKBAR_OVERFLOW)
 class TaskbarViewWithLayoutTransitionTest {
 
     @get:Rule(order = 0) val setFlagsRule = SetFlagsRule()
@@ -59,6 +61,9 @@
     private val desktopVisibilityController: DesktopVisibilityController
         get() = DesktopVisibilityController.INSTANCE[context]
 
+    private val maxShownRecents: Int
+        get() = taskbarView.maxNumIconViews - 2 // Account for All Apps and Divider.
+
     @Before
     fun obtainView() {
         taskbarView = taskbarUnitTestRule.activityContext.dragLayer.findViewById(R.id.taskbar_view)
@@ -260,4 +265,88 @@
         runOnMainSync { taskbarView.updateItems(emptyArray(), createRecents(1)) }
         assertThat(taskbarView).hasIconTypes(RECENT, DIVIDER, ALL_APPS)
     }
+
+    @Test
+    fun testUpdateItems_maxRecents_noOverflow() {
+        runOnMainSync { taskbarView.updateItems(emptyArray(), createRecents(maxShownRecents)) }
+        assertThat(taskbarView).hasIconTypes(ALL_APPS, DIVIDER, *RECENT * maxShownRecents)
+    }
+
+    @Test
+    fun testUpdateItems_moreThanMaxRecents_overflowShownBeforeRecents() {
+        val recentsSize = maxShownRecents + 2
+        runOnMainSync { taskbarView.updateItems(emptyArray(), createRecents(recentsSize)) }
+
+        val expectedNumRecents = RECENT * getExpectedNumRecentsWithOverflow()
+        assertThat(taskbarView).hasIconTypes(ALL_APPS, DIVIDER, OVERFLOW, *expectedNumRecents)
+    }
+
+    @Test
+    @ForceRtl
+    fun testUpdateItems_rtl_moreThanMaxRecents_overflowShownAfterRecents() {
+        val recentsSize = maxShownRecents + 2
+        runOnMainSync { taskbarView.updateItems(emptyArray(), createRecents(recentsSize)) }
+
+        val expectedRecents = RECENT * getExpectedNumRecentsWithOverflow()
+        assertThat(taskbarView).hasIconTypes(*expectedRecents, OVERFLOW, DIVIDER, ALL_APPS)
+    }
+
+    @Test
+    fun testUpdateItems_moreThanMaxRecentsWithHotseat_fewerRecentsShown() {
+        val hotseatSize = 4
+        val recentsSize = maxShownRecents + 2
+        runOnMainSync {
+            taskbarView.updateItems(createHotseatItems(hotseatSize), createRecents(recentsSize))
+        }
+
+        val expectedRecents = RECENT * getExpectedNumRecentsWithOverflow(hotseatSize)
+        assertThat(taskbarView)
+            .hasIconTypes(ALL_APPS, *HOTSEAT * hotseatSize, DIVIDER, OVERFLOW, *expectedRecents)
+    }
+
+    @Test
+    @ForceRtl
+    fun testUpdateItems_rtl_moreThanMaxRecentsWithHotseat_fewerRecentsShown() {
+        val hotseatSize = 4
+        val recentsSize = maxShownRecents + 2
+        runOnMainSync {
+            taskbarView.updateItems(createHotseatItems(hotseatSize), createRecents(recentsSize))
+        }
+
+        val expectedRecents = RECENT * getExpectedNumRecentsWithOverflow(hotseatSize)
+        assertThat(taskbarView)
+            .hasIconTypes(*expectedRecents, OVERFLOW, DIVIDER, *HOTSEAT * hotseatSize, ALL_APPS)
+    }
+
+    @Test
+    fun testUpdateItems_moreThanMaxRecents_verifyShownRecentsOrder() {
+        val recentsSize = maxShownRecents + 2
+        runOnMainSync { taskbarView.updateItems(emptyArray(), createRecents(recentsSize)) }
+
+        val expectedNumRecents = getExpectedNumRecentsWithOverflow()
+        assertThat(taskbarView)
+            .hasRecentsOrder(
+                startIndex = iconViews.size - expectedNumRecents,
+                expectedIds = ((recentsSize - expectedNumRecents)..<recentsSize).toList(),
+            )
+    }
+
+    @Test
+    @ForceRtl
+    fun testUpdateItems_rtl_moreThanMaxRecents_verifyShownRecentsReversed() {
+        val recentsSize = maxShownRecents + 2
+        runOnMainSync { taskbarView.updateItems(emptyArray(), createRecents(recentsSize)) }
+
+        val expectedNumRecents = getExpectedNumRecentsWithOverflow()
+        assertThat(taskbarView)
+            .hasRecentsOrder(
+                startIndex = 0,
+                expectedIds = ((recentsSize - expectedNumRecents)..<recentsSize).toList().reversed(),
+            )
+    }
+
+    /** Returns the number of expected recents outside of the overflow based on [hotseatSize]. */
+    private fun getExpectedNumRecentsWithOverflow(hotseatSize: Int = 0): Int {
+        return maxShownRecents - hotseatSize - 1 // Account for overflow.
+    }
 }