Calculate hotseat width based on available width

Navigation buttons take space on the hotseat, so hotseat width (qsb width and border space between icons) should be calculated instead of having a coded value.

Bug: 223724516
Bug: 228998463
Test: manual, changing display size
Test: manual, changing hotseatBarEndOffset value
Test: HotseatWidthCalculationTest
Change-Id: Ibd4f5ff2e06afda8e7420fb744db049d2e418e14
diff --git a/tests/Android.bp b/tests/Android.bp
index 54cded0..1584308 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -24,6 +24,18 @@
       "src/**/*.java",
       "src/**/*.kt"
     ],
+    exclude_srcs: [
+        ":launcher-non-quickstep-tests-src"
+    ],
+}
+
+// Source code used for non-quickstep tests
+filegroup {
+    name: "launcher-non-quickstep-tests-src",
+    srcs: [
+       "src/com/android/launcher3/nonquickstep/**/*.java",
+       "src/com/android/launcher3/nonquickstep/**/*.kt",
+    ],
 }
 
 // Source code used for oop test helpers
@@ -84,6 +96,7 @@
     name: "Launcher3Tests",
     srcs: [
         ":launcher-tests-src",
+        ":launcher-non-quickstep-tests-src",
     ],
     static_libs: ["Launcher3TestLib"],
     libs: [
diff --git a/tests/src/com/android/launcher3/DeviceProfileBaseTest.kt b/tests/src/com/android/launcher3/DeviceProfileBaseTest.kt
index 7046782..cf6be7f 100644
--- a/tests/src/com/android/launcher3/DeviceProfileBaseTest.kt
+++ b/tests/src/com/android/launcher3/DeviceProfileBaseTest.kt
@@ -114,7 +114,6 @@
                     PointF(16f, 16f)
             ).toTypedArray()
             folderBorderSpace = 16f
-            hotseatBorderSpaces = FloatArray(4) { 16f }
             inlineNavButtonsEndSpacing = R.dimen.taskbar_button_margin_4_5
 
             horizontalMargin = FloatArray(4) { 22f }
@@ -136,8 +135,6 @@
 
             numShownHotseatIcons = 4
 
-            numShrunkenHotseatIcons = 4
-
             numDatabaseHotseatIcons = 4
 
             hotseatColumnSpan = IntArray(4) { 4 }
@@ -200,7 +197,6 @@
                     PointF(16f, 64f),
                     PointF(16f, 64f)
             ).toTypedArray()
-            hotseatBorderSpaces = floatArrayOf(58f, 50.4f, 58f, 58f)
             inlineNavButtonsEndSpacing = R.dimen.taskbar_button_margin_6_5
 
             horizontalMargin = floatArrayOf(54f, 120f, 54f, 54f)
@@ -222,8 +218,6 @@
 
             numShownHotseatIcons = 6
 
-            numShrunkenHotseatIcons = 5
-
             numDatabaseHotseatIcons = 6
 
             hotseatColumnSpan = intArrayOf(6, 4, 6, 6)
@@ -297,7 +291,6 @@
                     PointF(20f, 20f)
             ).toTypedArray()
             folderBorderSpace = 16f
-            hotseatBorderSpaces = floatArrayOf(36f, 36f, 18f, 23.3f)
             inlineNavButtonsEndSpacing = R.dimen.taskbar_button_margin_4_4
 
             horizontalMargin = floatArrayOf(21.5f, 21.5f, 22.5f, 30.5f)
@@ -319,8 +312,6 @@
 
             numShownHotseatIcons = 6
 
-            numShrunkenHotseatIcons = 6
-
             numDatabaseHotseatIcons = 6
 
             hotseatColumnSpan = IntArray(4) { 6 }
diff --git a/tests/src/com/android/launcher3/HotseatShownIconsTest.kt b/tests/src/com/android/launcher3/HotseatShownIconsTest.kt
deleted file mode 100644
index 95651ca..0000000
--- a/tests/src/com/android/launcher3/HotseatShownIconsTest.kt
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright (C) 2022 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.launcher3
-
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import com.android.launcher3.InvariantDeviceProfile.TYPE_MULTI_DISPLAY
-import com.android.launcher3.InvariantDeviceProfile.TYPE_PHONE
-import com.android.launcher3.InvariantDeviceProfile.TYPE_TABLET
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-import org.junit.runner.RunWith
-
-/**
- * Test for [DeviceProfile]
- */
-@SmallTest
-@RunWith(AndroidJUnit4::class)
-class HotseatShownIconsTest : DeviceProfileBaseTest() {
-
-    @Test
-    fun hotseat_size_is_shrunk_if_needed_when_large_screen() {
-        initializeVarsForTablet(isLandscape = true)
-        inv = inv!!.apply {
-            deviceType = TYPE_MULTI_DISPLAY
-            inlineQsb = booleanArrayOf(
-                false,
-                false,
-                false,
-                true // two panels landscape
-            )
-        }
-        useTwoPanels = true
-
-        isGestureMode = false
-        val dp = newDP()
-
-        if (dp.hotseatQsbHeight > 0) {
-            assertThat(dp.isQsbInline).isTrue()
-            assertThat(dp.numShownHotseatIcons).isEqualTo(5)
-        } else { // Launcher3 doesn't have QSB height
-            assertThat(dp.isQsbInline).isFalse()
-            assertThat(dp.numShownHotseatIcons).isEqualTo(6)
-        }
-    }
-
-    /**
-     * For consistency, the hotseat should shrink if any orientation on the device type has an
-     * inline qsb
-     */
-    @Test
-    fun hotseat_size_is_shrunk_even_in_portrait_when_large_screen() {
-        initializeVarsForTablet()
-        inv = inv!!.apply {
-            deviceType = TYPE_MULTI_DISPLAY
-            inlineQsb = booleanArrayOf(
-                false,
-                false,
-                false,
-                true // two panels landscape
-            )
-        }
-        useTwoPanels = true
-
-        isGestureMode = false
-        val dp = newDP()
-
-        if (dp.hotseatQsbHeight > 0) {
-            assertThat(dp.isQsbInline).isFalse()
-            assertThat(dp.numShownHotseatIcons).isEqualTo(5)
-        } else { // Launcher3 doesn't have QSB height
-            assertThat(dp.isQsbInline).isFalse()
-            assertThat(dp.numShownHotseatIcons).isEqualTo(6)
-        }
-    }
-
-    @Test
-    fun hotseat_size_is_default_when_small_screen() {
-        initializeVarsForPhone()
-        inv = inv!!.apply {
-            deviceType = TYPE_MULTI_DISPLAY
-        }
-        useTwoPanels = true
-
-        val dp = newDP()
-
-        assertThat(dp.numShownHotseatIcons).isEqualTo(4)
-    }
-
-    @Test
-    fun hotseat_size_is_not_shrunk_on_gesture_tablet() {
-        initializeVarsForTablet(isLandscape = true)
-        inv = inv!!.apply {
-            deviceType = TYPE_TABLET
-            inlineQsb = booleanArrayOf(
-                    false,
-                    true, // landscape
-                    false,
-                    false
-            )
-            numShownHotseatIcons = 6
-        }
-
-        isGestureMode = true
-        val dp = newDP()
-
-        if (dp.hotseatQsbHeight > 0) {
-            assertThat(dp.isQsbInline).isTrue()
-            assertThat(dp.numShownHotseatIcons).isEqualTo(6)
-        } else { // Launcher3 doesn't have QSB height
-            assertThat(dp.isQsbInline).isFalse()
-            assertThat(dp.numShownHotseatIcons).isEqualTo(6)
-        }
-    }
-
-    @Test
-    fun hotseat_size_is_shrunk_if_needed_on_tablet() {
-        initializeVarsForTablet(isLandscape = true)
-        inv = inv!!.apply {
-            deviceType = TYPE_TABLET
-            inlineQsb = booleanArrayOf(
-                false,
-                true, // landscape
-                false,
-                false
-            )
-            numShownHotseatIcons = 6
-        }
-
-        isGestureMode = false
-        val dp = newDP()
-
-        if (dp.hotseatQsbHeight > 0) {
-            assertThat(dp.isQsbInline).isTrue()
-            assertThat(dp.numShownHotseatIcons).isEqualTo(5)
-        } else { // Launcher3 doesn't have QSB height
-            assertThat(dp.isQsbInline).isFalse()
-            assertThat(dp.numShownHotseatIcons).isEqualTo(6)
-        }
-    }
-
-    /**
-     * For consistency, the hotseat should shrink if any orientation on the device type has an
-     * inline qsb
-     */
-    @Test
-    fun hotseat_size_is_shrunk_even_in_portrait_on_tablet() {
-        initializeVarsForTablet()
-        inv = inv!!.apply {
-            deviceType = TYPE_TABLET
-            inlineQsb = booleanArrayOf(
-                false,
-                true, // landscape
-                false,
-                false
-            )
-            numShownHotseatIcons = 6
-        }
-
-        isGestureMode = false
-        val dp = newDP()
-
-        if (dp.hotseatQsbHeight > 0) {
-            assertThat(dp.isQsbInline).isFalse()
-            assertThat(dp.numShownHotseatIcons).isEqualTo(5)
-        } else { // Launcher3 doesn't have QSB height
-            assertThat(dp.isQsbInline).isFalse()
-            assertThat(dp.numShownHotseatIcons).isEqualTo(6)
-        }
-    }
-
-}
\ No newline at end of file
diff --git a/tests/src/com/android/launcher3/nonquickstep/HotseatWidthCalculationTest.kt b/tests/src/com/android/launcher3/nonquickstep/HotseatWidthCalculationTest.kt
new file mode 100644
index 0000000..55520e8
--- /dev/null
+++ b/tests/src/com/android/launcher3/nonquickstep/HotseatWidthCalculationTest.kt
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2022 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.launcher3.nonquickstep
+
+import android.graphics.Rect
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.launcher3.DeviceProfileBaseTest
+import com.android.launcher3.util.WindowBounds
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class HotseatWidthCalculationTest : DeviceProfileBaseTest() {
+
+    /**
+     * This is a case when after setting the hotseat, the space needs to be recalculated
+     * but it doesn't need to change QSB width or remove icons
+     */
+    @Test
+    fun distribute_border_space_when_space_is_enough_portrait() {
+        initializeVarsForTablet(isGestureMode = false)
+        windowBounds = WindowBounds(Rect(0, 0, 1800, 2560), Rect(0, 104, 0, 0))
+        val dp = newDP()
+        dp.isTaskbarPresentInApps = true
+
+        assertThat(dp.hotseatBarEndOffset).isEqualTo(0)
+        assertThat(dp.numShownHotseatIcons).isEqualTo(6)
+        assertThat(dp.hotseatBorderSpace).isEqualTo(145)
+
+        assertThat(dp.getHotseatLayoutPadding(context).left).isEqualTo(177)
+        assertThat(dp.getHotseatLayoutPadding(context).right).isEqualTo(177)
+
+        assertThat(dp.isQsbInline).isFalse()
+        assertThat(dp.hotseatQsbWidth).isEqualTo(1445)
+    }
+
+    /**
+     * This is a case when after setting the hotseat, and recalculating spaces
+     * it still needs to remove icons for everything to fit
+     */
+    @Test
+    fun decrease_num_of_icons_when_not_enough_space_portrait() {
+        initializeVarsForTablet(isGestureMode = false)
+        windowBounds = WindowBounds(Rect(0, 0, 1300, 2560), Rect(0, 104, 0, 0))
+        val dp = newDP()
+        dp.isTaskbarPresentInApps = true
+
+        assertThat(dp.hotseatBarEndOffset).isEqualTo(0)
+        assertThat(dp.numShownHotseatIcons).isEqualTo(6)
+        assertThat(dp.hotseatBorderSpace).isEqualTo(94)
+
+        assertThat(dp.getHotseatLayoutPadding(context).left).isEqualTo(121)
+        assertThat(dp.getHotseatLayoutPadding(context).right).isEqualTo(121)
+
+        assertThat(dp.isQsbInline).isFalse()
+        assertThat(dp.hotseatQsbWidth).isEqualTo(1058)
+    }
+
+    /**
+     * This is a case when after setting the hotseat, the space needs to be recalculated
+     * but it doesn't need to change QSB width or remove icons
+     */
+    @Test
+    fun distribute_border_space_when_space_is_enough_landscape() {
+        initializeVarsForTwoPanel(isGestureMode = false, isLandscape = true)
+        val dp = newDP()
+        dp.isTaskbarPresentInApps = true
+
+        assertThat(dp.hotseatBarEndOffset).isEqualTo(0)
+        assertThat(dp.numShownHotseatIcons).isEqualTo(6)
+        assertThat(dp.hotseatBorderSpace).isEqualTo(105)
+
+        assertThat(dp.getHotseatLayoutPadding(context).left).isEqualTo(370)
+        assertThat(dp.getHotseatLayoutPadding(context).right).isEqualTo(370)
+
+        assertThat(dp.isQsbInline).isFalse()
+        assertThat(dp.hotseatQsbWidth).isEqualTo(1467)
+    }
+
+    /**
+     * This is a case when the hotseat spans a certain amount of columns
+     * and the nav buttons push the hotseat to the side, but not enough to change the border space.
+     */
+    @Test
+    fun nav_buttons_dont_interfere_with_required_hotseat_width() {
+        initializeVarsForTablet(isGestureMode = false, isLandscape = true)
+        inv?.apply {
+            hotseatColumnSpan = IntArray(4) { 4 }
+            inlineQsb = BooleanArray(4) { false }
+        }
+        val dp = newDP()
+        dp.isTaskbarPresentInApps = true
+
+        assertThat(dp.hotseatBarEndOffset).isEqualTo(0)
+        assertThat(dp.numShownHotseatIcons).isEqualTo(6)
+        assertThat(dp.hotseatBorderSpace).isEqualTo(100)
+
+        assertThat(dp.getHotseatLayoutPadding(context).left).isEqualTo(668)
+        assertThat(dp.getHotseatLayoutPadding(context).right).isEqualTo(668)
+
+        assertThat(dp.isQsbInline).isFalse()
+        assertThat(dp.hotseatQsbWidth).isEqualTo(1224)
+    }
+
+    /**
+     * This is a case when after setting the hotseat, the QSB width needs to be changed to fit
+     */
+    @Test
+    fun decrease_qsb_when_not_enough_space_landscape() {
+        initializeVarsForTablet(isGestureMode = false, isLandscape = true)
+        windowBounds = WindowBounds(Rect(0, 0, 2460, 1600), Rect(0, 104, 0, 0))
+        val dp = newDP()
+        dp.isTaskbarPresentInApps = true
+
+        assertThat(dp.hotseatBarEndOffset).isEqualTo(0)
+        assertThat(dp.numShownHotseatIcons).isEqualTo(6)
+        assertThat(dp.hotseatBorderSpace).isEqualTo(96)
+
+        assertThat(dp.getHotseatLayoutPadding(context).left).isEqualTo(643)
+        assertThat(dp.getHotseatLayoutPadding(context).right).isEqualTo(643)
+
+        assertThat(dp.isQsbInline).isFalse()
+        assertThat(dp.hotseatQsbWidth).isEqualTo(1174)
+    }
+
+    /**
+     * This is a case when after setting the hotseat, changing QSB width, and recalculating spaces
+     * it still needs to remove icons for everything to fit
+     */
+    @Test
+    fun decrease_num_of_icons_when_not_enough_space_landscape() {
+        initializeVarsForTablet(isGestureMode = false, isLandscape = true)
+        windowBounds = WindowBounds(Rect(0, 0, 2260, 1600), Rect(0, 104, 0, 0))
+        val dp = newDP()
+        dp.isTaskbarPresentInApps = true
+
+        assertThat(dp.hotseatBarEndOffset).isEqualTo(0)
+        assertThat(dp.numShownHotseatIcons).isEqualTo(6)
+        assertThat(dp.hotseatBorderSpace).isEqualTo(89)
+
+        assertThat(dp.getHotseatLayoutPadding(context).left).isEqualTo(589)
+        assertThat(dp.getHotseatLayoutPadding(context).right).isEqualTo(589)
+
+        assertThat(dp.isQsbInline).isFalse()
+        assertThat(dp.hotseatQsbWidth).isEqualTo(1081)
+    }
+}