Merge "adding the new Material U App Shortcut Popup design" into tm-qpr-dev
diff --git a/quickstep/res/drawable/keyboard_quick_switch_overview_button_background.xml b/quickstep/res/drawable/keyboard_quick_switch_overview_button_background.xml
new file mode 100644
index 0000000..286a3c4
--- /dev/null
+++ b/quickstep/res/drawable/keyboard_quick_switch_overview_button_background.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<shape
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ android:shape="rectangle">
+ <solid android:color="?androidprv:attr/colorSurfaceVariant" />
+ <corners android:radius="@dimen/keyboard_quick_switch_task_view_radius" />
+</shape>
diff --git a/quickstep/res/drawable/keyboard_quick_switch_task_view_background.xml b/quickstep/res/drawable/keyboard_quick_switch_task_view_background.xml
new file mode 100644
index 0000000..d0aac8c
--- /dev/null
+++ b/quickstep/res/drawable/keyboard_quick_switch_task_view_background.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<shape
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <solid android:color="@android:color/transparent" />
+ <corners android:radius="@dimen/keyboard_quick_switch_task_view_radius" />
+</shape>
diff --git a/quickstep/res/drawable/keyboard_quick_switch_view_background.xml b/quickstep/res/drawable/keyboard_quick_switch_view_background.xml
new file mode 100644
index 0000000..19aaed4
--- /dev/null
+++ b/quickstep/res/drawable/keyboard_quick_switch_view_background.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<shape
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <solid android:color="?attr/overviewScrimColor" />
+ <corners android:radius="@dimen/keyboard_quick_switch_view_radius" />
+</shape>
diff --git a/quickstep/res/layout-land/keyboard_quick_switch_taskview.xml b/quickstep/res/layout-land/keyboard_quick_switch_taskview.xml
new file mode 100644
index 0000000..18c0e1f
--- /dev/null
+++ b/quickstep/res/layout-land/keyboard_quick_switch_taskview.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<com.android.launcher3.taskbar.KeyboardQuickSwitchTaskView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:launcher="http://schemas.android.com/apk/res-auto"
+ android:layout_width="@dimen/keyboard_quick_switch_taskview_width"
+ android:layout_height="@dimen/keyboard_quick_switch_taskview_height"
+ android:importantForAccessibility="yes"
+ android:background="@drawable/keyboard_quick_switch_task_view_background"
+ android:clipToOutline="true"
+ launcher:borderColor="?androidprv:attr/colorAccentSecondaryVariant">
+
+ <include
+ layout="@layout/keyboard_quick_switch_thumbnail"
+ android:id="@+id/thumbnail1"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toStartOf="@id/thumbnail2"/>
+
+ <include
+ layout="@layout/keyboard_quick_switch_thumbnail"
+ android:id="@+id/thumbnail2"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:visibility="gone"
+ android:layout_marginStart="@dimen/keyboard_quick_switch_split_view_spacing"
+
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toEndOf="@id/thumbnail1"
+ app:layout_constraintEnd_toEndOf="parent"/>
+
+</com.android.launcher3.taskbar.KeyboardQuickSwitchTaskView>
diff --git a/quickstep/res/layout/keyboard_quick_switch_overview.xml b/quickstep/res/layout/keyboard_quick_switch_overview.xml
new file mode 100644
index 0000000..bf21a3e
--- /dev/null
+++ b/quickstep/res/layout/keyboard_quick_switch_overview.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<com.android.launcher3.taskbar.KeyboardQuickSwitchTaskView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:launcher="http://schemas.android.com/apk/res-auto"
+ android:layout_width="@dimen/keyboard_quick_switch_taskview_width"
+ android:layout_height="@dimen/keyboard_quick_switch_taskview_height"
+ android:background="@drawable/keyboard_quick_switch_overview_button_background"
+ android:clipToOutline="true"
+ android:importantForAccessibility="yes"
+ launcher:borderColor="?androidprv:attr/colorAccentSecondaryVariant">
+
+ <ImageView
+ android:id="@+id/icon"
+ android:layout_width="@dimen/keyboard_quick_switch_recents_icon_size"
+ android:layout_height="@dimen/keyboard_quick_switch_recents_icon_size"
+ android:layout_marginBottom="8dp"
+ android:src="@drawable/ic_empty_recents"
+
+ app:tint="?android:attr/textColorPrimary"
+ app:layout_constraintVertical_chainStyle="packed"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toTopOf="@id/text"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"/>
+
+ <TextView
+ style="@style/KeyboardQuickSwitchOverview"
+ android:id="@+id/text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAlignment="center"
+
+ app:layout_constraintTop_toBottomOf="@id/icon"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"/>
+
+</com.android.launcher3.taskbar.KeyboardQuickSwitchTaskView>
diff --git a/quickstep/res/layout/keyboard_quick_switch_taskview.xml b/quickstep/res/layout/keyboard_quick_switch_taskview.xml
new file mode 100644
index 0000000..48e6276
--- /dev/null
+++ b/quickstep/res/layout/keyboard_quick_switch_taskview.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<com.android.launcher3.taskbar.KeyboardQuickSwitchTaskView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:launcher="http://schemas.android.com/apk/res-auto"
+ android:layout_width="@dimen/keyboard_quick_switch_taskview_width"
+ android:layout_height="@dimen/keyboard_quick_switch_taskview_height"
+ android:importantForAccessibility="yes"
+ android:background="@drawable/keyboard_quick_switch_task_view_background"
+ android:clipToOutline="true"
+ launcher:borderColor="?androidprv:attr/colorAccentSecondaryVariant">
+
+ <include
+ layout="@layout/keyboard_quick_switch_thumbnail"
+ android:id="@+id/thumbnail1"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toTopOf="@id/thumbnail2"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"/>
+
+ <include
+ layout="@layout/keyboard_quick_switch_thumbnail"
+ android:id="@+id/thumbnail2"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:visibility="gone"
+ android:layout_marginTop="@dimen/keyboard_quick_switch_split_view_spacing"
+
+ app:layout_constraintTop_toBottomOf="@id/thumbnail1"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"/>
+
+</com.android.launcher3.taskbar.KeyboardQuickSwitchTaskView>
diff --git a/quickstep/res/layout/keyboard_quick_switch_thumbnail.xml b/quickstep/res/layout/keyboard_quick_switch_thumbnail.xml
new file mode 100644
index 0000000..cd6587c
--- /dev/null
+++ b/quickstep/res/layout/keyboard_quick_switch_thumbnail.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<ImageView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:scaleType="centerCrop"
+ android:background="@drawable/keyboard_quick_switch_task_view_background"
+ android:clipToOutline="true"/>
diff --git a/quickstep/res/layout/keyboard_quick_switch_view.xml b/quickstep/res/layout/keyboard_quick_switch_view.xml
new file mode 100644
index 0000000..5c20a2d
--- /dev/null
+++ b/quickstep/res/layout/keyboard_quick_switch_view.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<com.android.launcher3.taskbar.KeyboardQuickSwitchView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingVertical="@dimen/keyboard_quick_switch_view_spacing"
+ android:layout_marginTop="@dimen/keyboard_quick_switch_margin_top"
+ android:layout_marginHorizontal="@dimen/keyboard_quick_switch_margin_ends"
+ android:background="@drawable/keyboard_quick_switch_view_background"
+ android:clipToOutline="true"
+ android:alpha="0"
+ android:visibility="invisible"
+ android:focusableInTouchMode="true">
+
+ <HorizontalScrollView
+ android:id="@+id/scroll_view"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:fillViewport="true"
+ android:scrollbars="none"
+ android:alpha="0"
+ android:visibility="invisible"
+
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toStartOf="parent">
+
+ <androidx.constraintlayout.widget.ConstraintLayout
+ android:id="@+id/content"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+
+ </HorizontalScrollView>
+
+</com.android.launcher3.taskbar.KeyboardQuickSwitchView>
diff --git a/quickstep/res/values-land/dimens.xml b/quickstep/res/values-land/dimens.xml
index 30983c4..ee594c8 100644
--- a/quickstep/res/values-land/dimens.xml
+++ b/quickstep/res/values-land/dimens.xml
@@ -82,4 +82,6 @@
<dimen name="taskbar_suw_frame">96dp</dimen>
<dimen name="taskbar_suw_insets">24dp</dimen>
-</resources>
\ No newline at end of file
+ <dimen name="keyboard_quick_switch_taskview_width">205dp</dimen>
+ <dimen name="keyboard_quick_switch_taskview_height">119dp</dimen>
+</resources>
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index fb04cc0..d5e8351 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -331,4 +331,13 @@
<!-- Keyboard Quick Switch -->
<dimen name="keyboard_quick_switch_border_width">4dp</dimen>
+ <dimen name="keyboard_quick_switch_taskview_width">104dp</dimen>
+ <dimen name="keyboard_quick_switch_taskview_height">134dp</dimen>
+ <dimen name="keyboard_quick_switch_recents_icon_size">20dp</dimen>
+ <dimen name="keyboard_quick_switch_margin_top">56dp</dimen>
+ <dimen name="keyboard_quick_switch_margin_ends">16dp</dimen>
+ <dimen name="keyboard_quick_switch_view_spacing">16dp</dimen>
+ <dimen name="keyboard_quick_switch_split_view_spacing">2dp</dimen>
+ <dimen name="keyboard_quick_switch_view_radius">28dp</dimen>
+ <dimen name="keyboard_quick_switch_task_view_radius">16dp</dimen>
</resources>
diff --git a/quickstep/res/values/strings.xml b/quickstep/res/values/strings.xml
index d2f5802..01d92d1 100644
--- a/quickstep/res/values/strings.xml
+++ b/quickstep/res/values/strings.xml
@@ -282,4 +282,12 @@
<string name="move_drop_target_top_or_left">Move to top/left</string>
<!-- Label for moving drop target to the bottom or right side of the screen, depending on orientation (from the Taskbar only). -->
<string name="move_drop_target_bottom_or_right">Move to bottom/right</string>
+
+ <!-- Label for quick switch tile showing how many more apps are available [CHAR LIMIT=NONE] -->
+ <string name="quick_switch_overflow">{count, plural,
+ =1{Show # more app.}
+ other{Show # more apps.}
+ }</string>
+ <!-- Accessibility label for quick switch tiles showing split tasks [CHAR LIMIT=NONE] -->
+ <string name="quick_switch_split_task"><xliff:g id="app_name_1" example="Chrome">%1$s</xliff:g> and <xliff:g id="app_name_2" example="Gmail">%2$s</xliff:g></string>
</resources>
diff --git a/quickstep/res/values/styles.xml b/quickstep/res/values/styles.xml
index 6119eb6..4417407 100644
--- a/quickstep/res/values/styles.xml
+++ b/quickstep/res/values/styles.xml
@@ -223,4 +223,11 @@
<item name="android:fontFamily">google-sans-text</item>
<item name="android:textSize">14sp</item>
</style>
-</resources>
\ No newline at end of file
+
+ <style name="KeyboardQuickSwitchOverview">
+ <item name="fontFamily">google-sans-text</item>
+ <item name="android:textSize">14sp</item>
+ <item name="android:textColor">?android:attr/textColorPrimary</item>
+ <item name="lineHeight">20sp</item>
+ </style>
+</resources>
diff --git a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchController.java b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchController.java
new file mode 100644
index 0000000..c4962cd
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchController.java
@@ -0,0 +1,192 @@
+/*
+ * 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.launcher3.taskbar;
+
+import android.content.ComponentName;
+import android.content.pm.ActivityInfo;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.launcher3.R;
+import com.android.launcher3.taskbar.overlay.TaskbarOverlayContext;
+import com.android.quickstep.RecentsModel;
+import com.android.quickstep.util.GroupTask;
+import com.android.systemui.shared.recents.model.Task;
+import com.android.systemui.shared.recents.model.ThumbnailData;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
+
+/**
+ * Handles initialization of the {@link KeyboardQuickSwitchViewController}.
+ */
+public final class KeyboardQuickSwitchController implements
+ TaskbarControllers.LoggableTaskbarController {
+
+ static final int MAX_TASKS = 6;
+
+ @NonNull private final ControllerCallbacks mControllerCallbacks = new ControllerCallbacks();
+
+ // Initialized on init
+ @Nullable private RecentsModel mModel;
+
+ // Used to keep track of the last requested task list id, so that we do not request to load the
+ // tasks again if we have already requested it and the task list has not changed
+ private int mTaskListChangeId = -1;
+ // Only empty before the recent tasks list has been loaded the first time
+ @NonNull private List<GroupTask> mTasks = new ArrayList<>();
+ private int mNumHiddenTasks = 0;
+
+ // Initialized in init
+ private TaskbarControllers mControllers;
+
+ @Nullable private KeyboardQuickSwitchViewController mQuickSwitchViewController;
+
+ /** Initialize the controller. */
+ public void init(@NonNull TaskbarControllers controllers) {
+ mControllers = controllers;
+ mModel = RecentsModel.INSTANCE.get(controllers.taskbarActivityContext);
+ }
+
+ void onConfigurationChanged(@ActivityInfo.Config int configChanges) {
+ if (mQuickSwitchViewController == null) {
+ return;
+ }
+ if ((configChanges & (ActivityInfo.CONFIG_KEYBOARD
+ | ActivityInfo.CONFIG_KEYBOARD_HIDDEN)) != 0) {
+ mQuickSwitchViewController.closeQuickSwitchView(true);
+ return;
+ }
+ int currentFocusedIndex = mQuickSwitchViewController.getCurrentFocusedIndex();
+ onDestroy();
+ if (currentFocusedIndex != -1) {
+ mControllers.taskbarActivityContext.getMainThreadHandler().post(
+ () -> openQuickSwitchView(currentFocusedIndex));
+ }
+ }
+
+ void openQuickSwitchView() {
+ openQuickSwitchView(-1);
+ }
+
+ private void openQuickSwitchView(int currentFocusedIndex) {
+ if (mQuickSwitchViewController != null) {
+ return;
+ }
+ TaskbarOverlayContext overlayContext =
+ mControllers.taskbarOverlayController.requestWindow();
+ KeyboardQuickSwitchView keyboardQuickSwitchView =
+ (KeyboardQuickSwitchView) overlayContext.getLayoutInflater()
+ .inflate(
+ R.layout.keyboard_quick_switch_view,
+ overlayContext.getDragLayer(),
+ /* attachToRoot= */ false);
+ mQuickSwitchViewController = new KeyboardQuickSwitchViewController(
+ mControllers, overlayContext, keyboardQuickSwitchView, mControllerCallbacks);
+
+ if (mModel.isTaskListValid(mTaskListChangeId)) {
+ mQuickSwitchViewController.openQuickSwitchView(
+ mTasks, mNumHiddenTasks, /* updateTasks= */ false, currentFocusedIndex);
+ return;
+ }
+ mTaskListChangeId = mModel.getTasks((tasks) -> {
+ // Only store MAX_TASK tasks, from most to least recent
+ Collections.reverse(tasks);
+ mTasks = tasks.stream().limit(MAX_TASKS).collect(Collectors.toList());
+ mNumHiddenTasks = Math.max(0, tasks.size() - MAX_TASKS);
+ mQuickSwitchViewController.openQuickSwitchView(
+ mTasks, mNumHiddenTasks, /* updateTasks= */ true, currentFocusedIndex);
+ });
+ }
+
+ void closeQuickSwitchView() {
+ if (mQuickSwitchViewController == null) {
+ return;
+ }
+ mQuickSwitchViewController.closeQuickSwitchView(true);
+ }
+
+ /**
+ * See {@link TaskbarUIController#launchFocusedTask()}
+ */
+ int launchFocusedTask() {
+ // Return -1 so that the RecentsView is not incorrectly opened when the user closes the
+ // quick switch view by tapping the screen.
+ return mQuickSwitchViewController == null
+ ? -1 : mQuickSwitchViewController.launchFocusedTask();
+ }
+
+ void onDestroy() {
+ if (mQuickSwitchViewController != null) {
+ mQuickSwitchViewController.onDestroy();
+ }
+ }
+
+ @Override
+ public void dumpLogs(String prefix, PrintWriter pw) {
+ pw.println(prefix + "KeyboardQuickSwitchController:");
+
+ pw.println(prefix + "\tisOpen=" + (mQuickSwitchViewController != null));
+ pw.println(prefix + "\tmNumHiddenTasks=" + mNumHiddenTasks);
+ pw.println(prefix + "\tmTaskListChangeId=" + mTaskListChangeId);
+ pw.println(prefix + "\tmTasks=[");
+ for (GroupTask task : mTasks) {
+ Task task1 = task.task1;
+ Task task2 = task.task2;
+ ComponentName cn1 = task1.getTopComponent();
+ ComponentName cn2 = task2 != null ? task2.getTopComponent() : null;
+ pw.println(prefix + "\t\tt1: (id=" + task1.key.id
+ + "; package=" + (cn1 != null ? cn1.getPackageName() + ")" : "no package)")
+ + " t2: (id=" + (task2 != null ? task2.key.id : "-1")
+ + "; package=" + (cn2 != null ? cn2.getPackageName() + ")"
+ : "no package)"));
+ }
+ pw.println(prefix + "\t]");
+
+ if (mQuickSwitchViewController != null) {
+ mQuickSwitchViewController.dumpLogs(prefix + '\t', pw);
+ }
+ }
+
+ class ControllerCallbacks {
+
+ int getTaskCount() {
+ return mNumHiddenTasks == 0 ? mTasks.size() : MAX_TASKS + 1;
+ }
+
+ @Nullable
+ GroupTask getTaskAt(int index) {
+ return index < 0 || index >= mTasks.size() ? null : mTasks.get(index);
+ }
+
+ void updateThumbnailInBackground(Task task, Consumer<ThumbnailData> callback) {
+ mModel.getThumbnailCache().updateThumbnailInBackground(task, callback);
+ }
+
+ void updateTitleInBackground(Task task, Consumer<Task> callback) {
+ mModel.getIconCache().updateIconInBackground(task, callback);
+ }
+
+ void onCloseComplete() {
+ mQuickSwitchViewController = null;
+ }
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchTaskView.java b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchTaskView.java
new file mode 100644
index 0000000..84129fd
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchTaskView.java
@@ -0,0 +1,173 @@
+/*
+ * 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.launcher3.taskbar;
+
+import static com.android.quickstep.util.BorderAnimator.DEFAULT_BORDER_COLOR;
+
+import android.animation.Animator;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.util.AttributeSet;
+import android.widget.ImageView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.constraintlayout.widget.ConstraintLayout;
+
+import com.android.launcher3.R;
+import com.android.quickstep.util.BorderAnimator;
+import com.android.systemui.shared.recents.model.Task;
+import com.android.systemui.shared.recents.model.ThumbnailData;
+
+import java.util.function.Consumer;
+
+/**
+ * A view that displays a recent task during a keyboard quick switch.
+ */
+public class KeyboardQuickSwitchTaskView extends ConstraintLayout {
+
+ @NonNull private final BorderAnimator mBorderAnimator;
+
+ @Nullable private ImageView mThumbnailView1;
+ @Nullable private ImageView mThumbnailView2;
+
+ public KeyboardQuickSwitchTaskView(@NonNull Context context) {
+ this(context, null);
+ }
+
+ public KeyboardQuickSwitchTaskView(@NonNull Context context, @Nullable AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public KeyboardQuickSwitchTaskView(
+ @NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public KeyboardQuickSwitchTaskView(
+ @NonNull Context context,
+ @Nullable AttributeSet attrs,
+ int defStyleAttr,
+ int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ setWillNotDraw(false);
+ Resources resources = context.getResources();
+ mBorderAnimator = new BorderAnimator(
+ /* borderBoundsBuilder= */ bounds -> bounds.set(0, 0, getWidth(), getHeight()),
+ /* borderWidthPx= */ resources.getDimensionPixelSize(
+ R.dimen.keyboard_quick_switch_border_width),
+ /* borderRadiusPx= */ resources.getDimensionPixelSize(
+ R.dimen.keyboard_quick_switch_task_view_radius),
+ /* borderColor= */ attrs == null
+ ? DEFAULT_BORDER_COLOR
+ : context.getTheme()
+ .obtainStyledAttributes(
+ attrs,
+ R.styleable.TaskView,
+ defStyleAttr,
+ defStyleRes)
+ .getColor(
+ R.styleable.TaskView_borderColor,
+ DEFAULT_BORDER_COLOR),
+ /* invalidateViewCallback= */ KeyboardQuickSwitchTaskView.this::invalidate);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+
+ mThumbnailView1 = findViewById(R.id.thumbnail1);
+ mThumbnailView2 = findViewById(R.id.thumbnail2);
+ }
+
+ @NonNull
+ protected Animator getFocusAnimator(boolean focused) {
+ return mBorderAnimator.buildAnimator(focused);
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ super.draw(canvas);
+ mBorderAnimator.drawBorder(canvas);
+ }
+
+ protected void setThumbnails(
+ @NonNull Task task1,
+ @Nullable Task task2,
+ @Nullable ThumbnailUpdateFunction thumbnailUpdateFunction,
+ @Nullable TitleUpdateFunction titleUpdateFunction) {
+ applyThumbnail(mThumbnailView1, task1, thumbnailUpdateFunction);
+ applyThumbnail(mThumbnailView2, task2, thumbnailUpdateFunction);
+
+ if (titleUpdateFunction == null) {
+ setContentDescription(task2 == null
+ ? task1.titleDescription
+ : getContext().getString(
+ R.string.quick_switch_split_task,
+ task1.titleDescription,
+ task2.titleDescription));
+ return;
+ }
+ titleUpdateFunction.updateTitleInBackground(task1, t ->
+ setContentDescription(task1.titleDescription));
+ if (task2 == null) {
+ return;
+ }
+ titleUpdateFunction.updateTitleInBackground(task2, t ->
+ setContentDescription(getContext().getString(
+ R.string.quick_switch_split_task,
+ task1.titleDescription,
+ task2.titleDescription)));
+ }
+
+ private void applyThumbnail(
+ @Nullable ImageView thumbnailView,
+ @Nullable Task task,
+ @Nullable ThumbnailUpdateFunction updateFunction) {
+ if (thumbnailView == null) {
+ return;
+ }
+ if (task == null) {
+ return;
+ }
+ if (updateFunction == null) {
+ applyThumbnail(thumbnailView, task.thumbnail);
+ return;
+ }
+ updateFunction.updateThumbnailInBackground(
+ task, thumbnailData -> applyThumbnail(thumbnailView, thumbnailData));
+ }
+
+ private void applyThumbnail(
+ @NonNull ImageView thumbnailView, ThumbnailData thumbnailData) {
+ Bitmap bm = thumbnailData == null ? null : thumbnailData.thumbnail;
+
+ thumbnailView.setVisibility(VISIBLE);
+ thumbnailView.setImageBitmap(bm);
+ }
+
+ protected interface ThumbnailUpdateFunction {
+
+ void updateThumbnailInBackground(Task task, Consumer<ThumbnailData> callback);
+ }
+
+ protected interface TitleUpdateFunction {
+
+ void updateTitleInBackground(Task task, Consumer<Task> callback);
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchView.java b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchView.java
new file mode 100644
index 0000000..94d62b2
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchView.java
@@ -0,0 +1,497 @@
+/*
+ * 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.launcher3.taskbar;
+
+import static androidx.constraintlayout.widget.ConstraintLayout.LayoutParams.PARENT_ID;
+
+import static com.android.launcher3.taskbar.KeyboardQuickSwitchController.MAX_TASKS;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Outline;
+import android.graphics.Rect;
+import android.icu.text.MessageFormat;
+import android.util.AttributeSet;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewOutlineProvider;
+import android.view.ViewTreeObserver;
+import android.view.animation.Interpolator;
+import android.widget.HorizontalScrollView;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.constraintlayout.widget.ConstraintLayout;
+
+import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.anim.AnimatedFloat;
+import com.android.launcher3.anim.Interpolators;
+import com.android.quickstep.util.GroupTask;
+
+import java.util.HashMap;
+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.
+ */
+public class KeyboardQuickSwitchView extends ConstraintLayout {
+
+ private static final long OUTLINE_ANIMATION_DURATION_MS = 333;
+ private static final float OUTLINE_START_HEIGHT_FACTOR = 0.45f;
+ private static final float OUTLINE_START_RADIUS_FACTOR = 0.25f;
+ private static final Interpolator OPEN_OUTLINE_INTERPOLATOR =
+ Interpolators.EMPHASIZED_DECELERATE;
+ private static final Interpolator CLOSE_OUTLINE_INTERPOLATOR =
+ Interpolators.EMPHASIZED_ACCELERATE;
+
+ private static final long ALPHA_ANIMATION_DURATION_MS = 83;
+ private static final long ALPHA_ANIMATION_START_DELAY_MS = 67;
+
+ private static final long CONTENT_TRANSLATION_X_ANIMATION_DURATION_MS = 500;
+ private static final long CONTENT_TRANSLATION_Y_ANIMATION_DURATION_MS = 333;
+ private static final float CONTENT_START_TRANSLATION_X_DP = 32;
+ private static final float CONTENT_START_TRANSLATION_Y_DP = 40;
+ private static final Interpolator OPEN_TRANSLATION_X_INTERPOLATOR = Interpolators.EMPHASIZED;
+ private static final Interpolator OPEN_TRANSLATION_Y_INTERPOLATOR =
+ Interpolators.EMPHASIZED_DECELERATE;
+ private static final Interpolator CLOSE_TRANSLATION_Y_INTERPOLATOR =
+ Interpolators.EMPHASIZED_ACCELERATE;
+
+ private static final long CONTENT_ALPHA_ANIMATION_DURATION_MS = 83;
+ private static final long CONTENT_ALPHA_ANIMATION_START_DELAY_MS = 83;
+
+ private final AnimatedFloat mOutlineAnimationProgress = new AnimatedFloat(
+ this::invalidateOutline);
+
+ private HorizontalScrollView mScrollView;
+ private ConstraintLayout mContent;
+
+ private int mTaskViewHeight;
+ private int mSpacing;
+ private int mOutlineRadius;
+ private boolean mIsRtl;
+
+ @Nullable private AnimatorSet mOpenAnimation;
+
+ @Nullable private KeyboardQuickSwitchViewController.ViewCallbacks mViewCallbacks;
+
+ public KeyboardQuickSwitchView(@NonNull Context context) {
+ this(context, null);
+ }
+
+ public KeyboardQuickSwitchView(@NonNull Context context, @Nullable AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public KeyboardQuickSwitchView(@NonNull Context context, @Nullable AttributeSet attrs,
+ int defStyleAttr) {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public KeyboardQuickSwitchView(@NonNull Context context, @Nullable AttributeSet attrs,
+ int defStyleAttr,
+ int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mScrollView = findViewById(R.id.scroll_view);
+ mContent = findViewById(R.id.content);
+
+ Resources resources = getResources();
+ mTaskViewHeight = resources.getDimensionPixelSize(
+ R.dimen.keyboard_quick_switch_taskview_height);
+ mSpacing = resources.getDimensionPixelSize(R.dimen.keyboard_quick_switch_view_spacing);
+ mOutlineRadius = resources.getDimensionPixelSize(R.dimen.keyboard_quick_switch_view_radius);
+ mIsRtl = Utilities.isRtl(resources);
+ }
+
+ @NonNull
+ private KeyboardQuickSwitchTaskView createAndAddTaskView(
+ int index,
+ int width,
+ boolean isFinalView,
+ boolean updateTasks,
+ @NonNull LayoutInflater layoutInflater,
+ @Nullable View previousView,
+ @NonNull List<GroupTask> groupTasks) {
+ KeyboardQuickSwitchTaskView taskView = (KeyboardQuickSwitchTaskView) layoutInflater.inflate(
+ R.layout.keyboard_quick_switch_taskview, mContent, false);
+ taskView.setId(View.generateViewId());
+ taskView.setOnClickListener(v -> mViewCallbacks.launchTappedTask(index));
+
+ LayoutParams lp = new LayoutParams(width, mTaskViewHeight);
+ // Create a right-to-left ordering of views (or left-to-right in RTL locales)
+ if (previousView != null) {
+ lp.endToStart = previousView.getId();
+ } else {
+ lp.endToEnd = PARENT_ID;
+ }
+ lp.topToTop = PARENT_ID;
+ lp.bottomToBottom = PARENT_ID;
+ // Add spacing between views
+ lp.setMarginEnd(mSpacing);
+ if (isFinalView) {
+ // Add spacing to the start of the final view so that scrolling ends with some padding.
+ lp.startToStart = PARENT_ID;
+ lp.setMarginStart(mSpacing);
+ lp.horizontalBias = 1f;
+ }
+
+ GroupTask groupTask = groupTasks.get(index);
+ taskView.setThumbnails(
+ groupTask.task1,
+ groupTask.task2,
+ updateTasks ? mViewCallbacks::updateThumbnailInBackground : null,
+ updateTasks ? mViewCallbacks::updateTitleInBackground : null);
+
+ mContent.addView(taskView, lp);
+ return taskView;
+ }
+
+ private void createAndAddOverviewButton(
+ int width,
+ @NonNull LayoutInflater layoutInflater,
+ @Nullable View previousView,
+ @NonNull String overflowString) {
+ KeyboardQuickSwitchTaskView overviewButton =
+ (KeyboardQuickSwitchTaskView) layoutInflater.inflate(
+ R.layout.keyboard_quick_switch_overview, this, false);
+ overviewButton.setOnClickListener(v -> mViewCallbacks.launchTappedTask(MAX_TASKS));
+
+ overviewButton.<TextView>findViewById(R.id.text).setText(overflowString);
+
+ ConstraintLayout.LayoutParams lp = new ConstraintLayout.LayoutParams(
+ width, mTaskViewHeight);
+ lp.startToStart = PARENT_ID;
+ lp.endToStart = previousView.getId();
+ lp.topToTop = PARENT_ID;
+ lp.bottomToBottom = PARENT_ID;
+ lp.setMarginEnd(mSpacing);
+ lp.setMarginStart(mSpacing);
+
+ mContent.addView(overviewButton, lp);
+ }
+
+ protected void applyLoadPlan(
+ @NonNull Context context,
+ @NonNull List<GroupTask> groupTasks,
+ int numHiddenTasks,
+ boolean updateTasks,
+ int currentFocusIndexOverride,
+ @NonNull KeyboardQuickSwitchViewController.ViewCallbacks viewCallbacks) {
+ if (groupTasks.isEmpty()) {
+ // Do not show the quick switch view.
+ return;
+ }
+ mViewCallbacks = viewCallbacks;
+ Resources resources = context.getResources();
+ int width = resources.getDimensionPixelSize(R.dimen.keyboard_quick_switch_taskview_width);
+ View previousView = null;
+
+ LayoutInflater layoutInflater = LayoutInflater.from(context);
+ int tasksToDisplay = Math.min(MAX_TASKS, groupTasks.size());
+ for (int i = 0; i < tasksToDisplay; i++) {
+ previousView = createAndAddTaskView(
+ i,
+ width,
+ /* isFinalView= */ i == tasksToDisplay - 1 && numHiddenTasks == 0,
+ updateTasks,
+ layoutInflater,
+ previousView,
+ groupTasks);
+ }
+
+ if (numHiddenTasks > 0) {
+ HashMap<String, Integer> args = new HashMap<>();
+ args.put("count", numHiddenTasks);
+ createAndAddOverviewButton(
+ width,
+ layoutInflater,
+ previousView,
+ new MessageFormat(
+ resources.getString(R.string.quick_switch_overflow),
+ Locale.getDefault()).format(args));
+ }
+
+ getViewTreeObserver().addOnGlobalLayoutListener(
+ new ViewTreeObserver.OnGlobalLayoutListener() {
+ @Override
+ public void onGlobalLayout() {
+ animateOpen(currentFocusIndexOverride);
+
+ getViewTreeObserver().removeOnGlobalLayoutListener(this);
+ }
+ });
+ }
+
+ protected Animator getCloseAnimation() {
+ AnimatorSet closeAnimation = new AnimatorSet();
+
+ Animator outlineAnimation = mOutlineAnimationProgress.animateToValue(0f);
+ outlineAnimation.setDuration(OUTLINE_ANIMATION_DURATION_MS);
+ outlineAnimation.setInterpolator(CLOSE_OUTLINE_INTERPOLATOR);
+ closeAnimation.play(outlineAnimation);
+
+ Animator alphaAnimation = ObjectAnimator.ofFloat(this, ALPHA, 1f, 0f);
+ alphaAnimation.setStartDelay(ALPHA_ANIMATION_START_DELAY_MS);
+ alphaAnimation.setDuration(ALPHA_ANIMATION_DURATION_MS);
+ closeAnimation.play(alphaAnimation);
+
+ Animator translationYAnimation = ObjectAnimator.ofFloat(
+ mScrollView, TRANSLATION_Y, 0, -Utilities.dpToPx(CONTENT_START_TRANSLATION_Y_DP));
+ translationYAnimation.setDuration(CONTENT_TRANSLATION_Y_ANIMATION_DURATION_MS);
+ translationYAnimation.setInterpolator(CLOSE_TRANSLATION_Y_INTERPOLATOR);
+ closeAnimation.play(translationYAnimation);
+
+ Animator contentAlphaAnimation = ObjectAnimator.ofFloat(mScrollView, ALPHA, 1f, 0f);
+ contentAlphaAnimation.setDuration(CONTENT_ALPHA_ANIMATION_DURATION_MS);
+ closeAnimation.play(contentAlphaAnimation);
+
+ closeAnimation.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ super.onAnimationStart(animation);
+ if (mOpenAnimation != null) {
+ mOpenAnimation.cancel();
+ }
+ }
+ });
+
+ return closeAnimation;
+ }
+
+ private void animateOpen(int currentFocusIndexOverride) {
+ if (mOpenAnimation != null) {
+ // Restart animation since currentFocusIndexOverride can change the initial scroll.
+ mOpenAnimation.cancel();
+ }
+ mOpenAnimation = new AnimatorSet();
+
+ Animator outlineAnimation = mOutlineAnimationProgress.animateToValue(1f);
+ outlineAnimation.setDuration(OUTLINE_ANIMATION_DURATION_MS);
+ mOpenAnimation.play(outlineAnimation);
+
+ Animator alphaAnimation = ObjectAnimator.ofFloat(this, ALPHA, 0f, 1f);
+ alphaAnimation.setDuration(ALPHA_ANIMATION_DURATION_MS);
+ mOpenAnimation.play(alphaAnimation);
+
+ Animator translationXAnimation = ObjectAnimator.ofFloat(
+ mScrollView, TRANSLATION_X, -Utilities.dpToPx(CONTENT_START_TRANSLATION_X_DP), 0);
+ translationXAnimation.setDuration(CONTENT_TRANSLATION_X_ANIMATION_DURATION_MS);
+ translationXAnimation.setInterpolator(OPEN_TRANSLATION_X_INTERPOLATOR);
+ mOpenAnimation.play(translationXAnimation);
+
+ Animator translationYAnimation = ObjectAnimator.ofFloat(
+ mScrollView, TRANSLATION_Y, -Utilities.dpToPx(CONTENT_START_TRANSLATION_Y_DP), 0);
+ translationYAnimation.setDuration(CONTENT_TRANSLATION_Y_ANIMATION_DURATION_MS);
+ translationYAnimation.setInterpolator(OPEN_TRANSLATION_Y_INTERPOLATOR);
+ mOpenAnimation.play(translationYAnimation);
+
+ Animator contentAlphaAnimation = ObjectAnimator.ofFloat(mScrollView, ALPHA, 0f, 1f);
+ contentAlphaAnimation.setStartDelay(CONTENT_ALPHA_ANIMATION_START_DELAY_MS);
+ contentAlphaAnimation.setDuration(CONTENT_ALPHA_ANIMATION_DURATION_MS);
+ mOpenAnimation.play(contentAlphaAnimation);
+
+ ViewOutlineProvider outlineProvider = getOutlineProvider();
+ mOpenAnimation.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ super.onAnimationStart(animation);
+ setClipToPadding(false);
+ setOutlineProvider(new ViewOutlineProvider() {
+ @Override
+ public void getOutline(View view, Outline outline) {
+ outline.setRoundRect(
+ /* rect= */ new Rect(
+ /* left= */ 0,
+ /* top= */ 0,
+ /* right= */ getWidth(),
+ /* bottom= */
+ (int) (getHeight() * Utilities.mapBoundToRange(
+ mOutlineAnimationProgress.value,
+ /* lowerBound= */ 0f,
+ /* upperBound= */ 1f,
+ /* toMin= */ OUTLINE_START_HEIGHT_FACTOR,
+ /* toMax= */ 1f,
+ OPEN_OUTLINE_INTERPOLATOR))),
+ /* radius= */ mOutlineRadius * Utilities.mapBoundToRange(
+ mOutlineAnimationProgress.value,
+ /* lowerBound= */ 0f,
+ /* upperBound= */ 1f,
+ /* toMin= */ OUTLINE_START_RADIUS_FACTOR,
+ /* toMax= */ 1f,
+ OPEN_OUTLINE_INTERPOLATOR));
+ }
+ });
+ if (currentFocusIndexOverride == -1) {
+ initializeScroll(/* index= */ 0, /* shouldTruncateTarget= */ false);
+ } else {
+ animateFocusMove(-1, currentFocusIndexOverride);
+ }
+ mScrollView.setVisibility(VISIBLE);
+ setVisibility(VISIBLE);
+ requestFocus();
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ setClipToPadding(true);
+ setOutlineProvider(outlineProvider);
+ invalidateOutline();
+ mOpenAnimation = null;
+ }
+ });
+
+ mOpenAnimation.start();
+ }
+
+ protected void animateFocusMove(int fromIndex, int toIndex) {
+ KeyboardQuickSwitchTaskView focusedTask = getTaskAt(toIndex);
+ if (focusedTask == null) {
+ return;
+ }
+ AnimatorSet focusAnimation = new AnimatorSet();
+ focusAnimation.play(focusedTask.getFocusAnimator(true));
+
+ KeyboardQuickSwitchTaskView previouslyFocusedTask = getTaskAt(fromIndex);
+ if (previouslyFocusedTask != null) {
+ focusAnimation.play(previouslyFocusedTask.getFocusAnimator(false));
+ }
+
+ focusAnimation.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationStart(Animator animation) {
+ super.onAnimationStart(animation);
+ focusedTask.requestAccessibilityFocus();
+ if (fromIndex == -1) {
+ int firstVisibleTaskIndex = toIndex == 0
+ ? toIndex
+ : getTaskAt(toIndex - 1) == null
+ ? toIndex : toIndex - 1;
+ // Scroll so that the previous task view is truncated as a visual hint that
+ // there are more tasks
+ initializeScroll(
+ firstVisibleTaskIndex,
+ /* shouldTruncateTarget= */ firstVisibleTaskIndex != toIndex);
+ } else if (toIndex > fromIndex || toIndex == 0) {
+ // Scrolling to next task view
+ if (mIsRtl) {
+ scrollRightTo(focusedTask);
+ } else {
+ scrollLeftTo(focusedTask);
+ }
+ } else {
+ // Scrolling to previous task view
+ if (mIsRtl) {
+ scrollLeftTo(focusedTask);
+ } else {
+ scrollRightTo(focusedTask);
+ }
+ }
+ if (mViewCallbacks != null) {
+ mViewCallbacks.updateCurrentFocusIndex(toIndex);
+ }
+ }
+ });
+
+ focusAnimation.start();
+ }
+
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+ return (mViewCallbacks != null && mViewCallbacks.onKeyUp(keyCode, event))
+ || super.onKeyUp(keyCode, event);
+ }
+
+ private void initializeScroll(int index, boolean shouldTruncateTarget) {
+ View task = getTaskAt(index);
+ if (task == null) {
+ return;
+ }
+ if (mIsRtl) {
+ scrollRightTo(
+ task, shouldTruncateTarget, /* smoothScroll= */ false);
+ } else {
+ scrollLeftTo(
+ task, shouldTruncateTarget, /* smoothScroll= */ false);
+ }
+ }
+
+ private void scrollRightTo(@NonNull View targetTask) {
+ scrollRightTo(targetTask, /* shouldTruncateTarget= */ false, /* smoothScroll= */ true);
+ }
+
+ private void scrollRightTo(
+ @NonNull View targetTask, boolean shouldTruncateTarget, boolean smoothScroll) {
+ if (smoothScroll && !shouldScroll(targetTask, shouldTruncateTarget)) {
+ return;
+ }
+ int scrollTo = targetTask.getLeft() - mSpacing
+ + (shouldTruncateTarget ? targetTask.getWidth() / 2 : 0);
+ // Scroll so that the focused task is to the left of the list
+ if (smoothScroll) {
+ mScrollView.smoothScrollTo(scrollTo, 0);
+ } else {
+ mScrollView.scrollTo(scrollTo, 0);
+ }
+ }
+
+ private void scrollLeftTo(@NonNull View targetTask) {
+ scrollLeftTo(targetTask, /* shouldTruncateTarget= */ false, /* smoothScroll= */ true);
+ }
+
+ private void scrollLeftTo(
+ @NonNull View targetTask, boolean shouldTruncateTarget, boolean smoothScroll) {
+ if (smoothScroll && !shouldScroll(targetTask, shouldTruncateTarget)) {
+ return;
+ }
+ int scrollTo = targetTask.getRight() + mSpacing - mScrollView.getWidth()
+ - (shouldTruncateTarget ? targetTask.getWidth() / 2 : 0);
+ // Scroll so that the focused task is to the right of the list
+ if (smoothScroll) {
+ mScrollView.smoothScrollTo(scrollTo, 0);
+ } else {
+ mScrollView.scrollTo(scrollTo, 0);
+ }
+ }
+
+ private boolean shouldScroll(@NonNull View targetTask, boolean shouldTruncateTarget) {
+ boolean isTargetTruncated =
+ targetTask.getRight() + mSpacing > mScrollView.getScrollX() + mScrollView.getWidth()
+ || Math.max(0, targetTask.getLeft() - mSpacing) < mScrollView.getScrollX();
+
+ return isTargetTruncated && !shouldTruncateTarget;
+ }
+
+ @Nullable
+ protected KeyboardQuickSwitchTaskView getTaskAt(int index) {
+ return index < 0 || index >= mContent.getChildCount()
+ ? null : (KeyboardQuickSwitchTaskView) mContent.getChildAt(index);
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchViewController.java b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchViewController.java
new file mode 100644
index 0000000..f0f361e
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/KeyboardQuickSwitchViewController.java
@@ -0,0 +1,200 @@
+/*
+ * 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.launcher3.taskbar;
+
+import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
+
+import android.animation.Animator;
+import android.view.KeyEvent;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.launcher3.anim.AnimationSuccessListener;
+import com.android.launcher3.taskbar.overlay.TaskbarOverlayContext;
+import com.android.launcher3.taskbar.overlay.TaskbarOverlayDragLayer;
+import com.android.quickstep.util.GroupTask;
+import com.android.systemui.shared.recents.model.Task;
+import com.android.systemui.shared.recents.model.ThumbnailData;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
+
+import java.io.PrintWriter;
+import java.util.List;
+import java.util.function.Consumer;
+
+/**
+ * Handles initialization of the {@link KeyboardQuickSwitchView} and supplies it with the list of
+ * tasks.
+ */
+public class KeyboardQuickSwitchViewController {
+
+ @NonNull private final ViewCallbacks mViewCallbacks = new ViewCallbacks();
+ @NonNull private final TaskbarControllers mControllers;
+ @NonNull private final TaskbarOverlayContext mOverlayContext;
+ @NonNull private final KeyboardQuickSwitchView mKeyboardQuickSwitchView;
+ @NonNull private final KeyboardQuickSwitchController.ControllerCallbacks mControllerCallbacks;
+
+ @Nullable private Animator mCloseAnimation;
+
+ private int mCurrentFocusIndex = -1;
+
+ protected KeyboardQuickSwitchViewController(
+ @NonNull TaskbarControllers controllers,
+ @NonNull TaskbarOverlayContext overlayContext,
+ @NonNull KeyboardQuickSwitchView keyboardQuickSwitchView,
+ @NonNull KeyboardQuickSwitchController.ControllerCallbacks controllerCallbacks) {
+ mControllers = controllers;
+ mOverlayContext = overlayContext;
+ mKeyboardQuickSwitchView = keyboardQuickSwitchView;
+ mControllerCallbacks = controllerCallbacks;
+ }
+
+ protected int getCurrentFocusedIndex() {
+ return mCurrentFocusIndex;
+ }
+
+ protected void openQuickSwitchView(
+ @NonNull List<GroupTask> tasks,
+ int numHiddenTasks,
+ boolean updateTasks,
+ int currentFocusIndexOverride) {
+ TaskbarOverlayDragLayer dragLayer = mOverlayContext.getDragLayer();
+ dragLayer.addView(mKeyboardQuickSwitchView);
+ dragLayer.runOnClickOnce(v -> closeQuickSwitchView(true));
+
+ mKeyboardQuickSwitchView.applyLoadPlan(
+ mOverlayContext,
+ tasks,
+ numHiddenTasks,
+ updateTasks,
+ currentFocusIndexOverride,
+ mViewCallbacks);
+ }
+
+ protected void closeQuickSwitchView(boolean animate) {
+ if (mCloseAnimation != null) {
+ if (animate) {
+ // Let currently-running animation finish.
+ return;
+ } else {
+ mCloseAnimation.cancel();
+ }
+ }
+ if (!animate) {
+ mCloseAnimation = null;
+ onCloseComplete();
+ return;
+ }
+ mCloseAnimation = mKeyboardQuickSwitchView.getCloseAnimation();
+
+ mCloseAnimation.addListener(new AnimationSuccessListener() {
+ @Override
+ public void onAnimationSuccess(Animator animator) {
+ mCloseAnimation = null;
+ onCloseComplete();
+ }
+ });
+ mCloseAnimation.start();
+ }
+
+ /**
+ * Launched the currently-focused task.
+ *
+ * Returns index -1 iff the RecentsView shouldn't be opened.
+ *
+ * If the index is not -1, then the {@link com.android.quickstep.views.TaskView} at the returned
+ * index will be focused.
+ */
+ protected int launchFocusedTask() {
+ // Launch the second-most recent task if the user quick switches too quickly, if possible.
+ return launchTaskAt(mCurrentFocusIndex == -1
+ ? (mControllerCallbacks.getTaskCount() > 1 ? 1 : 0) : mCurrentFocusIndex);
+ }
+
+ private int launchTaskAt(int index) {
+ KeyboardQuickSwitchTaskView taskView = mKeyboardQuickSwitchView.getTaskAt(index);
+ GroupTask task = mControllerCallbacks.getTaskAt(index);
+ if (taskView == null || task == null) {
+ return Math.max(0, index);
+ } else if (task.task2 == null) {
+ UI_HELPER_EXECUTOR.execute(() ->
+ ActivityManagerWrapper.getInstance().startActivityFromRecents(
+ task.task1.key,
+ mControllers.taskbarActivityContext.getActivityLaunchOptions(
+ taskView, null).options));
+ } else {
+ mControllers.uiController.launchSplitTasks(taskView, task);
+ }
+ return -1;
+ }
+
+ private void onCloseComplete() {
+ mOverlayContext.getDragLayer().removeView(mKeyboardQuickSwitchView);
+ mControllerCallbacks.onCloseComplete();
+ }
+
+ protected void onDestroy() {
+ closeQuickSwitchView(false);
+ }
+
+ public void dumpLogs(String prefix, PrintWriter pw) {
+ pw.println(prefix + "KeyboardQuickSwitchViewController:");
+
+ pw.println(prefix + "\thasFocus=" + mKeyboardQuickSwitchView.hasFocus());
+ pw.println(prefix + "\tcloseAnimationRunning=" + (mCloseAnimation != null));
+ pw.println(prefix + "\tmCurrentFocusIndex=" + mCurrentFocusIndex);
+ }
+
+ class ViewCallbacks {
+
+ boolean onKeyUp(int keyCode, KeyEvent event) {
+ if (keyCode != KeyEvent.KEYCODE_TAB) {
+ return false;
+ }
+ int taskCount = mControllerCallbacks.getTaskCount();
+ int toIndex = mCurrentFocusIndex == -1
+ // Focus the second-most recent app if possible
+ ? (taskCount > 1 ? 1 : 0)
+ : (event.isShiftPressed()
+ // focus a more recent task or loop back to the opposite end
+ ? Math.max(0, mCurrentFocusIndex == 0
+ ? taskCount - 1 : mCurrentFocusIndex - 1)
+ // focus a less recent app or loop back to the opposite end
+ : ((mCurrentFocusIndex + 1) % taskCount));
+
+ mKeyboardQuickSwitchView.animateFocusMove(mCurrentFocusIndex, toIndex);
+
+ return true;
+ }
+
+ void updateCurrentFocusIndex(int index) {
+ mCurrentFocusIndex = index;
+ }
+
+ void launchTappedTask(int index) {
+ KeyboardQuickSwitchViewController.this.launchTaskAt(index);
+ closeQuickSwitchView(true);
+ }
+
+ void updateThumbnailInBackground(Task task, Consumer<ThumbnailData> callback) {
+ mControllerCallbacks.updateThumbnailInBackground(task, callback);
+ }
+
+ void updateTitleInBackground(Task task, Consumer<Task> callback) {
+ mControllerCallbacks.updateTitleInBackground(task, callback);
+ }
+ }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index c0c14a3..6e746ef 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -15,7 +15,6 @@
*/
package com.android.launcher3.taskbar;
-import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.content.pm.PackageManager.FEATURE_PC;
import static android.os.Trace.TRACE_TAG_APP;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
@@ -236,7 +235,8 @@
isDesktopMode
? new DesktopTaskbarRecentAppsController(this)
: TaskbarRecentAppsController.DEFAULT,
- new TaskbarEduTooltipController(this));
+ new TaskbarEduTooltipController(this),
+ new KeyboardQuickSwitchController());
}
public void init(@NonNull TaskbarSharedState sharedState) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
index ea70de4..931d79f 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
@@ -59,6 +59,7 @@
public final TaskbarTranslationController taskbarTranslationController;
public final TaskbarOverlayController taskbarOverlayController;
public final TaskbarEduTooltipController taskbarEduTooltipController;
+ public final KeyboardQuickSwitchController keyboardQuickSwitchController;
@Nullable private LoggableTaskbarController[] mControllersToLog = null;
@Nullable private BackgroundRendererController[] mBackgroundRendererControllers = null;
@@ -103,7 +104,8 @@
VoiceInteractionWindowController voiceInteractionWindowController,
TaskbarTranslationController taskbarTranslationController,
TaskbarRecentAppsController taskbarRecentAppsController,
- TaskbarEduTooltipController taskbarEduTooltipController) {
+ TaskbarEduTooltipController taskbarEduTooltipController,
+ KeyboardQuickSwitchController keyboardQuickSwitchController) {
this.taskbarActivityContext = taskbarActivityContext;
this.taskbarDragController = taskbarDragController;
this.navButtonController = navButtonController;
@@ -127,6 +129,7 @@
this.taskbarTranslationController = taskbarTranslationController;
this.taskbarRecentAppsController = taskbarRecentAppsController;
this.taskbarEduTooltipController = taskbarEduTooltipController;
+ this.keyboardQuickSwitchController = keyboardQuickSwitchController;
}
/**
@@ -159,6 +162,7 @@
taskbarRecentAppsController.init(this);
taskbarTranslationController.init(this);
taskbarEduTooltipController.init(this);
+ keyboardQuickSwitchController.init(this);
mControllersToLog = new LoggableTaskbarController[] {
taskbarDragController, navButtonController, navbarButtonsViewController,
@@ -167,7 +171,7 @@
stashedHandleViewController, taskbarStashController, taskbarEduController,
taskbarAutohideSuspendController, taskbarPopupController, taskbarInsetsController,
voiceInteractionWindowController, taskbarTranslationController,
- taskbarEduTooltipController
+ taskbarEduTooltipController, keyboardQuickSwitchController
};
mBackgroundRendererControllers = new BackgroundRendererController[] {
taskbarDragLayerController, taskbarScrimViewController,
@@ -191,6 +195,7 @@
public void onConfigurationChanged(@Config int configChanges) {
navbarButtonsViewController.onConfigurationChanged(configChanges);
taskbarDragLayerController.onConfigurationChanged();
+ keyboardQuickSwitchController.onConfigurationChanged(configChanges);
}
/**
@@ -216,6 +221,7 @@
taskbarInsetsController.onDestroy();
voiceInteractionWindowController.onDestroy();
taskbarRecentAppsController.onDestroy();
+ keyboardQuickSwitchController.onDestroy();
mControllersToLog = null;
mBackgroundRendererControllers = null;
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
index a388388..6324715 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
@@ -231,6 +231,38 @@
}
/**
+ * Opens the Keyboard Quick Switch View.
+ *
+ * This will set the focus to the first task from the right (from the left in RTL)
+ */
+ public void openQuickSwitchView() {
+ mControllers.keyboardQuickSwitchController.openQuickSwitchView();
+ }
+
+ /**
+ * Closes the Keyboard Quick Switch View.
+ *
+ * No-op if the view is already closed
+ */
+ public void closeQuickSwitchView() {
+ mControllers.keyboardQuickSwitchController.closeQuickSwitchView();
+ }
+
+ /**
+ * Launches the focused task and closes the Keyboard Quick Switch View.
+ *
+ * If the overlay or view are closed, or the overview task is focused, then Overview is
+ * launched. If the overview task is launched, then the first hidden task is focused.
+ *
+ * @return the index of what task should be focused in ; -1 iff Overview shouldn't be launched
+ */
+ public int launchFocusedTask() {
+ int focusedTaskIndex = mControllers.keyboardQuickSwitchController.launchFocusedTask();
+ mControllers.keyboardQuickSwitchController.closeQuickSwitchView();
+ return focusedTaskIndex;
+ }
+
+ /**
* Launches the focused task in splitscreen.
*
* No-op if the view is not yet open.
diff --git a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
index b5240fd..d0fd65f 100644
--- a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
+++ b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
@@ -31,7 +31,10 @@
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.statemanager.StatefulActivity;
+import com.android.launcher3.taskbar.TaskbarUIController;
import com.android.launcher3.util.RunnableList;
import com.android.quickstep.RecentsAnimationCallbacks.RecentsAnimationListener;
import com.android.quickstep.views.RecentsView;
@@ -174,8 +177,25 @@
mOverviewComponentObserver.getActivityInterface();
RecentsView recents = activityInterface.getVisibleRecentsView();
if (recents == null) {
+ T activity = activityInterface.getCreatedActivity();
+ DeviceProfile dp = activity == null ? null : activity.getDeviceProfile();
+ TaskbarUIController uiController = activityInterface.getTaskbarController();
+ boolean allowQuickSwitch = FeatureFlags.ENABLE_KEYBOARD_QUICK_SWITCH.get()
+ && uiController != null
+ && dp != null
+ && (dp.isTablet || dp.isTwoPanels);
+
if (cmd.type == TYPE_HIDE) {
- // already hidden
+ if (!allowQuickSwitch) {
+ return true;
+ }
+ mTaskFocusIndexOverride = uiController.launchFocusedTask();
+ if (mTaskFocusIndexOverride == -1) {
+ return true;
+ }
+ }
+ if (cmd.type == TYPE_KEYBOARD_INPUT && allowQuickSwitch) {
+ uiController.openQuickSwitchView();
return true;
}
if (cmd.type == TYPE_HOME) {
diff --git a/quickstep/src/com/android/quickstep/util/BorderAnimator.java b/quickstep/src/com/android/quickstep/util/BorderAnimator.java
index 532edb2..1f1c15b 100644
--- a/quickstep/src/com/android/quickstep/util/BorderAnimator.java
+++ b/quickstep/src/com/android/quickstep/util/BorderAnimator.java
@@ -38,7 +38,8 @@
* 1. Create an instance in the target view.
* 2. Override the target view's {@link android.view.View#draw(Canvas)} method and call
* {@link BorderAnimator#drawBorder(Canvas)} after {@code super.draw(canvas)}.
- * 3. Call {@link BorderAnimator#buildAnimator(boolean)} and start the animation where appropriate.
+ * 3. Call {@link BorderAnimator#buildAnimator(boolean)} and start the animation or call
+ * {@link BorderAnimator#setBorderVisible(boolean)} where appropriate.
*/
public final class BorderAnimator {
@@ -138,6 +139,7 @@
/**
* Builds the border appearance/disappearance animation.
*/
+ @NonNull
public Animator buildAnimator(boolean isAppearing) {
mBorderBoundsBuilder.updateBorderBounds(mBorderBounds);
mRunningBorderAnimation = mBorderAnimationProgress.animateToValue(isAppearing ? 1f : 0f);
@@ -151,6 +153,18 @@
}
/**
+ * Immediately shows/hides the border without an animation.
+ *
+ * To animate the appearance/disappearance, see {@link BorderAnimator#buildAnimator(boolean)}
+ */
+ public void setBorderVisible(boolean visible) {
+ if (mRunningBorderAnimation != null) {
+ mRunningBorderAnimation.end();
+ }
+ mBorderAnimationProgress.updateValue(visible ? 1f : 0f);
+ }
+
+ /**
* Callback to update the border bounds when building this animation.
*/
public interface BorderBoundsBuilder {
diff --git a/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarBaseTestCase.kt b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarBaseTestCase.kt
index 8a78d8c..28229a6 100644
--- a/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarBaseTestCase.kt
+++ b/quickstep/tests/src/com/android/launcher3/taskbar/TaskbarBaseTestCase.kt
@@ -52,6 +52,7 @@
@Mock lateinit var taskbarTranslationController: TaskbarTranslationController
@Mock lateinit var taskbarOverlayController: TaskbarOverlayController
@Mock lateinit var taskbarEduTooltipController: TaskbarEduTooltipController
+ @Mock lateinit var keyboardQuickSwitchController: KeyboardQuickSwitchController
lateinit var mTaskbarControllers: TaskbarControllers
@@ -90,6 +91,7 @@
taskbarTranslationController,
taskbarRecentAppsController,
taskbarEduTooltipController,
+ keyboardQuickSwitchController
)
}
}
diff --git a/res/values-land/dimens.xml b/res/values-land/dimens.xml
index 422240c..d0c26aa 100644
--- a/res/values-land/dimens.xml
+++ b/res/values-land/dimens.xml
@@ -23,7 +23,6 @@
<!-- Dynamic grid -->
<dimen name="dynamic_grid_edge_margin">15.28dp</dimen>
- <dimen name="dynamic_grid_icon_drawable_padding">4dp</dimen>
<dimen name="dynamic_grid_drop_target_size">36dp</dimen>
<dimen name="cell_layout_padding">20dp</dimen>
diff --git a/res/values-sw600dp/dimens.xml b/res/values-sw600dp/dimens.xml
index 0af0603..cc1f09e 100644
--- a/res/values-sw600dp/dimens.xml
+++ b/res/values-sw600dp/dimens.xml
@@ -35,7 +35,6 @@
<!-- Dynamic grid -->
<dimen name="dynamic_grid_edge_margin">9dp</dimen>
- <dimen name="dynamic_grid_icon_drawable_padding">7dp</dimen>
<dimen name="cell_layout_padding">9dp</dimen>
<!-- Hotseat -->
diff --git a/res/values-sw600dp/styles.xml b/res/values-sw600dp/styles.xml
new file mode 100644
index 0000000..63bd46b
--- /dev/null
+++ b/res/values-sw600dp/styles.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ 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.
+ -->
+
+<resources>
+ <style name="CellStyleDefault">
+ <item name="iconDrawablePadding">7dp</item>
+ </style>
+</resources>
\ No newline at end of file
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index d292017..ba6e547 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -21,7 +21,6 @@
<!-- Dynamic Grid -->
<dimen name="dynamic_grid_edge_margin">10.77dp</dimen>
<dimen name="dynamic_grid_left_right_margin">8dp</dimen>
- <dimen name="dynamic_grid_icon_drawable_padding">7dp</dimen>
<!-- Minimum amount of next page visible in spring loaded mode -->
<dimen name="dynamic_grid_spring_loaded_min_next_space_visible">24dp</dimen>
diff --git a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
index dd37bab..7641728 100644
--- a/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/ActivityAllAppsContainerView.java
@@ -439,9 +439,11 @@
return;
}
- RecyclerView.ItemDecoration decoration = getMainAdapterProvider().getDecorator();
- getSearchRecyclerView().removeItemDecoration(decoration);
- getSearchRecyclerView().addItemDecoration(decoration);
+ if (!FeatureFlags.ENABLE_SEARCH_RESULT_BACKGROUND_DRAWABLES.get()) {
+ RecyclerView.ItemDecoration decoration = getMainAdapterProvider().getDecorator();
+ getSearchRecyclerView().removeItemDecoration(decoration);
+ getSearchRecyclerView().addItemDecoration(decoration);
+ }
// replaceAppsRVcontainer() needs to use both mUsingTabs value to remove the old view AND
// showTabs value to create new view. Hence the mUsingTabs new value assignment MUST happen
diff --git a/src/com/android/launcher3/graphics/SysUiScrim.java b/src/com/android/launcher3/graphics/SysUiScrim.java
index 11e7dc8..e983a30 100644
--- a/src/com/android/launcher3/graphics/SysUiScrim.java
+++ b/src/com/android/launcher3/graphics/SysUiScrim.java
@@ -32,11 +32,10 @@
import android.util.DisplayMetrics;
import android.util.FloatProperty;
import android.view.View;
-import android.view.WindowInsets;
import com.android.launcher3.BaseDraggingActivity;
+import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.testing.shared.ResourceUtils;
import com.android.launcher3.util.DynamicResource;
@@ -185,21 +184,18 @@
/**
* Determines whether to draw the top and/or bottom scrim based on new insets.
+ *
+ * In order for the bottom scrim to be drawn this 3 condition should be meet at the same time:
+ * the device is in 3 button navigation, the taskbar is not present and the Hotseat is
+ * horizontal
*/
public void onInsetsChanged(Rect insets) {
+ DeviceProfile dp = mActivity.getDeviceProfile();
mDrawTopScrim = mTopScrim != null && insets.top > 0;
mDrawBottomScrim = mBottomMask != null
- && !mActivity.getDeviceProfile().isVerticalBarLayout()
- && hasBottomNavButtons();
- }
-
- private boolean hasBottomNavButtons() {
- if (Utilities.ATLEAST_Q && mActivity.getRootView() != null
- && mActivity.getRootView().getRootWindowInsets() != null) {
- WindowInsets windowInsets = mActivity.getRootView().getRootWindowInsets();
- return windowInsets.getTappableElementInsets().bottom > 0;
- }
- return true;
+ && !dp.isVerticalBarLayout()
+ && !dp.isGestureMode
+ && !dp.isTaskbarPresent;
}
@Override
diff --git a/src/com/android/launcher3/widget/picker/WidgetsListSearchHeaderHolder.java b/src/com/android/launcher3/widget/picker/WidgetsListSearchHeaderHolder.java
deleted file mode 100644
index 9562af3..0000000
--- a/src/com/android/launcher3/widget/picker/WidgetsListSearchHeaderHolder.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2021 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.widget.picker;
-
-import androidx.recyclerview.widget.RecyclerView.ViewHolder;
-
-/**
- * A {@link ViewHolder} for {@link WidgetsListHeader} of an app, which renders the app icon, the app
- * name, label and a button for showing / hiding widgets.
- */
-public final class WidgetsListSearchHeaderHolder extends ViewHolder {
- final WidgetsListHeader mWidgetsListHeader;
-
- public WidgetsListSearchHeaderHolder(WidgetsListHeader view) {
- super(view);
-
- mWidgetsListHeader = view;
- }
-}
diff --git a/tests/src/com/android/launcher3/AbstractDeviceProfileTest.kt b/tests/src/com/android/launcher3/AbstractDeviceProfileTest.kt
index dcc669b..0fe8bee 100644
--- a/tests/src/com/android/launcher3/AbstractDeviceProfileTest.kt
+++ b/tests/src/com/android/launcher3/AbstractDeviceProfileTest.kt
@@ -93,6 +93,24 @@
gesturePx = 0,
cutoutPx = 0
),
+ "twopanel-phone" to
+ DeviceSpec(
+ Pair(1080, 2092),
+ densityDpi = 420,
+ statusBarNaturalPx = 133,
+ statusBarRotatedPx = 110,
+ gesturePx = 63,
+ cutoutPx = 133
+ ),
+ "twopanel-tablet" to
+ DeviceSpec(
+ Pair(2208, 1840),
+ densityDpi = 420,
+ statusBarNaturalPx = 110,
+ statusBarRotatedPx = 133,
+ gesturePx = 0,
+ cutoutPx = 0
+ )
)
protected fun initializeVarsForPhone(
diff --git a/tests/src/com/android/launcher3/nonquickstep/DeviceProfileDumpTest.kt b/tests/src/com/android/launcher3/nonquickstep/DeviceProfileDumpTest.kt
new file mode 100644
index 0000000..d981267
--- /dev/null
+++ b/tests/src/com/android/launcher3/nonquickstep/DeviceProfileDumpTest.kt
@@ -0,0 +1,1626 @@
+/*
+ * 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.launcher3.nonquickstep
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.launcher3.AbstractDeviceProfileTest
+import com.android.launcher3.DeviceProfile
+import com.android.launcher3.InvariantDeviceProfile
+import com.google.common.truth.Truth.assertThat
+import java.io.PrintWriter
+import java.io.StringWriter
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/** Tests for DeviceProfile. */
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class DeviceProfileDumpTest : AbstractDeviceProfileTest() {
+
+ @Test
+ fun phonePortrait3Button() {
+ initializeVarsForPhone(deviceSpecs["phone"]!!, isGestureMode = false)
+ val dp = getDeviceProfileForGrid("5_by_5")
+
+ assertThat(dump(dp))
+ .isEqualTo(
+ "DeviceProfile:\n" +
+ "\t1 dp = 2.625 px\n" +
+ "\tisTablet:false\n" +
+ "\tisPhone:true\n" +
+ "\ttransposeLayoutWithOrientation:true\n" +
+ "\tisGestureMode:false\n" +
+ "\tisLandscape:false\n" +
+ "\tisMultiWindowMode:false\n" +
+ "\tisTwoPanels:false\n" +
+ "\twindowX: 0.0px (0.0dp)\n" +
+ "\twindowY: 0.0px (0.0dp)\n" +
+ "\twidthPx: 1080.0px (411.42856dp)\n" +
+ "\theightPx: 2400.0px (914.2857dp)\n" +
+ "\tavailableWidthPx: 1080.0px (411.42856dp)\n" +
+ "\tavailableHeightPx: 2156.0px (821.3333dp)\n" +
+ "\tmInsets.left: 0.0px (0.0dp)\n" +
+ "\tmInsets.top: 118.0px (44.95238dp)\n" +
+ "\tmInsets.right: 0.0px (0.0dp)\n" +
+ "\tmInsets.bottom: 126.0px (48.0dp)\n" +
+ "\taspectRatio:2.2222223\n" +
+ "\tisScalableGrid:false\n" +
+ "\tinv.numRows: 5\n" +
+ "\tinv.numColumns: 5\n" +
+ "\tinv.numSearchContainerColumns: 5\n" +
+ "\tminCellSize: PointF(0.0, 0.0)dp\n" +
+ "\tcellWidthPx: 165.0px (62.857143dp)\n" +
+ "\tcellHeightPx: 235.0px (89.52381dp)\n" +
+ "\tgetCellSize().x: 207.0px (78.85714dp)\n" +
+ "\tgetCellSize().y: 379.0px (144.38095dp)\n" +
+ "\tcellLayoutBorderSpacePx Horizontal: 0.0px (0.0dp)\n" +
+ "\tcellLayoutBorderSpacePx Vertical: 0.0px (0.0dp)\n" +
+ "\tcellLayoutPaddingPx.left: 21.0px (8.0dp)\n" +
+ "\tcellLayoutPaddingPx.top: 28.0px (10.666667dp)\n" +
+ "\tcellLayoutPaddingPx.right: 21.0px (8.0dp)\n" +
+ "\tcellLayoutPaddingPx.bottom: 28.0px (10.666667dp)\n" +
+ "\ticonSizePx: 147.0px (56.0dp)\n" +
+ "\ticonTextSizePx: 38.0px (14.476191dp)\n" +
+ "\ticonDrawablePaddingPx: 18.0px (6.857143dp)\n" +
+ "\tfolderCellWidthPx: 195.0px (74.28571dp)\n" +
+ "\tfolderCellHeightPx: 230.0px (87.61905dp)\n" +
+ "\tfolderChildIconSizePx: 147.0px (56.0dp)\n" +
+ "\tfolderChildTextSizePx: 38.0px (14.476191dp)\n" +
+ "\tfolderChildDrawablePaddingPx: 10.0px (3.8095238dp)\n" +
+ "\tfolderCellLayoutBorderSpacePx: 0.0px (0.0dp)\n" +
+ "\tfolderContentPaddingLeftRight: 21.0px (8.0dp)\n" +
+ "\tfolderTopPadding: 63.0px (24.0dp)\n" +
+ "\tfolderFooterHeight: 147.0px (56.0dp)\n" +
+ "\tbottomSheetTopPadding: 146.0px (55.61905dp)\n" +
+ "\tbottomSheetOpenDuration: 267\n" +
+ "\tbottomSheetCloseDuration: 267\n" +
+ "\tbottomSheetWorkspaceScale: 1.0\n" +
+ "\tbottomSheetDepth: 0.0\n" +
+ "\tallAppsShiftRange: 788.0px (300.1905dp)\n" +
+ "\tallAppsTopPadding: 0.0px (0.0dp)\n" +
+ "\tallAppsOpenDuration: 600\n" +
+ "\tallAppsCloseDuration: 300\n" +
+ "\tallAppsIconSizePx: 147.0px (56.0dp)\n" +
+ "\tallAppsIconTextSizePx: 38.0px (14.476191dp)\n" +
+ "\tallAppsIconDrawablePaddingPx: 21.0px (8.0dp)\n" +
+ "\tallAppsCellHeightPx: 315.0px (120.0dp)\n" +
+ "\tallAppsCellWidthPx: 189.0px (72.0dp)\n" +
+ "\tallAppsBorderSpacePxX: 42.0px (16.0dp)\n" +
+ "\tallAppsBorderSpacePxY: 42.0px (16.0dp)\n" +
+ "\tnumShownAllAppsColumns: 5\n" +
+ "\tallAppsLeftRightPadding: 21.0px (8.0dp)\n" +
+ "\tallAppsLeftRightMargin: 0.0px (0.0dp)\n" +
+ "\thotseatBarSizePx: 294.0px (112.0dp)\n" +
+ "\tinv.hotseatColumnSpan: 5\n" +
+ "\thotseatCellHeightPx: 166.0px (63.238094dp)\n" +
+ "\thotseatBarBottomSpacePx: 147.0px (56.0dp)\n" +
+ "\thotseatBarSidePaddingStartPx: 0.0px (0.0dp)\n" +
+ "\thotseatBarSidePaddingEndPx: 0.0px (0.0dp)\n" +
+ "\thotseatBarEndOffset: 0.0px (0.0dp)\n" +
+ "\thotseatQsbSpace: 0.0px (0.0dp)\n" +
+ "\thotseatQsbHeight: 0.0px (0.0dp)\n" +
+ "\tspringLoadedHotseatBarTopMarginPx: 200.0px (76.190475dp)\n" +
+ "\tgetHotseatLayoutPadding(context).top: 0.0px (0.0dp)\n" +
+ "\tgetHotseatLayoutPadding(context).bottom: 128.0px (48.761906dp)\n" +
+ "\tgetHotseatLayoutPadding(context).left: 21.0px (8.0dp)\n" +
+ "\tgetHotseatLayoutPadding(context).right: 21.0px (8.0dp)\n" +
+ "\tnumShownHotseatIcons: 5\n" +
+ "\thotseatBorderSpace: 0.0px (0.0dp)\n" +
+ "\tisQsbInline: false\n" +
+ "\thotseatQsbWidth: 0.0px (0.0dp)\n" +
+ "\tisTaskbarPresent:false\n" +
+ "\tisTaskbarPresentInApps:false\n" +
+ "\ttaskbarSize: 0.0px (0.0dp)\n" +
+ "\tdesiredWorkspaceHorizontalMarginPx: 21.0px (8.0dp)\n" +
+ "\tworkspacePadding.left: 0.0px (0.0dp)\n" +
+ "\tworkspacePadding.top: 0.0px (0.0dp)\n" +
+ "\tworkspacePadding.right: 0.0px (0.0dp)\n" +
+ "\tworkspacePadding.bottom: 203.0px (77.333336dp)\n" +
+ "\ticonScale: 1.0px (0.3809524dp)\n" +
+ "\tcellScaleToFit : 1.0px (0.3809524dp)\n" +
+ "\textraSpace: 722.0px (275.0476dp)\n" +
+ "\tunscaled extraSpace: 722.0px (275.0476dp)\n" +
+ "\tmaxEmptySpace: 0.0px (0.0dp)\n" +
+ "\tworkspaceTopPadding: 0.0px (0.0dp)\n" +
+ "\tworkspaceBottomPadding: 0.0px (0.0dp)\n" +
+ "\toverviewTaskMarginPx: 0.0px (0.0dp)\n" +
+ "\toverviewTaskIconSizePx: 0.0px (0.0dp)\n" +
+ "\toverviewTaskIconDrawableSizePx: 0.0px (0.0dp)\n" +
+ "\toverviewTaskIconDrawableSizeGridPx: 0.0px (0.0dp)\n" +
+ "\toverviewTaskThumbnailTopMarginPx: 0.0px (0.0dp)\n" +
+ "\toverviewActionsTopMarginPx: 0.0px (0.0dp)\n" +
+ "\toverviewActionsHeight: 0.0px (0.0dp)\n" +
+ "\toverviewActionsClaimedSpaceBelow: 126.0px (48.0dp)\n" +
+ "\toverviewActionsButtonSpacing: 0.0px (0.0dp)\n" +
+ "\toverviewPageSpacing: 0.0px (0.0dp)\n" +
+ "\toverviewRowSpacing: 0.0px (0.0dp)\n" +
+ "\toverviewGridSideMargin: 0.0px (0.0dp)\n" +
+ "\tdropTargetBarTopMarginPx: 84.0px (32.0dp)\n" +
+ "\tdropTargetBarSizePx: 147.0px (56.0dp)\n" +
+ "\tdropTargetBarBottomMarginPx: 42.0px (16.0dp)\n" +
+ "\tgetCellLayoutSpringLoadShrunkTop(): 391.0px (148.95238dp)\n" +
+ "\tgetCellLayoutSpringLoadShrunkBottom(): 1906.0px (726.0952dp)\n" +
+ "\tworkspaceSpringLoadedMinNextPageVisiblePx: 63.0px (24.0dp)\n" +
+ "\tgetWorkspaceSpringLoadScale(): 0.77572966px (0.29551607dp)\n" +
+ "\tgetCellLayoutHeight(): 1953.0px (744.0dp)\n" +
+ "\tgetCellLayoutWidth(): 1080.0px (411.42856dp)\n"
+ )
+ }
+
+ @Test
+ fun phonePortrait() {
+ initializeVarsForPhone(deviceSpecs["phone"]!!)
+ val dp = getDeviceProfileForGrid("5_by_5")
+
+ assertThat(dump(dp))
+ .isEqualTo(
+ "DeviceProfile:\n" +
+ "\t1 dp = 2.625 px\n" +
+ "\tisTablet:false\n" +
+ "\tisPhone:true\n" +
+ "\ttransposeLayoutWithOrientation:true\n" +
+ "\tisGestureMode:true\n" +
+ "\tisLandscape:false\n" +
+ "\tisMultiWindowMode:false\n" +
+ "\tisTwoPanels:false\n" +
+ "\twindowX: 0.0px (0.0dp)\n" +
+ "\twindowY: 0.0px (0.0dp)\n" +
+ "\twidthPx: 1080.0px (411.42856dp)\n" +
+ "\theightPx: 2400.0px (914.2857dp)\n" +
+ "\tavailableWidthPx: 1080.0px (411.42856dp)\n" +
+ "\tavailableHeightPx: 2219.0px (845.3333dp)\n" +
+ "\tmInsets.left: 0.0px (0.0dp)\n" +
+ "\tmInsets.top: 118.0px (44.95238dp)\n" +
+ "\tmInsets.right: 0.0px (0.0dp)\n" +
+ "\tmInsets.bottom: 63.0px (24.0dp)\n" +
+ "\taspectRatio:2.2222223\n" +
+ "\tisScalableGrid:false\n" +
+ "\tinv.numRows: 5\n" +
+ "\tinv.numColumns: 5\n" +
+ "\tinv.numSearchContainerColumns: 5\n" +
+ "\tminCellSize: PointF(0.0, 0.0)dp\n" +
+ "\tcellWidthPx: 165.0px (62.857143dp)\n" +
+ "\tcellHeightPx: 235.0px (89.52381dp)\n" +
+ "\tgetCellSize().x: 207.0px (78.85714dp)\n" +
+ "\tgetCellSize().y: 383.0px (145.90475dp)\n" +
+ "\tcellLayoutBorderSpacePx Horizontal: 0.0px (0.0dp)\n" +
+ "\tcellLayoutBorderSpacePx Vertical: 0.0px (0.0dp)\n" +
+ "\tcellLayoutPaddingPx.left: 21.0px (8.0dp)\n" +
+ "\tcellLayoutPaddingPx.top: 28.0px (10.666667dp)\n" +
+ "\tcellLayoutPaddingPx.right: 21.0px (8.0dp)\n" +
+ "\tcellLayoutPaddingPx.bottom: 28.0px (10.666667dp)\n" +
+ "\ticonSizePx: 147.0px (56.0dp)\n" +
+ "\ticonTextSizePx: 38.0px (14.476191dp)\n" +
+ "\ticonDrawablePaddingPx: 18.0px (6.857143dp)\n" +
+ "\tfolderCellWidthPx: 195.0px (74.28571dp)\n" +
+ "\tfolderCellHeightPx: 230.0px (87.61905dp)\n" +
+ "\tfolderChildIconSizePx: 147.0px (56.0dp)\n" +
+ "\tfolderChildTextSizePx: 38.0px (14.476191dp)\n" +
+ "\tfolderChildDrawablePaddingPx: 10.0px (3.8095238dp)\n" +
+ "\tfolderCellLayoutBorderSpacePx: 0.0px (0.0dp)\n" +
+ "\tfolderContentPaddingLeftRight: 21.0px (8.0dp)\n" +
+ "\tfolderTopPadding: 63.0px (24.0dp)\n" +
+ "\tfolderFooterHeight: 147.0px (56.0dp)\n" +
+ "\tbottomSheetTopPadding: 146.0px (55.61905dp)\n" +
+ "\tbottomSheetOpenDuration: 267\n" +
+ "\tbottomSheetCloseDuration: 267\n" +
+ "\tbottomSheetWorkspaceScale: 1.0\n" +
+ "\tbottomSheetDepth: 0.0\n" +
+ "\tallAppsShiftRange: 788.0px (300.1905dp)\n" +
+ "\tallAppsTopPadding: 0.0px (0.0dp)\n" +
+ "\tallAppsOpenDuration: 600\n" +
+ "\tallAppsCloseDuration: 300\n" +
+ "\tallAppsIconSizePx: 147.0px (56.0dp)\n" +
+ "\tallAppsIconTextSizePx: 38.0px (14.476191dp)\n" +
+ "\tallAppsIconDrawablePaddingPx: 21.0px (8.0dp)\n" +
+ "\tallAppsCellHeightPx: 315.0px (120.0dp)\n" +
+ "\tallAppsCellWidthPx: 189.0px (72.0dp)\n" +
+ "\tallAppsBorderSpacePxX: 42.0px (16.0dp)\n" +
+ "\tallAppsBorderSpacePxY: 42.0px (16.0dp)\n" +
+ "\tnumShownAllAppsColumns: 5\n" +
+ "\tallAppsLeftRightPadding: 21.0px (8.0dp)\n" +
+ "\tallAppsLeftRightMargin: 0.0px (0.0dp)\n" +
+ "\thotseatBarSizePx: 273.0px (104.0dp)\n" +
+ "\tinv.hotseatColumnSpan: 5\n" +
+ "\thotseatCellHeightPx: 166.0px (63.238094dp)\n" +
+ "\thotseatBarBottomSpacePx: 126.0px (48.0dp)\n" +
+ "\thotseatBarSidePaddingStartPx: 0.0px (0.0dp)\n" +
+ "\thotseatBarSidePaddingEndPx: 0.0px (0.0dp)\n" +
+ "\thotseatBarEndOffset: 0.0px (0.0dp)\n" +
+ "\thotseatQsbSpace: 0.0px (0.0dp)\n" +
+ "\thotseatQsbHeight: 0.0px (0.0dp)\n" +
+ "\tspringLoadedHotseatBarTopMarginPx: 200.0px (76.190475dp)\n" +
+ "\tgetHotseatLayoutPadding(context).top: 0.0px (0.0dp)\n" +
+ "\tgetHotseatLayoutPadding(context).bottom: 107.0px (40.761906dp)\n" +
+ "\tgetHotseatLayoutPadding(context).left: 21.0px (8.0dp)\n" +
+ "\tgetHotseatLayoutPadding(context).right: 21.0px (8.0dp)\n" +
+ "\tnumShownHotseatIcons: 5\n" +
+ "\thotseatBorderSpace: 0.0px (0.0dp)\n" +
+ "\tisQsbInline: false\n" +
+ "\thotseatQsbWidth: 0.0px (0.0dp)\n" +
+ "\tisTaskbarPresent:false\n" +
+ "\tisTaskbarPresentInApps:false\n" +
+ "\ttaskbarSize: 0.0px (0.0dp)\n" +
+ "\tdesiredWorkspaceHorizontalMarginPx: 21.0px (8.0dp)\n" +
+ "\tworkspacePadding.left: 0.0px (0.0dp)\n" +
+ "\tworkspacePadding.top: 0.0px (0.0dp)\n" +
+ "\tworkspacePadding.right: 0.0px (0.0dp)\n" +
+ "\tworkspacePadding.bottom: 245.0px (93.333336dp)\n" +
+ "\ticonScale: 1.0px (0.3809524dp)\n" +
+ "\tcellScaleToFit : 1.0px (0.3809524dp)\n" +
+ "\textraSpace: 743.0px (283.0476dp)\n" +
+ "\tunscaled extraSpace: 743.0px (283.0476dp)\n" +
+ "\tmaxEmptySpace: 0.0px (0.0dp)\n" +
+ "\tworkspaceTopPadding: 0.0px (0.0dp)\n" +
+ "\tworkspaceBottomPadding: 0.0px (0.0dp)\n" +
+ "\toverviewTaskMarginPx: 0.0px (0.0dp)\n" +
+ "\toverviewTaskIconSizePx: 0.0px (0.0dp)\n" +
+ "\toverviewTaskIconDrawableSizePx: 0.0px (0.0dp)\n" +
+ "\toverviewTaskIconDrawableSizeGridPx: 0.0px (0.0dp)\n" +
+ "\toverviewTaskThumbnailTopMarginPx: 0.0px (0.0dp)\n" +
+ "\toverviewActionsTopMarginPx: 0.0px (0.0dp)\n" +
+ "\toverviewActionsHeight: 0.0px (0.0dp)\n" +
+ "\toverviewActionsClaimedSpaceBelow: 63.0px (24.0dp)\n" +
+ "\toverviewActionsButtonSpacing: 0.0px (0.0dp)\n" +
+ "\toverviewPageSpacing: 0.0px (0.0dp)\n" +
+ "\toverviewRowSpacing: 0.0px (0.0dp)\n" +
+ "\toverviewGridSideMargin: 0.0px (0.0dp)\n" +
+ "\tdropTargetBarTopMarginPx: 84.0px (32.0dp)\n" +
+ "\tdropTargetBarSizePx: 147.0px (56.0dp)\n" +
+ "\tdropTargetBarBottomMarginPx: 42.0px (16.0dp)\n" +
+ "\tgetCellLayoutSpringLoadShrunkTop(): 391.0px (148.95238dp)\n" +
+ "\tgetCellLayoutSpringLoadShrunkBottom(): 1927.0px (734.0952dp)\n" +
+ "\tworkspaceSpringLoadedMinNextPageVisiblePx: 63.0px (24.0dp)\n" +
+ "\tgetWorkspaceSpringLoadScale(): 0.7781155px (0.29642496dp)\n" +
+ "\tgetCellLayoutHeight(): 1974.0px (752.0dp)\n" +
+ "\tgetCellLayoutWidth(): 1080.0px (411.42856dp)\n"
+ )
+ }
+
+ @Test
+ fun phoneVerticalBar3Button() {
+ initializeVarsForPhone(deviceSpecs["phone"]!!, isVerticalBar = true, isGestureMode = false)
+ val dp = getDeviceProfileForGrid("5_by_5")
+
+ assertThat(dump(dp))
+ .isEqualTo(
+ "DeviceProfile:\n" +
+ "\t1 dp = 2.625 px\n" +
+ "\tisTablet:false\n" +
+ "\tisPhone:true\n" +
+ "\ttransposeLayoutWithOrientation:true\n" +
+ "\tisGestureMode:false\n" +
+ "\tisLandscape:true\n" +
+ "\tisMultiWindowMode:false\n" +
+ "\tisTwoPanels:false\n" +
+ "\twindowX: 0.0px (0.0dp)\n" +
+ "\twindowY: 0.0px (0.0dp)\n" +
+ "\twidthPx: 2400.0px (914.2857dp)\n" +
+ "\theightPx: 1080.0px (411.42856dp)\n" +
+ "\tavailableWidthPx: 2156.0px (821.3333dp)\n" +
+ "\tavailableHeightPx: 1006.0px (383.2381dp)\n" +
+ "\tmInsets.left: 118.0px (44.95238dp)\n" +
+ "\tmInsets.top: 74.0px (28.190475dp)\n" +
+ "\tmInsets.right: 126.0px (48.0dp)\n" +
+ "\tmInsets.bottom: 0.0px (0.0dp)\n" +
+ "\taspectRatio:2.2222223\n" +
+ "\tisScalableGrid:false\n" +
+ "\tinv.numRows: 5\n" +
+ "\tinv.numColumns: 5\n" +
+ "\tinv.numSearchContainerColumns: 5\n" +
+ "\tminCellSize: PointF(0.0, 0.0)dp\n" +
+ "\tcellWidthPx: 158.0px (60.190475dp)\n" +
+ "\tcellHeightPx: 166.0px (63.238094dp)\n" +
+ "\tgetCellSize().x: 368.0px (140.19048dp)\n" +
+ "\tgetCellSize().y: 193.0px (73.52381dp)\n" +
+ "\tcellLayoutBorderSpacePx Horizontal: 0.0px (0.0dp)\n" +
+ "\tcellLayoutBorderSpacePx Vertical: 0.0px (0.0dp)\n" +
+ "\tcellLayoutPaddingPx.left: 53.0px (20.190475dp)\n" +
+ "\tcellLayoutPaddingPx.top: 0.0px (0.0dp)\n" +
+ "\tcellLayoutPaddingPx.right: 53.0px (20.190475dp)\n" +
+ "\tcellLayoutPaddingPx.bottom: 40.0px (15.238095dp)\n" +
+ "\ticonSizePx: 147.0px (56.0dp)\n" +
+ "\ticonTextSizePx: 0.0px (0.0dp)\n" +
+ "\ticonDrawablePaddingPx: 0.0px (0.0dp)\n" +
+ "\tfolderCellWidthPx: 142.0px (54.095238dp)\n" +
+ "\tfolderCellHeightPx: 168.0px (64.0dp)\n" +
+ "\tfolderChildIconSizePx: 108.0px (41.142857dp)\n" +
+ "\tfolderChildTextSizePx: 28.0px (10.666667dp)\n" +
+ "\tfolderChildDrawablePaddingPx: 7.0px (2.6666667dp)\n" +
+ "\tfolderCellLayoutBorderSpacePx: 0.0px (0.0dp)\n" +
+ "\tfolderContentPaddingLeftRight: 21.0px (8.0dp)\n" +
+ "\tfolderTopPadding: 63.0px (24.0dp)\n" +
+ "\tfolderFooterHeight: 147.0px (56.0dp)\n" +
+ "\tbottomSheetTopPadding: 114.0px (43.42857dp)\n" +
+ "\tbottomSheetOpenDuration: 267\n" +
+ "\tbottomSheetCloseDuration: 267\n" +
+ "\tbottomSheetWorkspaceScale: 1.0\n" +
+ "\tbottomSheetDepth: 0.0\n" +
+ "\tallAppsShiftRange: 788.0px (300.1905dp)\n" +
+ "\tallAppsTopPadding: 0.0px (0.0dp)\n" +
+ "\tallAppsOpenDuration: 600\n" +
+ "\tallAppsCloseDuration: 300\n" +
+ "\tallAppsIconSizePx: 147.0px (56.0dp)\n" +
+ "\tallAppsIconTextSizePx: 38.0px (14.476191dp)\n" +
+ "\tallAppsIconDrawablePaddingPx: 21.0px (8.0dp)\n" +
+ "\tallAppsCellHeightPx: 321.0px (122.28571dp)\n" +
+ "\tallAppsCellWidthPx: 189.0px (72.0dp)\n" +
+ "\tallAppsBorderSpacePxX: 42.0px (16.0dp)\n" +
+ "\tallAppsBorderSpacePxY: 42.0px (16.0dp)\n" +
+ "\tnumShownAllAppsColumns: 5\n" +
+ "\tallAppsLeftRightPadding: 0.0px (0.0dp)\n" +
+ "\tallAppsLeftRightMargin: 0.0px (0.0dp)\n" +
+ "\thotseatBarSizePx: 252.0px (96.0dp)\n" +
+ "\tinv.hotseatColumnSpan: 5\n" +
+ "\thotseatCellHeightPx: 166.0px (63.238094dp)\n" +
+ "\thotseatBarBottomSpacePx: 126.0px (48.0dp)\n" +
+ "\thotseatBarSidePaddingStartPx: 63.0px (24.0dp)\n" +
+ "\thotseatBarSidePaddingEndPx: 42.0px (16.0dp)\n" +
+ "\thotseatBarEndOffset: 0.0px (0.0dp)\n" +
+ "\thotseatQsbSpace: 0.0px (0.0dp)\n" +
+ "\thotseatQsbHeight: 0.0px (0.0dp)\n" +
+ "\tspringLoadedHotseatBarTopMarginPx: 118.0px (44.95238dp)\n" +
+ "\tgetHotseatLayoutPadding(context).top: 64.0px (24.380953dp)\n" +
+ "\tgetHotseatLayoutPadding(context).bottom: 49.0px (18.666666dp)\n" +
+ "\tgetHotseatLayoutPadding(context).left: 42.0px (16.0dp)\n" +
+ "\tgetHotseatLayoutPadding(context).right: 189.0px (72.0dp)\n" +
+ "\tnumShownHotseatIcons: 5\n" +
+ "\thotseatBorderSpace: 0.0px (0.0dp)\n" +
+ "\tisQsbInline: false\n" +
+ "\thotseatQsbWidth: 0.0px (0.0dp)\n" +
+ "\tisTaskbarPresent:false\n" +
+ "\tisTaskbarPresentInApps:false\n" +
+ "\ttaskbarSize: 0.0px (0.0dp)\n" +
+ "\tdesiredWorkspaceHorizontalMarginPx: 0.0px (0.0dp)\n" +
+ "\tworkspacePadding.left: 10.0px (3.8095238dp)\n" +
+ "\tworkspacePadding.top: 0.0px (0.0dp)\n" +
+ "\tworkspacePadding.right: 199.0px (75.809525dp)\n" +
+ "\tworkspacePadding.bottom: 0.0px (0.0dp)\n" +
+ "\ticonScale: 1.0px (0.3809524dp)\n" +
+ "\tcellScaleToFit : 1.0px (0.3809524dp)\n" +
+ "\textraSpace: 136.0px (51.809525dp)\n" +
+ "\tunscaled extraSpace: 136.0px (51.809525dp)\n" +
+ "\tmaxEmptySpace: 0.0px (0.0dp)\n" +
+ "\tworkspaceTopPadding: 0.0px (0.0dp)\n" +
+ "\tworkspaceBottomPadding: 0.0px (0.0dp)\n" +
+ "\toverviewTaskMarginPx: 0.0px (0.0dp)\n" +
+ "\toverviewTaskIconSizePx: 0.0px (0.0dp)\n" +
+ "\toverviewTaskIconDrawableSizePx: 0.0px (0.0dp)\n" +
+ "\toverviewTaskIconDrawableSizeGridPx: 0.0px (0.0dp)\n" +
+ "\toverviewTaskThumbnailTopMarginPx: 0.0px (0.0dp)\n" +
+ "\toverviewActionsTopMarginPx: 0.0px (0.0dp)\n" +
+ "\toverviewActionsHeight: 0.0px (0.0dp)\n" +
+ "\toverviewActionsClaimedSpaceBelow: 0.0px (0.0dp)\n" +
+ "\toverviewActionsButtonSpacing: 0.0px (0.0dp)\n" +
+ "\toverviewPageSpacing: 0.0px (0.0dp)\n" +
+ "\toverviewRowSpacing: 0.0px (0.0dp)\n" +
+ "\toverviewGridSideMargin: 0.0px (0.0dp)\n" +
+ "\tdropTargetBarTopMarginPx: 16.0px (6.095238dp)\n" +
+ "\tdropTargetBarSizePx: 95.0px (36.190475dp)\n" +
+ "\tdropTargetBarBottomMarginPx: 16.0px (6.095238dp)\n" +
+ "\tgetCellLayoutSpringLoadShrunkTop(): 201.0px (76.57143dp)\n" +
+ "\tgetCellLayoutSpringLoadShrunkBottom(): 1008.0px (384.0dp)\n" +
+ "\tworkspaceSpringLoadedMinNextPageVisiblePx: 63.0px (24.0dp)\n" +
+ "\tgetWorkspaceSpringLoadScale(): 0.8021869px (0.305595dp)\n" +
+ "\tgetCellLayoutHeight(): 1006.0px (383.2381dp)\n" +
+ "\tgetCellLayoutWidth(): 1947.0px (741.7143dp)\n"
+ )
+ }
+
+ @Test
+ fun phoneVerticalBar() {
+ initializeVarsForPhone(deviceSpecs["phone"]!!, isVerticalBar = true)
+ val dp = getDeviceProfileForGrid("5_by_5")
+
+ assertThat(dump(dp))
+ .isEqualTo(
+ "DeviceProfile:\n" +
+ "\t1 dp = 2.625 px\n" +
+ "\tisTablet:false\n" +
+ "\tisPhone:true\n" +
+ "\ttransposeLayoutWithOrientation:true\n" +
+ "\tisGestureMode:true\n" +
+ "\tisLandscape:true\n" +
+ "\tisMultiWindowMode:false\n" +
+ "\tisTwoPanels:false\n" +
+ "\twindowX: 0.0px (0.0dp)\n" +
+ "\twindowY: 0.0px (0.0dp)\n" +
+ "\twidthPx: 2400.0px (914.2857dp)\n" +
+ "\theightPx: 1080.0px (411.42856dp)\n" +
+ "\tavailableWidthPx: 2282.0px (869.3333dp)\n" +
+ "\tavailableHeightPx: 943.0px (359.2381dp)\n" +
+ "\tmInsets.left: 118.0px (44.95238dp)\n" +
+ "\tmInsets.top: 74.0px (28.190475dp)\n" +
+ "\tmInsets.right: 0.0px (0.0dp)\n" +
+ "\tmInsets.bottom: 63.0px (24.0dp)\n" +
+ "\taspectRatio:2.2222223\n" +
+ "\tisScalableGrid:false\n" +
+ "\tinv.numRows: 5\n" +
+ "\tinv.numColumns: 5\n" +
+ "\tinv.numSearchContainerColumns: 5\n" +
+ "\tminCellSize: PointF(0.0, 0.0)dp\n" +
+ "\tcellWidthPx: 158.0px (60.190475dp)\n" +
+ "\tcellHeightPx: 166.0px (63.238094dp)\n" +
+ "\tgetCellSize().x: 393.0px (149.71428dp)\n" +
+ "\tgetCellSize().y: 180.0px (68.57143dp)\n" +
+ "\tcellLayoutBorderSpacePx Horizontal: 0.0px (0.0dp)\n" +
+ "\tcellLayoutBorderSpacePx Vertical: 0.0px (0.0dp)\n" +
+ "\tcellLayoutPaddingPx.left: 53.0px (20.190475dp)\n" +
+ "\tcellLayoutPaddingPx.top: 0.0px (0.0dp)\n" +
+ "\tcellLayoutPaddingPx.right: 53.0px (20.190475dp)\n" +
+ "\tcellLayoutPaddingPx.bottom: 40.0px (15.238095dp)\n" +
+ "\ticonSizePx: 147.0px (56.0dp)\n" +
+ "\ticonTextSizePx: 0.0px (0.0dp)\n" +
+ "\ticonDrawablePaddingPx: 0.0px (0.0dp)\n" +
+ "\tfolderCellWidthPx: 128.0px (48.761906dp)\n" +
+ "\tfolderCellHeightPx: 152.0px (57.904762dp)\n" +
+ "\tfolderChildIconSizePx: 98.0px (37.333332dp)\n" +
+ "\tfolderChildTextSizePx: 25.0px (9.523809dp)\n" +
+ "\tfolderChildDrawablePaddingPx: 6.0px (2.2857144dp)\n" +
+ "\tfolderCellLayoutBorderSpacePx: 0.0px (0.0dp)\n" +
+ "\tfolderContentPaddingLeftRight: 21.0px (8.0dp)\n" +
+ "\tfolderTopPadding: 63.0px (24.0dp)\n" +
+ "\tfolderFooterHeight: 147.0px (56.0dp)\n" +
+ "\tbottomSheetTopPadding: 114.0px (43.42857dp)\n" +
+ "\tbottomSheetOpenDuration: 267\n" +
+ "\tbottomSheetCloseDuration: 267\n" +
+ "\tbottomSheetWorkspaceScale: 1.0\n" +
+ "\tbottomSheetDepth: 0.0\n" +
+ "\tallAppsShiftRange: 788.0px (300.1905dp)\n" +
+ "\tallAppsTopPadding: 0.0px (0.0dp)\n" +
+ "\tallAppsOpenDuration: 600\n" +
+ "\tallAppsCloseDuration: 300\n" +
+ "\tallAppsIconSizePx: 147.0px (56.0dp)\n" +
+ "\tallAppsIconTextSizePx: 38.0px (14.476191dp)\n" +
+ "\tallAppsIconDrawablePaddingPx: 21.0px (8.0dp)\n" +
+ "\tallAppsCellHeightPx: 321.0px (122.28571dp)\n" +
+ "\tallAppsCellWidthPx: 189.0px (72.0dp)\n" +
+ "\tallAppsBorderSpacePxX: 42.0px (16.0dp)\n" +
+ "\tallAppsBorderSpacePxY: 42.0px (16.0dp)\n" +
+ "\tnumShownAllAppsColumns: 5\n" +
+ "\tallAppsLeftRightPadding: 0.0px (0.0dp)\n" +
+ "\tallAppsLeftRightMargin: 0.0px (0.0dp)\n" +
+ "\thotseatBarSizePx: 252.0px (96.0dp)\n" +
+ "\tinv.hotseatColumnSpan: 5\n" +
+ "\thotseatCellHeightPx: 166.0px (63.238094dp)\n" +
+ "\thotseatBarBottomSpacePx: 126.0px (48.0dp)\n" +
+ "\thotseatBarSidePaddingStartPx: 63.0px (24.0dp)\n" +
+ "\thotseatBarSidePaddingEndPx: 42.0px (16.0dp)\n" +
+ "\thotseatBarEndOffset: 0.0px (0.0dp)\n" +
+ "\thotseatQsbSpace: 0.0px (0.0dp)\n" +
+ "\thotseatQsbHeight: 0.0px (0.0dp)\n" +
+ "\tspringLoadedHotseatBarTopMarginPx: 118.0px (44.95238dp)\n" +
+ "\tgetHotseatLayoutPadding(context).top: 64.0px (24.380953dp)\n" +
+ "\tgetHotseatLayoutPadding(context).bottom: 112.0px (42.666668dp)\n" +
+ "\tgetHotseatLayoutPadding(context).left: 42.0px (16.0dp)\n" +
+ "\tgetHotseatLayoutPadding(context).right: 63.0px (24.0dp)\n" +
+ "\tnumShownHotseatIcons: 5\n" +
+ "\thotseatBorderSpace: 0.0px (0.0dp)\n" +
+ "\tisQsbInline: false\n" +
+ "\thotseatQsbWidth: 0.0px (0.0dp)\n" +
+ "\tisTaskbarPresent:false\n" +
+ "\tisTaskbarPresentInApps:false\n" +
+ "\ttaskbarSize: 0.0px (0.0dp)\n" +
+ "\tdesiredWorkspaceHorizontalMarginPx: 0.0px (0.0dp)\n" +
+ "\tworkspacePadding.left: 10.0px (3.8095238dp)\n" +
+ "\tworkspacePadding.top: 0.0px (0.0dp)\n" +
+ "\tworkspacePadding.right: 199.0px (75.809525dp)\n" +
+ "\tworkspacePadding.bottom: 0.0px (0.0dp)\n" +
+ "\ticonScale: 1.0px (0.3809524dp)\n" +
+ "\tcellScaleToFit : 1.0px (0.3809524dp)\n" +
+ "\textraSpace: 73.0px (27.809525dp)\n" +
+ "\tunscaled extraSpace: 73.0px (27.809525dp)\n" +
+ "\tmaxEmptySpace: 0.0px (0.0dp)\n" +
+ "\tworkspaceTopPadding: 0.0px (0.0dp)\n" +
+ "\tworkspaceBottomPadding: 0.0px (0.0dp)\n" +
+ "\toverviewTaskMarginPx: 0.0px (0.0dp)\n" +
+ "\toverviewTaskIconSizePx: 0.0px (0.0dp)\n" +
+ "\toverviewTaskIconDrawableSizePx: 0.0px (0.0dp)\n" +
+ "\toverviewTaskIconDrawableSizeGridPx: 0.0px (0.0dp)\n" +
+ "\toverviewTaskThumbnailTopMarginPx: 0.0px (0.0dp)\n" +
+ "\toverviewActionsTopMarginPx: 0.0px (0.0dp)\n" +
+ "\toverviewActionsHeight: 0.0px (0.0dp)\n" +
+ "\toverviewActionsClaimedSpaceBelow: 63.0px (24.0dp)\n" +
+ "\toverviewActionsButtonSpacing: 0.0px (0.0dp)\n" +
+ "\toverviewPageSpacing: 0.0px (0.0dp)\n" +
+ "\toverviewRowSpacing: 0.0px (0.0dp)\n" +
+ "\toverviewGridSideMargin: 0.0px (0.0dp)\n" +
+ "\tdropTargetBarTopMarginPx: 16.0px (6.095238dp)\n" +
+ "\tdropTargetBarSizePx: 95.0px (36.190475dp)\n" +
+ "\tdropTargetBarBottomMarginPx: 16.0px (6.095238dp)\n" +
+ "\tgetCellLayoutSpringLoadShrunkTop(): 201.0px (76.57143dp)\n" +
+ "\tgetCellLayoutSpringLoadShrunkBottom(): 952.0px (362.66666dp)\n" +
+ "\tworkspaceSpringLoadedMinNextPageVisiblePx: 63.0px (24.0dp)\n" +
+ "\tgetWorkspaceSpringLoadScale(): 0.79639447px (0.30338836dp)\n" +
+ "\tgetCellLayoutHeight(): 943.0px (359.2381dp)\n" +
+ "\tgetCellLayoutWidth(): 2073.0px (789.7143dp)\n"
+ )
+ }
+
+ @Test
+ fun tabletLandscape3Button() {
+ initializeVarsForTablet(deviceSpecs["tablet"]!!, isLandscape = true, isGestureMode = false)
+ val dp = getDeviceProfileForGrid("6_by_5")
+ dp.isTaskbarPresentInApps = true
+
+ assertThat(dump(dp))
+ .isEqualTo(
+ "DeviceProfile:\n" +
+ "\t1 dp = 2.0 px\n" +
+ "\tisTablet:true\n" +
+ "\tisPhone:false\n" +
+ "\ttransposeLayoutWithOrientation:false\n" +
+ "\tisGestureMode:false\n" +
+ "\tisLandscape:true\n" +
+ "\tisMultiWindowMode:false\n" +
+ "\tisTwoPanels:false\n" +
+ "\twindowX: 0.0px (0.0dp)\n" +
+ "\twindowY: 0.0px (0.0dp)\n" +
+ "\twidthPx: 2560.0px (1280.0dp)\n" +
+ "\theightPx: 1600.0px (800.0dp)\n" +
+ "\tavailableWidthPx: 2560.0px (1280.0dp)\n" +
+ "\tavailableHeightPx: 1496.0px (748.0dp)\n" +
+ "\tmInsets.left: 0.0px (0.0dp)\n" +
+ "\tmInsets.top: 104.0px (52.0dp)\n" +
+ "\tmInsets.right: 0.0px (0.0dp)\n" +
+ "\tmInsets.bottom: 0.0px (0.0dp)\n" +
+ "\taspectRatio:1.6\n" +
+ "\tisScalableGrid:true\n" +
+ "\tinv.numRows: 5\n" +
+ "\tinv.numColumns: 6\n" +
+ "\tinv.numSearchContainerColumns: 3\n" +
+ "\tminCellSize: PointF(120.0, 104.0)dp\n" +
+ "\tcellWidthPx: 240.0px (120.0dp)\n" +
+ "\tcellHeightPx: 208.0px (104.0dp)\n" +
+ "\tgetCellSize().x: 240.0px (120.0dp)\n" +
+ "\tgetCellSize().y: 208.0px (104.0dp)\n" +
+ "\tcellLayoutBorderSpacePx Horizontal: 128.0px (64.0dp)\n" +
+ "\tcellLayoutBorderSpacePx Vertical: 32.0px (16.0dp)\n" +
+ "\tcellLayoutPaddingPx.left: 59.0px (29.5dp)\n" +
+ "\tcellLayoutPaddingPx.top: 25.0px (12.5dp)\n" +
+ "\tcellLayoutPaddingPx.right: 59.0px (29.5dp)\n" +
+ "\tcellLayoutPaddingPx.bottom: 59.0px (29.5dp)\n" +
+ "\ticonSizePx: 120.0px (60.0dp)\n" +
+ "\ticonTextSizePx: 28.0px (14.0dp)\n" +
+ "\ticonDrawablePaddingPx: 14.0px (7.0dp)\n" +
+ "\tfolderCellWidthPx: 397.0px (198.5dp)\n" +
+ "\tfolderCellHeightPx: 371.0px (185.5dp)\n" +
+ "\tfolderChildIconSizePx: 99.0px (49.5dp)\n" +
+ "\tfolderChildTextSizePx: 23.0px (11.5dp)\n" +
+ "\tfolderChildDrawablePaddingPx: 80.0px (40.0dp)\n" +
+ "\tfolderCellLayoutBorderSpacePx: 0.0px (0.0dp)\n" +
+ "\tfolderContentPaddingLeftRight: 0.0px (0.0dp)\n" +
+ "\tfolderTopPadding: 48.0px (24.0dp)\n" +
+ "\tfolderFooterHeight: 0.0px (0.0dp)\n" +
+ "\tbottomSheetTopPadding: 104.0px (52.0dp)\n" +
+ "\tbottomSheetOpenDuration: 500\n" +
+ "\tbottomSheetCloseDuration: 500\n" +
+ "\tbottomSheetWorkspaceScale: 0.97\n" +
+ "\tbottomSheetDepth: 0.0\n" +
+ "\tallAppsShiftRange: 1496.0px (748.0dp)\n" +
+ "\tallAppsTopPadding: 104.0px (52.0dp)\n" +
+ "\tallAppsOpenDuration: 500\n" +
+ "\tallAppsCloseDuration: 500\n" +
+ "\tallAppsIconSizePx: 120.0px (60.0dp)\n" +
+ "\tallAppsIconTextSizePx: 28.0px (14.0dp)\n" +
+ "\tallAppsIconDrawablePaddingPx: 14.0px (7.0dp)\n" +
+ "\tallAppsCellHeightPx: 284.0px (142.0dp)\n" +
+ "\tallAppsCellWidthPx: 252.0px (126.0dp)\n" +
+ "\tallAppsBorderSpacePxX: 32.0px (16.0dp)\n" +
+ "\tallAppsBorderSpacePxY: 32.0px (16.0dp)\n" +
+ "\tnumShownAllAppsColumns: 6\n" +
+ "\tallAppsLeftRightPadding: 32.0px (16.0dp)\n" +
+ "\tallAppsLeftRightMargin: 412.0px (206.0dp)\n" +
+ "\thotseatBarSizePx: 200.0px (100.0dp)\n" +
+ "\tinv.hotseatColumnSpan: 4\n" +
+ "\thotseatCellHeightPx: 135.0px (67.5dp)\n" +
+ "\thotseatBarBottomSpacePx: 80.0px (40.0dp)\n" +
+ "\thotseatBarSidePaddingStartPx: 0.0px (0.0dp)\n" +
+ "\thotseatBarSidePaddingEndPx: 0.0px (0.0dp)\n" +
+ "\thotseatBarEndOffset: 0.0px (0.0dp)\n" +
+ "\thotseatQsbSpace: 0.0px (0.0dp)\n" +
+ "\thotseatQsbHeight: 0.0px (0.0dp)\n" +
+ "\tspringLoadedHotseatBarTopMarginPx: 128.0px (64.0dp)\n" +
+ "\tgetHotseatLayoutPadding(context).top: 0.0px (0.0dp)\n" +
+ "\tgetHotseatLayoutPadding(context).bottom: 65.0px (32.5dp)\n" +
+ "\tgetHotseatLayoutPadding(context).left: 668.0px (334.0dp)\n" +
+ "\tgetHotseatLayoutPadding(context).right: 668.0px (334.0dp)\n" +
+ "\tnumShownHotseatIcons: 6\n" +
+ "\thotseatBorderSpace: 100.0px (50.0dp)\n" +
+ "\tisQsbInline: false\n" +
+ "\thotseatQsbWidth: 1224.0px (612.0dp)\n" +
+ "\tisTaskbarPresent:false\n" +
+ "\tisTaskbarPresentInApps:true\n" +
+ "\ttaskbarSize: 0.0px (0.0dp)\n" +
+ "\tdesiredWorkspaceHorizontalMarginPx: 240.0px (120.0dp)\n" +
+ "\tworkspacePadding.left: 181.0px (90.5dp)\n" +
+ "\tworkspacePadding.top: 0.0px (0.0dp)\n" +
+ "\tworkspacePadding.right: 181.0px (90.5dp)\n" +
+ "\tworkspacePadding.bottom: 244.0px (122.0dp)\n" +
+ "\ticonScale: 1.0px (0.5dp)\n" +
+ "\tcellScaleToFit : 1.0px (0.5dp)\n" +
+ "\textraSpace: 80.0px (40.0dp)\n" +
+ "\tunscaled extraSpace: 80.0px (40.0dp)\n" +
+ "\tmaxEmptySpace: 200.0px (100.0dp)\n" +
+ "\tworkspaceTopPadding: 25.0px (12.5dp)\n" +
+ "\tworkspaceBottomPadding: 55.0px (27.5dp)\n" +
+ "\toverviewTaskMarginPx: 0.0px (0.0dp)\n" +
+ "\toverviewTaskIconSizePx: 0.0px (0.0dp)\n" +
+ "\toverviewTaskIconDrawableSizePx: 0.0px (0.0dp)\n" +
+ "\toverviewTaskIconDrawableSizeGridPx: 0.0px (0.0dp)\n" +
+ "\toverviewTaskThumbnailTopMarginPx: 0.0px (0.0dp)\n" +
+ "\toverviewActionsTopMarginPx: 0.0px (0.0dp)\n" +
+ "\toverviewActionsHeight: 0.0px (0.0dp)\n" +
+ "\toverviewActionsClaimedSpaceBelow: 0.0px (0.0dp)\n" +
+ "\toverviewActionsButtonSpacing: 0.0px (0.0dp)\n" +
+ "\toverviewPageSpacing: 0.0px (0.0dp)\n" +
+ "\toverviewRowSpacing: 0.0px (0.0dp)\n" +
+ "\toverviewGridSideMargin: 0.0px (0.0dp)\n" +
+ "\tdropTargetBarTopMarginPx: 0.0px (0.0dp)\n" +
+ "\tdropTargetBarSizePx: 144.0px (72.0dp)\n" +
+ "\tdropTargetBarBottomMarginPx: 64.0px (32.0dp)\n" +
+ "\tgetCellLayoutSpringLoadShrunkTop(): 312.0px (156.0dp)\n" +
+ "\tgetCellLayoutSpringLoadShrunkBottom(): 1272.0px (636.0dp)\n" +
+ "\tworkspaceSpringLoadedMinNextPageVisiblePx: 48.0px (24.0dp)\n" +
+ "\tgetWorkspaceSpringLoadScale(): 0.76677316px (0.38338658dp)\n" +
+ "\tgetCellLayoutHeight(): 1252.0px (626.0dp)\n" +
+ "\tgetCellLayoutWidth(): 2198.0px (1099.0dp)\n"
+ )
+ }
+
+ @Test
+ fun tabletLandscape() {
+ initializeVarsForTablet(deviceSpecs["tablet"]!!, isLandscape = true)
+ val dp = getDeviceProfileForGrid("6_by_5")
+ dp.isTaskbarPresentInApps = true
+
+ assertThat(dump(dp))
+ .isEqualTo(
+ "DeviceProfile:\n" +
+ "\t1 dp = 2.0 px\n" +
+ "\tisTablet:true\n" +
+ "\tisPhone:false\n" +
+ "\ttransposeLayoutWithOrientation:false\n" +
+ "\tisGestureMode:true\n" +
+ "\tisLandscape:true\n" +
+ "\tisMultiWindowMode:false\n" +
+ "\tisTwoPanels:false\n" +
+ "\twindowX: 0.0px (0.0dp)\n" +
+ "\twindowY: 0.0px (0.0dp)\n" +
+ "\twidthPx: 2560.0px (1280.0dp)\n" +
+ "\theightPx: 1600.0px (800.0dp)\n" +
+ "\tavailableWidthPx: 2560.0px (1280.0dp)\n" +
+ "\tavailableHeightPx: 1496.0px (748.0dp)\n" +
+ "\tmInsets.left: 0.0px (0.0dp)\n" +
+ "\tmInsets.top: 104.0px (52.0dp)\n" +
+ "\tmInsets.right: 0.0px (0.0dp)\n" +
+ "\tmInsets.bottom: 0.0px (0.0dp)\n" +
+ "\taspectRatio:1.6\n" +
+ "\tisScalableGrid:true\n" +
+ "\tinv.numRows: 5\n" +
+ "\tinv.numColumns: 6\n" +
+ "\tinv.numSearchContainerColumns: 3\n" +
+ "\tminCellSize: PointF(120.0, 104.0)dp\n" +
+ "\tcellWidthPx: 240.0px (120.0dp)\n" +
+ "\tcellHeightPx: 208.0px (104.0dp)\n" +
+ "\tgetCellSize().x: 240.0px (120.0dp)\n" +
+ "\tgetCellSize().y: 208.0px (104.0dp)\n" +
+ "\tcellLayoutBorderSpacePx Horizontal: 128.0px (64.0dp)\n" +
+ "\tcellLayoutBorderSpacePx Vertical: 32.0px (16.0dp)\n" +
+ "\tcellLayoutPaddingPx.left: 59.0px (29.5dp)\n" +
+ "\tcellLayoutPaddingPx.top: 25.0px (12.5dp)\n" +
+ "\tcellLayoutPaddingPx.right: 59.0px (29.5dp)\n" +
+ "\tcellLayoutPaddingPx.bottom: 59.0px (29.5dp)\n" +
+ "\ticonSizePx: 120.0px (60.0dp)\n" +
+ "\ticonTextSizePx: 28.0px (14.0dp)\n" +
+ "\ticonDrawablePaddingPx: 14.0px (7.0dp)\n" +
+ "\tfolderCellWidthPx: 397.0px (198.5dp)\n" +
+ "\tfolderCellHeightPx: 371.0px (185.5dp)\n" +
+ "\tfolderChildIconSizePx: 99.0px (49.5dp)\n" +
+ "\tfolderChildTextSizePx: 23.0px (11.5dp)\n" +
+ "\tfolderChildDrawablePaddingPx: 80.0px (40.0dp)\n" +
+ "\tfolderCellLayoutBorderSpacePx: 0.0px (0.0dp)\n" +
+ "\tfolderContentPaddingLeftRight: 0.0px (0.0dp)\n" +
+ "\tfolderTopPadding: 48.0px (24.0dp)\n" +
+ "\tfolderFooterHeight: 0.0px (0.0dp)\n" +
+ "\tbottomSheetTopPadding: 104.0px (52.0dp)\n" +
+ "\tbottomSheetOpenDuration: 500\n" +
+ "\tbottomSheetCloseDuration: 500\n" +
+ "\tbottomSheetWorkspaceScale: 0.97\n" +
+ "\tbottomSheetDepth: 0.0\n" +
+ "\tallAppsShiftRange: 1496.0px (748.0dp)\n" +
+ "\tallAppsTopPadding: 104.0px (52.0dp)\n" +
+ "\tallAppsOpenDuration: 500\n" +
+ "\tallAppsCloseDuration: 500\n" +
+ "\tallAppsIconSizePx: 120.0px (60.0dp)\n" +
+ "\tallAppsIconTextSizePx: 28.0px (14.0dp)\n" +
+ "\tallAppsIconDrawablePaddingPx: 14.0px (7.0dp)\n" +
+ "\tallAppsCellHeightPx: 284.0px (142.0dp)\n" +
+ "\tallAppsCellWidthPx: 252.0px (126.0dp)\n" +
+ "\tallAppsBorderSpacePxX: 32.0px (16.0dp)\n" +
+ "\tallAppsBorderSpacePxY: 32.0px (16.0dp)\n" +
+ "\tnumShownAllAppsColumns: 6\n" +
+ "\tallAppsLeftRightPadding: 32.0px (16.0dp)\n" +
+ "\tallAppsLeftRightMargin: 412.0px (206.0dp)\n" +
+ "\thotseatBarSizePx: 200.0px (100.0dp)\n" +
+ "\tinv.hotseatColumnSpan: 4\n" +
+ "\thotseatCellHeightPx: 135.0px (67.5dp)\n" +
+ "\thotseatBarBottomSpacePx: 80.0px (40.0dp)\n" +
+ "\thotseatBarSidePaddingStartPx: 0.0px (0.0dp)\n" +
+ "\thotseatBarSidePaddingEndPx: 0.0px (0.0dp)\n" +
+ "\thotseatBarEndOffset: 0.0px (0.0dp)\n" +
+ "\thotseatQsbSpace: 0.0px (0.0dp)\n" +
+ "\thotseatQsbHeight: 0.0px (0.0dp)\n" +
+ "\tspringLoadedHotseatBarTopMarginPx: 128.0px (64.0dp)\n" +
+ "\tgetHotseatLayoutPadding(context).top: 0.0px (0.0dp)\n" +
+ "\tgetHotseatLayoutPadding(context).bottom: 65.0px (32.5dp)\n" +
+ "\tgetHotseatLayoutPadding(context).left: 668.0px (334.0dp)\n" +
+ "\tgetHotseatLayoutPadding(context).right: 668.0px (334.0dp)\n" +
+ "\tnumShownHotseatIcons: 6\n" +
+ "\thotseatBorderSpace: 100.0px (50.0dp)\n" +
+ "\tisQsbInline: false\n" +
+ "\thotseatQsbWidth: 1224.0px (612.0dp)\n" +
+ "\tisTaskbarPresent:false\n" +
+ "\tisTaskbarPresentInApps:true\n" +
+ "\ttaskbarSize: 0.0px (0.0dp)\n" +
+ "\tdesiredWorkspaceHorizontalMarginPx: 240.0px (120.0dp)\n" +
+ "\tworkspacePadding.left: 181.0px (90.5dp)\n" +
+ "\tworkspacePadding.top: 0.0px (0.0dp)\n" +
+ "\tworkspacePadding.right: 181.0px (90.5dp)\n" +
+ "\tworkspacePadding.bottom: 244.0px (122.0dp)\n" +
+ "\ticonScale: 1.0px (0.5dp)\n" +
+ "\tcellScaleToFit : 1.0px (0.5dp)\n" +
+ "\textraSpace: 80.0px (40.0dp)\n" +
+ "\tunscaled extraSpace: 80.0px (40.0dp)\n" +
+ "\tmaxEmptySpace: 200.0px (100.0dp)\n" +
+ "\tworkspaceTopPadding: 25.0px (12.5dp)\n" +
+ "\tworkspaceBottomPadding: 55.0px (27.5dp)\n" +
+ "\toverviewTaskMarginPx: 0.0px (0.0dp)\n" +
+ "\toverviewTaskIconSizePx: 0.0px (0.0dp)\n" +
+ "\toverviewTaskIconDrawableSizePx: 0.0px (0.0dp)\n" +
+ "\toverviewTaskIconDrawableSizeGridPx: 0.0px (0.0dp)\n" +
+ "\toverviewTaskThumbnailTopMarginPx: 0.0px (0.0dp)\n" +
+ "\toverviewActionsTopMarginPx: 0.0px (0.0dp)\n" +
+ "\toverviewActionsHeight: 0.0px (0.0dp)\n" +
+ "\toverviewActionsClaimedSpaceBelow: 0.0px (0.0dp)\n" +
+ "\toverviewActionsButtonSpacing: 0.0px (0.0dp)\n" +
+ "\toverviewPageSpacing: 0.0px (0.0dp)\n" +
+ "\toverviewRowSpacing: 0.0px (0.0dp)\n" +
+ "\toverviewGridSideMargin: 0.0px (0.0dp)\n" +
+ "\tdropTargetBarTopMarginPx: 0.0px (0.0dp)\n" +
+ "\tdropTargetBarSizePx: 144.0px (72.0dp)\n" +
+ "\tdropTargetBarBottomMarginPx: 64.0px (32.0dp)\n" +
+ "\tgetCellLayoutSpringLoadShrunkTop(): 312.0px (156.0dp)\n" +
+ "\tgetCellLayoutSpringLoadShrunkBottom(): 1272.0px (636.0dp)\n" +
+ "\tworkspaceSpringLoadedMinNextPageVisiblePx: 48.0px (24.0dp)\n" +
+ "\tgetWorkspaceSpringLoadScale(): 0.76677316px (0.38338658dp)\n" +
+ "\tgetCellLayoutHeight(): 1252.0px (626.0dp)\n" +
+ "\tgetCellLayoutWidth(): 2198.0px (1099.0dp)\n"
+ )
+ }
+
+ @Test
+ fun tabletPortrait3Button() {
+ initializeVarsForTablet(deviceSpecs["tablet"]!!, isGestureMode = false)
+ val dp = getDeviceProfileForGrid("6_by_5")
+ dp.isTaskbarPresentInApps = true
+
+ assertThat(dump(dp))
+ .isEqualTo(
+ "DeviceProfile:\n" +
+ "\t1 dp = 2.0 px\n" +
+ "\tisTablet:true\n" +
+ "\tisPhone:false\n" +
+ "\ttransposeLayoutWithOrientation:false\n" +
+ "\tisGestureMode:false\n" +
+ "\tisLandscape:false\n" +
+ "\tisMultiWindowMode:false\n" +
+ "\tisTwoPanels:false\n" +
+ "\twindowX: 0.0px (0.0dp)\n" +
+ "\twindowY: 0.0px (0.0dp)\n" +
+ "\twidthPx: 1600.0px (800.0dp)\n" +
+ "\theightPx: 2560.0px (1280.0dp)\n" +
+ "\tavailableWidthPx: 1600.0px (800.0dp)\n" +
+ "\tavailableHeightPx: 2456.0px (1228.0dp)\n" +
+ "\tmInsets.left: 0.0px (0.0dp)\n" +
+ "\tmInsets.top: 104.0px (52.0dp)\n" +
+ "\tmInsets.right: 0.0px (0.0dp)\n" +
+ "\tmInsets.bottom: 0.0px (0.0dp)\n" +
+ "\taspectRatio:1.6\n" +
+ "\tisScalableGrid:true\n" +
+ "\tinv.numRows: 5\n" +
+ "\tinv.numColumns: 6\n" +
+ "\tinv.numSearchContainerColumns: 3\n" +
+ "\tminCellSize: PointF(102.0, 120.0)dp\n" +
+ "\tcellWidthPx: 204.0px (102.0dp)\n" +
+ "\tcellHeightPx: 240.0px (120.0dp)\n" +
+ "\tgetCellSize().x: 204.0px (102.0dp)\n" +
+ "\tgetCellSize().y: 240.0px (120.0dp)\n" +
+ "\tcellLayoutBorderSpacePx Horizontal: 32.0px (16.0dp)\n" +
+ "\tcellLayoutBorderSpacePx Vertical: 128.0px (64.0dp)\n" +
+ "\tcellLayoutPaddingPx.left: 72.0px (36.0dp)\n" +
+ "\tcellLayoutPaddingPx.top: 72.0px (36.0dp)\n" +
+ "\tcellLayoutPaddingPx.right: 72.0px (36.0dp)\n" +
+ "\tcellLayoutPaddingPx.bottom: 72.0px (36.0dp)\n" +
+ "\ticonSizePx: 120.0px (60.0dp)\n" +
+ "\ticonTextSizePx: 28.0px (14.0dp)\n" +
+ "\ticonDrawablePaddingPx: 14.0px (7.0dp)\n" +
+ "\tfolderCellWidthPx: 408.0px (204.0dp)\n" +
+ "\tfolderCellHeightPx: 648.0px (324.0dp)\n" +
+ "\tfolderChildIconSizePx: 120.0px (60.0dp)\n" +
+ "\tfolderChildTextSizePx: 28.0px (14.0dp)\n" +
+ "\tfolderChildDrawablePaddingPx: 163.0px (81.5dp)\n" +
+ "\tfolderCellLayoutBorderSpacePx: 0.0px (0.0dp)\n" +
+ "\tfolderContentPaddingLeftRight: 0.0px (0.0dp)\n" +
+ "\tfolderTopPadding: 48.0px (24.0dp)\n" +
+ "\tfolderFooterHeight: 0.0px (0.0dp)\n" +
+ "\tbottomSheetTopPadding: 704.0px (352.0dp)\n" +
+ "\tbottomSheetOpenDuration: 500\n" +
+ "\tbottomSheetCloseDuration: 500\n" +
+ "\tbottomSheetWorkspaceScale: 0.97\n" +
+ "\tbottomSheetDepth: 0.0\n" +
+ "\tallAppsShiftRange: 1810.0px (905.0dp)\n" +
+ "\tallAppsTopPadding: 750.0px (375.0dp)\n" +
+ "\tallAppsOpenDuration: 500\n" +
+ "\tallAppsCloseDuration: 500\n" +
+ "\tallAppsIconSizePx: 120.0px (60.0dp)\n" +
+ "\tallAppsIconTextSizePx: 28.0px (14.0dp)\n" +
+ "\tallAppsIconDrawablePaddingPx: 14.0px (7.0dp)\n" +
+ "\tallAppsCellHeightPx: 316.0px (158.0dp)\n" +
+ "\tallAppsCellWidthPx: 192.0px (96.0dp)\n" +
+ "\tallAppsBorderSpacePxX: 16.0px (8.0dp)\n" +
+ "\tallAppsBorderSpacePxY: 32.0px (16.0dp)\n" +
+ "\tnumShownAllAppsColumns: 6\n" +
+ "\tallAppsLeftRightPadding: 32.0px (16.0dp)\n" +
+ "\tallAppsLeftRightMargin: 152.0px (76.0dp)\n" +
+ "\thotseatBarSizePx: 272.0px (136.0dp)\n" +
+ "\tinv.hotseatColumnSpan: 6\n" +
+ "\thotseatCellHeightPx: 135.0px (67.5dp)\n" +
+ "\thotseatBarBottomSpacePx: 152.0px (76.0dp)\n" +
+ "\thotseatBarSidePaddingStartPx: 0.0px (0.0dp)\n" +
+ "\thotseatBarSidePaddingEndPx: 0.0px (0.0dp)\n" +
+ "\thotseatBarEndOffset: 0.0px (0.0dp)\n" +
+ "\thotseatQsbSpace: 0.0px (0.0dp)\n" +
+ "\thotseatQsbHeight: 0.0px (0.0dp)\n" +
+ "\tspringLoadedHotseatBarTopMarginPx: 216.0px (108.0dp)\n" +
+ "\tgetHotseatLayoutPadding(context).top: 0.0px (0.0dp)\n" +
+ "\tgetHotseatLayoutPadding(context).bottom: 137.0px (68.5dp)\n" +
+ "\tgetHotseatLayoutPadding(context).left: 150.0px (75.0dp)\n" +
+ "\tgetHotseatLayoutPadding(context).right: 150.0px (75.0dp)\n" +
+ "\tnumShownHotseatIcons: 6\n" +
+ "\thotseatBorderSpace: 116.0px (58.0dp)\n" +
+ "\tisQsbInline: false\n" +
+ "\thotseatQsbWidth: 1300.0px (650.0dp)\n" +
+ "\tisTaskbarPresent:false\n" +
+ "\tisTaskbarPresentInApps:true\n" +
+ "\ttaskbarSize: 0.0px (0.0dp)\n" +
+ "\tdesiredWorkspaceHorizontalMarginPx: 108.0px (54.0dp)\n" +
+ "\tworkspacePadding.left: 36.0px (18.0dp)\n" +
+ "\tworkspacePadding.top: 132.0px (66.0dp)\n" +
+ "\tworkspacePadding.right: 36.0px (18.0dp)\n" +
+ "\tworkspacePadding.bottom: 468.0px (234.0dp)\n" +
+ "\ticonScale: 1.0px (0.5dp)\n" +
+ "\tcellScaleToFit : 1.0px (0.5dp)\n" +
+ "\textraSpace: 424.0px (212.0dp)\n" +
+ "\tunscaled extraSpace: 424.0px (212.0dp)\n" +
+ "\tmaxEmptySpace: 19998.0px (9999.0dp)\n" +
+ "\tworkspaceTopPadding: 204.0px (102.0dp)\n" +
+ "\tworkspaceBottomPadding: 220.0px (110.0dp)\n" +
+ "\toverviewTaskMarginPx: 0.0px (0.0dp)\n" +
+ "\toverviewTaskIconSizePx: 0.0px (0.0dp)\n" +
+ "\toverviewTaskIconDrawableSizePx: 0.0px (0.0dp)\n" +
+ "\toverviewTaskIconDrawableSizeGridPx: 0.0px (0.0dp)\n" +
+ "\toverviewTaskThumbnailTopMarginPx: 0.0px (0.0dp)\n" +
+ "\toverviewActionsTopMarginPx: 0.0px (0.0dp)\n" +
+ "\toverviewActionsHeight: 0.0px (0.0dp)\n" +
+ "\toverviewActionsClaimedSpaceBelow: 0.0px (0.0dp)\n" +
+ "\toverviewActionsButtonSpacing: 0.0px (0.0dp)\n" +
+ "\toverviewPageSpacing: 0.0px (0.0dp)\n" +
+ "\toverviewRowSpacing: 0.0px (0.0dp)\n" +
+ "\toverviewGridSideMargin: 0.0px (0.0dp)\n" +
+ "\tdropTargetBarTopMarginPx: 220.0px (110.0dp)\n" +
+ "\tdropTargetBarSizePx: 144.0px (72.0dp)\n" +
+ "\tdropTargetBarBottomMarginPx: 96.0px (48.0dp)\n" +
+ "\tgetCellLayoutSpringLoadShrunkTop(): 564.0px (282.0dp)\n" +
+ "\tgetCellLayoutSpringLoadShrunkBottom(): 2072.0px (1036.0dp)\n" +
+ "\tworkspaceSpringLoadedMinNextPageVisiblePx: 48.0px (24.0dp)\n" +
+ "\tgetWorkspaceSpringLoadScale(): 0.8125px (0.40625dp)\n" +
+ "\tgetCellLayoutHeight(): 1856.0px (928.0dp)\n" +
+ "\tgetCellLayoutWidth(): 1528.0px (764.0dp)\n"
+ )
+ }
+
+ @Test
+ fun tabletPortrait() {
+ initializeVarsForTablet(deviceSpecs["tablet"]!!)
+ val dp = getDeviceProfileForGrid("6_by_5")
+ dp.isTaskbarPresentInApps = true
+
+ assertThat(dump(dp))
+ .isEqualTo(
+ "DeviceProfile:\n" +
+ "\t1 dp = 2.0 px\n" +
+ "\tisTablet:true\n" +
+ "\tisPhone:false\n" +
+ "\ttransposeLayoutWithOrientation:false\n" +
+ "\tisGestureMode:true\n" +
+ "\tisLandscape:false\n" +
+ "\tisMultiWindowMode:false\n" +
+ "\tisTwoPanels:false\n" +
+ "\twindowX: 0.0px (0.0dp)\n" +
+ "\twindowY: 0.0px (0.0dp)\n" +
+ "\twidthPx: 1600.0px (800.0dp)\n" +
+ "\theightPx: 2560.0px (1280.0dp)\n" +
+ "\tavailableWidthPx: 1600.0px (800.0dp)\n" +
+ "\tavailableHeightPx: 2456.0px (1228.0dp)\n" +
+ "\tmInsets.left: 0.0px (0.0dp)\n" +
+ "\tmInsets.top: 104.0px (52.0dp)\n" +
+ "\tmInsets.right: 0.0px (0.0dp)\n" +
+ "\tmInsets.bottom: 0.0px (0.0dp)\n" +
+ "\taspectRatio:1.6\n" +
+ "\tisScalableGrid:true\n" +
+ "\tinv.numRows: 5\n" +
+ "\tinv.numColumns: 6\n" +
+ "\tinv.numSearchContainerColumns: 3\n" +
+ "\tminCellSize: PointF(102.0, 120.0)dp\n" +
+ "\tcellWidthPx: 204.0px (102.0dp)\n" +
+ "\tcellHeightPx: 240.0px (120.0dp)\n" +
+ "\tgetCellSize().x: 204.0px (102.0dp)\n" +
+ "\tgetCellSize().y: 240.0px (120.0dp)\n" +
+ "\tcellLayoutBorderSpacePx Horizontal: 32.0px (16.0dp)\n" +
+ "\tcellLayoutBorderSpacePx Vertical: 128.0px (64.0dp)\n" +
+ "\tcellLayoutPaddingPx.left: 72.0px (36.0dp)\n" +
+ "\tcellLayoutPaddingPx.top: 72.0px (36.0dp)\n" +
+ "\tcellLayoutPaddingPx.right: 72.0px (36.0dp)\n" +
+ "\tcellLayoutPaddingPx.bottom: 72.0px (36.0dp)\n" +
+ "\ticonSizePx: 120.0px (60.0dp)\n" +
+ "\ticonTextSizePx: 28.0px (14.0dp)\n" +
+ "\ticonDrawablePaddingPx: 14.0px (7.0dp)\n" +
+ "\tfolderCellWidthPx: 408.0px (204.0dp)\n" +
+ "\tfolderCellHeightPx: 648.0px (324.0dp)\n" +
+ "\tfolderChildIconSizePx: 120.0px (60.0dp)\n" +
+ "\tfolderChildTextSizePx: 28.0px (14.0dp)\n" +
+ "\tfolderChildDrawablePaddingPx: 163.0px (81.5dp)\n" +
+ "\tfolderCellLayoutBorderSpacePx: 0.0px (0.0dp)\n" +
+ "\tfolderContentPaddingLeftRight: 0.0px (0.0dp)\n" +
+ "\tfolderTopPadding: 48.0px (24.0dp)\n" +
+ "\tfolderFooterHeight: 0.0px (0.0dp)\n" +
+ "\tbottomSheetTopPadding: 704.0px (352.0dp)\n" +
+ "\tbottomSheetOpenDuration: 500\n" +
+ "\tbottomSheetCloseDuration: 500\n" +
+ "\tbottomSheetWorkspaceScale: 0.97\n" +
+ "\tbottomSheetDepth: 0.0\n" +
+ "\tallAppsShiftRange: 1810.0px (905.0dp)\n" +
+ "\tallAppsTopPadding: 750.0px (375.0dp)\n" +
+ "\tallAppsOpenDuration: 500\n" +
+ "\tallAppsCloseDuration: 500\n" +
+ "\tallAppsIconSizePx: 120.0px (60.0dp)\n" +
+ "\tallAppsIconTextSizePx: 28.0px (14.0dp)\n" +
+ "\tallAppsIconDrawablePaddingPx: 14.0px (7.0dp)\n" +
+ "\tallAppsCellHeightPx: 316.0px (158.0dp)\n" +
+ "\tallAppsCellWidthPx: 192.0px (96.0dp)\n" +
+ "\tallAppsBorderSpacePxX: 16.0px (8.0dp)\n" +
+ "\tallAppsBorderSpacePxY: 32.0px (16.0dp)\n" +
+ "\tnumShownAllAppsColumns: 6\n" +
+ "\tallAppsLeftRightPadding: 32.0px (16.0dp)\n" +
+ "\tallAppsLeftRightMargin: 152.0px (76.0dp)\n" +
+ "\thotseatBarSizePx: 272.0px (136.0dp)\n" +
+ "\tinv.hotseatColumnSpan: 6\n" +
+ "\thotseatCellHeightPx: 135.0px (67.5dp)\n" +
+ "\thotseatBarBottomSpacePx: 152.0px (76.0dp)\n" +
+ "\thotseatBarSidePaddingStartPx: 0.0px (0.0dp)\n" +
+ "\thotseatBarSidePaddingEndPx: 0.0px (0.0dp)\n" +
+ "\thotseatBarEndOffset: 0.0px (0.0dp)\n" +
+ "\thotseatQsbSpace: 0.0px (0.0dp)\n" +
+ "\thotseatQsbHeight: 0.0px (0.0dp)\n" +
+ "\tspringLoadedHotseatBarTopMarginPx: 216.0px (108.0dp)\n" +
+ "\tgetHotseatLayoutPadding(context).top: 0.0px (0.0dp)\n" +
+ "\tgetHotseatLayoutPadding(context).bottom: 137.0px (68.5dp)\n" +
+ "\tgetHotseatLayoutPadding(context).left: 150.0px (75.0dp)\n" +
+ "\tgetHotseatLayoutPadding(context).right: 150.0px (75.0dp)\n" +
+ "\tnumShownHotseatIcons: 6\n" +
+ "\thotseatBorderSpace: 116.0px (58.0dp)\n" +
+ "\tisQsbInline: false\n" +
+ "\thotseatQsbWidth: 1300.0px (650.0dp)\n" +
+ "\tisTaskbarPresent:false\n" +
+ "\tisTaskbarPresentInApps:true\n" +
+ "\ttaskbarSize: 0.0px (0.0dp)\n" +
+ "\tdesiredWorkspaceHorizontalMarginPx: 108.0px (54.0dp)\n" +
+ "\tworkspacePadding.left: 36.0px (18.0dp)\n" +
+ "\tworkspacePadding.top: 132.0px (66.0dp)\n" +
+ "\tworkspacePadding.right: 36.0px (18.0dp)\n" +
+ "\tworkspacePadding.bottom: 468.0px (234.0dp)\n" +
+ "\ticonScale: 1.0px (0.5dp)\n" +
+ "\tcellScaleToFit : 1.0px (0.5dp)\n" +
+ "\textraSpace: 424.0px (212.0dp)\n" +
+ "\tunscaled extraSpace: 424.0px (212.0dp)\n" +
+ "\tmaxEmptySpace: 19998.0px (9999.0dp)\n" +
+ "\tworkspaceTopPadding: 204.0px (102.0dp)\n" +
+ "\tworkspaceBottomPadding: 220.0px (110.0dp)\n" +
+ "\toverviewTaskMarginPx: 0.0px (0.0dp)\n" +
+ "\toverviewTaskIconSizePx: 0.0px (0.0dp)\n" +
+ "\toverviewTaskIconDrawableSizePx: 0.0px (0.0dp)\n" +
+ "\toverviewTaskIconDrawableSizeGridPx: 0.0px (0.0dp)\n" +
+ "\toverviewTaskThumbnailTopMarginPx: 0.0px (0.0dp)\n" +
+ "\toverviewActionsTopMarginPx: 0.0px (0.0dp)\n" +
+ "\toverviewActionsHeight: 0.0px (0.0dp)\n" +
+ "\toverviewActionsClaimedSpaceBelow: 0.0px (0.0dp)\n" +
+ "\toverviewActionsButtonSpacing: 0.0px (0.0dp)\n" +
+ "\toverviewPageSpacing: 0.0px (0.0dp)\n" +
+ "\toverviewRowSpacing: 0.0px (0.0dp)\n" +
+ "\toverviewGridSideMargin: 0.0px (0.0dp)\n" +
+ "\tdropTargetBarTopMarginPx: 220.0px (110.0dp)\n" +
+ "\tdropTargetBarSizePx: 144.0px (72.0dp)\n" +
+ "\tdropTargetBarBottomMarginPx: 96.0px (48.0dp)\n" +
+ "\tgetCellLayoutSpringLoadShrunkTop(): 564.0px (282.0dp)\n" +
+ "\tgetCellLayoutSpringLoadShrunkBottom(): 2072.0px (1036.0dp)\n" +
+ "\tworkspaceSpringLoadedMinNextPageVisiblePx: 48.0px (24.0dp)\n" +
+ "\tgetWorkspaceSpringLoadScale(): 0.8125px (0.40625dp)\n" +
+ "\tgetCellLayoutHeight(): 1856.0px (928.0dp)\n" +
+ "\tgetCellLayoutWidth(): 1528.0px (764.0dp)\n"
+ )
+ }
+
+ @Test
+ fun twoPanelLandscape3Button() {
+ initializeVarsForTwoPanel(
+ deviceSpecs["twopanel-tablet"]!!,
+ deviceSpecs["twopanel-phone"]!!,
+ isLandscape = true,
+ isGestureMode = false
+ )
+ val dp = getDeviceProfileForGrid("4_by_4")
+ dp.isTaskbarPresentInApps = true
+
+ assertThat(dump(dp))
+ .isEqualTo(
+ "DeviceProfile:\n" +
+ "\t1 dp = 2.625 px\n" +
+ "\tisTablet:true\n" +
+ "\tisPhone:false\n" +
+ "\ttransposeLayoutWithOrientation:false\n" +
+ "\tisGestureMode:false\n" +
+ "\tisLandscape:true\n" +
+ "\tisMultiWindowMode:false\n" +
+ "\tisTwoPanels:true\n" +
+ "\twindowX: 0.0px (0.0dp)\n" +
+ "\twindowY: 0.0px (0.0dp)\n" +
+ "\twidthPx: 2208.0px (841.1429dp)\n" +
+ "\theightPx: 1840.0px (700.9524dp)\n" +
+ "\tavailableWidthPx: 2208.0px (841.1429dp)\n" +
+ "\tavailableHeightPx: 1730.0px (659.0476dp)\n" +
+ "\tmInsets.left: 0.0px (0.0dp)\n" +
+ "\tmInsets.top: 110.0px (41.904762dp)\n" +
+ "\tmInsets.right: 0.0px (0.0dp)\n" +
+ "\tmInsets.bottom: 0.0px (0.0dp)\n" +
+ "\taspectRatio:1.2\n" +
+ "\tisScalableGrid:false\n" +
+ "\tinv.numRows: 4\n" +
+ "\tinv.numColumns: 4\n" +
+ "\tinv.numSearchContainerColumns: 4\n" +
+ "\tminCellSize: PointF(0.0, 0.0)dp\n" +
+ "\tcellWidthPx: 159.0px (60.57143dp)\n" +
+ "\tcellHeightPx: 223.0px (84.95238dp)\n" +
+ "\tgetCellSize().x: 270.0px (102.85714dp)\n" +
+ "\tgetCellSize().y: 342.0px (130.28572dp)\n" +
+ "\tcellLayoutBorderSpacePx Horizontal: 0.0px (0.0dp)\n" +
+ "\tcellLayoutBorderSpacePx Vertical: 0.0px (0.0dp)\n" +
+ "\tcellLayoutPaddingPx.left: 0.0px (0.0dp)\n" +
+ "\tcellLayoutPaddingPx.top: 0.0px (0.0dp)\n" +
+ "\tcellLayoutPaddingPx.right: 0.0px (0.0dp)\n" +
+ "\tcellLayoutPaddingPx.bottom: 0.0px (0.0dp)\n" +
+ "\ticonSizePx: 141.0px (53.714287dp)\n" +
+ "\ticonTextSizePx: 34.0px (12.952381dp)\n" +
+ "\ticonDrawablePaddingPx: 18.0px (6.857143dp)\n" +
+ "\tfolderCellWidthPx: 189.0px (72.0dp)\n" +
+ "\tfolderCellHeightPx: 219.0px (83.42857dp)\n" +
+ "\tfolderChildIconSizePx: 141.0px (53.714287dp)\n" +
+ "\tfolderChildTextSizePx: 34.0px (12.952381dp)\n" +
+ "\tfolderChildDrawablePaddingPx: 10.0px (3.8095238dp)\n" +
+ "\tfolderCellLayoutBorderSpacePx: 0.0px (0.0dp)\n" +
+ "\tfolderContentPaddingLeftRight: 21.0px (8.0dp)\n" +
+ "\tfolderTopPadding: 63.0px (24.0dp)\n" +
+ "\tfolderFooterHeight: 147.0px (56.0dp)\n" +
+ "\tbottomSheetTopPadding: 110.0px (41.904762dp)\n" +
+ "\tbottomSheetOpenDuration: 500\n" +
+ "\tbottomSheetCloseDuration: 500\n" +
+ "\tbottomSheetWorkspaceScale: 0.97\n" +
+ "\tbottomSheetDepth: 1.0\n" +
+ "\tallAppsShiftRange: 1730.0px (659.0476dp)\n" +
+ "\tallAppsTopPadding: 110.0px (41.904762dp)\n" +
+ "\tallAppsOpenDuration: 500\n" +
+ "\tallAppsCloseDuration: 500\n" +
+ "\tallAppsIconSizePx: 141.0px (53.714287dp)\n" +
+ "\tallAppsIconTextSizePx: 34.0px (12.952381dp)\n" +
+ "\tallAppsIconDrawablePaddingPx: 21.0px (8.0dp)\n" +
+ "\tallAppsCellHeightPx: 315.0px (120.0dp)\n" +
+ "\tallAppsCellWidthPx: 183.0px (69.71429dp)\n" +
+ "\tallAppsBorderSpacePxX: 42.0px (16.0dp)\n" +
+ "\tallAppsBorderSpacePxY: 42.0px (16.0dp)\n" +
+ "\tnumShownAllAppsColumns: 8\n" +
+ "\tallAppsLeftRightPadding: 42.0px (16.0dp)\n" +
+ "\tallAppsLeftRightMargin: 183.0px (69.71429dp)\n" +
+ "\thotseatBarSizePx: 267.0px (101.71429dp)\n" +
+ "\tinv.hotseatColumnSpan: 4\n" +
+ "\thotseatCellHeightPx: 159.0px (60.57143dp)\n" +
+ "\thotseatBarBottomSpacePx: 126.0px (48.0dp)\n" +
+ "\thotseatBarSidePaddingStartPx: 0.0px (0.0dp)\n" +
+ "\thotseatBarSidePaddingEndPx: 0.0px (0.0dp)\n" +
+ "\thotseatBarEndOffset: 0.0px (0.0dp)\n" +
+ "\thotseatQsbSpace: 0.0px (0.0dp)\n" +
+ "\thotseatQsbHeight: 0.0px (0.0dp)\n" +
+ "\tspringLoadedHotseatBarTopMarginPx: 116.0px (44.190475dp)\n" +
+ "\tgetHotseatLayoutPadding(context).top: 0.0px (0.0dp)\n" +
+ "\tgetHotseatLayoutPadding(context).bottom: 108.0px (41.142857dp)\n" +
+ "\tgetHotseatLayoutPadding(context).left: 113.0px (43.04762dp)\n" +
+ "\tgetHotseatLayoutPadding(context).right: 113.0px (43.04762dp)\n" +
+ "\tnumShownHotseatIcons: 6\n" +
+ "\thotseatBorderSpace: 0.0px (0.0dp)\n" +
+ "\tisQsbInline: false\n" +
+ "\thotseatQsbWidth: 0.0px (0.0dp)\n" +
+ "\tisTaskbarPresent:false\n" +
+ "\tisTaskbarPresentInApps:true\n" +
+ "\ttaskbarSize: 0.0px (0.0dp)\n" +
+ "\tdesiredWorkspaceHorizontalMarginPx: 21.0px (8.0dp)\n" +
+ "\tworkspacePadding.left: 21.0px (8.0dp)\n" +
+ "\tworkspacePadding.top: 30.0px (11.428572dp)\n" +
+ "\tworkspacePadding.right: 21.0px (8.0dp)\n" +
+ "\tworkspacePadding.bottom: 330.0px (125.71429dp)\n" +
+ "\ticonScale: 1.0px (0.3809524dp)\n" +
+ "\tcellScaleToFit : 1.0px (0.3809524dp)\n" +
+ "\textraSpace: 478.0px (182.09525dp)\n" +
+ "\tunscaled extraSpace: 478.0px (182.09525dp)\n" +
+ "\tmaxEmptySpace: 0.0px (0.0dp)\n" +
+ "\tworkspaceTopPadding: 0.0px (0.0dp)\n" +
+ "\tworkspaceBottomPadding: 0.0px (0.0dp)\n" +
+ "\toverviewTaskMarginPx: 0.0px (0.0dp)\n" +
+ "\toverviewTaskIconSizePx: 0.0px (0.0dp)\n" +
+ "\toverviewTaskIconDrawableSizePx: 0.0px (0.0dp)\n" +
+ "\toverviewTaskIconDrawableSizeGridPx: 0.0px (0.0dp)\n" +
+ "\toverviewTaskThumbnailTopMarginPx: 0.0px (0.0dp)\n" +
+ "\toverviewActionsTopMarginPx: 0.0px (0.0dp)\n" +
+ "\toverviewActionsHeight: 0.0px (0.0dp)\n" +
+ "\toverviewActionsClaimedSpaceBelow: 0.0px (0.0dp)\n" +
+ "\toverviewActionsButtonSpacing: 0.0px (0.0dp)\n" +
+ "\toverviewPageSpacing: 0.0px (0.0dp)\n" +
+ "\toverviewRowSpacing: 0.0px (0.0dp)\n" +
+ "\toverviewGridSideMargin: 0.0px (0.0dp)\n" +
+ "\tdropTargetBarTopMarginPx: 0.0px (0.0dp)\n" +
+ "\tdropTargetBarSizePx: 147.0px (56.0dp)\n" +
+ "\tdropTargetBarBottomMarginPx: 42.0px (16.0dp)\n" +
+ "\tgetCellLayoutSpringLoadShrunkTop(): 299.0px (113.90476dp)\n" +
+ "\tgetCellLayoutSpringLoadShrunkBottom(): 1457.0px (555.0476dp)\n" +
+ "\tworkspaceSpringLoadedMinNextPageVisiblePx: 63.0px (24.0dp)\n" +
+ "\tgetWorkspaceSpringLoadScale(): 0.8452555px (0.32200208dp)\n" +
+ "\tgetCellLayoutHeight(): 1370.0px (521.9048dp)\n" +
+ "\tgetCellLayoutWidth(): 1083.0px (412.57144dp)\n"
+ )
+ }
+
+ @Test
+ fun twoPanelLandscape() {
+ initializeVarsForTwoPanel(
+ deviceSpecs["twopanel-tablet"]!!,
+ deviceSpecs["twopanel-phone"]!!,
+ isLandscape = true
+ )
+ val dp = getDeviceProfileForGrid("4_by_4")
+ dp.isTaskbarPresentInApps = true
+
+ assertThat(dump(dp))
+ .isEqualTo(
+ "DeviceProfile:\n" +
+ "\t1 dp = 2.625 px\n" +
+ "\tisTablet:true\n" +
+ "\tisPhone:false\n" +
+ "\ttransposeLayoutWithOrientation:false\n" +
+ "\tisGestureMode:true\n" +
+ "\tisLandscape:true\n" +
+ "\tisMultiWindowMode:false\n" +
+ "\tisTwoPanels:true\n" +
+ "\twindowX: 0.0px (0.0dp)\n" +
+ "\twindowY: 0.0px (0.0dp)\n" +
+ "\twidthPx: 2208.0px (841.1429dp)\n" +
+ "\theightPx: 1840.0px (700.9524dp)\n" +
+ "\tavailableWidthPx: 2208.0px (841.1429dp)\n" +
+ "\tavailableHeightPx: 1730.0px (659.0476dp)\n" +
+ "\tmInsets.left: 0.0px (0.0dp)\n" +
+ "\tmInsets.top: 110.0px (41.904762dp)\n" +
+ "\tmInsets.right: 0.0px (0.0dp)\n" +
+ "\tmInsets.bottom: 0.0px (0.0dp)\n" +
+ "\taspectRatio:1.2\n" +
+ "\tisScalableGrid:false\n" +
+ "\tinv.numRows: 4\n" +
+ "\tinv.numColumns: 4\n" +
+ "\tinv.numSearchContainerColumns: 4\n" +
+ "\tminCellSize: PointF(0.0, 0.0)dp\n" +
+ "\tcellWidthPx: 159.0px (60.57143dp)\n" +
+ "\tcellHeightPx: 223.0px (84.95238dp)\n" +
+ "\tgetCellSize().x: 270.0px (102.85714dp)\n" +
+ "\tgetCellSize().y: 342.0px (130.28572dp)\n" +
+ "\tcellLayoutBorderSpacePx Horizontal: 0.0px (0.0dp)\n" +
+ "\tcellLayoutBorderSpacePx Vertical: 0.0px (0.0dp)\n" +
+ "\tcellLayoutPaddingPx.left: 0.0px (0.0dp)\n" +
+ "\tcellLayoutPaddingPx.top: 0.0px (0.0dp)\n" +
+ "\tcellLayoutPaddingPx.right: 0.0px (0.0dp)\n" +
+ "\tcellLayoutPaddingPx.bottom: 0.0px (0.0dp)\n" +
+ "\ticonSizePx: 141.0px (53.714287dp)\n" +
+ "\ticonTextSizePx: 34.0px (12.952381dp)\n" +
+ "\ticonDrawablePaddingPx: 18.0px (6.857143dp)\n" +
+ "\tfolderCellWidthPx: 189.0px (72.0dp)\n" +
+ "\tfolderCellHeightPx: 219.0px (83.42857dp)\n" +
+ "\tfolderChildIconSizePx: 141.0px (53.714287dp)\n" +
+ "\tfolderChildTextSizePx: 34.0px (12.952381dp)\n" +
+ "\tfolderChildDrawablePaddingPx: 10.0px (3.8095238dp)\n" +
+ "\tfolderCellLayoutBorderSpacePx: 0.0px (0.0dp)\n" +
+ "\tfolderContentPaddingLeftRight: 21.0px (8.0dp)\n" +
+ "\tfolderTopPadding: 63.0px (24.0dp)\n" +
+ "\tfolderFooterHeight: 147.0px (56.0dp)\n" +
+ "\tbottomSheetTopPadding: 110.0px (41.904762dp)\n" +
+ "\tbottomSheetOpenDuration: 500\n" +
+ "\tbottomSheetCloseDuration: 500\n" +
+ "\tbottomSheetWorkspaceScale: 0.97\n" +
+ "\tbottomSheetDepth: 1.0\n" +
+ "\tallAppsShiftRange: 1730.0px (659.0476dp)\n" +
+ "\tallAppsTopPadding: 110.0px (41.904762dp)\n" +
+ "\tallAppsOpenDuration: 500\n" +
+ "\tallAppsCloseDuration: 500\n" +
+ "\tallAppsIconSizePx: 141.0px (53.714287dp)\n" +
+ "\tallAppsIconTextSizePx: 34.0px (12.952381dp)\n" +
+ "\tallAppsIconDrawablePaddingPx: 21.0px (8.0dp)\n" +
+ "\tallAppsCellHeightPx: 315.0px (120.0dp)\n" +
+ "\tallAppsCellWidthPx: 183.0px (69.71429dp)\n" +
+ "\tallAppsBorderSpacePxX: 42.0px (16.0dp)\n" +
+ "\tallAppsBorderSpacePxY: 42.0px (16.0dp)\n" +
+ "\tnumShownAllAppsColumns: 8\n" +
+ "\tallAppsLeftRightPadding: 42.0px (16.0dp)\n" +
+ "\tallAppsLeftRightMargin: 183.0px (69.71429dp)\n" +
+ "\thotseatBarSizePx: 267.0px (101.71429dp)\n" +
+ "\tinv.hotseatColumnSpan: 4\n" +
+ "\thotseatCellHeightPx: 159.0px (60.57143dp)\n" +
+ "\thotseatBarBottomSpacePx: 126.0px (48.0dp)\n" +
+ "\thotseatBarSidePaddingStartPx: 0.0px (0.0dp)\n" +
+ "\thotseatBarSidePaddingEndPx: 0.0px (0.0dp)\n" +
+ "\thotseatBarEndOffset: 0.0px (0.0dp)\n" +
+ "\thotseatQsbSpace: 0.0px (0.0dp)\n" +
+ "\thotseatQsbHeight: 0.0px (0.0dp)\n" +
+ "\tspringLoadedHotseatBarTopMarginPx: 116.0px (44.190475dp)\n" +
+ "\tgetHotseatLayoutPadding(context).top: 0.0px (0.0dp)\n" +
+ "\tgetHotseatLayoutPadding(context).bottom: 108.0px (41.142857dp)\n" +
+ "\tgetHotseatLayoutPadding(context).left: 113.0px (43.04762dp)\n" +
+ "\tgetHotseatLayoutPadding(context).right: 113.0px (43.04762dp)\n" +
+ "\tnumShownHotseatIcons: 6\n" +
+ "\thotseatBorderSpace: 0.0px (0.0dp)\n" +
+ "\tisQsbInline: false\n" +
+ "\thotseatQsbWidth: 0.0px (0.0dp)\n" +
+ "\tisTaskbarPresent:false\n" +
+ "\tisTaskbarPresentInApps:true\n" +
+ "\ttaskbarSize: 0.0px (0.0dp)\n" +
+ "\tdesiredWorkspaceHorizontalMarginPx: 21.0px (8.0dp)\n" +
+ "\tworkspacePadding.left: 21.0px (8.0dp)\n" +
+ "\tworkspacePadding.top: 30.0px (11.428572dp)\n" +
+ "\tworkspacePadding.right: 21.0px (8.0dp)\n" +
+ "\tworkspacePadding.bottom: 330.0px (125.71429dp)\n" +
+ "\ticonScale: 1.0px (0.3809524dp)\n" +
+ "\tcellScaleToFit : 1.0px (0.3809524dp)\n" +
+ "\textraSpace: 478.0px (182.09525dp)\n" +
+ "\tunscaled extraSpace: 478.0px (182.09525dp)\n" +
+ "\tmaxEmptySpace: 0.0px (0.0dp)\n" +
+ "\tworkspaceTopPadding: 0.0px (0.0dp)\n" +
+ "\tworkspaceBottomPadding: 0.0px (0.0dp)\n" +
+ "\toverviewTaskMarginPx: 0.0px (0.0dp)\n" +
+ "\toverviewTaskIconSizePx: 0.0px (0.0dp)\n" +
+ "\toverviewTaskIconDrawableSizePx: 0.0px (0.0dp)\n" +
+ "\toverviewTaskIconDrawableSizeGridPx: 0.0px (0.0dp)\n" +
+ "\toverviewTaskThumbnailTopMarginPx: 0.0px (0.0dp)\n" +
+ "\toverviewActionsTopMarginPx: 0.0px (0.0dp)\n" +
+ "\toverviewActionsHeight: 0.0px (0.0dp)\n" +
+ "\toverviewActionsClaimedSpaceBelow: 0.0px (0.0dp)\n" +
+ "\toverviewActionsButtonSpacing: 0.0px (0.0dp)\n" +
+ "\toverviewPageSpacing: 0.0px (0.0dp)\n" +
+ "\toverviewRowSpacing: 0.0px (0.0dp)\n" +
+ "\toverviewGridSideMargin: 0.0px (0.0dp)\n" +
+ "\tdropTargetBarTopMarginPx: 0.0px (0.0dp)\n" +
+ "\tdropTargetBarSizePx: 147.0px (56.0dp)\n" +
+ "\tdropTargetBarBottomMarginPx: 42.0px (16.0dp)\n" +
+ "\tgetCellLayoutSpringLoadShrunkTop(): 299.0px (113.90476dp)\n" +
+ "\tgetCellLayoutSpringLoadShrunkBottom(): 1457.0px (555.0476dp)\n" +
+ "\tworkspaceSpringLoadedMinNextPageVisiblePx: 63.0px (24.0dp)\n" +
+ "\tgetWorkspaceSpringLoadScale(): 0.8452555px (0.32200208dp)\n" +
+ "\tgetCellLayoutHeight(): 1370.0px (521.9048dp)\n" +
+ "\tgetCellLayoutWidth(): 1083.0px (412.57144dp)\n"
+ )
+ }
+
+ @Test
+ fun twoPanelPortrait3Button() {
+ initializeVarsForTwoPanel(
+ deviceSpecs["twopanel-tablet"]!!,
+ deviceSpecs["twopanel-phone"]!!,
+ isGestureMode = false
+ )
+ val dp = getDeviceProfileForGrid("4_by_4")
+ dp.isTaskbarPresentInApps = true
+
+ assertThat(dump(dp))
+ .isEqualTo(
+ "DeviceProfile:\n" +
+ "\t1 dp = 2.625 px\n" +
+ "\tisTablet:true\n" +
+ "\tisPhone:false\n" +
+ "\ttransposeLayoutWithOrientation:false\n" +
+ "\tisGestureMode:false\n" +
+ "\tisLandscape:false\n" +
+ "\tisMultiWindowMode:false\n" +
+ "\tisTwoPanels:true\n" +
+ "\twindowX: 0.0px (0.0dp)\n" +
+ "\twindowY: 0.0px (0.0dp)\n" +
+ "\twidthPx: 1840.0px (700.9524dp)\n" +
+ "\theightPx: 2208.0px (841.1429dp)\n" +
+ "\tavailableWidthPx: 1840.0px (700.9524dp)\n" +
+ "\tavailableHeightPx: 2075.0px (790.4762dp)\n" +
+ "\tmInsets.left: 0.0px (0.0dp)\n" +
+ "\tmInsets.top: 133.0px (50.666668dp)\n" +
+ "\tmInsets.right: 0.0px (0.0dp)\n" +
+ "\tmInsets.bottom: 0.0px (0.0dp)\n" +
+ "\taspectRatio:1.2\n" +
+ "\tisScalableGrid:false\n" +
+ "\tinv.numRows: 4\n" +
+ "\tinv.numColumns: 4\n" +
+ "\tinv.numSearchContainerColumns: 4\n" +
+ "\tminCellSize: PointF(0.0, 0.0)dp\n" +
+ "\tcellWidthPx: 159.0px (60.57143dp)\n" +
+ "\tcellHeightPx: 223.0px (84.95238dp)\n" +
+ "\tgetCellSize().x: 224.0px (85.333336dp)\n" +
+ "\tgetCellSize().y: 430.0px (163.80952dp)\n" +
+ "\tcellLayoutBorderSpacePx Horizontal: 0.0px (0.0dp)\n" +
+ "\tcellLayoutBorderSpacePx Vertical: 0.0px (0.0dp)\n" +
+ "\tcellLayoutPaddingPx.left: 0.0px (0.0dp)\n" +
+ "\tcellLayoutPaddingPx.top: 0.0px (0.0dp)\n" +
+ "\tcellLayoutPaddingPx.right: 0.0px (0.0dp)\n" +
+ "\tcellLayoutPaddingPx.bottom: 0.0px (0.0dp)\n" +
+ "\ticonSizePx: 141.0px (53.714287dp)\n" +
+ "\ticonTextSizePx: 34.0px (12.952381dp)\n" +
+ "\ticonDrawablePaddingPx: 18.0px (6.857143dp)\n" +
+ "\tfolderCellWidthPx: 189.0px (72.0dp)\n" +
+ "\tfolderCellHeightPx: 219.0px (83.42857dp)\n" +
+ "\tfolderChildIconSizePx: 141.0px (53.714287dp)\n" +
+ "\tfolderChildTextSizePx: 34.0px (12.952381dp)\n" +
+ "\tfolderChildDrawablePaddingPx: 10.0px (3.8095238dp)\n" +
+ "\tfolderCellLayoutBorderSpacePx: 0.0px (0.0dp)\n" +
+ "\tfolderContentPaddingLeftRight: 21.0px (8.0dp)\n" +
+ "\tfolderTopPadding: 63.0px (24.0dp)\n" +
+ "\tfolderFooterHeight: 147.0px (56.0dp)\n" +
+ "\tbottomSheetTopPadding: 133.0px (50.666668dp)\n" +
+ "\tbottomSheetOpenDuration: 500\n" +
+ "\tbottomSheetCloseDuration: 500\n" +
+ "\tbottomSheetWorkspaceScale: 0.97\n" +
+ "\tbottomSheetDepth: 1.0\n" +
+ "\tallAppsShiftRange: 1826.0px (695.619dp)\n" +
+ "\tallAppsTopPadding: 382.0px (145.5238dp)\n" +
+ "\tallAppsOpenDuration: 500\n" +
+ "\tallAppsCloseDuration: 500\n" +
+ "\tallAppsIconSizePx: 141.0px (53.714287dp)\n" +
+ "\tallAppsIconTextSizePx: 34.0px (12.952381dp)\n" +
+ "\tallAppsIconDrawablePaddingPx: 21.0px (8.0dp)\n" +
+ "\tallAppsCellHeightPx: 315.0px (120.0dp)\n" +
+ "\tallAppsCellWidthPx: 183.0px (69.71429dp)\n" +
+ "\tallAppsBorderSpacePxX: 42.0px (16.0dp)\n" +
+ "\tallAppsBorderSpacePxY: 42.0px (16.0dp)\n" +
+ "\tnumShownAllAppsColumns: 8\n" +
+ "\tallAppsLeftRightPadding: 42.0px (16.0dp)\n" +
+ "\tallAppsLeftRightMargin: 1.0px (0.3809524dp)\n" +
+ "\thotseatBarSizePx: 267.0px (101.71429dp)\n" +
+ "\tinv.hotseatColumnSpan: 4\n" +
+ "\thotseatCellHeightPx: 159.0px (60.57143dp)\n" +
+ "\thotseatBarBottomSpacePx: 126.0px (48.0dp)\n" +
+ "\thotseatBarSidePaddingStartPx: 0.0px (0.0dp)\n" +
+ "\thotseatBarSidePaddingEndPx: 0.0px (0.0dp)\n" +
+ "\thotseatBarEndOffset: 0.0px (0.0dp)\n" +
+ "\thotseatQsbSpace: 0.0px (0.0dp)\n" +
+ "\thotseatQsbHeight: 0.0px (0.0dp)\n" +
+ "\tspringLoadedHotseatBarTopMarginPx: 171.0px (65.14286dp)\n" +
+ "\tgetHotseatLayoutPadding(context).top: 0.0px (0.0dp)\n" +
+ "\tgetHotseatLayoutPadding(context).bottom: 108.0px (41.142857dp)\n" +
+ "\tgetHotseatLayoutPadding(context).left: 98.0px (37.333332dp)\n" +
+ "\tgetHotseatLayoutPadding(context).right: 98.0px (37.333332dp)\n" +
+ "\tnumShownHotseatIcons: 6\n" +
+ "\thotseatBorderSpace: 0.0px (0.0dp)\n" +
+ "\tisQsbInline: false\n" +
+ "\thotseatQsbWidth: 0.0px (0.0dp)\n" +
+ "\tisTaskbarPresent:false\n" +
+ "\tisTaskbarPresentInApps:true\n" +
+ "\ttaskbarSize: 0.0px (0.0dp)\n" +
+ "\tdesiredWorkspaceHorizontalMarginPx: 21.0px (8.0dp)\n" +
+ "\tworkspacePadding.left: 21.0px (8.0dp)\n" +
+ "\tworkspacePadding.top: 24.0px (9.142858dp)\n" +
+ "\tworkspacePadding.right: 21.0px (8.0dp)\n" +
+ "\tworkspacePadding.bottom: 330.0px (125.71429dp)\n" +
+ "\ticonScale: 1.0px (0.3809524dp)\n" +
+ "\tcellScaleToFit : 1.0px (0.3809524dp)\n" +
+ "\textraSpace: 829.0px (315.8095dp)\n" +
+ "\tunscaled extraSpace: 829.0px (315.8095dp)\n" +
+ "\tmaxEmptySpace: 0.0px (0.0dp)\n" +
+ "\tworkspaceTopPadding: 0.0px (0.0dp)\n" +
+ "\tworkspaceBottomPadding: 0.0px (0.0dp)\n" +
+ "\toverviewTaskMarginPx: 0.0px (0.0dp)\n" +
+ "\toverviewTaskIconSizePx: 0.0px (0.0dp)\n" +
+ "\toverviewTaskIconDrawableSizePx: 0.0px (0.0dp)\n" +
+ "\toverviewTaskIconDrawableSizeGridPx: 0.0px (0.0dp)\n" +
+ "\toverviewTaskThumbnailTopMarginPx: 0.0px (0.0dp)\n" +
+ "\toverviewActionsTopMarginPx: 0.0px (0.0dp)\n" +
+ "\toverviewActionsHeight: 0.0px (0.0dp)\n" +
+ "\toverviewActionsClaimedSpaceBelow: 0.0px (0.0dp)\n" +
+ "\toverviewActionsButtonSpacing: 0.0px (0.0dp)\n" +
+ "\toverviewPageSpacing: 0.0px (0.0dp)\n" +
+ "\toverviewRowSpacing: 0.0px (0.0dp)\n" +
+ "\toverviewGridSideMargin: 0.0px (0.0dp)\n" +
+ "\tdropTargetBarTopMarginPx: 168.0px (64.0dp)\n" +
+ "\tdropTargetBarSizePx: 147.0px (56.0dp)\n" +
+ "\tdropTargetBarBottomMarginPx: 42.0px (16.0dp)\n" +
+ "\tgetCellLayoutSpringLoadShrunkTop(): 490.0px (186.66667dp)\n" +
+ "\tgetCellLayoutSpringLoadShrunkBottom(): 1770.0px (674.2857dp)\n" +
+ "\tworkspaceSpringLoadedMinNextPageVisiblePx: 63.0px (24.0dp)\n" +
+ "\tgetWorkspaceSpringLoadScale(): 0.7437536px (0.2833347dp)\n" +
+ "\tgetCellLayoutHeight(): 1721.0px (655.619dp)\n" +
+ "\tgetCellLayoutWidth(): 899.0px (342.4762dp)\n"
+ )
+ }
+
+ @Test
+ fun twoPanelPortrait() {
+ initializeVarsForTwoPanel(deviceSpecs["twopanel-tablet"]!!, deviceSpecs["twopanel-phone"]!!)
+ val dp = getDeviceProfileForGrid("4_by_4")
+ dp.isTaskbarPresentInApps = true
+
+ assertThat(dump(dp))
+ .isEqualTo(
+ "DeviceProfile:\n" +
+ "\t1 dp = 2.625 px\n" +
+ "\tisTablet:true\n" +
+ "\tisPhone:false\n" +
+ "\ttransposeLayoutWithOrientation:false\n" +
+ "\tisGestureMode:true\n" +
+ "\tisLandscape:false\n" +
+ "\tisMultiWindowMode:false\n" +
+ "\tisTwoPanels:true\n" +
+ "\twindowX: 0.0px (0.0dp)\n" +
+ "\twindowY: 0.0px (0.0dp)\n" +
+ "\twidthPx: 1840.0px (700.9524dp)\n" +
+ "\theightPx: 2208.0px (841.1429dp)\n" +
+ "\tavailableWidthPx: 1840.0px (700.9524dp)\n" +
+ "\tavailableHeightPx: 2075.0px (790.4762dp)\n" +
+ "\tmInsets.left: 0.0px (0.0dp)\n" +
+ "\tmInsets.top: 133.0px (50.666668dp)\n" +
+ "\tmInsets.right: 0.0px (0.0dp)\n" +
+ "\tmInsets.bottom: 0.0px (0.0dp)\n" +
+ "\taspectRatio:1.2\n" +
+ "\tisScalableGrid:false\n" +
+ "\tinv.numRows: 4\n" +
+ "\tinv.numColumns: 4\n" +
+ "\tinv.numSearchContainerColumns: 4\n" +
+ "\tminCellSize: PointF(0.0, 0.0)dp\n" +
+ "\tcellWidthPx: 159.0px (60.57143dp)\n" +
+ "\tcellHeightPx: 223.0px (84.95238dp)\n" +
+ "\tgetCellSize().x: 224.0px (85.333336dp)\n" +
+ "\tgetCellSize().y: 430.0px (163.80952dp)\n" +
+ "\tcellLayoutBorderSpacePx Horizontal: 0.0px (0.0dp)\n" +
+ "\tcellLayoutBorderSpacePx Vertical: 0.0px (0.0dp)\n" +
+ "\tcellLayoutPaddingPx.left: 0.0px (0.0dp)\n" +
+ "\tcellLayoutPaddingPx.top: 0.0px (0.0dp)\n" +
+ "\tcellLayoutPaddingPx.right: 0.0px (0.0dp)\n" +
+ "\tcellLayoutPaddingPx.bottom: 0.0px (0.0dp)\n" +
+ "\ticonSizePx: 141.0px (53.714287dp)\n" +
+ "\ticonTextSizePx: 34.0px (12.952381dp)\n" +
+ "\ticonDrawablePaddingPx: 18.0px (6.857143dp)\n" +
+ "\tfolderCellWidthPx: 189.0px (72.0dp)\n" +
+ "\tfolderCellHeightPx: 219.0px (83.42857dp)\n" +
+ "\tfolderChildIconSizePx: 141.0px (53.714287dp)\n" +
+ "\tfolderChildTextSizePx: 34.0px (12.952381dp)\n" +
+ "\tfolderChildDrawablePaddingPx: 10.0px (3.8095238dp)\n" +
+ "\tfolderCellLayoutBorderSpacePx: 0.0px (0.0dp)\n" +
+ "\tfolderContentPaddingLeftRight: 21.0px (8.0dp)\n" +
+ "\tfolderTopPadding: 63.0px (24.0dp)\n" +
+ "\tfolderFooterHeight: 147.0px (56.0dp)\n" +
+ "\tbottomSheetTopPadding: 133.0px (50.666668dp)\n" +
+ "\tbottomSheetOpenDuration: 500\n" +
+ "\tbottomSheetCloseDuration: 500\n" +
+ "\tbottomSheetWorkspaceScale: 0.97\n" +
+ "\tbottomSheetDepth: 1.0\n" +
+ "\tallAppsShiftRange: 1826.0px (695.619dp)\n" +
+ "\tallAppsTopPadding: 382.0px (145.5238dp)\n" +
+ "\tallAppsOpenDuration: 500\n" +
+ "\tallAppsCloseDuration: 500\n" +
+ "\tallAppsIconSizePx: 141.0px (53.714287dp)\n" +
+ "\tallAppsIconTextSizePx: 34.0px (12.952381dp)\n" +
+ "\tallAppsIconDrawablePaddingPx: 21.0px (8.0dp)\n" +
+ "\tallAppsCellHeightPx: 315.0px (120.0dp)\n" +
+ "\tallAppsCellWidthPx: 183.0px (69.71429dp)\n" +
+ "\tallAppsBorderSpacePxX: 42.0px (16.0dp)\n" +
+ "\tallAppsBorderSpacePxY: 42.0px (16.0dp)\n" +
+ "\tnumShownAllAppsColumns: 8\n" +
+ "\tallAppsLeftRightPadding: 42.0px (16.0dp)\n" +
+ "\tallAppsLeftRightMargin: 1.0px (0.3809524dp)\n" +
+ "\thotseatBarSizePx: 267.0px (101.71429dp)\n" +
+ "\tinv.hotseatColumnSpan: 4\n" +
+ "\thotseatCellHeightPx: 159.0px (60.57143dp)\n" +
+ "\thotseatBarBottomSpacePx: 126.0px (48.0dp)\n" +
+ "\thotseatBarSidePaddingStartPx: 0.0px (0.0dp)\n" +
+ "\thotseatBarSidePaddingEndPx: 0.0px (0.0dp)\n" +
+ "\thotseatBarEndOffset: 0.0px (0.0dp)\n" +
+ "\thotseatQsbSpace: 0.0px (0.0dp)\n" +
+ "\thotseatQsbHeight: 0.0px (0.0dp)\n" +
+ "\tspringLoadedHotseatBarTopMarginPx: 171.0px (65.14286dp)\n" +
+ "\tgetHotseatLayoutPadding(context).top: 0.0px (0.0dp)\n" +
+ "\tgetHotseatLayoutPadding(context).bottom: 108.0px (41.142857dp)\n" +
+ "\tgetHotseatLayoutPadding(context).left: 98.0px (37.333332dp)\n" +
+ "\tgetHotseatLayoutPadding(context).right: 98.0px (37.333332dp)\n" +
+ "\tnumShownHotseatIcons: 6\n" +
+ "\thotseatBorderSpace: 0.0px (0.0dp)\n" +
+ "\tisQsbInline: false\n" +
+ "\thotseatQsbWidth: 0.0px (0.0dp)\n" +
+ "\tisTaskbarPresent:false\n" +
+ "\tisTaskbarPresentInApps:true\n" +
+ "\ttaskbarSize: 0.0px (0.0dp)\n" +
+ "\tdesiredWorkspaceHorizontalMarginPx: 21.0px (8.0dp)\n" +
+ "\tworkspacePadding.left: 21.0px (8.0dp)\n" +
+ "\tworkspacePadding.top: 24.0px (9.142858dp)\n" +
+ "\tworkspacePadding.right: 21.0px (8.0dp)\n" +
+ "\tworkspacePadding.bottom: 330.0px (125.71429dp)\n" +
+ "\ticonScale: 1.0px (0.3809524dp)\n" +
+ "\tcellScaleToFit : 1.0px (0.3809524dp)\n" +
+ "\textraSpace: 829.0px (315.8095dp)\n" +
+ "\tunscaled extraSpace: 829.0px (315.8095dp)\n" +
+ "\tmaxEmptySpace: 0.0px (0.0dp)\n" +
+ "\tworkspaceTopPadding: 0.0px (0.0dp)\n" +
+ "\tworkspaceBottomPadding: 0.0px (0.0dp)\n" +
+ "\toverviewTaskMarginPx: 0.0px (0.0dp)\n" +
+ "\toverviewTaskIconSizePx: 0.0px (0.0dp)\n" +
+ "\toverviewTaskIconDrawableSizePx: 0.0px (0.0dp)\n" +
+ "\toverviewTaskIconDrawableSizeGridPx: 0.0px (0.0dp)\n" +
+ "\toverviewTaskThumbnailTopMarginPx: 0.0px (0.0dp)\n" +
+ "\toverviewActionsTopMarginPx: 0.0px (0.0dp)\n" +
+ "\toverviewActionsHeight: 0.0px (0.0dp)\n" +
+ "\toverviewActionsClaimedSpaceBelow: 0.0px (0.0dp)\n" +
+ "\toverviewActionsButtonSpacing: 0.0px (0.0dp)\n" +
+ "\toverviewPageSpacing: 0.0px (0.0dp)\n" +
+ "\toverviewRowSpacing: 0.0px (0.0dp)\n" +
+ "\toverviewGridSideMargin: 0.0px (0.0dp)\n" +
+ "\tdropTargetBarTopMarginPx: 168.0px (64.0dp)\n" +
+ "\tdropTargetBarSizePx: 147.0px (56.0dp)\n" +
+ "\tdropTargetBarBottomMarginPx: 42.0px (16.0dp)\n" +
+ "\tgetCellLayoutSpringLoadShrunkTop(): 490.0px (186.66667dp)\n" +
+ "\tgetCellLayoutSpringLoadShrunkBottom(): 1770.0px (674.2857dp)\n" +
+ "\tworkspaceSpringLoadedMinNextPageVisiblePx: 63.0px (24.0dp)\n" +
+ "\tgetWorkspaceSpringLoadScale(): 0.7437536px (0.2833347dp)\n" +
+ "\tgetCellLayoutHeight(): 1721.0px (655.619dp)\n" +
+ "\tgetCellLayoutWidth(): 899.0px (342.4762dp)\n"
+ )
+ }
+
+ private fun getDeviceProfileForGrid(gridName: String): DeviceProfile {
+ return InvariantDeviceProfile(context, gridName).getDeviceProfile(context)
+ }
+
+ private fun dump(dp: DeviceProfile): String {
+ val stringWriter = StringWriter()
+ val printWriter = PrintWriter(stringWriter)
+ dp.dump(context, "", printWriter)
+ printWriter.flush()
+ return stringWriter.toString()
+ }
+}