Merge "Hide taskbar view for app open/close animation." into tm-qpr-dev
diff --git a/protos/launcher_atom.proto b/protos/launcher_atom.proto
index c638ba9..b1064f7 100644
--- a/protos/launcher_atom.proto
+++ b/protos/launcher_atom.proto
@@ -128,10 +128,17 @@
// Bit encoded value to capture pinned and predicted taskbar positions.
optional int32 cardinality = 2;
+
+ // Container where taskbar was invoked.
+ oneof ParentContainer {
+ TaskSwitcherContainer task_switcher_container = 3;
+ }
}
// Next value 44
enum Attribute {
+ option allow_alias = true;
+
UNKNOWN = 0;
DEFAULT_LAYOUT = 1; // icon automatically placed in workspace, folder, hotseat
BACKUP_RESTORE = 2; // icon layout restored from backup
@@ -166,7 +173,8 @@
ALL_APPS_SEARCH_RESULT_SLICE = 19;
ALL_APPS_SEARCH_RESULT_WIDGETS = 20;
ALL_APPS_SEARCH_RESULT_PLAY = 21;
- ALL_APPS_SEARCH_RESULT_SUGGEST = 22;
+ ALL_APPS_SEARCH_RESULT_FALLBACK = 22;
+ ALL_APPS_SEARCH_RESULT_SUGGEST = 22 [deprecated = true];
ALL_APPS_SEARCH_RESULT_ASSISTANT = 23;
ALL_APPS_SEARCH_RESULT_CHROMETAB = 24;
ALL_APPS_SEARCH_RESULT_NAVVYSITE = 25;
diff --git a/quickstep/res/drawable/ic_desktop.xml b/quickstep/res/drawable/ic_desktop.xml
index dfaf8b8..8de275d 100644
--- a/quickstep/res/drawable/ic_desktop.xml
+++ b/quickstep/res/drawable/ic_desktop.xml
@@ -25,7 +25,7 @@
android:translateX="6.0"
android:translateY="6.0">
<path
- android:fillColor="?android:attr/textColorPrimary"
+ android:fillColor="@android:color/black"
android:pathData="M5.958,37.708Q4.458,37.708 3.354,36.604Q2.25,35.5 2.25,34V18.292Q2.25,16.792 3.354,15.688Q4.458,14.583 5.958,14.583H9.5V5.958Q9.5,4.458 10.625,3.354Q11.75,2.25 13.208,2.25H34Q35.542,2.25 36.646,3.354Q37.75,4.458 37.75,5.958V21.667Q37.75,23.167 36.646,24.271Q35.542,25.375 34,25.375H30.5V34Q30.5,35.5 29.396,36.604Q28.292,37.708 26.792,37.708ZM5.958,34H26.792Q26.792,34 26.792,34Q26.792,34 26.792,34V21.542H5.958V34Q5.958,34 5.958,34Q5.958,34 5.958,34ZM30.5,21.667H34Q34,21.667 34,21.667Q34,21.667 34,21.667V9.208H13.208V14.583H26.833Q28.375,14.583 29.438,15.667Q30.5,16.75 30.5,18.25Z"/>
</group>
</vector>
diff --git a/quickstep/res/drawable/ic_empty_desktop.xml b/quickstep/res/drawable/ic_empty_desktop.xml
deleted file mode 100644
index cbf1856..0000000
--- a/quickstep/res/drawable/ic_empty_desktop.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<?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.
- -->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="92dp"
- android:height="80dp"
- android:tint="?android:attr/textColorPrimary"
- android:viewportHeight="80.0"
- android:viewportWidth="92.0">
- <path
- android:fillColor="#AAFFFFFF"
- android:pathData="M 14.365954,80 Q 10.981668,80 8.4908345,77.509166 6,75.018332 6,71.634046 V 36.193807 q 0,-3.384286 2.4908345,-5.87512 2.4908335,-2.493091 5.8751195,-2.493091 H 22.35738 V 8.365954 q 0,-3.3842855 2.538217,-5.8751198 Q 27.433811,0 30.723337,0 h 46.910711 q 3.479041,0 5.969878,2.4908342 2.490834,2.4908343 2.490834,5.8751198 v 35.442495 q 0,3.384286 -2.490834,5.87512 -2.490837,2.490835 -5.969878,2.490835 h -7.896671 v 19.459642 q 0,3.384286 -2.49083,5.87512 Q 64.755713,80 61.371423,80 Z m 0,-8.365954 h 47.005469 q 0,0 0,0 0,0 0,0 V 43.526426 H 14.365954 v 28.10762 q 0,0 0,0 0,0 0,0 z M 69.737377,43.808449 h 7.896671 q 0,0 0,0 0,0 0,0 V 15.698573 H 30.723337 v 12.127023 h 30.740592 q 3.479048,0 5.877376,2.445711 2.396072,2.443454 2.396072,5.82774 z" />
-</vector>
diff --git a/quickstep/res/layout/activity_allset.xml b/quickstep/res/layout/activity_allset.xml
index f08cabe..7ea92b5 100644
--- a/quickstep/res/layout/activity_allset.xml
+++ b/quickstep/res/layout/activity_allset.xml
@@ -38,6 +38,7 @@
app:lottie_loop="true" />
<androidx.constraintlayout.widget.ConstraintLayout
+ android:id="@+id/text_content_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="@dimen/allset_page_margin_horizontal"
diff --git a/quickstep/res/layout/task_desktop.xml b/quickstep/res/layout/task_desktop.xml
index f454835..2ec9d4c 100644
--- a/quickstep/res/layout/task_desktop.xml
+++ b/quickstep/res/layout/task_desktop.xml
@@ -32,19 +32,6 @@
android:layout_width="match_parent"
android:layout_height="match_parent" />
- <TextView
- android:id="@+id/empty_view"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:layout_marginTop="@dimen/overview_task_margin"
- android:drawablePadding="@dimen/recents_empty_message_text_padding"
- android:text="@string/recents_empty_desktop_message"
- android:textColor="?android:textColorPrimary"
- android:textSize="@dimen/recents_empty_message_text_size"
- android:drawableTop="@drawable/ic_empty_desktop"
- android:drawableTint="?android:attr/textColorPrimary" />
-
<!--
TODO(b249371338): DesktopTaskView extends from TaskView. TaskView expects TaskThumbnailView
and IconView with these ids to be present. Need to refactor RecentsView to accept child
diff --git a/quickstep/res/values-night/colors.xml b/quickstep/res/values-night/colors.xml
index af6e064..6474c48 100644
--- a/quickstep/res/values-night/colors.xml
+++ b/quickstep/res/values-night/colors.xml
@@ -13,7 +13,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<resources>
+<resources xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
<color name="gesture_tutorial_back_arrow_color">#99000000</color>
@@ -24,4 +24,6 @@
<color name="all_set_page_background">#FF000000</color>
+ <!-- Turn on work apps button -->
+ <color name="work_turn_on_stroke">?androidprv:attr/colorAccentSecondaryVariant</color>
</resources>
\ No newline at end of file
diff --git a/quickstep/res/values/colors.xml b/quickstep/res/values/colors.xml
index 55df38f..7ac3979 100644
--- a/quickstep/res/values/colors.xml
+++ b/quickstep/res/values/colors.xml
@@ -13,7 +13,7 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<resources xmlns:android="http://schemas.android.com/apk/res/android">
+<resources xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
<color name="chip_hint_foreground_color">#fff</color>
<color name="chip_scrim_start_color">#39000000</color>
@@ -95,4 +95,6 @@
<color name="lottie_yellow400">#fcc934</color>
<color name="lottie_yellow600">#f9ab00</color>
+ <!-- Turn on work apps button -->
+ <color name="work_turn_on_stroke">?androidprv:attr/colorAccentPrimaryVariant</color>
</resources>
\ No newline at end of file
diff --git a/quickstep/res/values/strings.xml b/quickstep/res/values/strings.xml
index 2b5975d..eb5fed2 100644
--- a/quickstep/res/values/strings.xml
+++ b/quickstep/res/values/strings.xml
@@ -30,9 +30,6 @@
<!-- Recents: The empty recents string. [CHAR LIMIT=NONE] -->
<string name="recents_empty_message">No recent items</string>
- <!-- Recents: The empty recents desktop tile string. [CHAR LIMIT=NONE] -->
- <string name="recents_empty_desktop_message">No desktop items</string>
-
<!-- Content description for the recent apps's accessibility option that opens its usage settings. [CHAR LIMIT=NONE] -->
<string name="accessibility_app_usage_settings">App usage settings</string>
@@ -278,6 +275,10 @@
<string name="taskbar_button_quick_settings">Quick Settings</string>
<!-- Accessibility title for the Taskbar window. [CHAR_LIMIT=NONE] -->
<string name="taskbar_a11y_title">Taskbar</string>
+ <!-- Accessibility title for the Taskbar window appeared. [CHAR_LIMIT=NONE] -->
+ <string name="taskbar_a11y_shown_title">Taskbar shown</string>
+ <!-- Accessibility title for the Taskbar window being close. [CHAR_LIMIT=NONE] -->
+ <string name="taskbar_a11y_hidden_title">Taskbar hidden</string>
<!-- Accessibility title for the Taskbar window on phones. [CHAR_LIMIT=NONE] -->
<string name="taskbar_phone_a11y_title">Navigation bar</string>
diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
index 793c68e..95fea3e 100644
--- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
@@ -341,6 +341,11 @@
}
@Override
+ protected boolean isInOverview() {
+ return mTaskbarLauncherStateController.isInOverview();
+ }
+
+ @Override
public RecentsView getRecentsView() {
return mLauncher.getOverviewPanel();
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
index bafd5b4..84bf02e 100644
--- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
@@ -288,14 +288,9 @@
updateButtonLayoutSpacing();
updateStateForFlag(FLAG_SMALL_SCREEN, isPhoneButtonNavMode(mContext));
- // Animate taskbar background when either..
- // notification shade expanded AND not on keyguard
- // back is visible for bouncer
mPropertyHolders.add(new StatePropertyHolder(
mControllers.taskbarDragLayerController.getNavbarBackgroundAlpha(),
- flags -> ((flags & FLAG_NOTIFICATION_SHADE_EXPANDED) != 0
- && (flags & FLAG_KEYGUARD_VISIBLE) == 0)
- || (flags & FLAG_ONLY_BACK_FOR_BOUNCER_VISIBLE) != 0));
+ flags -> (flags & FLAG_ONLY_BACK_FOR_BOUNCER_VISIBLE) != 0));
// Rotation button
RotationButton rotationButton = new RotationButtonImpl(
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index 2864ac7..57e11de 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -432,11 +432,16 @@
}
LauncherAtom.ContainerInfo oldContainer = itemInfoBuilder.getContainerInfo();
+ LauncherAtom.TaskBarContainer.Builder taskbarBuilder =
+ LauncherAtom.TaskBarContainer.newBuilder();
+ if (mControllers.uiController.isInOverview()) {
+ taskbarBuilder.setTaskSwitcherContainer(
+ LauncherAtom.TaskSwitcherContainer.newBuilder());
+ }
+
if (oldContainer.hasPredictedHotseatContainer()) {
LauncherAtom.PredictedHotseatContainer predictedHotseat =
oldContainer.getPredictedHotseatContainer();
- LauncherAtom.TaskBarContainer.Builder taskbarBuilder =
- LauncherAtom.TaskBarContainer.newBuilder();
if (predictedHotseat.hasIndex()) {
taskbarBuilder.setIndex(predictedHotseat.getIndex());
@@ -449,8 +454,6 @@
.setTaskBarContainer(taskbarBuilder));
} else if (oldContainer.hasHotseat()) {
LauncherAtom.HotseatContainer hotseat = oldContainer.getHotseat();
- LauncherAtom.TaskBarContainer.Builder taskbarBuilder =
- LauncherAtom.TaskBarContainer.newBuilder();
if (hotseat.hasIndex()) {
taskbarBuilder.setIndex(hotseat.getIndex());
@@ -462,8 +465,6 @@
LauncherAtom.FolderContainer.Builder folderBuilder = oldContainer.getFolder()
.toBuilder();
LauncherAtom.HotseatContainer hotseat = folderBuilder.getHotseat();
- LauncherAtom.TaskBarContainer.Builder taskbarBuilder =
- LauncherAtom.TaskBarContainer.newBuilder();
if (hotseat.hasIndex()) {
taskbarBuilder.setIndex(hotseat.getIndex());
@@ -476,11 +477,11 @@
} else if (oldContainer.hasAllAppsContainer()) {
itemInfoBuilder.setContainerInfo(LauncherAtom.ContainerInfo.newBuilder()
.setAllAppsContainer(oldContainer.getAllAppsContainer().toBuilder()
- .setTaskbarContainer(LauncherAtom.TaskBarContainer.newBuilder())));
+ .setTaskbarContainer(taskbarBuilder)));
} else if (oldContainer.hasPredictionContainer()) {
itemInfoBuilder.setContainerInfo(LauncherAtom.ContainerInfo.newBuilder()
.setPredictionContainer(oldContainer.getPredictionContainer().toBuilder()
- .setTaskbarContainer(LauncherAtom.TaskBarContainer.newBuilder())));
+ .setTaskbarContainer(taskbarBuilder)));
}
}
@@ -588,10 +589,8 @@
AnimatorSet anim = new AnimatorSet();
anim.play(mControllers.taskbarViewController.getTaskbarIconAlpha().get(
TaskbarViewController.ALPHA_INDEX_NOTIFICATION_EXPANDED).animateToValue(alpha));
- if (!isThreeButtonNav()) {
- anim.play(mControllers.taskbarDragLayerController.getNotificationShadeBgTaskbar()
- .animateToValue(alpha));
- }
+ anim.play(mControllers.taskbarDragLayerController.getNotificationShadeBgTaskbar()
+ .animateToValue(alpha));
anim.start();
if (skipAnim) {
anim.end();
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
index 5ac0570..4d163aa 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
@@ -406,6 +406,10 @@
return mLauncherState != LauncherState.ALL_APPS;
}
+ boolean isInOverview() {
+ return mLauncherState == LauncherState.OVERVIEW;
+ }
+
private void playStateTransitionAnim(AnimatorSet animatorSet, long duration,
boolean committed) {
boolean isInStashedState = mLauncherState.isTaskbarStashed(mLauncher);
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
index babafd5..150d3db 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
@@ -600,6 +600,7 @@
if (!mIsStashed) {
tryStartTaskbarTimeout();
}
+ mControllers.taskbarViewController.announceForAccessibility();
}
});
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
index 13f0405..4c6d3fa 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
@@ -168,6 +168,11 @@
return true;
}
+ /** Returns {@code true} if Taskbar is currently within overview. */
+ protected boolean isInOverview() {
+ return false;
+ }
+
@CallSuper
protected void dumpLogs(String prefix, PrintWriter pw) {
pw.println(String.format(
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
index 3d5089f..dee867e 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
@@ -16,15 +16,18 @@
package com.android.launcher3.taskbar;
import static android.content.pm.PackageManager.FEATURE_PC;
+import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Rect;
+import android.os.Bundle;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
+import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout;
import androidx.annotation.LayoutRes;
@@ -153,7 +156,26 @@
// TODO: Disable touch events on QSB otherwise it can crash.
mQsb = LayoutInflater.from(context).inflate(R.layout.search_container_hotseat, this, false);
+ }
+ @Override
+ public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
+ if (action == AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS) {
+ announceForAccessibility(mContext.getString(R.string.taskbar_a11y_shown_title));
+ } else if (action == AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS) {
+ announceForAccessibility(mContext.getString(R.string.taskbar_a11y_hidden_title));
+ }
+ return super.performAccessibilityActionInternal(action, arguments);
+
+ }
+
+ protected void announceAccessibilityChanges() {
+ this.performAccessibilityAction(
+ isVisibleToUser() ? AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS
+ : AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS, null);
+
+ ActivityContext.lookupContext(getContext()).getDragLayer()
+ .sendAccessibilityEvent(TYPE_WINDOW_CONTENT_CHANGED);
}
private int getColorWithGivenLuminance(int color, float luminance) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
index 3143f23..8b009e6 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
@@ -189,6 +189,13 @@
mActivity.addOnDeviceProfileChangeListener(mDeviceProfileChangeListener);
}
+ /**
+ * Announcement for Accessibility when Taskbar stashes/unstashes.
+ */
+ public void announceForAccessibility() {
+ mTaskbarView.announceAccessibilityChanges();
+ }
+
public void onDestroy() {
LauncherAppState.getInstance(mActivity).getModel().removeCallbacks(mModelCallbacks);
mActivity.removeOnDeviceProfileChangeListener(mDeviceProfileChangeListener);
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index a53f08a..0457fc4 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -40,6 +40,9 @@
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_LAUNCH_TAP;
import static com.android.launcher3.model.data.ItemInfo.NO_MATCHING_ID;
import static com.android.launcher3.popup.QuickstepSystemShortcut.getSplitSelectShortcutByPosition;
+import static com.android.launcher3.popup.SystemShortcut.APP_INFO;
+import static com.android.launcher3.popup.SystemShortcut.INSTALL;
+import static com.android.launcher3.popup.SystemShortcut.WIDGETS;
import static com.android.launcher3.taskbar.LauncherTaskbarUIController.ALL_APPS_PAGE_PROGRESS_INDEX;
import static com.android.launcher3.taskbar.LauncherTaskbarUIController.MINUS_ONE_PAGE_PROGRESS_INDEX;
import static com.android.launcher3.taskbar.LauncherTaskbarUIController.WIDGETS_PAGE_PROGRESS_INDEX;
@@ -80,7 +83,6 @@
import android.view.HapticFeedbackConstants;
import android.view.RemoteAnimationTarget;
import android.view.View;
-import android.view.WindowManagerGlobal;
import android.window.BackEvent;
import android.window.OnBackAnimationCallback;
import android.window.OnBackInvokedDispatcher;
@@ -186,6 +188,8 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.function.Predicate;
@@ -385,22 +389,30 @@
@Override
public Stream<SystemShortcut.Factory> getSupportedShortcuts() {
- Stream<SystemShortcut.Factory> base = Stream.of(WellbeingModel.SHORTCUT_FACTORY);
- if (ENABLE_SPLIT_FROM_WORKSPACE.get() && mDeviceProfile.isTablet) {
- RecentsView recentsView = getOverviewPanel();
- // TODO(b/266482558): Pull it out of PagedOrentationHandler for split from workspace.
- List<SplitPositionOption> positions =
- recentsView.getPagedOrientationHandler().getSplitPositionOptions(
- mDeviceProfile);
- List<SystemShortcut.Factory<QuickstepLauncher>> splitShortcuts = new ArrayList<>();
- for (SplitPositionOption position : positions) {
- splitShortcuts.add(getSplitSelectShortcutByPosition(position));
- }
- base = Stream.concat(base, splitShortcuts.stream());
+ // Order matters as it affects order of appearance in popup container
+ List<SystemShortcut.Factory> shortcuts = new ArrayList(Arrays.asList(
+ APP_INFO, WellbeingModel.SHORTCUT_FACTORY, mHotseatPredictionController));
+ shortcuts.addAll(getSplitShortcuts());
+ shortcuts.add(WIDGETS);
+ shortcuts.add(INSTALL);
+ return shortcuts.stream();
+ }
+
+ private List<SystemShortcut.Factory<QuickstepLauncher>> getSplitShortcuts() {
+
+ if (!ENABLE_SPLIT_FROM_WORKSPACE.get() || !mDeviceProfile.isTablet) {
+ return Collections.emptyList();
}
- return Stream.concat(
- Stream.of(mHotseatPredictionController),
- Stream.concat(base, super.getSupportedShortcuts()));
+ RecentsView recentsView = getOverviewPanel();
+ // TODO(b/266482558): Pull it out of PagedOrentationHandler for split from workspace.
+ List<SplitPositionOption> positions =
+ recentsView.getPagedOrientationHandler().getSplitPositionOptions(
+ mDeviceProfile);
+ List<SystemShortcut.Factory<QuickstepLauncher>> splitShortcuts = new ArrayList<>();
+ for (SplitPositionOption position : positions) {
+ splitShortcuts.add(getSplitSelectShortcutByPosition(position));
+ }
+ return splitShortcuts;
}
/**
@@ -408,15 +420,18 @@
*/
private void onStateOrResumeChanging(boolean inTransition) {
LauncherState state = getStateManager().getState();
- if (!ENABLE_PIP_KEEP_CLEAR_ALGORITHM) {
- boolean started = ((getActivityFlags() & ACTIVITY_STATE_STARTED)) != 0;
- if (started) {
- DeviceProfile profile = getDeviceProfile();
- boolean willUserBeActive =
- (getActivityFlags() & ACTIVITY_STATE_USER_WILL_BE_ACTIVE) != 0;
- boolean visible = (state == NORMAL || state == OVERVIEW)
- && (willUserBeActive || isUserActive())
- && !profile.isVerticalBarLayout();
+ boolean started = ((getActivityFlags() & ACTIVITY_STATE_STARTED)) != 0;
+ if (started) {
+ DeviceProfile profile = getDeviceProfile();
+ boolean willUserBeActive =
+ (getActivityFlags() & ACTIVITY_STATE_USER_WILL_BE_ACTIVE) != 0;
+ boolean visible = (state == NORMAL || state == OVERVIEW)
+ && (willUserBeActive || isUserActive())
+ && !profile.isVerticalBarLayout();
+ if (ENABLE_PIP_KEEP_CLEAR_ALGORITHM) {
+ SystemUiProxy.INSTANCE.get(this)
+ .setLauncherKeepClearAreaHeight(visible, profile.hotseatBarSizePx);
+ } else {
SystemUiProxy.INSTANCE.get(this).setShelfHeight(visible, profile.hotseatBarSizePx);
}
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/flags/DebugFlag.java b/quickstep/src/com/android/launcher3/uioverrides/flags/DebugFlag.java
index 177a399..d4944d0 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/flags/DebugFlag.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/flags/DebugFlag.java
@@ -24,8 +24,6 @@
public final boolean defaultValue;
- boolean mHasBeenChangedAtLeastOnce;
-
public DebugFlag(String key, String description, boolean defaultValue, boolean currentValue) {
super(currentValue);
this.key = key;
diff --git a/quickstep/src/com/android/launcher3/uioverrides/flags/FlagTogglerPrefUi.java b/quickstep/src/com/android/launcher3/uioverrides/flags/FlagTogglerPrefUi.java
index 4ca7e31..b7fb2ed 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/flags/FlagTogglerPrefUi.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/flags/FlagTogglerPrefUi.java
@@ -35,6 +35,9 @@
import com.android.launcher3.R;
import com.android.launcher3.config.FeatureFlags;
+import java.util.List;
+import java.util.Set;
+
/**
* Dev-build only UI allowing developers to toggle flag settings. See {@link FeatureFlags}.
*/
@@ -50,31 +53,15 @@
@Override
public void putBoolean(String key, boolean value) {
- for (DebugFlag flag : FlagsFactory.getDebugFlags()) {
- if (flag.key.equals(key)) {
- SharedPreferences prefs = mContext.getSharedPreferences(
- FLAGS_PREF_NAME, Context.MODE_PRIVATE);
- SharedPreferences.Editor editor = prefs.edit();
- // We keep the key in the prefs even if it has the default value, because it's a
- // signal that it has been changed at one point.
- if (!prefs.contains(key) && value == flag.defaultValue) {
- editor.remove(key).apply();
- flag.mHasBeenChangedAtLeastOnce = false;
- } else {
- editor.putBoolean(key, value).apply();
- flag.mHasBeenChangedAtLeastOnce = true;
- }
- updateMenu();
- }
- }
+ mSharedPreferences.edit().putBoolean(key, value).apply();
+ updateMenu();
}
@Override
public boolean getBoolean(String key, boolean defaultValue) {
for (DebugFlag flag : FlagsFactory.getDebugFlags()) {
if (flag.key.equals(key)) {
- return mContext.getSharedPreferences(FLAGS_PREF_NAME, Context.MODE_PRIVATE)
- .getBoolean(key, flag.defaultValue);
+ return mSharedPreferences.getBoolean(key, flag.defaultValue);
}
}
return defaultValue;
@@ -89,11 +76,22 @@
}
public void applyTo(PreferenceGroup parent) {
+ Set<String> modifiedPrefs = mSharedPreferences.getAll().keySet();
+ List<DebugFlag> flags = FlagsFactory.getDebugFlags();
+ flags.sort((f1, f2) -> {
+ // Sort first by any prefs that the user has changed, then alphabetically.
+ int changeComparison = Boolean.compare(
+ modifiedPrefs.contains(f2.key), modifiedPrefs.contains(f1.key));
+ return changeComparison != 0
+ ? changeComparison
+ : f1.key.compareToIgnoreCase(f2.key);
+ });
+
// For flag overrides we only want to store when the engineer chose to override the
// flag with a different value than the default. That way, when we flip flags in
// future, engineers will pick up the new value immediately. To accomplish this, we use a
// custom preference data store.
- for (DebugFlag flag : FlagsFactory.getDebugFlags()) {
+ for (DebugFlag flag : flags) {
SwitchPreference switchPreference = new SwitchPreference(mContext);
switchPreference.setKey(flag.key);
switchPreference.setDefaultValue(flag.defaultValue);
diff --git a/quickstep/src/com/android/launcher3/uioverrides/flags/FlagsFactory.java b/quickstep/src/com/android/launcher3/uioverrides/flags/FlagsFactory.java
index 84b873d..888cc9d 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/flags/FlagsFactory.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/flags/FlagsFactory.java
@@ -53,7 +53,6 @@
private static final List<DebugFlag> sDebugFlags = new ArrayList<>();
-
private final Set<String> mKeySet = new HashSet<>();
private boolean mRestartRequested = false;
@@ -75,7 +74,6 @@
.getSharedPreferences(FLAGS_PREF_NAME, Context.MODE_PRIVATE);
boolean currentValue = prefs.getBoolean(key, defaultValue);
DebugFlag flag = new DebugFlag(key, description, defaultValue, currentValue);
- flag.mHasBeenChangedAtLeastOnce = prefs.contains(key);
sDebugFlags.add(flag);
return flag;
} else {
@@ -96,7 +94,6 @@
boolean currentValue = prefs.getBoolean(key, defaultValue);
DebugFlag flag = new DeviceFlag(key, description, defaultValue, currentValue,
defaultValueInCode);
- flag.mHasBeenChangedAtLeastOnce = prefs.contains(key);
sDebugFlags.add(flag);
return flag;
} else {
@@ -117,19 +114,9 @@
if (!Utilities.IS_DEBUG_DEVICE) {
return Collections.emptyList();
}
- List<DebugFlag> flags;
synchronized (sDebugFlags) {
- flags = new ArrayList<>(sDebugFlags);
+ return new ArrayList<>(sDebugFlags);
}
- flags.sort((f1, f2) -> {
- // Sort first by any prefs that the user has changed, then alphabetically.
- int changeComparison = Boolean.compare(
- f2.mHasBeenChangedAtLeastOnce, f1.mHasBeenChangedAtLeastOnce);
- return changeComparison != 0
- ? changeComparison
- : f1.key.compareToIgnoreCase(f2.key);
- });
- return flags;
}
/**
diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java
index 86b02aa..7c09805 100644
--- a/quickstep/src/com/android/quickstep/SystemUiProxy.java
+++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java
@@ -87,6 +87,7 @@
new MainThreadInitializedObject<>(SystemUiProxy::new);
private static final int MSG_SET_SHELF_HEIGHT = 1;
+ private static final int MSG_SET_LAUNCHER_KEEP_CLEAR_AREA_HEIGHT = 2;
private ISystemUiProxy mSystemUiProxy;
private IPip mPip;
@@ -121,6 +122,10 @@
private int mLastShelfHeight;
private boolean mLastShelfVisible;
+ // Used to dedupe calls to SystemUI
+ private int mLastLauncherKeepClearAreaHeight;
+ private boolean mLastLauncherKeepClearAreaHeightVisible;
+
private final Context mContext;
private final Handler mAsyncHandler;
@@ -454,6 +459,33 @@
}
/**
+ * Sets the height of the keep clear area that is going to be reported by
+ * the Launcher for the Hotseat.
+ */
+ public void setLauncherKeepClearAreaHeight(boolean visible, int height) {
+ Message.obtain(mAsyncHandler, MSG_SET_LAUNCHER_KEEP_CLEAR_AREA_HEIGHT,
+ visible ? 1 : 0 , height).sendToTarget();
+ }
+
+ @WorkerThread
+ private void setLauncherKeepClearAreaHeight(int visibleInt, int height) {
+ boolean visible = visibleInt != 0;
+ boolean changed = visible != mLastLauncherKeepClearAreaHeightVisible
+ || height != mLastLauncherKeepClearAreaHeight;
+ IPip pip = mPip;
+ if (pip != null && changed) {
+ mLastLauncherKeepClearAreaHeightVisible = visible;
+ mLastLauncherKeepClearAreaHeight = height;
+ try {
+ pip.setLauncherKeepClearAreaHeight(visible, height);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Failed call setLauncherKeepClearAreaHeight visible: " + visible
+ + " height: " + height, e);
+ }
+ }
+ }
+
+ /**
* Sets listener to get pip animation callbacks.
*/
public void setPipAnimationListener(IPipAnimationListener listener) {
@@ -945,6 +977,9 @@
case MSG_SET_SHELF_HEIGHT:
setShelfHeightAsync(msg.arg1, msg.arg2);
return true;
+ case MSG_SET_LAUNCHER_KEEP_CLEAR_AREA_HEIGHT:
+ setLauncherKeepClearAreaHeight(msg.arg1, msg.arg2);
+ return true;
}
return false;
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/TaskbarStashInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/TaskbarStashInputConsumer.java
index 1630d0f..9982162 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/TaskbarStashInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/TaskbarStashInputConsumer.java
@@ -52,7 +52,7 @@
private final float mUnstashArea;
private final float mScreenWidth;
- private final int mTaskbarNavThresholdY;
+ private final int mTaskbarNavThreshold;
private final boolean mIsTaskbarAllAppsOpen;
private boolean mHasPassedTaskbarNavThreshold;
@@ -73,9 +73,7 @@
Resources res = context.getResources();
mUnstashArea = res.getDimensionPixelSize(R.dimen.taskbar_unstash_input_area);
- int taskbarNavThreshold = res.getDimensionPixelSize(R.dimen.taskbar_nav_threshold);
- int screenHeight = taskbarActivityContext.getDeviceProfile().heightPx;
- mTaskbarNavThresholdY = screenHeight - taskbarNavThreshold;
+ mTaskbarNavThreshold = res.getDimensionPixelSize(R.dimen.taskbar_nav_threshold);
mIsTaskbarAllAppsOpen =
mTaskbarActivityContext != null && mTaskbarActivityContext.isTaskbarAllAppsOpen();
@@ -157,7 +155,7 @@
if (mIsTransientTaskbar) {
float dY = mLastPos.y - mDownPos.y;
boolean passedTaskbarNavThreshold = dY < 0
- && mLastPos.y < mTaskbarNavThresholdY;
+ && Math.abs(dY) >= mTaskbarNavThreshold;
if (!mHasPassedTaskbarNavThreshold && passedTaskbarNavThreshold) {
mHasPassedTaskbarNavThreshold = true;
@@ -165,7 +163,7 @@
}
if (dY < 0) {
- dY = -OverScroll.dampedScroll(-dY, mTaskbarNavThresholdY);
+ dY = -OverScroll.dampedScroll(-dY, mTaskbarNavThreshold);
if (mTransitionCallback != null && !mIsTaskbarAllAppsOpen) {
mTransitionCallback.onActionMove(dY);
}
diff --git a/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java b/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java
index 0389d07..79971de 100644
--- a/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java
+++ b/quickstep/src/com/android/quickstep/interaction/AllSetActivity.java
@@ -88,6 +88,10 @@
private static final float ANIMATION_PAUSE_ALPHA_THRESHOLD = 0.1f;
+ private final Rect mTempSettingsBounds = new Rect();
+ private final Rect mTempInclusionBounds = new Rect();
+ private final Rect mTempExclusionBounds = new Rect();
+
private TISBindHelper mTISBindHelper;
private TISBinder mBinder;
@@ -131,9 +135,9 @@
!TextUtils.isEmpty(suwDeviceName)
? suwDeviceName : getString(R.string.default_device_name)));
- TextView tv = findViewById(R.id.navigation_settings);
- tv.setTextColor(accentColor);
- tv.setOnClickListener(v -> {
+ TextView settings = findViewById(R.id.navigation_settings);
+ settings.setTextColor(accentColor);
+ settings.setOnClickListener(v -> {
try {
startActivityForResult(
Intent.parseUri(URI_SYSTEM_NAVIGATION_SETTING, 0), 0);
@@ -142,12 +146,41 @@
}
});
- TextView hintTextView = findViewById(R.id.hint);
+ TextView hint = findViewById(R.id.hint);
DeviceProfile dp = InvariantDeviceProfile.INSTANCE.get(this).getDeviceProfile(this);
if (!dp.isGestureMode) {
- hintTextView.setText(R.string.allset_button_hint);
+ hint.setText(R.string.allset_button_hint);
}
- hintTextView.setAccessibilityDelegate(new SkipButtonAccessibilityDelegate());
+ hint.setAccessibilityDelegate(new SkipButtonAccessibilityDelegate());
+
+ View textContent = findViewById(R.id.text_content_view);
+ textContent.addOnLayoutChangeListener(
+ (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
+ mTempSettingsBounds.set(
+ settings.getLeft(),
+ settings.getTop(),
+ settings.getRight(),
+ settings.getBottom());
+ mTempInclusionBounds.set(
+ 0,
+ // Do not allow overlapping with the subtitle text
+ subtitle.getBottom(),
+ textContent.getWidth(),
+ textContent.getHeight());
+ mTempExclusionBounds.set(
+ hint.getLeft(),
+ hint.getTop(),
+ hint.getRight(),
+ hint.getBottom());
+
+ Utilities.translateOverlappingView(
+ settings,
+ mTempSettingsBounds,
+ mTempInclusionBounds,
+ mTempExclusionBounds,
+ Utilities.TRANSLATE_UP);
+ });
+
mTISBindHelper = new TISBindHelper(this, this::onTISConnected);
mVibrator = getSystemService(Vibrator.class);
diff --git a/quickstep/src/com/android/quickstep/interaction/RootSandboxLayout.java b/quickstep/src/com/android/quickstep/interaction/RootSandboxLayout.java
index bd0ce34..b508484 100644
--- a/quickstep/src/com/android/quickstep/interaction/RootSandboxLayout.java
+++ b/quickstep/src/com/android/quickstep/interaction/RootSandboxLayout.java
@@ -19,6 +19,7 @@
import android.content.Context;
import android.graphics.Insets;
+import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
@@ -34,6 +35,10 @@
/** Root layout that TutorialFragment uses to intercept motion events. */
public class RootSandboxLayout extends RelativeLayout {
+ private final Rect mTempStepIndicatorBounds = new Rect();
+ private final Rect mTempInclusionBounds = new Rect();
+ private final Rect mTempExclusionBounds = new Rect();
+
private View mFeedbackView;
private View mTutorialStepView;
private View mSkipButton;
@@ -98,18 +103,23 @@
private void updateTutorialStepViewTranslation(
@NonNull View anchorView, boolean translateToRight) {
- mTutorialStepView.setTranslationX(translateToRight
- ? Math.min(
- // Translate to the right if the views are overlapping on large fonts and
- // display sizes.
- Math.max(0, anchorView.getRight() - mTutorialStepView.getLeft()),
- // Do not translate beyond the bounds of the container view.
- mFeedbackView.getWidth() - mTutorialStepView.getRight())
- : Math.max(
- // Translate to the left if the views are overlapping on large fonts and
- // display sizes.
- Math.min(0, anchorView.getLeft() - mTutorialStepView.getRight()),
- // Do not translate beyond the bounds of the container view.
- -mTutorialStepView.getLeft()));
+ mTempStepIndicatorBounds.set(
+ mTutorialStepView.getLeft(),
+ mTutorialStepView.getTop(),
+ mTutorialStepView.getRight(),
+ mTutorialStepView.getBottom());
+ mTempInclusionBounds.set(0, 0, mFeedbackView.getWidth(), mFeedbackView.getHeight());
+ mTempExclusionBounds.set(
+ anchorView.getLeft(),
+ anchorView.getTop(),
+ anchorView.getRight(),
+ anchorView.getBottom());
+
+ Utilities.translateOverlappingView(
+ mTutorialStepView,
+ mTempStepIndicatorBounds,
+ mTempInclusionBounds,
+ mTempExclusionBounds,
+ translateToRight ? Utilities.TRANSLATE_RIGHT : Utilities.TRANSLATE_LEFT);
}
}
diff --git a/quickstep/src/com/android/quickstep/util/DesktopTask.java b/quickstep/src/com/android/quickstep/util/DesktopTask.java
index 433d23f..b3f5d82 100644
--- a/quickstep/src/com/android/quickstep/util/DesktopTask.java
+++ b/quickstep/src/com/android/quickstep/util/DesktopTask.java
@@ -16,6 +16,8 @@
package com.android.quickstep.util;
+import androidx.annotation.NonNull;
+
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.recents.model.Task;
@@ -27,9 +29,10 @@
*/
public class DesktopTask extends GroupTask {
- public ArrayList<Task> tasks;
+ @NonNull
+ public final ArrayList<Task> tasks;
- public DesktopTask(ArrayList<Task> tasks) {
+ public DesktopTask(@NonNull ArrayList<Task> tasks) {
super(tasks.get(0), null, null, TaskView.Type.DESKTOP);
this.tasks = tasks;
}
diff --git a/quickstep/src/com/android/quickstep/views/DesktopTaskView.java b/quickstep/src/com/android/quickstep/views/DesktopTaskView.java
index 14898b1..5414068 100644
--- a/quickstep/src/com/android/quickstep/views/DesktopTaskView.java
+++ b/quickstep/src/com/android/quickstep/views/DesktopTaskView.java
@@ -92,7 +92,6 @@
private final ArrayList<CancellableTask<?>> mPendingThumbnailRequests = new ArrayList<>();
private View mBackgroundView;
- private View mEmptyView;
public DesktopTaskView(Context context) {
this(context, null);
@@ -111,7 +110,6 @@
super.onFinishInflate();
mBackgroundView = findViewById(R.id.background);
- mEmptyView = findViewById(R.id.empty_view);
int topMarginPx =
mActivity.getDeviceProfile().overviewTaskThumbnailTopMarginPx;
@@ -187,8 +185,6 @@
mSnapshotViewMap.put(task.key.id, snapshotView);
}
- mEmptyView.setVisibility(mTasks.isEmpty() ? View.VISIBLE : View.GONE);
-
updateTaskIdContainer();
updateTaskIdAttributeContainer();
diff --git a/quickstep/src/com/android/quickstep/views/FloatingWidgetBackgroundView.java b/quickstep/src/com/android/quickstep/views/FloatingWidgetBackgroundView.java
index adea1a4..4ea7753 100644
--- a/quickstep/src/com/android/quickstep/views/FloatingWidgetBackgroundView.java
+++ b/quickstep/src/com/android/quickstep/views/FloatingWidgetBackgroundView.java
@@ -27,8 +27,10 @@
import android.view.ViewOutlineProvider;
import android.widget.RemoteViews.RemoteViewOutlineProvider;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import com.android.launcher3.R;
import com.android.launcher3.widget.LauncherAppWidgetHostView;
import com.android.launcher3.widget.RoundedCornerEnforcement;
@@ -65,14 +67,20 @@
setClipToOutline(true);
}
- void init(LauncherAppWidgetHostView hostView, View backgroundView, float finalRadius,
- int fallbackBackgroundColor) {
+ void init(LauncherAppWidgetHostView hostView, @NonNull View backgroundView,
+ float finalRadius, int fallbackBackgroundColor) {
mFinalRadius = finalRadius;
mSourceView = backgroundView;
mInitialOutlineRadius = getOutlineRadius(hostView, backgroundView);
mIsUsingFallback = false;
if (isSupportedDrawable(backgroundView.getForeground())) {
- mOriginalForeground = backgroundView.getForeground();
+ if (backgroundView.getTag(R.id.saved_floating_widget_foreground) == null) {
+ mOriginalForeground = backgroundView.getForeground();
+ backgroundView.setTag(R.id.saved_floating_widget_foreground, mOriginalForeground);
+ } else {
+ mOriginalForeground = (Drawable) backgroundView.getTag(
+ R.id.saved_floating_widget_foreground);
+ }
mForegroundProperties.init(
mOriginalForeground.getConstantState().newDrawable().mutate());
setForeground(mForegroundProperties.mDrawable);
@@ -82,7 +90,13 @@
mSourceView.setForeground(clipPlaceholder);
}
if (isSupportedDrawable(backgroundView.getBackground())) {
- mOriginalBackground = backgroundView.getBackground();
+ if (backgroundView.getTag(R.id.saved_floating_widget_background) == null) {
+ mOriginalBackground = backgroundView.getBackground();
+ backgroundView.setTag(R.id.saved_floating_widget_background, mOriginalBackground);
+ } else {
+ mOriginalBackground = (Drawable) backgroundView.getTag(
+ R.id.saved_floating_widget_background);
+ }
mBackgroundProperties.init(
mOriginalBackground.getConstantState().newDrawable().mutate());
setBackground(mBackgroundProperties.mDrawable);
@@ -115,6 +129,10 @@
}
void recycle() {
+ if (mSourceView != null) {
+ mSourceView.setTag(R.id.saved_floating_widget_foreground, null);
+ mSourceView.setTag(R.id.saved_floating_widget_background, null);
+ }
mSourceView = null;
mOriginalForeground = null;
mOriginalBackground = null;
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index ac59403..717300e 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -147,8 +147,6 @@
import com.android.launcher3.statehandlers.DepthController;
import com.android.launcher3.statemanager.BaseState;
import com.android.launcher3.statemanager.StatefulActivity;
-import com.android.launcher3.testing.TestLogging;
-import com.android.launcher3.testing.shared.TestProtocol;
import com.android.launcher3.touch.OverScroll;
import com.android.launcher3.touch.PagedOrientationHandler;
import com.android.launcher3.util.DynamicResource;
@@ -1518,9 +1516,10 @@
mMovingTaskView = null;
runningTaskView.resetPersistentViewTransforms();
int frontTaskIndex = 0;
- if (DesktopTaskView.DESKTOP_IS_PROTO2_ENABLED && !runningTaskView.isDesktopTask()) {
- // If desktop mode is enabled, desktop task view is pinned at first position.
- // Move running task to position 1
+ if (DesktopTaskView.DESKTOP_IS_PROTO2_ENABLED && mDesktopTaskView != null
+ && !runningTaskView.isDesktopTask()) {
+ // If desktop mode is enabled, desktop task view is pinned at first position if present.
+ // Move running task to position 1.
frontTaskIndex = 1;
}
addView(runningTaskView, frontTaskIndex);
@@ -1653,14 +1652,18 @@
if (!taskGroups.isEmpty()) {
addView(mClearAllButton);
-
- if (DesktopTaskView.DESKTOP_IS_PROTO2_ENABLED
- && !getSplitSelectController().isSplitSelectActive()) {
- mDesktopTaskView = (DesktopTaskView) getTaskViewFromPool(TaskView.Type.DESKTOP);
- // Always add a desktop task to the first position. Even if it is empty
- addView(mDesktopTaskView, 0);
- ArrayList<Task> tasks = desktopTask != null ? desktopTask.tasks : new ArrayList<>();
- mDesktopTaskView.bind(tasks, mOrientationState);
+ if (DesktopTaskView.DESKTOP_IS_PROTO2_ENABLED) {
+ // Check if we have apps on the desktop
+ if (desktopTask != null && !desktopTask.tasks.isEmpty()) {
+ // If we are actively choosing apps for split, skip the desktop tile
+ if (!getSplitSelectController().isSplitSelectActive()) {
+ mDesktopTaskView = (DesktopTaskView) getTaskViewFromPool(
+ TaskView.Type.DESKTOP);
+ // Always add a desktop task to the first position
+ addView(mDesktopTaskView, 0);
+ mDesktopTaskView.bind(desktopTask.tasks, mOrientationState);
+ }
+ }
}
}
@@ -4493,7 +4496,6 @@
* Attempts to initiate split with an existing taskView, if one exists
*/
public void initiateSplitSelect(SplitSelectSource splitSelectSource) {
- TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "enterSplitSelect");
mSplitSelectSource = splitSelectSource;
mSplitHiddenTaskView = getTaskViewByTaskId(splitSelectSource.alreadyRunningTaskId);
mSplitHiddenTaskViewIndex = indexOfChild(mSplitHiddenTaskView);
@@ -5201,7 +5203,7 @@
}
private int getFirstViewIndex() {
- if (DesktopTaskView.DESKTOP_IS_PROTO2_ENABLED) {
+ if (DesktopTaskView.DESKTOP_IS_PROTO2_ENABLED && mDesktopTaskView != null) {
// Desktop task is at position 0, that is the first view
return 0;
}
diff --git a/quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java b/quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java
deleted file mode 100644
index f10b917..0000000
--- a/quickstep/tests/src/com/android/quickstep/TaplTestsSplitscreen.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.quickstep;
-
-import android.content.Intent;
-
-import com.android.launcher3.ui.TaplTestsLauncher3;
-import com.android.launcher3.util.rule.TestStabilityRule;
-import com.android.quickstep.TaskbarModeSwitchRule.TaskbarModeSwitch;
-
-import org.junit.After;
-import org.junit.Assume;
-import org.junit.Before;
-import org.junit.Test;
-
-public class TaplTestsSplitscreen extends AbstractQuickStepTest {
- private static final String CALCULATOR_APP_NAME = "Calculator";
- private static final String CALCULATOR_APP_PACKAGE =
- resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR);
-
- @Override
- @Before
- public void setUp() throws Exception {
- super.setUp();
- TaplTestsLauncher3.initialize(this);
-
- mLauncher.getWorkspace()
- .deleteAppIcon(mLauncher.getWorkspace().getHotseatAppIcon(0))
- .switchToAllApps()
- .getAppIcon(CALCULATOR_APP_NAME)
- .dragToHotseat(0);
-
- startAppFast(CALCULATOR_APP_PACKAGE);
- mLauncher.enableBlockTimeout(true);
- mLauncher.showTaskbarIfHidden();
- }
-
- @After
- public void tearDown() {
- mLauncher.enableBlockTimeout(false);
- }
-
- @Test
- // TODO (b/270201357): When this test is proven stable, remove this TestStabilityRule and
- // introduce into presubmit as well.
- @TestStabilityRule.Stability(
- flavors = TestStabilityRule.LOCAL | TestStabilityRule.PLATFORM_POSTSUBMIT)
- @PortraitLandscape
- @TaskbarModeSwitch
- public void testSplitAppFromHomeWithItself() throws Exception {
- Assume.assumeTrue(mLauncher.isTablet());
-
- mLauncher.goHome()
- .switchToAllApps()
- .getAppIcon(CALCULATOR_APP_NAME)
- .openMenu()
- .getSplitScreenMenuItem()
- .click();
-
- mLauncher.getLaunchedAppState()
- .getTaskbar()
- .getAppIcon(CALCULATOR_APP_NAME)
- .launchIntoSplitScreen();
- }
-}
diff --git a/res/drawable/bg_work_apps_paused_action_button.xml b/res/drawable/bg_work_apps_paused_action_button.xml
index 74d4693..57d1ae5 100644
--- a/res/drawable/bg_work_apps_paused_action_button.xml
+++ b/res/drawable/bg_work_apps_paused_action_button.xml
@@ -21,11 +21,12 @@
<solid android:color="@android:color/white" />
</shape>
</item>
-
<item android:id="@android:id/background">
<shape android:shape="rectangle">
- <solid android:color="?android:attr/colorControlHighlight" />
<corners android:radius="@dimen/rounded_button_radius" />
+ <stroke
+ android:width="@dimen/work_apps_paused_button_stroke"
+ android:color="@color/work_turn_on_stroke" />
</shape>
</item>
</ripple>
\ No newline at end of file
diff --git a/res/drawable/ic_split_horizontal.xml b/res/drawable/ic_split_horizontal.xml
index ee710d0..2efd2b9 100644
--- a/res/drawable/ic_split_horizontal.xml
+++ b/res/drawable/ic_split_horizontal.xml
@@ -1,9 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="20dp"
- android:height="16dp"
- android:viewportWidth="20"
- android:viewportHeight="16">
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
<path
- android:pathData="M18,14L13,14L13,2L18,2L18,14ZM20,14L20,2C20,0.9 19.1,-0 18,-0L13,-0C11.9,-0 11,0.9 11,2L11,14C11,15.1 11.9,16 13,16L18,16C19.1,16 20,15.1 20,14ZM7,14L2,14L2,2L7,2L7,14ZM9,14L9,2C9,0.9 8.1,-0 7,-0L2,-0C0.9,-0 -0,0.9 -0,2L-0,14C-0,15.1 0.9,16 2,16L7,16C8.1,16 9,15.1 9,14Z"
+ android:pathData="M4,6L9,6L9,18L4,18L4,6ZM2,6L2,18C2,19.1 2.9,20 4,20L9,20C10.1,20 11,19.1 11,18L11,6C11,4.9 10.1,4 9,4L4,4C2.9,4 2,4.9 2,6ZM15,6L20,6L20,18L15,18L15,6ZM13,6L13,18C13,19.1 13.9,20 15,20L20,20C21.1,20 22,19.1 22,18L22,6C22,4.9 21.1,4 20,4L15,4C13.9,4 13,4.9 13,6Z"
android:fillColor="#000000"/>
</vector>
diff --git a/res/layout/system_shortcut_icons_container.xml b/res/layout/system_shortcut_icons_container.xml
index ee104d9..dc4fdb3 100644
--- a/res/layout/system_shortcut_icons_container.xml
+++ b/res/layout/system_shortcut_icons_container.xml
@@ -22,11 +22,4 @@
android:orientation="horizontal"
android:gravity="end|center_vertical"
android:background="@drawable/single_item_primary"
- android:elevation="@dimen/deep_shortcuts_elevation"
- android:clipToPadding="true">
-
- <Space android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:id="@+id/separator"/>
-</LinearLayout>
+ android:elevation="@dimen/deep_shortcuts_elevation"/>
diff --git a/res/layout/system_shortcut_icons_container_material_u.xml b/res/layout/system_shortcut_icons_container_material_u.xml
index afd11e6..70950ba 100644
--- a/res/layout/system_shortcut_icons_container_material_u.xml
+++ b/res/layout/system_shortcut_icons_container_material_u.xml
@@ -23,10 +23,4 @@
android:orientation="horizontal"
android:gravity="end|center_vertical"
android:background="@drawable/popup_background_material_u"
- android:elevation="@dimen/deep_shortcuts_elevation">
-
- <Space android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:id="@+id/separator"/>
-</LinearLayout>
+ android:elevation="@dimen/deep_shortcuts_elevation"/>
diff --git a/res/layout/system_shortcut_rows_container_material_u.xml b/res/layout/system_shortcut_rows_container.xml
similarity index 100%
rename from res/layout/system_shortcut_rows_container_material_u.xml
rename to res/layout/system_shortcut_rows_container.xml
diff --git a/res/layout/system_shortcut_spacer.xml b/res/layout/system_shortcut_spacer.xml
new file mode 100644
index 0000000..60ea9ec
--- /dev/null
+++ b/res/layout/system_shortcut_spacer.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<Space
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:id="@+id/shortcut_spacer"/>
\ No newline at end of file
diff --git a/res/layout/work_apps_paused.xml b/res/layout/work_apps_paused.xml
index f614d9b..52c5a49 100644
--- a/res/layout/work_apps_paused.xml
+++ b/res/layout/work_apps_paused.xml
@@ -21,7 +21,7 @@
<TextView
style="@style/PrimaryHeadline"
- android:textColor="?attr/workProfileOverlayTextColor"
+ android:textColor="?android:attr/textColorPrimary"
android:id="@+id/work_apps_paused_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -45,7 +45,7 @@
android:layout_width="wrap_content"
android:layout_height="@dimen/rounded_button_height"
android:id="@+id/enable_work_apps"
- android:textColor="?attr/workProfileOverlayTextColor"
+ android:textColor="?android:attr/textColorPrimary"
android:text="@string/work_apps_enable_btn_text"
android:textAlignment="center"
android:background="@drawable/bg_work_apps_paused_action_button"
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index f70937a..96938ca 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -50,7 +50,6 @@
<attr name="folderTextColor" format="color" />
<attr name="folderHintColor" format="color" />
<attr name="isFolderDarkText" format="boolean" />
- <attr name="workProfileOverlayTextColor" format="color" />
<attr name="workspaceAccentColor" format="color" />
<attr name="dropTargetHoverTextColor" format="color" />
<attr name="preloadIconAccentColor" format="color" />
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 9d6927b..8788557 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -86,4 +86,6 @@
<color name="preload_icon_background_color_light">#B5CAD7</color>
<color name="preload_icon_accent_color_dark">#4BB6E8</color>
<color name="preload_icon_background_color_dark">#40484D</color>
+
+ <color name="work_turn_on_stroke">?android:attr/colorAccent</color>
</resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 82758bf..aa84d2b 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -155,6 +155,7 @@
<dimen name="work_edu_card_margin">16dp</dimen>
<dimen name="work_edu_card_radius">16dp</dimen>
<dimen name="work_edu_card_bottom_margin">26dp</dimen>
+ <dimen name="work_apps_paused_button_stroke">1dp</dimen>
<dimen name="work_card_margin">24dp</dimen>
<!-- (x) icon button inside work edu card -->
diff --git a/res/values/id.xml b/res/values/id.xml
index 375750f..dc81944 100644
--- a/res/values/id.xml
+++ b/res/values/id.xml
@@ -38,4 +38,7 @@
<item type="id" name="cache_entry_tag_id" />
<item type="id" name="saved_clip_children_tag_id" />
+
+ <item type="id" name="saved_floating_widget_foreground" />
+ <item type="id" name="saved_floating_widget_background" />
</resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 474a289..65d215f 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -59,7 +59,6 @@
<item name="folderHintColor">@color/folder_hint_text_color_dark</item>
<item name="loadingIconColor">#CCFFFFFF</item>
<item name="iconOnlyShortcutColor">?android:attr/textColorSecondary</item>
- <item name="workProfileOverlayTextColor">#FF212121</item>
<item name="eduHalfSheetBGColor">?android:attr/colorAccent</item>
<item name="workspaceAccentColor">@color/workspace_accent_color_light</item>
<item name="dropTargetHoverTextColor">@color/workspace_text_color_dark</item>
@@ -114,7 +113,6 @@
<item name="isMainColorDark">true</item>
<item name="loadingIconColor">#99FFFFFF</item>
<item name="iconOnlyShortcutColor">#B3FFFFFF</item>
- <item name="workProfileOverlayTextColor">@android:color/white</item>
<item name="eduHalfSheetBGColor">#DD000000</item>
<item name="overviewScrimColor">@color/overview_scrim_dark</item>
<item name="preloadIconAccentColor">@color/preload_icon_accent_color_dark</item>
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index c7431ed..b5bc60d 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -16,8 +16,6 @@
package com.android.launcher3;
-import static androidx.annotation.VisibleForTesting.PACKAGE_PRIVATE;
-
import static com.android.launcher3.anim.Interpolators.SCROLL;
import static com.android.launcher3.compat.AccessibilityManagerCompat.isAccessibilityEnabled;
import static com.android.launcher3.compat.AccessibilityManagerCompat.isObservedEventType;
@@ -52,7 +50,6 @@
import android.widget.ScrollView;
import androidx.annotation.Nullable;
-import androidx.annotation.VisibleForTesting;
import com.android.launcher3.compat.AccessibilityManagerCompat;
import com.android.launcher3.config.FeatureFlags;
@@ -319,7 +316,6 @@
/**
* Returns an IntSet with the indices of the currently visible pages
*/
- @VisibleForTesting(otherwise = PACKAGE_PRIVATE)
public IntSet getVisiblePageIndices() {
return getPageIndices(mCurrentPage);
}
@@ -1370,8 +1366,14 @@
int velocity = (int) mOrientationHandler.getPrimaryVelocity(velocityTracker,
mActivePointerId);
float delta = primaryDirection - mDownMotionPrimary;
- int pageOrientedSize = (int) (mOrientationHandler.getMeasuredSize(
- getPageAt(mCurrentPage))
+
+ View current = getPageAt(mCurrentPage);
+ if (current == null) {
+ Log.e(TAG, "current page was null. this should not happen.");
+ return true;
+ }
+
+ int pageOrientedSize = (int) (mOrientationHandler.getMeasuredSize(current)
* mOrientationHandler.getPrimaryScale(this));
boolean isSignificantMove = isSignificantMove(Math.abs(delta), pageOrientedSize);
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index 59327dc..0fbaecb 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -65,6 +65,7 @@
import android.view.animation.Interpolator;
import androidx.annotation.ChecksSdkIntAtLeast;
+import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.core.graphics.ColorUtils;
@@ -136,6 +137,14 @@
@Deprecated
public static final boolean IS_DEBUG_DEVICE = BuildConfig.IS_DEBUG_DEVICE;
+ public static final int TRANSLATE_UP = 0;
+ public static final int TRANSLATE_DOWN = 1;
+ public static final int TRANSLATE_LEFT = 2;
+ public static final int TRANSLATE_RIGHT = 3;
+
+ @IntDef({TRANSLATE_UP, TRANSLATE_DOWN, TRANSLATE_LEFT, TRANSLATE_RIGHT})
+ public @interface AdjustmentDirection{}
+
/**
* Returns true if theme is dark.
*/
@@ -731,4 +740,63 @@
matrixValues[Matrix.MTRANS_X], matrixValues[Matrix.MTRANS_Y]
));
}
+
+ /**
+ * Translates the {@code targetView} so that it overlaps with {@code exclusionBounds} as little
+ * as possible, while remaining within {@code inclusionBounds}.
+ * <p>
+ * {@code inclusionBounds} will always take precedence over {@code exclusionBounds}, so if
+ * {@code targetView} needs to be translated outside of {@code inclusionBounds} to fully fix an
+ * overlap with {@code exclusionBounds}, then {@code targetView} will only be translated up to
+ * the border of {@code inclusionBounds}.
+ * <p>
+ * Note: {@code targetViewBounds}, {@code inclusionBounds} and {@code exclusionBounds} must all
+ * be in relation to the same reference point on screen.
+ * <p>
+ * @param targetView the view being translated
+ * @param targetViewBounds the bounds of the {@code targetView}
+ * @param inclusionBounds the bounds the {@code targetView} absolutely must stay within
+ * @param exclusionBounds the bounds to try to move the {@code targetView} away from
+ * @param adjustmentDirection the translation direction that should be attempted to fix an
+ * overlap
+ */
+ public static void translateOverlappingView(
+ @NonNull View targetView,
+ @NonNull Rect targetViewBounds,
+ @NonNull Rect inclusionBounds,
+ @NonNull Rect exclusionBounds,
+ @AdjustmentDirection int adjustmentDirection) {
+ switch (adjustmentDirection) {
+ case TRANSLATE_RIGHT:
+ targetView.setTranslationX(Math.min(
+ // Translate to the right if the view is overlapping on the left.
+ Math.max(0, exclusionBounds.right - targetViewBounds.left),
+ // Do not translate beyond the inclusion bounds.
+ inclusionBounds.right - targetViewBounds.right));
+ break;
+ case TRANSLATE_LEFT:
+ targetView.setTranslationX(Math.max(
+ // Translate to the left if the view is overlapping on the right.
+ Math.min(0, exclusionBounds.left - targetViewBounds.right),
+ // Do not translate beyond the inclusion bounds.
+ inclusionBounds.left - targetViewBounds.left));
+ break;
+ case TRANSLATE_DOWN:
+ targetView.setTranslationY(Math.min(
+ // Translate downwards if the view is overlapping on the top.
+ Math.max(0, exclusionBounds.bottom - targetViewBounds.top),
+ // Do not translate beyond the inclusion bounds.
+ inclusionBounds.bottom - targetViewBounds.bottom));
+ break;
+ case TRANSLATE_UP:
+ targetView.setTranslationY(Math.max(
+ // Translate upwards if the view is overlapping on the bottom.
+ Math.min(0, exclusionBounds.top - targetViewBounds.bottom),
+ // Do not translate beyond the inclusion bounds.
+ inclusionBounds.top - targetViewBounds.top));
+ break;
+ default:
+ // No-Op
+ }
+ }
}
diff --git a/src/com/android/launcher3/graphics/SysUiScrim.java b/src/com/android/launcher3/graphics/SysUiScrim.java
index e983a30..be995bc 100644
--- a/src/com/android/launcher3/graphics/SysUiScrim.java
+++ b/src/com/android/launcher3/graphics/SysUiScrim.java
@@ -126,8 +126,14 @@
mMaskHeight = ResourceUtils.pxFromDp(ALPHA_MASK_BITMAP_DP,
view.getResources().getDisplayMetrics());
mTopScrim = Themes.getAttrDrawable(view.getContext(), R.attr.workspaceStatusBarScrim);
- mBottomMask = mTopScrim == null ? null : createDitheredAlphaMask();
- mHideSysUiScrim = mTopScrim == null;
+ if (mTopScrim != null) {
+ mTopScrim.setDither(true);
+ mBottomMask = createDitheredAlphaMask();
+ mHideSysUiScrim = false;
+ } else {
+ mBottomMask = null;
+ mHideSysUiScrim = true;
+ }
mDrawWallpaperScrim = FeatureFlags.ENABLE_WALLPAPER_SCRIM.get()
&& !Themes.getAttrBoolean(view.getContext(), R.attr.isMainColorDark)
diff --git a/src/com/android/launcher3/popup/ArrowPopup.java b/src/com/android/launcher3/popup/ArrowPopup.java
index a0f21dc..be3a09b 100644
--- a/src/com/android/launcher3/popup/ArrowPopup.java
+++ b/src/com/android/launcher3/popup/ArrowPopup.java
@@ -60,9 +60,7 @@
import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.views.BaseDragLayer;
-import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collections;
/**
* A container for shortcuts to deep links and notifications associated with an app.
@@ -337,23 +335,6 @@
}
/**
- * Shows the popup at the desired location, optionally reversing the children.
- * @param viewsToFlip number of views from the top to to flip in case of reverse order
- */
- protected void reorderAndShow(int viewsToFlip) {
- setupForDisplay();
- boolean reverseOrder = !ENABLE_MATERIAL_U_POPUP.get() && mIsAboveIcon;
- if (reverseOrder) {
- reverseOrder(viewsToFlip);
- }
- assignMarginsAndBackgrounds(this);
- if (shouldAddArrow()) {
- addArrow();
- }
- animateOpen();
- }
-
- /**
* Shows the popup at the desired location.
*/
public void show() {
@@ -372,22 +353,6 @@
orientAboutObject();
}
- private void reverseOrder(int viewsToFlip) {
- int count = getChildCount();
- ArrayList<View> allViews = new ArrayList<>(count);
- for (int i = 0; i < count; i++) {
- if (i == viewsToFlip) {
- Collections.reverse(allViews);
- }
- allViews.add(getChildAt(i));
- }
- Collections.reverse(allViews);
- removeAllViews();
- for (int i = 0; i < count; i++) {
- addView(allViews.get(i));
- }
- }
-
private int getArrowLeft() {
if (mIsLeftAligned) {
return mArrowOffsetHorizontal;
diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
index 8fef5c6..c20ac17 100644
--- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java
+++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
@@ -227,17 +227,18 @@
if (ENABLE_MATERIAL_U_POPUP.get()) {
container = (PopupContainerWithArrow) launcher.getLayoutInflater().inflate(
R.layout.popup_container_material_u, launcher.getDragLayer(), false);
+ container.configureForLauncher(launcher);
container.populateAndShowRowsMaterialU(icon, deepShortcutCount, systemShortcuts);
} else {
container = (PopupContainerWithArrow) launcher.getLayoutInflater().inflate(
R.layout.popup_container, launcher.getDragLayer(), false);
+ container.configureForLauncher(launcher);
container.populateAndShow(
icon,
deepShortcutCount,
popupDataProvider.getNotificationKeysForItem(item),
systemShortcuts);
}
- container.configureForLauncher(launcher);
launcher.refreshAndBindWidgetsForPackageUser(PackageUserKey.fromItemInfo(item));
container.requestFocus();
return container;
@@ -257,14 +258,19 @@
}
// If there is only 1 shortcut, add it to its own container so it can show text and icon
if (shortcuts.size() == 1) {
- initializeSystemShortcut(R.layout.system_shortcut, this, shortcuts.get(0));
+ mSystemShortcutContainer = inflateAndAdd(R.layout.system_shortcut_rows_container,
+ this, 0);
+ initializeSystemShortcut(R.layout.system_shortcut, mSystemShortcutContainer,
+ shortcuts.get(0), false);
return;
}
- mSystemShortcutContainer = inflateAndAdd(R.layout.system_shortcut_icons_container, this);
- for (SystemShortcut shortcut : shortcuts) {
+ mSystemShortcutContainer = inflateAndAdd(R.layout.system_shortcut_icons_container, this, 0);
+ for (int i = 0; i < shortcuts.size(); i++) {
initializeSystemShortcut(
- R.layout.system_shortcut_icon_only, mSystemShortcutContainer,
- shortcut);
+ R.layout.system_shortcut_icon_only,
+ mSystemShortcutContainer,
+ shortcuts.get(i),
+ i < shortcuts.size() - 1);
}
}
@@ -289,7 +295,6 @@
}
updateNotificationHeader();
}
- int viewsToFlip = getChildCount();
mSystemShortcutContainer = this;
if (mDeepShortcutContainer == null) {
mDeepShortcutContainer = findViewById(R.id.deep_shortcuts_container);
@@ -314,8 +319,7 @@
Optional<SystemShortcut.Widgets> widgetShortcutOpt = getWidgetShortcut(shortcuts);
if (widgetShortcutOpt.isPresent()) {
if (mWidgetContainer == null) {
- mWidgetContainer = inflateAndAdd(R.layout.widget_shortcut_container,
- this);
+ mWidgetContainer = inflateAndAdd(R.layout.widget_shortcut_container, this, 0);
}
initializeWidgetShortcut(mWidgetContainer, widgetShortcutOpt.get());
}
@@ -324,14 +328,17 @@
} else {
mDeepShortcutContainer.setVisibility(View.GONE);
if (!shortcuts.isEmpty()) {
- for (SystemShortcut shortcut : shortcuts) {
- initializeSystemShortcut(R.layout.system_shortcut, this, shortcut);
+ for (int i = 0; i < shortcuts.size(); i++) {
+ initializeSystemShortcut(
+ R.layout.system_shortcut,
+ this,
+ shortcuts.get(i),
+ i < shortcuts.size() - 1);
}
}
}
-
- reorderAndShow(viewsToFlip);
- showPopupContainer((ItemInfo) originalIcon.getTag(), notificationKeys);
+ show();
+ loadAppShortcuts((ItemInfo) originalIcon.getTag(), notificationKeys);
}
/**
@@ -351,19 +358,17 @@
addAllShortcutsMaterialU(deepShortcutCount, systemShortcuts);
} else if (!systemShortcuts.isEmpty()) {
addSystemShortcutsMaterialU(systemShortcuts,
- R.layout.system_shortcut_rows_container_material_u,
+ R.layout.system_shortcut_rows_container,
R.layout.system_shortcut);
}
-
- // no reversing needed for U design
- reorderAndShow(0);
- showPopupContainer((ItemInfo) originalIcon.getTag(), /* notificationKeys= */ emptyList());
+ show();
+ loadAppShortcuts((ItemInfo) originalIcon.getTag(), /* notificationKeys= */ emptyList());
}
/**
* Animates and loads shortcuts on background thread for this popup container
*/
- private void showPopupContainer(ItemInfo originalItemInfo,
+ private void loadAppShortcuts(ItemInfo originalItemInfo,
List<NotificationKeyData> notificationKeys) {
if (ATLEAST_P) {
@@ -390,7 +395,7 @@
if (deepShortcutCount + systemShortcuts.size() <= SHORTCUT_COLLAPSE_THRESHOLD) {
// add all system shortcuts including widgets shortcut to same container
addSystemShortcutsMaterialU(systemShortcuts,
- R.layout.system_shortcut_rows_container_material_u,
+ R.layout.system_shortcut_rows_container,
R.layout.system_shortcut);
addDeepShortcutsMaterialU(deepShortcutCount);
return;
@@ -458,8 +463,12 @@
return;
}
mSystemShortcutContainer = inflateAndAdd(systemShortcutContainerLayout, this);
- for (SystemShortcut shortcut : systemShortcuts) {
- initializeSystemShortcut(systemShortcutLayout, mSystemShortcutContainer, shortcut);
+ for (int i = 0; i < systemShortcuts.size(); i++) {
+ initializeSystemShortcut(
+ systemShortcutLayout,
+ mSystemShortcutContainer,
+ systemShortcuts.get(i),
+ i < systemShortcuts.size() - 1);
}
}
@@ -533,20 +542,31 @@
}
protected void initializeWidgetShortcut(ViewGroup container, SystemShortcut info) {
- View view = initializeSystemShortcut(R.layout.system_shortcut, container, info);
+ View view = initializeSystemShortcut(R.layout.system_shortcut, container, info, false);
view.getLayoutParams().width = mContainerWidth;
}
- protected View initializeSystemShortcut(int resId, ViewGroup container, SystemShortcut info) {
- View view = inflateAndAdd(
- resId, container, getInsertIndexForSystemShortcut(container, info));
+ /**
+ * Initializes and adds View for given SystemShortcut to a container.
+ * @param resId Resource id to use for SystemShortcut View.
+ * @param container ViewGroup to add the shortcut View to as a parent
+ * @param info The SystemShortcut instance to create a View for.
+ * @param shouldAddSpacer If True, will add a spacer after the shortcut, when showing the
+ * SystemShortcut as an icon only. Used to space the shortcut icons
+ * evenly.
+ * @return The view inflated for the SystemShortcut
+ */
+ protected View initializeSystemShortcut(int resId, ViewGroup container, SystemShortcut info,
+ boolean shouldAddSpacer) {
+ View view = inflateAndAdd(resId, container);
if (view instanceof DeepShortcutView) {
- // Expanded system shortcut, with both icon and text shown on white background.
+ // System shortcut takes entire row with icon and text
final DeepShortcutView shortcutView = (DeepShortcutView) view;
info.setIconAndLabelFor(shortcutView.getIconView(), shortcutView.getBubbleText());
} else if (view instanceof ImageView) {
- // Only the system shortcut icon shows on a gray background header.
+ // System shortcut is just an icon
info.setIconAndContentDescriptionFor((ImageView) view);
+ if (shouldAddSpacer) inflateAndAdd(R.layout.system_shortcut_spacer, container);
view.setTooltipText(view.getContentDescription());
}
view.setTag(info);
@@ -555,17 +575,6 @@
}
/**
- * Returns an index for inserting a shortcut into a container.
- */
- private int getInsertIndexForSystemShortcut(ViewGroup container, SystemShortcut shortcut) {
- final View separator = container.findViewById(R.id.separator);
-
- return separator != null && shortcut.isLeftGroup() ?
- container.indexOfChild(separator) :
- container.getChildCount();
- }
-
- /**
* Determines when the deferred drag should be started.
*
* Current behavior:
diff --git a/src/com/android/launcher3/views/IconButtonView.java b/src/com/android/launcher3/views/IconButtonView.java
index 71f6756..0ac1919 100644
--- a/src/com/android/launcher3/views/IconButtonView.java
+++ b/src/com/android/launcher3/views/IconButtonView.java
@@ -29,6 +29,7 @@
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.util.AttributeSet;
+import android.view.accessibility.AccessibilityEvent;
import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
@@ -78,6 +79,12 @@
}
}
+ @Override
+ public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
+ super.onPopulateAccessibilityEvent(event);
+ event.getText().add(this.getContentDescription());
+ }
+
/** Sets given Drawable as icon */
public void setIconDrawable(@NonNull Drawable drawable) {
ColorStateList tintList = getBackgroundTintList();
diff --git a/src/com/android/launcher3/widget/BaseWidgetSheet.java b/src/com/android/launcher3/widget/BaseWidgetSheet.java
index 68ece03..4f94c92 100644
--- a/src/com/android/launcher3/widget/BaseWidgetSheet.java
+++ b/src/com/android/launcher3/widget/BaseWidgetSheet.java
@@ -33,6 +33,7 @@
import androidx.annotation.GuardedBy;
import androidx.annotation.Nullable;
+import androidx.annotation.Px;
import androidx.core.view.ViewCompat;
import com.android.launcher3.DeviceProfile;
@@ -61,7 +62,7 @@
implements OnClickListener, OnLongClickListener, DragSource,
PopupDataProvider.PopupDataChangeListener, Insettable {
/** The default number of cells that can fit horizontally in a widget sheet. */
- protected static final int DEFAULT_MAX_HORIZONTAL_SPANS = 4;
+ public static final int DEFAULT_MAX_HORIZONTAL_SPANS = 4;
protected static final String KEY_WIDGETS_EDUCATION_TIP_SEEN =
"launcher.widgets_education_tip_seen";
@@ -70,15 +71,18 @@
/* Touch handling related member variables. */
private Toast mWidgetInstructionToast;
- private int mContentHorizontalMarginInPx;
+ @Px protected int mContentHorizontalMargin;
+ @Px protected int mWidgetCellHorizontalPadding;
protected int mNavBarScrimHeight;
private final Paint mNavBarScrimPaint;
public BaseWidgetSheet(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
- mContentHorizontalMarginInPx = getResources().getDimensionPixelSize(
+ mContentHorizontalMargin = getResources().getDimensionPixelSize(
R.dimen.widget_list_horizontal_margin);
+ mWidgetCellHorizontalPadding = getResources().getDimensionPixelSize(
+ R.dimen.widget_cell_horizontal_padding);
mNavBarScrimPaint = new Paint();
mNavBarScrimPaint.setColor(Themes.getAttrColor(context, R.attr.allAppsNavBarScrimColor));
}
@@ -138,11 +142,11 @@
@Override
public void setInsets(Rect insets) {
mInsets.set(insets);
- int contentHorizontalMarginInPx = getResources().getDimensionPixelSize(
+ @Px int contentHorizontalMargin = getResources().getDimensionPixelSize(
R.dimen.widget_list_horizontal_margin);
- if (contentHorizontalMarginInPx != mContentHorizontalMarginInPx) {
- onContentHorizontalMarginChanged(contentHorizontalMarginInPx);
- mContentHorizontalMarginInPx = contentHorizontalMarginInPx;
+ if (contentHorizontalMargin != mContentHorizontalMargin) {
+ onContentHorizontalMarginChanged(contentHorizontalMargin);
+ mContentHorizontalMargin = contentHorizontalMargin;
}
}
@@ -198,19 +202,6 @@
MeasureSpec.getSize(heightMeasureSpec));
}
- /** Returns the number of cells that can fit horizontally in a given {@code content}. */
- protected int computeMaxHorizontalSpans(View content, int contentHorizontalPaddingPx) {
- DeviceProfile deviceProfile = mActivityContext.getDeviceProfile();
- int availableWidth = content.getMeasuredWidth()
- - contentHorizontalPaddingPx
- - (2 * mContentHorizontalMarginInPx);
- Point cellSize = deviceProfile.getCellSize();
- if (cellSize.x > 0) {
- return availableWidth / cellSize.x;
- }
- return DEFAULT_MAX_HORIZONTAL_SPANS;
- }
-
private boolean beginDraggingWidget(WidgetCell v) {
if (TestProtocol.sDebugTracing) {
Log.d(TestProtocol.NO_DROP_TARGET, "2");
diff --git a/src/com/android/launcher3/widget/WidgetsBottomSheet.java b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
index 4099302..06c622d 100644
--- a/src/com/android/launcher3/widget/WidgetsBottomSheet.java
+++ b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
@@ -36,6 +36,8 @@
import android.widget.TableRow;
import android.widget.TextView;
+import androidx.annotation.Px;
+
import com.android.launcher3.R;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.model.WidgetItem;
@@ -69,8 +71,7 @@
private static final long EDUCATION_TIP_DELAY_MS = 300;
private ItemInfo mOriginalItemInfo;
- private int mMaxHorizontalSpan = DEFAULT_MAX_HORIZONTAL_SPANS;
- private final int mWidgetCellHorizontalPadding;
+ @Px private int mMaxHorizontalSpan;
private final OnLayoutChangeListener mLayoutChangeListenerToShowTips =
new OnLayoutChangeListener() {
@@ -111,8 +112,6 @@
if (!hasSeenEducationTip()) {
addOnLayoutChangeListener(mLayoutChangeListenerToShowTips);
}
- mWidgetCellHorizontalPadding = getResources().getDimensionPixelSize(
- R.dimen.widget_cell_horizontal_padding);
setContentBackground(getContext().getDrawable(R.drawable.bg_rounded_corner_bottom_sheet));
}
@@ -134,7 +133,7 @@
private boolean updateMaxSpansPerRow() {
if (getMeasuredWidth() == 0) return false;
- int maxHorizontalSpan = computeMaxHorizontalSpans(mContent, mWidgetCellHorizontalPadding);
+ @Px int maxHorizontalSpan = mContent.getMeasuredWidth() - (2 * mContentHorizontalMargin);
if (mMaxHorizontalSpan != maxHorizontalSpan) {
// Ensure the table layout is showing widgets in the right column after measure.
mMaxHorizontalSpan = maxHorizontalSpan;
@@ -184,7 +183,9 @@
TableLayout widgetsTable = findViewById(R.id.widgets_table);
widgetsTable.removeAllViews();
- WidgetsTableUtils.groupWidgetItemsIntoTableWithReordering(widgets, mMaxHorizontalSpan)
+ WidgetsTableUtils.groupWidgetItemsUsingRowPxWithReordering(widgets, mActivityContext,
+ mActivityContext.getDeviceProfile(), mMaxHorizontalSpan,
+ mWidgetCellHorizontalPadding)
.forEach(row -> {
TableRow tableRow = new TableRow(getContext());
tableRow.setGravity(Gravity.TOP);
diff --git a/src/com/android/launcher3/widget/model/WidgetsListContentEntry.java b/src/com/android/launcher3/widget/model/WidgetsListContentEntry.java
index 626e0b9..d709196 100644
--- a/src/com/android/launcher3/widget/model/WidgetsListContentEntry.java
+++ b/src/com/android/launcher3/widget/model/WidgetsListContentEntry.java
@@ -15,6 +15,8 @@
*/
package com.android.launcher3.widget.model;
+import androidx.annotation.Px;
+
import com.android.launcher3.model.WidgetItem;
import com.android.launcher3.model.data.PackageItemInfo;
@@ -26,7 +28,7 @@
*/
public final class WidgetsListContentEntry extends WidgetsListBaseEntry {
- private final int mMaxSpanSizeInCells;
+ @Px private final int mMaxSpanSize;
/**
* Constructor for {@link WidgetsListContentEntry}.
@@ -37,7 +39,7 @@
*/
public WidgetsListContentEntry(PackageItemInfo pkgItem, String titleSectionName,
List<WidgetItem> items) {
- this(pkgItem, titleSectionName, items, /* maxSpanSizeInCells= */ 0);
+ this(pkgItem, titleSectionName, items, /* maxSpanSize= */ 0);
}
/**
@@ -46,43 +48,43 @@
* @param pkgItem package info associated with the entry
* @param titleSectionName title section name associated with the entry.
* @param items list of widgets for the package.
- * @param maxSpanSizeInCells the max horizontal span in cells that is allowed for grouping more
+ * @param maxSpanSize the max horizontal span in pixels that is allowed for grouping more
* than one widgets in a table row.
*/
public WidgetsListContentEntry(PackageItemInfo pkgItem, String titleSectionName,
- List<WidgetItem> items, int maxSpanSizeInCells) {
+ List<WidgetItem> items, @Px int maxSpanSize) {
super(pkgItem, titleSectionName, items);
- mMaxSpanSizeInCells = maxSpanSizeInCells;
+ mMaxSpanSize = maxSpanSize;
}
@Override
public String toString() {
- return "Content:" + mPkgItem.packageName + ":" + mWidgets.size() + " maxSpanSizeInCells: "
- + mMaxSpanSizeInCells;
+ return "Content:" + mPkgItem.packageName + ":" + mWidgets.size() + " maxSpanSize: "
+ + mMaxSpanSize;
}
/**
- * Returns a copy of this {@link WidgetsListContentEntry} with updated
- * {@param maxSpanSizeInCells}.
+ * Returns a copy of this {@link WidgetsListContentEntry} with updated {@code maxSpanSize}.
*
- * @param maxSpanSizeInCells the maximum horizontal span in cells that is allowed for grouping
+ * @param maxSpanSize the maximum horizontal span in pixels that is allowed for grouping
* more than one widgets in a table row.
*/
- public WidgetsListContentEntry withMaxSpanSize(int maxSpanSizeInCells) {
- if (mMaxSpanSizeInCells == maxSpanSizeInCells) return this;
+ public WidgetsListContentEntry withMaxSpanSize(@Px int maxSpanSize) {
+ if (mMaxSpanSize == maxSpanSize) return this;
return new WidgetsListContentEntry(
mPkgItem,
mTitleSectionName,
mWidgets,
- /* maxSpanSizeInCells= */ maxSpanSizeInCells);
+ /* maxSpanSize= */ maxSpanSize);
}
/**
- * Returns the max horizontal span size in cells that is allowed for grouping more than one
+ * Returns the max horizontal span size in pixels that is allowed for grouping more than one
* widget in a table row.
*/
- public int getMaxSpanSizeInCells() {
- return mMaxSpanSizeInCells;
+ @Px
+ public int getMaxSpanSize() {
+ return mMaxSpanSize;
}
@Override
@@ -91,6 +93,6 @@
WidgetsListContentEntry otherEntry = (WidgetsListContentEntry) obj;
return mWidgets.equals(otherEntry.mWidgets) && mPkgItem.equals(otherEntry.mPkgItem)
&& mTitleSectionName.equals(otherEntry.mTitleSectionName)
- && mMaxSpanSizeInCells == otherEntry.mMaxSpanSizeInCells;
+ && mMaxSpanSize == otherEntry.mMaxSpanSize;
}
}
diff --git a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
index f4d6749..d5c4315 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java
@@ -53,6 +53,7 @@
import androidx.annotation.FloatRange;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.annotation.Px;
import androidx.annotation.VisibleForTesting;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.RecyclerView;
@@ -181,14 +182,13 @@
}
};
- private final int mTabsHeight;
- private final int mWidgetSheetContentHorizontalPadding;
+ @Px private final int mTabsHeight;
@Nullable private WidgetsRecyclerView mCurrentWidgetsRecyclerView;
@Nullable private PersonalWorkPagedView mViewPager;
private boolean mIsInSearchMode;
private boolean mIsNoWidgetsViewNeeded;
- private int mMaxSpansPerRow = DEFAULT_MAX_HORIZONTAL_SPANS;
+ @Px private int mMaxSpanPerRow;
private TextView mNoWidgetsView;
private StickyHeaderLayout mSearchScrollView;
@@ -224,8 +224,6 @@
mTabsHeight = mHasWorkProfile
? resources.getDimensionPixelSize(R.dimen.all_apps_header_pill_height)
: 0;
- mWidgetSheetContentHorizontalPadding = 2 * resources.getDimensionPixelSize(
- R.dimen.widget_cell_horizontal_padding);
mUserManagerState.init(UserCache.INSTANCE.get(context),
context.getSystemService(UserManager.class));
@@ -337,7 +335,7 @@
: mSearchScrollView.findViewById(R.id.title);
mRightPane = mIsTwoPane ? mContent.findViewById(R.id.right_pane) : null;
mWidgetsListTableViewHolderBinder =
- new WidgetsListTableViewHolderBinder(layoutInflater, this, this);
+ new WidgetsListTableViewHolderBinder(mActivityContext, layoutInflater, this, this);
onRecommendedWidgetsBound();
onWidgetsBound();
@@ -536,22 +534,20 @@
View content = mHasWorkProfile
? mViewPager
: mAdapters.get(AdapterHolder.PRIMARY).mWidgetsRecyclerView;
-
if (mIsTwoPane && mRightPane != null) {
content = mRightPane;
}
- int maxHorizontalSpans = computeMaxHorizontalSpans(content,
- mWidgetSheetContentHorizontalPadding);
- if (mMaxSpansPerRow != maxHorizontalSpans) {
- mMaxSpansPerRow = maxHorizontalSpans;
- mAdapters.get(AdapterHolder.PRIMARY).mWidgetsListAdapter.setMaxHorizontalSpansPerRow(
- mMaxSpansPerRow);
- mAdapters.get(AdapterHolder.SEARCH).mWidgetsListAdapter.setMaxHorizontalSpansPerRow(
- mMaxSpansPerRow);
+ @Px int maxHorizontalSpan = content.getMeasuredWidth() - (2 * mContentHorizontalMargin);
+ if (mMaxSpanPerRow != maxHorizontalSpan) {
+ mMaxSpanPerRow = maxHorizontalSpan;
+ mAdapters.get(AdapterHolder.PRIMARY).mWidgetsListAdapter.setMaxHorizontalSpansPxPerRow(
+ maxHorizontalSpan);
+ mAdapters.get(AdapterHolder.SEARCH).mWidgetsListAdapter.setMaxHorizontalSpansPxPerRow(
+ maxHorizontalSpan);
if (mHasWorkProfile) {
- mAdapters.get(AdapterHolder.WORK).mWidgetsListAdapter.setMaxHorizontalSpansPerRow(
- mMaxSpansPerRow);
+ mAdapters.get(AdapterHolder.WORK).mWidgetsListAdapter.setMaxHorizontalSpansPxPerRow(
+ maxHorizontalSpan);
}
onRecommendedWidgetsBound();
return true;
@@ -700,8 +696,12 @@
- noWidgetsViewHeight) * RECOMMENDATION_TABLE_HEIGHT_RATIO;
List<ArrayList<WidgetItem>> recommendedWidgetsInTable =
- WidgetsTableUtils.groupWidgetItemsIntoTableWithoutReordering(
- recommendedWidgets, mMaxSpansPerRow);
+ WidgetsTableUtils.groupWidgetItemsUsingRowPxWithoutReordering(
+ recommendedWidgets,
+ mActivityContext,
+ mActivityContext.getDeviceProfile(),
+ mMaxSpanPerRow,
+ mWidgetCellHorizontalPadding);
mRecommendedWidgetsTable.setRecommendedWidgets(
recommendedWidgetsInTable, maxTableHeight);
} else {
@@ -1051,7 +1051,7 @@
if (mAdapterType == PRIMARY || mAdapterType == WORK) {
mWidgetsRecyclerView.addOnAttachStateChangeListener(mBindScrollbarInSearchMode);
}
- mWidgetsListAdapter.setMaxHorizontalSpansPerRow(mMaxSpansPerRow);
+ mWidgetsListAdapter.setMaxHorizontalSpansPxPerRow(mMaxSpanPerRow);
}
}
diff --git a/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java b/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java
index c28402e..c89eea8 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java
@@ -19,6 +19,7 @@
import static com.android.launcher3.recyclerview.ViewHolderBinder.POSITION_DEFAULT;
import static com.android.launcher3.recyclerview.ViewHolderBinder.POSITION_FIRST;
import static com.android.launcher3.recyclerview.ViewHolderBinder.POSITION_LAST;
+import static com.android.launcher3.widget.BaseWidgetSheet.DEFAULT_MAX_HORIZONTAL_SPANS;
import android.content.Context;
import android.os.Process;
@@ -32,6 +33,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.annotation.Px;
import androidx.recyclerview.widget.DiffUtil;
import androidx.recyclerview.widget.DiffUtil.DiffResult;
import androidx.recyclerview.widget.LinearLayoutManager;
@@ -49,6 +51,7 @@
import com.android.launcher3.widget.model.WidgetsListBaseEntry;
import com.android.launcher3.widget.model.WidgetsListContentEntry;
import com.android.launcher3.widget.model.WidgetsListHeaderEntry;
+import com.android.launcher3.widget.util.WidgetSizes;
import java.util.ArrayList;
import java.util.Arrays;
@@ -99,7 +102,7 @@
@Nullable private Predicate<WidgetsListBaseEntry> mFilter = null;
@Nullable private RecyclerView mRecyclerView;
@Nullable private PackageUserKey mPendingClickHeader;
- private int mMaxSpanSize = 4;
+ @Px private int mMaxHorizontalSpan;
public WidgetsListAdapter(Context context, LayoutInflater layoutInflater,
IntSupplier emptySpaceHeightProvider, OnClickListener iconClickListener,
@@ -107,11 +110,14 @@
WidgetsFullSheet.HeaderChangeListener headerChangeListener) {
mHeaderChangeListener = headerChangeListener;
mContext = context;
+ mMaxHorizontalSpan = WidgetSizes.getWidgetSizePx(
+ ActivityContext.lookupContext(context).getDeviceProfile(),
+ DEFAULT_MAX_HORIZONTAL_SPANS, 1).getWidth();
mViewHolderBinders.put(
VIEW_TYPE_WIDGETS_LIST,
new WidgetsListTableViewHolderBinder(
- layoutInflater, iconClickListener, iconLongClickListener));
+ mContext, layoutInflater, iconClickListener, iconLongClickListener));
mViewHolderBinders.put(
VIEW_TYPE_WIDGETS_HEADER,
new WidgetsListHeaderViewHolderBinder(
@@ -199,7 +205,8 @@
} else if (entry instanceof WidgetsListContentEntry) {
// Adjust the original content entries to accommodate for the current
// maxSpanSize.
- return ((WidgetsListContentEntry) entry).withMaxSpanSize(mMaxSpanSize);
+ return ((WidgetsListContentEntry) entry).withMaxSpanSize(
+ mMaxHorizontalSpan);
}
return entry;
})
@@ -407,11 +414,11 @@
}
/**
- * Sets the max horizontal span in cells that is allowed for grouping more than one widget in a
+ * Sets the max horizontal span in pixels that is allowed for grouping more than one widget in a
* table row.
*/
- public void setMaxHorizontalSpansPerRow(int maxHorizontalSpans) {
- mMaxSpanSize = maxHorizontalSpans;
+ public void setMaxHorizontalSpansPxPerRow(@Px int maxHorizontalSpan) {
+ mMaxHorizontalSpan = maxHorizontalSpan;
updateVisibleEntries();
}
diff --git a/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinder.java b/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinder.java
index 2e8f0ab..c7d2aa3 100644
--- a/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinder.java
+++ b/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinder.java
@@ -15,6 +15,7 @@
*/
package com.android.launcher3.widget.picker;
+import android.content.Context;
import android.graphics.Bitmap;
import android.util.Log;
import android.util.Pair;
@@ -27,9 +28,13 @@
import android.widget.TableLayout;
import android.widget.TableRow;
+import androidx.annotation.NonNull;
+import androidx.annotation.Px;
+
import com.android.launcher3.R;
import com.android.launcher3.model.WidgetItem;
import com.android.launcher3.recyclerview.ViewHolderBinder;
+import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.widget.WidgetCell;
import com.android.launcher3.widget.model.WidgetsListContentEntry;
import com.android.launcher3.widget.util.WidgetsTableUtils;
@@ -47,13 +52,21 @@
private final LayoutInflater mLayoutInflater;
private final OnClickListener mIconClickListener;
+ private @NonNull final Context mContext;
+ private @NonNull final ActivityContext mActivityContext;
+ @Px private final int mCellPadding;
private final OnLongClickListener mIconLongClickListener;
public WidgetsListTableViewHolderBinder(
+ @NonNull Context context,
LayoutInflater layoutInflater,
OnClickListener iconClickListener,
OnLongClickListener iconLongClickListener) {
mLayoutInflater = layoutInflater;
+ mContext = context;
+ mActivityContext = ActivityContext.lookupContext(context);
+ mCellPadding = context.getResources().getDimensionPixelSize(
+ R.dimen.widget_cell_horizontal_padding);
mIconClickListener = iconClickListener;
mIconLongClickListener = iconLongClickListener;
}
@@ -87,8 +100,11 @@
(position & POSITION_LAST) != 0));
List<ArrayList<WidgetItem>> widgetItemsTable =
- WidgetsTableUtils.groupWidgetItemsIntoTableWithReordering(
- entry.mWidgets, entry.getMaxSpanSizeInCells());
+ WidgetsTableUtils.groupWidgetItemsUsingRowPxWithReordering(entry.mWidgets,
+ mContext,
+ mActivityContext.getDeviceProfile(),
+ entry.getMaxSpanSize(),
+ mCellPadding);
recycleTableBeforeBinding(table, widgetItemsTable);
// Bind the widget items.
diff --git a/src/com/android/launcher3/widget/util/WidgetsTableUtils.java b/src/com/android/launcher3/widget/util/WidgetsTableUtils.java
index 72e27bf..74d3062 100644
--- a/src/com/android/launcher3/widget/util/WidgetsTableUtils.java
+++ b/src/com/android/launcher3/widget/util/WidgetsTableUtils.java
@@ -15,6 +15,11 @@
*/
package com.android.launcher3.widget.util;
+import android.content.Context;
+
+import androidx.annotation.Px;
+
+import com.android.launcher3.DeviceProfile;
import com.android.launcher3.model.WidgetItem;
import java.util.ArrayList;
@@ -49,34 +54,41 @@
* Groups {@code widgetItems} items into a 2D array which matches their appearance in a UI
* table. This takes liberty to rearrange widgets to make the table visually appealing.
*/
- public static List<ArrayList<WidgetItem>> groupWidgetItemsIntoTableWithReordering(
- List<WidgetItem> widgetItems, final int maxSpansPerRow) {
+ public static List<ArrayList<WidgetItem>> groupWidgetItemsUsingRowPxWithReordering(
+ List<WidgetItem> widgetItems, Context context, final DeviceProfile dp,
+ final @Px int rowPx, final @Px int cellPadding) {
List<WidgetItem> sortedWidgetItems = widgetItems.stream().sorted(WIDGET_SHORTCUT_COMPARATOR)
.collect(Collectors.toList());
- return groupWidgetItemsIntoTableWithoutReordering(sortedWidgetItems, maxSpansPerRow);
+ return groupWidgetItemsUsingRowPxWithoutReordering(sortedWidgetItems, context, dp, rowPx,
+ cellPadding);
}
/**
* Groups {@code widgetItems} into a 2D array which matches their appearance in a UI table while
- * maintaining their order.
+ * maintaining their order. This function is a variant of
+ * {@code groupWidgetItemsIntoTableWithoutReordering} in that this uses widget pixels for
+ * calculation.
*
* <p>Grouping:
* 1. Widgets and shortcuts never group together in the same row.
- * 2. The ordered widgets are grouped together in the same row until their total horizontal
- * spans exceed the {@code maxSpansPerRow} - 1.
- * 3. The order shortcuts are grouped together in the same row until their total horizontal
- * spans exceed the {@code maxSpansPerRow} - 1.
- * 4. If there is only one widget in a row, its width may exceed the {@code maxSpansPerRow}.
+ * 2. The ordered widgets are grouped together in the same row until their individual occupying
+ * pixels exceed the total allowed pixels for the cell.
+ * 3. The ordered shortcuts are grouped together in the same row until their individual
+ * occupying pixels exceed the total allowed pixels for the cell.
+ * 4. If there is only one widget in a row, its width may exceed the {@code rowPx}.
*
- * <p>Let's say the {@code maxSpansPerRow} is set to 6. Widgets can be grouped in the same row
- * if their total horizontal spans added don't exceed 5.
- * Example 1: Row 1: 2x2, 2x3, 1x1. Total horizontal spans is 5. This is okay.
- * Example 2: Row 1: 2x2, 4x3, 1x1. the total horizontal spans is 7. This is wrong. 4x3 and 1x1
- * should be moved to a new row.
- * Example 3: Row 1: 6x4. This is okay because this is the only item in the row.
+ * <p>Let's say the {@code rowPx} is set to 600 and we have 5 widgets. Widgets can be grouped
+ * in the same row if each of their individual occupying pixels does not exceed
+ * {@code rowPx} / 5 - 2 * {@code cellPadding}.
+ * Example 1: Row 1: 200x200, 200x300, 100x100. Average horizontal pixels is 200 and no widgets
+ * exceed that width. This is okay.
+ * Example 2: Row 1: 200x200, 400x300, 100x100. Average horizontal pixels is 200 and one widget
+ * exceed that width. This is not allowed.
+ * Example 3: Row 1: 700x400. This is okay because this is the only item in the row.
*/
- public static List<ArrayList<WidgetItem>> groupWidgetItemsIntoTableWithoutReordering(
- List<WidgetItem> widgetItems, final int maxSpansPerRow) {
+ public static List<ArrayList<WidgetItem>> groupWidgetItemsUsingRowPxWithoutReordering(
+ List<WidgetItem> widgetItems, Context context, final DeviceProfile dp,
+ final @Px int rowPx, final @Px int cellPadding) {
List<ArrayList<WidgetItem>> widgetItemsTable = new ArrayList<>();
ArrayList<WidgetItem> widgetItemsAtRow = null;
@@ -86,23 +98,28 @@
widgetItemsTable.add(widgetItemsAtRow);
}
int numOfWidgetItems = widgetItemsAtRow.size();
- int totalHorizontalSpan = widgetItemsAtRow.stream().map(item -> item.spanX)
- .reduce(/* default= */ 0, Integer::sum);
- int totalHorizontalSpanAfterAddingWidget = widgetItem.spanX + totalHorizontalSpan;
+ @Px int individualSpan = (rowPx / (numOfWidgetItems + 1)) - (2 * cellPadding);
if (numOfWidgetItems == 0) {
widgetItemsAtRow.add(widgetItem);
} else if (
- // The max spans per row is reduced by 1 to ensure we don't pack too many
- // 1xn widgets on the same row, which may reduce the space for rendering a
- // widget's description.
- totalHorizontalSpanAfterAddingWidget <= maxSpansPerRow - 1
- && widgetItem.hasSameType(widgetItemsAtRow.get(numOfWidgetItems - 1))) {
+ // Since the size of the widget cell is determined by dividing the maximum span
+ // pixels evenly, making sure that each widget would have enough span pixels to
+ // show their contents.
+ widgetItem.hasSameType(widgetItemsAtRow.get(numOfWidgetItems - 1))
+ && widgetItemsAtRow.stream().allMatch(
+ item -> WidgetSizes.getWidgetItemSizePx(context, dp, item)
+ .getWidth() <= individualSpan)
+ && WidgetSizes.getWidgetItemSizePx(context, dp, widgetItem)
+ .getWidth() <= individualSpan) {
// Group items in the same row if
// 1. they are with the same type, i.e. a row can only have widgets or shortcuts but
// never a mix of both.
- // 2. the total number of horizontal spans are smaller than or equal to
- // MAX_SPAN_PER_ROW. If an item has a horizontal span > MAX_SPAN_PER_ROW, we just
- // place it in its own row regardless of the horizontal span limit.
+ // 2. Each widget will have horizontal cell span pixels that is at least as large as
+ // it is required to fit in the horizontal content, unless the widget horizontal
+ // span pixels is larger than the maximum allowed.
+ // If an item has horizontal span pixels larger than the maximum allowed pixels
+ // per row, we just place it in its own row regardless of the horizontal span
+ // limit.
widgetItemsAtRow.add(widgetItem);
} else {
widgetItemsAtRow = new ArrayList<>();
diff --git a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
index 19b8b0c..5f516eb 100644
--- a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
+++ b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
@@ -29,7 +29,9 @@
import android.content.Intent;
import android.graphics.Point;
+import android.os.SystemClock;
import android.platform.test.annotations.IwTest;
+import android.util.Log;
import androidx.test.filters.LargeTest;
import androidx.test.runner.AndroidJUnit4;
@@ -525,9 +527,11 @@
@Test
@PortraitLandscape
public void testDragAppIconToWorkspaceCell() throws Exception {
+ long startTime, endTime, elapsedTime;
Point[] targets = getCornersAndCenterPositions();
for (Point target : targets) {
+ startTime = SystemClock.uptimeMillis();
final HomeAllApps allApps = mLauncher.getWorkspace().switchToAllApps();
allApps.freeze();
try {
@@ -537,12 +541,21 @@
}
// Reset the workspace for the next shortcut creation.
initialize(this);
+ endTime = SystemClock.uptimeMillis();
+ elapsedTime = endTime - startTime;
+ Log.d("testDragAppIconToWorkspaceCellTime",
+ "Milliseconds taken to drag app icon to workspace cell: " + elapsedTime);
}
// test to move a shortcut to other cell.
final HomeAppIcon launcherTestAppIcon = createShortcutInCenterIfNotExist(APP_NAME);
for (Point target : targets) {
+ startTime = SystemClock.uptimeMillis();
launcherTestAppIcon.dragToWorkspace(target.x, target.y);
+ endTime = SystemClock.uptimeMillis();
+ elapsedTime = endTime - startTime;
+ Log.d("testDragAppIconToWorkspaceCellTime",
+ "Milliseconds taken to move shortcut to other cell: " + elapsedTime);
}
}
diff --git a/tests/src/com/android/launcher3/ui/widget/RequestPinItemTest.java b/tests/src/com/android/launcher3/ui/widget/RequestPinItemTest.java
index 9669010..bf9eb5a 100644
--- a/tests/src/com/android/launcher3/ui/widget/RequestPinItemTest.java
+++ b/tests/src/com/android/launcher3/ui/widget/RequestPinItemTest.java
@@ -42,6 +42,7 @@
import com.android.launcher3.testcomponent.AppWidgetWithConfig;
import com.android.launcher3.testcomponent.RequestPinItemActivity;
import com.android.launcher3.ui.AbstractLauncherUiTest;
+import com.android.launcher3.ui.TaplTestsLauncher3;
import com.android.launcher3.util.LauncherBindableItemsContainer.ItemOperator;
import com.android.launcher3.util.Wait;
import com.android.launcher3.util.Wait.Condition;
@@ -75,6 +76,7 @@
super.setUp();
mCallbackAction = UUID.randomUUID().toString();
mShortcutId = UUID.randomUUID().toString();
+ TaplTestsLauncher3.initialize(this);
}
@Test
diff --git a/tests/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinderTest.java b/tests/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinderTest.java
index 9dc46f1..e0101f5 100644
--- a/tests/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinderTest.java
+++ b/tests/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinderTest.java
@@ -94,6 +94,7 @@
}).when(mIconCache).getTitleNoCache(any());
mViewHolderBinder = new WidgetsListTableViewHolderBinder(
+ mContext,
LayoutInflater.from(mContext),
mOnIconClickListener,
mOnLongClickListener);
diff --git a/tests/src/com/android/launcher3/widget/picker/util/WidgetsTableUtilsTest.java b/tests/src/com/android/launcher3/widget/picker/util/WidgetsTableUtilsTest.java
index 715dcca..d2c2fd7 100644
--- a/tests/src/com/android/launcher3/widget/picker/util/WidgetsTableUtilsTest.java
+++ b/tests/src/com/android/launcher3/widget/picker/util/WidgetsTableUtilsTest.java
@@ -23,6 +23,7 @@
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.when;
import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
@@ -35,11 +36,13 @@
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
+import com.android.launcher3.DeviceProfile;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.icons.ComponentWithLabel;
import com.android.launcher3.icons.IconCache;
import com.android.launcher3.model.WidgetItem;
import com.android.launcher3.pm.ShortcutConfigActivityInfo;
+import com.android.launcher3.util.ActivityContextWrapper;
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import com.android.launcher3.widget.util.WidgetsTableUtils;
@@ -57,11 +60,19 @@
public final class WidgetsTableUtilsTest {
private static final String TEST_PACKAGE = "com.google.test";
+ private static final int SPACE_SIZE = 10;
+ private static final int CELL_SIZE = 50;
+ private static final int NUM_OF_COLS = 5;
+ private static final int NUM_OF_ROWS = 5;
+
@Mock
private IconCache mIconCache;
+ @Mock
+ private DeviceProfile mTestDeviceProfile;
+
private Context mContext;
- private InvariantDeviceProfile mTestProfile;
+ private InvariantDeviceProfile mTestInvariantProfile;
private WidgetItem mWidget1x1;
private WidgetItem mWidget2x2;
private WidgetItem mWidget2x3;
@@ -76,12 +87,13 @@
public void setUp() {
MockitoAnnotations.initMocks(this);
- mContext = getApplicationContext();
+ mContext = new ActivityContextWrapper(getApplicationContext());
- mTestProfile = new InvariantDeviceProfile();
- mTestProfile.numRows = 5;
- mTestProfile.numColumns = 5;
+ mTestInvariantProfile = new InvariantDeviceProfile();
+ mTestInvariantProfile.numColumns = NUM_OF_COLS;
+ mTestInvariantProfile.numRows = NUM_OF_ROWS;
+ initDP();
initTestWidgets();
initTestShortcuts();
@@ -92,17 +104,17 @@
@Test
- public void groupWidgetItemsIntoTableWithReordering_widgetsOnly_maxSpansPerRow5_shouldGroupWidgetsInTable() {
+ public void groupWidgetItemsIntoTableWithReordering_widgetsOnly_maxSpanPxPerRow220_cellPadding0_shouldGroupWidgetsInTable() {
List<WidgetItem> widgetItems = List.of(mWidget4x4, mWidget2x3, mWidget1x1, mWidget2x4,
mWidget2x2);
List<ArrayList<WidgetItem>> widgetItemInTable =
- WidgetsTableUtils.groupWidgetItemsIntoTableWithReordering(
- widgetItems, /* maxSpansPerRow= */ 5);
+ WidgetsTableUtils.groupWidgetItemsUsingRowPxWithReordering(widgetItems, mContext,
+ mTestDeviceProfile, 220, 0);
- // Row 0: 1x1, 2x2
- // Row 1: 2x3, 2x4
- // Row 2: 4x4
+ // Row 0: 1x1(50px), 2x2(110px)
+ // Row 1: 2x3(110px), 2x4(110px)
+ // Row 2: 4x4(230px)
assertThat(widgetItemInTable).hasSize(3);
assertThat(widgetItemInTable.get(0)).containsExactly(mWidget1x1, mWidget2x2);
assertThat(widgetItemInTable.get(1)).containsExactly(mWidget2x3, mWidget2x4);
@@ -110,65 +122,91 @@
}
@Test
- public void groupWidgetItemsIntoTableWithReordering_widgetsOnly_maxSpansPerRow4_shouldGroupWidgetsInTable() {
+ public void groupWidgetItemsIntoTableWithReordering_widgetsOnly_maxSpanPxPerRow220_cellPadding10_shouldGroupWidgetsInTable() {
List<WidgetItem> widgetItems = List.of(mWidget4x4, mWidget2x3, mWidget1x1, mWidget2x4,
mWidget2x2);
List<ArrayList<WidgetItem>> widgetItemInTable =
- WidgetsTableUtils.groupWidgetItemsIntoTableWithReordering(
- widgetItems, /* maxSpansPerRow= */ 4);
+ WidgetsTableUtils.groupWidgetItemsUsingRowPxWithReordering(widgetItems, mContext,
+ mTestDeviceProfile, 220, 10);
- // Row 0: 1x1, 2x2
- // Row 1: 2x3,
- // Row 2: 2x4,
- // Row 3: 4x4
- assertThat(widgetItemInTable).hasSize(4);
- assertThat(widgetItemInTable.get(0)).containsExactly(mWidget1x1, mWidget2x2);
- assertThat(widgetItemInTable.get(1)).containsExactly(mWidget2x3);
- assertThat(widgetItemInTable.get(2)).containsExactly(mWidget2x4);
- assertThat(widgetItemInTable.get(3)).containsExactly(mWidget4x4);
+ // Row 0: 1x1(50px), 2x2(110px)
+ // Row 1: 2x3(110px), 2x4(110px)
+ // Row 2: 4x4(230px)
+ assertThat(widgetItemInTable).hasSize(5);
+ assertThat(widgetItemInTable.get(0)).containsExactly(mWidget1x1);
+ assertThat(widgetItemInTable.get(1)).containsExactly(mWidget2x2);
+ assertThat(widgetItemInTable.get(2)).containsExactly(mWidget2x3);
+ assertThat(widgetItemInTable.get(3)).containsExactly(mWidget2x4);
+ assertThat(widgetItemInTable.get(4)).containsExactly(mWidget4x4);
}
@Test
- public void groupWidgetItemsIntoTableWithReordering_mixItems_maxSpansPerRow4_shouldGroupWidgetsInTable() {
+ public void groupWidgetItemsIntoTableWithReordering_widgetsOnly_maxSpanPxPerRow350_cellPadding0_shouldGroupWidgetsInTable() {
+ List<WidgetItem> widgetItems = List.of(mWidget4x4, mWidget2x3, mWidget1x1, mWidget2x4,
+ mWidget2x2);
+
+ List<ArrayList<WidgetItem>> widgetItemInTable =
+ WidgetsTableUtils.groupWidgetItemsUsingRowPxWithReordering(widgetItems, mContext,
+ mTestDeviceProfile, 350, 0);
+
+ // Row 0: 1x1(50px), 2x2(110px), 2x3(110px)
+ // Row 1: 2x4(110px)
+ // Row 2: 4x4(230px)
+ assertThat(widgetItemInTable).hasSize(3);
+ assertThat(widgetItemInTable.get(0)).containsExactly(mWidget1x1, mWidget2x2, mWidget2x3);
+ assertThat(widgetItemInTable.get(1)).containsExactly(mWidget2x4);
+ assertThat(widgetItemInTable.get(2)).containsExactly(mWidget4x4);
+ }
+
+ @Test
+ public void groupWidgetItemsIntoTableWithReordering_mixItems_maxSpanPxPerRow350_cellPadding0_shouldGroupWidgetsInTable() {
List<WidgetItem> widgetItems = List.of(mWidget4x4, mShortcut3, mWidget2x3, mShortcut1,
mWidget1x1, mShortcut2, mWidget2x4, mWidget2x2);
List<ArrayList<WidgetItem>> widgetItemInTable =
- WidgetsTableUtils.groupWidgetItemsIntoTableWithReordering(
- widgetItems, /* maxSpansPerRow= */ 4);
+ WidgetsTableUtils.groupWidgetItemsUsingRowPxWithReordering(widgetItems, mContext,
+ mTestDeviceProfile, 350, 0);
- // Row 0: 1x1, 2x2
- // Row 1: 2x3,
- // Row 2: 2x4,
- // Row 3: 4x4
- // Row 4: shortcut3, shortcut1, shortcut2
- assertThat(widgetItemInTable).hasSize(5);
- assertThat(widgetItemInTable.get(0)).containsExactly(mWidget1x1, mWidget2x2);
- assertThat(widgetItemInTable.get(1)).containsExactly(mWidget2x3);
- assertThat(widgetItemInTable.get(2)).containsExactly(mWidget2x4);
- assertThat(widgetItemInTable.get(3)).containsExactly(mWidget4x4);
- assertThat(widgetItemInTable.get(4)).containsExactly(mShortcut3, mShortcut2, mShortcut1);
+ // Row 0: 1x1(50px), 2x2(110px), 2x3(110px)
+ // Row 1: 2x4(110px),
+ // Row 2: 4x4(230px)
+ // Row 3: shortcut3(50px), shortcut1(50px), shortcut2(50px)
+ assertThat(widgetItemInTable).hasSize(4);
+ assertThat(widgetItemInTable.get(0)).containsExactly(mWidget1x1, mWidget2x2, mWidget2x3);
+ assertThat(widgetItemInTable.get(1)).containsExactly(mWidget2x4);
+ assertThat(widgetItemInTable.get(2)).containsExactly(mWidget4x4);
+ assertThat(widgetItemInTable.get(3)).containsExactly(mShortcut3, mShortcut2, mShortcut1);
}
@Test
- public void groupWidgetItemsIntoTableWithoutReordering_shouldMaintainTheOrder() {
+ public void groupWidgetItemsIntoTableWithoutReordering_maxSpanPxPerRow220_cellPadding0_shouldMaintainTheOrder() {
List<WidgetItem> widgetItems =
List.of(mWidget4x4, mWidget2x3, mWidget1x1, mWidget2x4, mWidget2x2);
List<ArrayList<WidgetItem>> widgetItemInTable =
- WidgetsTableUtils.groupWidgetItemsIntoTableWithoutReordering(
- widgetItems, /* maxSpansPerRow= */ 5);
+ WidgetsTableUtils.groupWidgetItemsUsingRowPxWithoutReordering(widgetItems, mContext,
+ mTestDeviceProfile, 220, 0);
- // Row 0: 4x4
- // Row 1: 2x3, 1x1
- // Row 2: 2x4, 2x2
+ // Row 0: 4x4(230px)
+ // Row 1: 2x3(110px), 1x1(50px)
+ // Row 2: 2x4(110px), 2x2(110px)
assertThat(widgetItemInTable).hasSize(3);
assertThat(widgetItemInTable.get(0)).containsExactly(mWidget4x4);
assertThat(widgetItemInTable.get(1)).containsExactly(mWidget2x3, mWidget1x1);
assertThat(widgetItemInTable.get(2)).containsExactly(mWidget2x4, mWidget2x2);
}
+ private void initDP() {
+ doAnswer(i -> {
+ ((Point) i.getArgument(0)).set(CELL_SIZE, CELL_SIZE);
+ return null;
+ }).when(mTestDeviceProfile).getCellSize(any(Point.class));
+ when(mTestDeviceProfile.getCellSize()).thenReturn(new Point(CELL_SIZE, CELL_SIZE));
+ mTestDeviceProfile.cellLayoutBorderSpacePx = new Point(SPACE_SIZE, SPACE_SIZE);
+ when(mTestDeviceProfile.shouldInsetWidgets()).thenReturn(false);
+ }
+
private void initTestWidgets() {
List<Point> widgetSizes = List.of(new Point(1, 1), new Point(2, 2), new Point(2, 3),
new Point(2, 4), new Point(4, 4));
@@ -184,7 +222,7 @@
LauncherAppWidgetProviderInfo.fromProviderInfo(mContext, info);
widgetInfo.spanX = widgetSize.x;
widgetInfo.spanY = widgetSize.y;
- widgetItems.add(new WidgetItem(widgetInfo, mTestProfile, mIconCache));
+ widgetItems.add(new WidgetItem(widgetInfo, mTestInvariantProfile, mIconCache));
}
);
mWidget1x1 = widgetItems.get(0);
diff --git a/tests/tapl/com/android/launcher3/tapl/AppIconMenu.java b/tests/tapl/com/android/launcher3/tapl/AppIconMenu.java
index 667290f..82d9630 100644
--- a/tests/tapl/com/android/launcher3/tapl/AppIconMenu.java
+++ b/tests/tapl/com/android/launcher3/tapl/AppIconMenu.java
@@ -54,14 +54,5 @@
return createMenuItem(menuItem);
}
- /**
- * Returns a menu item that matches the text "Split screen". Fails if it doesn't exist.
- */
- public SplitScreenMenuItem getSplitScreenMenuItem() {
- final UiObject2 menuItem = mLauncher.waitForObjectInContainer(mDeepShortcutsContainer,
- AppIcon.getAppIconSelector("Split screen", mLauncher));
- return new SplitScreenMenuItem(mLauncher, menuItem);
- }
-
protected abstract AppIconMenuItem createMenuItem(UiObject2 menuItem);
}
diff --git a/tests/tapl/com/android/launcher3/tapl/Launchable.java b/tests/tapl/com/android/launcher3/tapl/Launchable.java
index 48e327f..3dcb437 100644
--- a/tests/tapl/com/android/launcher3/tapl/Launchable.java
+++ b/tests/tapl/com/android/launcher3/tapl/Launchable.java
@@ -76,27 +76,6 @@
}
}
- /**
- * Clicks a launcher object to initiate splitscreen, where the selected app will be one of two
- * apps running on the screen. Should be called when Launcher is in a "split staging" state
- * and is waiting for the user's selection of a second app. Expects a SPLIT_START_EVENT to be
- * fired when the click is executed.
- */
- public LaunchedAppState launchIntoSplitScreen() {
- try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
- "want to launch split tasks from " + launchableType())) {
- LauncherInstrumentation.log("Launchable.launch before click "
- + mObject.getVisibleCenter() + " in " + mLauncher.getVisibleBounds(mObject));
-
- mLauncher.clickLauncherObject(mObject);
-
- try (LauncherInstrumentation.Closable c2 = mLauncher.addContextLayer("clicked")) {
- mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, OverviewTask.SPLIT_START_EVENT);
- return new LaunchedAppState(mLauncher);
- }
- }
- }
-
protected LaunchedAppState assertAppLaunched(BySelector selector) {
mLauncher.assertTrue(
"App didn't start: (" + selector + ")",
diff --git a/tests/tapl/com/android/launcher3/tapl/OverviewTask.java b/tests/tapl/com/android/launcher3/tapl/OverviewTask.java
index 90f3d13..adc993d 100644
--- a/tests/tapl/com/android/launcher3/tapl/OverviewTask.java
+++ b/tests/tapl/com/android/launcher3/tapl/OverviewTask.java
@@ -37,9 +37,10 @@
public final class OverviewTask {
private static final String SYSTEMUI_PACKAGE = "com.android.systemui";
- static final Pattern TASK_START_EVENT = Pattern.compile("startActivityFromRecentsAsync");
- static final Pattern SPLIT_SELECT_EVENT = Pattern.compile("enterSplitSelect");
- static final Pattern SPLIT_START_EVENT = Pattern.compile("launchSplitTasks");
+ static final Pattern TASK_START_EVENT =
+ Pattern.compile("startActivityFromRecentsAsync");
+ static final Pattern SPLIT_START_EVENT =
+ Pattern.compile("launchSplitTasks");
private final LauncherInstrumentation mLauncher;
private final UiObject2 mTask;
private final BaseOverview mOverview;
diff --git a/tests/tapl/com/android/launcher3/tapl/SplitScreenMenuItem.java b/tests/tapl/com/android/launcher3/tapl/SplitScreenMenuItem.java
deleted file mode 100644
index 47cf20b..0000000
--- a/tests/tapl/com/android/launcher3/tapl/SplitScreenMenuItem.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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.tapl;
-
-import androidx.test.uiautomator.UiObject2;
-
-import com.android.launcher3.testing.shared.TestProtocol;
-
-/**
- * A class representing the "Split screen" menu item in the app long-press menu. Used for TAPL
- * testing in a similar way as other menu items {@link AppIconMenuItem}, but unlike AppIconMenuItem,
- * the split screen command does not trigger an app launch. Instead, it causes Launcher to shift to
- * a different state (OverviewSplitSelect).
- */
-public final class SplitScreenMenuItem {
- private final LauncherInstrumentation mLauncher;
- private final UiObject2 mObject;
-
- SplitScreenMenuItem(LauncherInstrumentation launcher, UiObject2 object) {
- mLauncher = launcher;
- mObject = object;
- }
-
- /**
- * Executes a click command on this menu item. Expects a SPLIT_SELECT_EVENT to be fired.
- */
- public void click() {
- try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
- "want to enter split select from app long-press menu")) {
- LauncherInstrumentation.log("clicking on split screen menu item "
- + mObject.getVisibleCenter() + " in " + mLauncher.getVisibleBounds(mObject));
-
- mLauncher.clickLauncherObject(mObject);
-
- try (LauncherInstrumentation.Closable c2 = mLauncher.addContextLayer("clicked")) {
- mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, OverviewTask.SPLIT_SELECT_EVENT);
- mLauncher.waitForLauncherObject("split_placeholder");
- }
- }
- }
-}