+
+
+
+
+
+
+
+
+
+
diff --git a/res/values/strings.xml b/res/values/strings.xml
index ee5e024dac..829a21ddfa 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -277,6 +277,9 @@
Show notification dots
+
+ Developer Options
+
Add app icons to home screen
diff --git a/res/xml/device_profiles.xml b/res/xml/device_profiles.xml
index 07ce59862b..290bc8c4c8 100644
--- a/res/xml/device_profiles.xml
+++ b/res/xml/device_profiles.xml
@@ -144,6 +144,7 @@
launcher:numFolderRows="3"
launcher:numFolderColumns="3"
launcher:numHotseatIcons="6"
+ launcher:hotseatColumnSpanLandscape="4"
launcher:numAllAppsColumns="6"
launcher:isScalable="true"
launcher:devicePaddingId="@xml/paddings_6x5"
diff --git a/res/xml/launcher_preferences.xml b/res/xml/launcher_preferences.xml
index 90de4987f5..8a0c909ed8 100644
--- a/res/xml/launcher_preferences.xml
+++ b/res/xml/launcher_preferences.xml
@@ -53,7 +53,7 @@
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index 6302739bc5..878ac3b22b 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -53,6 +53,7 @@ import androidx.annotation.UiThread;
import com.android.launcher3.accessibility.BaseAccessibilityDelegate;
import com.android.launcher3.dot.DotInfo;
+import com.android.launcher3.dragndrop.DragOptions.PreDragCondition;
import com.android.launcher3.dragndrop.DraggableView;
import com.android.launcher3.folder.FolderIcon;
import com.android.launcher3.graphics.IconShape;
@@ -65,12 +66,11 @@ import com.android.launcher3.icons.cache.HandlerRunnable;
import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.ItemInfoWithIcon;
-import com.android.launcher3.model.data.PackageItemInfo;
-import com.android.launcher3.model.data.SearchActionItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
+import com.android.launcher3.popup.PopupContainerWithArrow;
import com.android.launcher3.util.SafeCloseable;
+import com.android.launcher3.util.ShortcutUtil;
import com.android.launcher3.views.ActivityContext;
-import com.android.launcher3.views.BubbleTextHolder;
import com.android.launcher3.views.IconLabelDotView;
import java.text.NumberFormat;
@@ -174,7 +174,6 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
private HandlerRunnable mIconLoadRequest;
private boolean mEnableIconUpdateAnimation = false;
- private BubbleTextHolder mBubbleTextHolder;
public BubbleTextView(Context context) {
this(context, null, 0);
@@ -253,7 +252,8 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
*/
public void reset() {
mDotInfo = null;
- mDotParams.color = Color.TRANSPARENT;
+ mDotParams.dotColor = Color.TRANSPARENT;
+ mDotParams.appColor = Color.TRANSPARENT;
cancelDotScaleAnim();
mDotParams.scale = 0f;
mForceHideDot = false;
@@ -361,15 +361,8 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
setDownloadStateContentDescription(info, info.getProgressLevel());
}
- private void setItemInfo(ItemInfoWithIcon itemInfo) {
+ protected void setItemInfo(ItemInfoWithIcon itemInfo) {
setTag(itemInfo);
- if (mBubbleTextHolder != null) {
- mBubbleTextHolder.onItemInfoUpdated(itemInfo);
- }
- }
-
- public void setBubbleTextHolder(BubbleTextHolder bubbleTextHolder) {
- mBubbleTextHolder = bubbleTextHolder;
}
@UiThread
@@ -381,7 +374,9 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
flags |= FLAG_NO_BADGE;
}
FastBitmapDrawable iconDrawable = info.newIcon(getContext(), flags);
- mDotParams.color = iconDrawable.getIconColor();
+ mDotParams.appColor = iconDrawable.getIconColor();
+ mDotParams.dotColor = getContext().getResources()
+ .getColor(android.R.color.system_accent3_100, getContext().getTheme());
setIcon(iconDrawable);
applyLabel(info);
}
@@ -917,10 +912,8 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
} else if (info instanceof WorkspaceItemInfo) {
applyFromWorkspaceItem((WorkspaceItemInfo) info);
mActivity.invalidateParent(info);
- } else if (info instanceof PackageItemInfo) {
- applyFromItemInfoWithIcon((PackageItemInfo) info);
- } else if (info instanceof SearchActionItemInfo) {
- applyFromItemInfoWithIcon((SearchActionItemInfo) info);
+ } else if (info != null) {
+ applyFromItemInfoWithIcon(info);
}
mDisableRelayout = false;
@@ -1058,4 +1051,19 @@ public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver,
args.put("count", notificationCount);
return icuCountFormat.format(args);
}
+
+ /**
+ * Starts a long press action and returns the corresponding pre-drag condition
+ */
+ public PreDragCondition startLongPressAction() {
+ PopupContainerWithArrow popup = PopupContainerWithArrow.showForIcon(this);
+ return popup != null ? popup.createPreDragCondition(true) : null;
+ }
+
+ /**
+ * Returns true if the view can show long-press popup
+ */
+ public boolean canShowLongPressPopup() {
+ return getTag() instanceof ItemInfo && ShortcutUtil.supportsShortcuts((ItemInfo) getTag());
+ }
}
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index 87bbac6cd4..76e945dc11 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -65,6 +65,7 @@ import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.dragndrop.DraggableView;
import com.android.launcher3.folder.PreviewBackground;
import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.model.data.LauncherAppWidgetInfo;
import com.android.launcher3.util.CellAndSpan;
import com.android.launcher3.util.GridOccupancy;
import com.android.launcher3.util.ParcelableSparseArray;
@@ -290,7 +291,7 @@ public class CellLayout extends ViewGroup {
for (int i = 0; i < mDragOutlineAnims.length; i++) {
final InterruptibleInOutAnimator anim =
- new InterruptibleInOutAnimator(duration, fromAlphaValue, toAlphaValue);
+ new InterruptibleInOutAnimator(duration, fromAlphaValue, toAlphaValue);
anim.getAnimator().setInterpolator(mEaseOutInterpolator);
final int thisIndex = i;
anim.getAnimator().addUpdateListener(new AnimatorUpdateListener() {
@@ -2440,7 +2441,7 @@ public class CellLayout extends ViewGroup {
// First we determine if things have moved enough to cause a different layout
ItemConfiguration swapSolution = findReorderSolution(pixelXY[0], pixelXY[1], spanX, spanY,
- spanX, spanY, direction, dragView, true, new ItemConfiguration());
+ spanX, spanY, direction, dragView, true, new ItemConfiguration());
setUseTempCoords(true);
if (swapSolution != null && swapSolution.isSolution) {
@@ -2477,7 +2478,7 @@ public class CellLayout extends ViewGroup {
// direction vector, since we want the solution to match the preview, and it's possible
// that the exact position of the item has changed to result in a new reordering outcome.
if ((mode == MODE_ON_DROP || mode == MODE_ON_DROP_EXTERNAL || mode == MODE_ACCEPT_DROP)
- && mPreviousReorderDirection[0] != INVALID_DIRECTION) {
+ && mPreviousReorderDirection[0] != INVALID_DIRECTION) {
mDirectionVector[0] = mPreviousReorderDirection[0];
mDirectionVector[1] = mPreviousReorderDirection[1];
// We reset this vector after drop
@@ -2493,7 +2494,7 @@ public class CellLayout extends ViewGroup {
// Find a solution involving pushing / displacing any items in the way
ItemConfiguration swapSolution = findReorderSolution(pixelX, pixelY, minSpanX, minSpanY,
- spanX, spanY, mDirectionVector, dragView, true, new ItemConfiguration());
+ spanX, spanY, mDirectionVector, dragView, true, new ItemConfiguration());
// We attempt the approach which doesn't shuffle views at all
ItemConfiguration noShuffleSolution = findConfigurationNoShuffle(pixelX, pixelY, minSpanX,
@@ -2733,12 +2734,24 @@ public class CellLayout extends ViewGroup {
}
public void markCellsAsOccupiedForView(View view) {
+ if (view instanceof LauncherAppWidgetHostView
+ && view.getTag() instanceof LauncherAppWidgetInfo) {
+ LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) view.getTag();
+ mOccupied.markCells(info.cellX, info.cellY, info.spanX, info.spanY, true);
+ return;
+ }
if (view == null || view.getParent() != mShortcutsAndWidgets) return;
LayoutParams lp = (LayoutParams) view.getLayoutParams();
mOccupied.markCells(lp.cellX, lp.cellY, lp.cellHSpan, lp.cellVSpan, true);
}
public void markCellsAsUnoccupiedForView(View view) {
+ if (view instanceof LauncherAppWidgetHostView
+ && view.getTag() instanceof LauncherAppWidgetInfo) {
+ LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) view.getTag();
+ mOccupied.markCells(info.cellX, info.cellY, info.spanX, info.spanY, false);
+ return;
+ }
if (view == null || view.getParent() != mShortcutsAndWidgets) return;
LayoutParams lp = (LayoutParams) view.getLayoutParams();
mOccupied.markCells(lp.cellX, lp.cellY, lp.cellHSpan, lp.cellVSpan, false);
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 31f1da85c4..be180a61cb 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -158,6 +158,7 @@ public class DeviceProfile {
public final int numShownHotseatIcons;
public int hotseatCellHeightPx;
private final int hotseatExtraVerticalSize;
+ private final boolean areNavButtonsInline;
// In portrait: size = height, in landscape: size = width
public int hotseatBarSizePx;
public int hotseatBarTopPaddingPx;
@@ -358,7 +359,7 @@ public class DeviceProfile {
// We shrink hotseat sizes regardless of orientation, if nav buttons are inline and QSB
// might be inline in either orientations, to keep hotseat size consistent across rotation.
- boolean areNavButtonsInline = isTaskbarPresent && !isGestureMode;
+ areNavButtonsInline = isTaskbarPresent && !isGestureMode;
if (areNavButtonsInline && canQsbInline) {
numShownHotseatIcons = inv.numShrunkenHotseatIcons;
} else {
@@ -373,15 +374,14 @@ public class DeviceProfile {
res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_top_padding);
if (isQsbInline) {
hotseatBarBottomPaddingPx = res.getDimensionPixelSize(R.dimen.inline_qsb_bottom_margin);
- qsbWidth = calculateQsbWidth();
} else {
hotseatBarBottomPaddingPx = (isTallDevice ? res.getDimensionPixelSize(
R.dimen.dynamic_grid_hotseat_bottom_tall_padding)
: res.getDimensionPixelSize(
R.dimen.dynamic_grid_hotseat_bottom_non_tall_padding))
+ res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_bottom_padding);
- qsbWidth = 0;
}
+
springLoadedHotseatBarTopMarginPx = res.getDimensionPixelSize(
R.dimen.spring_loaded_hotseat_top_margin);
hotseatBarSidePaddingEndPx =
@@ -390,9 +390,7 @@ public class DeviceProfile {
hotseatBarSidePaddingStartPx = isVerticalBarLayout() ? workspacePageIndicatorHeight : 0;
hotseatExtraVerticalSize =
res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_extra_vertical_size);
- hotseatBorderSpace = pxFromDp(inv.hotseatBorderSpaces[mTypeIndex], mMetrics);
- updateHotseatIconSize(
- pxFromDp(inv.iconSize[INDEX_DEFAULT], mMetrics));
+ updateHotseatIconSize(pxFromDp(inv.iconSize[INDEX_DEFAULT], mMetrics));
qsbBottomMarginOriginalPx = isScalableGrid
? res.getDimensionPixelSize(R.dimen.scalable_grid_qsb_bottom_margin)
@@ -483,6 +481,10 @@ public class DeviceProfile {
cellLayoutPadding);
updateWorkspacePadding();
+ // Hotseat and QSB width depends on updated cellSize and workspace padding
+ hotseatBorderSpace = calculateHotseatBorderSpace();
+ qsbWidth = calculateQsbWidth();
+
flingToDeleteThresholdVelocity = res.getDimensionPixelSize(
R.dimen.drag_flingToDeleteMinVelocity);
@@ -493,14 +495,26 @@ public class DeviceProfile {
new DotRenderer(allAppsIconSizePx, dotPath, DEFAULT_DOT_SIZE);
}
+ /**
+ * QSB width is always calculated because when in 3 button nav the width doesn't follow the
+ * width of the hotseat.
+ */
private int calculateQsbWidth() {
- int columns = isTwoPanels ? inv.numColumns * 2 : inv.numColumns;
+ if (isQsbInline) {
+ int columns = isTwoPanels ? inv.numColumns * 2 : inv.numColumns;
+ return getIconToIconWidthForColumns(columns)
+ - iconSizePx * numShownHotseatIcons
+ - hotseatBorderSpace * numShownHotseatIcons;
+ } else {
+ int columns = inv.hotseatColumnSpan[mTypeIndex];
+ return getIconToIconWidthForColumns(columns);
+ }
+ }
- return cellWidthPx * columns
- + cellLayoutBorderSpacePx.x * (columns - 1)
- - (cellWidthPx - iconSizePx) // left and right cell space
- - iconSizePx * numShownHotseatIcons
- - hotseatBorderSpace * numShownHotseatIcons;
+ private int getIconToIconWidthForColumns(int columns) {
+ return columns * getCellSize().x
+ + (columns - 1) * cellLayoutBorderSpacePx.x
+ - (getCellSize().x - iconSizePx); // left and right cell space
}
private int getHorizontalMarginPx(InvariantDeviceProfile idp, Resources res) {
@@ -651,11 +665,10 @@ public class DeviceProfile {
updateIconSize(1f, res);
updateWorkspacePadding();
- Point workspacePadding = getTotalWorkspacePadding();
// Check to see if the icons fit within the available height.
float usedHeight = getCellLayoutHeightSpecification();
- final int maxHeight = getWorkspaceHeight(workspacePadding);
+ final int maxHeight = getCellLayoutHeight();
float extraHeight = Math.max(0, maxHeight - usedHeight);
float scaleY = maxHeight / usedHeight;
boolean shouldScale = scaleY < 1f;
@@ -688,7 +701,7 @@ public class DeviceProfile {
}
private int getCellLayoutWidthSpecification() {
- int numColumns = isTwoPanels ? inv.numColumns * 2 : inv.numColumns;
+ int numColumns = getPanelCount() * inv.numColumns;
return (cellWidthPx * numColumns) + (cellLayoutBorderSpacePx.x * (numColumns - 1))
+ cellLayoutPaddingPx.left + cellLayoutPaddingPx.right;
}
@@ -741,13 +754,6 @@ public class DeviceProfile {
// All apps
updateAllAppsIconSize(scale, res);
- // Hotseat
- hotseatBorderSpace = pxFromDp(inv.hotseatBorderSpaces[mTypeIndex], mMetrics, scale);
- if (isQsbInline) {
- qsbWidth = calculateQsbWidth();
- } else {
- qsbWidth = 0;
- }
updateHotseatIconSize(iconSizePx);
// Folder icon
@@ -755,6 +761,23 @@ public class DeviceProfile {
folderIconOffsetYPx = (iconSizePx - folderIconSizePx) / 2;
}
+ /**
+ * Hotseat width spans a certain number of columns on scalable grids.
+ * This method calculates the space between the icons to achieve that width.
+ */
+ private int calculateHotseatBorderSpace() {
+ if (!isScalableGrid) return 0;
+ //TODO(http://b/228998082) remove this when 3 button spaces are fixed
+ if (areNavButtonsInline) {
+ return pxFromDp(inv.hotseatBorderSpaces[mTypeIndex], mMetrics);
+ } else {
+ int columns = inv.hotseatColumnSpan[mTypeIndex];
+ float hotseatWidthPx = getIconToIconWidthForColumns(columns);
+ float hotseatIconsTotalPx = iconSizePx * numShownHotseatIcons;
+ return (int) (hotseatWidthPx - hotseatIconsTotalPx) / (numShownHotseatIcons - 1);
+ }
+ }
+
/**
* Updates the iconSize for allApps* variants.
@@ -878,18 +901,24 @@ public class DeviceProfile {
result = new Point();
}
- // Since we are only concerned with the overall padding, layout direction does
- // not matter.
- Point padding = getTotalWorkspacePadding();
-
- int numColumns = isTwoPanels ? inv.numColumns * 2 : inv.numColumns;
- int screenWidthPx = getWorkspaceWidth(padding);
- result.x = calculateCellWidth(screenWidthPx, cellLayoutBorderSpacePx.x, numColumns);
- int screenHeightPx = getWorkspaceHeight(padding);
- result.y = calculateCellHeight(screenHeightPx, cellLayoutBorderSpacePx.y, inv.numRows);
+ int shortcutAndWidgetContainerWidth =
+ getCellLayoutWidth() - (cellLayoutPaddingPx.left + cellLayoutPaddingPx.right);
+ result.x = calculateCellWidth(shortcutAndWidgetContainerWidth, cellLayoutBorderSpacePx.x,
+ inv.numColumns);
+ int shortcutAndWidgetContainerHeight =
+ getCellLayoutHeight() - (cellLayoutPaddingPx.top + cellLayoutPaddingPx.bottom);
+ result.y = calculateCellHeight(shortcutAndWidgetContainerHeight, cellLayoutBorderSpacePx.y,
+ inv.numRows);
return result;
}
+ /**
+ * Gets the number of panels within the workspace.
+ */
+ public int getPanelCount() {
+ return isTwoPanels ? 2 : 1;
+ }
+
/**
* Gets the space in px from the bottom of last item in the vertical-bar hotseat to the
* bottom of the screen.
@@ -908,7 +937,7 @@ public class DeviceProfile {
/**
* Gets the scaled top of the workspace in px for the spring-loaded edit state.
*/
- public float getWorkspaceSpringLoadShrunkTop() {
+ public float getCellLayoutSpringLoadShrunkTop() {
workspaceSpringLoadShrunkTop = mInsets.top + dropTargetBarTopMarginPx + dropTargetBarSizePx
+ dropTargetBarBottomMarginPx;
return workspaceSpringLoadShrunkTop;
@@ -917,7 +946,7 @@ public class DeviceProfile {
/**
* Gets the scaled bottom of the workspace in px for the spring-loaded edit state.
*/
- private float getWorkspaceSpringLoadShrunkBottom() {
+ private float getCellLayoutSpringLoadShrunkBottom() {
int topOfHotseat = hotseatBarSizePx + springLoadedHotseatBarTopMarginPx;
workspaceSpringLoadShrunkBottom =
heightPx - (isVerticalBarLayout() ? getVerticalHotseatLastItemBottomOffset()
@@ -936,13 +965,12 @@ public class DeviceProfile {
* Gets the scale of the workspace for the spring-loaded edit state.
*/
public float getWorkspaceSpringLoadScale() {
- float cellLayoutHeight = availableHeightPx - workspacePadding.top - workspacePadding.bottom;
- float scale = (getWorkspaceSpringLoadShrunkBottom() - getWorkspaceSpringLoadShrunkTop())
- / cellLayoutHeight;
+ float scale = (getCellLayoutSpringLoadShrunkBottom() - getCellLayoutSpringLoadShrunkTop())
+ / getCellLayoutHeight();
scale = Math.min(scale, 1f);
// Reduce scale if next pages would not be visible after scaling the workspace
- int workspaceWidth = getWorkspaceWidth();
+ int workspaceWidth = availableWidthPx;
float scaledWorkspaceWidth = workspaceWidth * scale;
float maxAvailableWidth =
workspaceWidth - (2 * getWorkspaceSpringLoadedMinimumNextPageVisible());
@@ -952,19 +980,23 @@ public class DeviceProfile {
return scale;
}
- public int getWorkspaceWidth() {
- return getWorkspaceWidth(getTotalWorkspacePadding());
+ /**
+ * Gets the width of a single Cell Layout, aka a single panel within a Workspace.
+ *
+ * This is the width of a Workspace, less its horizontal padding. Note that two-panel
+ * layouts have two Cell Layouts per workspace.
+ */
+ public int getCellLayoutWidth() {
+ return (availableWidthPx - getTotalWorkspacePadding().x) / getPanelCount();
}
- public int getWorkspaceWidth(Point workspacePadding) {
- int cellLayoutTotalPadding =
- (isTwoPanels ? 2 : 1) * (cellLayoutPaddingPx.left + cellLayoutPaddingPx.right);
- return availableWidthPx - workspacePadding.x - cellLayoutTotalPadding;
- }
-
- private int getWorkspaceHeight(Point workspacePadding) {
- return availableHeightPx - workspacePadding.y - (cellLayoutPaddingPx.top
- + cellLayoutPaddingPx.bottom);
+ /**
+ * Gets the height of a single Cell Layout, aka a single panel within a Workspace.
+ *
+ *
This is the height of a Workspace, less its vertical padding.
+ */
+ public int getCellLayoutHeight() {
+ return availableHeightPx - getTotalWorkspacePadding().y;
}
public Point getTotalWorkspacePadding() {
@@ -1070,6 +1102,13 @@ public class DeviceProfile {
mHotseatPadding.left -= diff;
mHotseatPadding.right += diff;
}
+ } else if (isScalableGrid) {
+ int sideSpacing = (availableWidthPx - qsbWidth) / 2;
+ mHotseatPadding.set(sideSpacing,
+ hotseatBarTopPaddingPx,
+ sideSpacing,
+ hotseatBarSizePx - hotseatCellHeightPx - hotseatBarTopPaddingPx
+ + mInsets.bottom);
} else {
// We want the edges of the hotseat to line up with the edges of the workspace, but the
// icons in the hotseat are a different size, and so don't line up perfectly. To account
@@ -1129,7 +1168,7 @@ public class DeviceProfile {
return ((taskbarSize - overviewActionsHeight) / 2) + getTaskbarOffsetY();
}
- return 0;
+ return isTaskbarPresent ? stashedTaskbarSize : mInsets.bottom;
}
/** Gets the space that the overview actions will take, including bottom margin. */
@@ -1306,6 +1345,7 @@ public class DeviceProfile {
writer.println(prefix + pxToDpStr("allAppsLeftRightMargin", allAppsLeftRightMargin));
writer.println(prefix + pxToDpStr("hotseatBarSizePx", hotseatBarSizePx));
+ writer.println(prefix + "\tinv.hotseatColumnSpan: " + inv.hotseatColumnSpan[mTypeIndex]);
writer.println(prefix + pxToDpStr("hotseatCellHeightPx", hotseatCellHeightPx));
writer.println(prefix + pxToDpStr("hotseatBarTopPaddingPx", hotseatBarTopPaddingPx));
writer.println(prefix + pxToDpStr("hotseatBarBottomPaddingPx", hotseatBarBottomPaddingPx));
@@ -1384,7 +1424,7 @@ public class DeviceProfile {
private static Context getContext(Context c, Info info, int orientation, WindowBounds bounds) {
Configuration config = new Configuration(c.getResources().getConfiguration());
config.orientation = orientation;
- config.densityDpi = info.densityDpi;
+ config.densityDpi = info.getDensityDpi();
config.smallestScreenWidthDp = (int) info.smallestSizeDp(bounds);
return c.createConfigurationContext(config);
}
diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java
index a9db5ce089..76106fc58d 100644
--- a/src/com/android/launcher3/Hotseat.java
+++ b/src/com/android/launcher3/Hotseat.java
@@ -173,17 +173,9 @@ public class Hotseat extends CellLayout implements Insettable {
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- int width;
- if (mActivity.getDeviceProfile().isQsbInline) {
- width = mActivity.getDeviceProfile().qsbWidth;
- } else {
- MarginLayoutParams qsbParams = (MarginLayoutParams) mQsb.getLayoutParams();
- width = getShortcutsAndWidgets().getMeasuredWidth()
- - qsbParams.getMarginStart()
- - qsbParams.getMarginEnd();
- }
+ int qsbWidth = mActivity.getDeviceProfile().qsbWidth;
- mQsb.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
+ mQsb.measure(MeasureSpec.makeMeasureSpec(qsbWidth, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(mQsbHeight, MeasureSpec.EXACTLY));
}
diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java
index 1f920793fd..db43b44f72 100644
--- a/src/com/android/launcher3/InvariantDeviceProfile.java
+++ b/src/com/android/launcher3/InvariantDeviceProfile.java
@@ -154,6 +154,8 @@ public class InvariantDeviceProfile {
*/
public int numDatabaseHotseatIcons;
+ public int[] hotseatColumnSpan;
+
/**
* Number of columns in the all apps list.
*/
@@ -357,6 +359,7 @@ public class InvariantDeviceProfile {
numShrunkenHotseatIcons = closestProfile.numShrunkenHotseatIcons;
numDatabaseHotseatIcons = deviceType == TYPE_MULTI_DISPLAY
? closestProfile.numDatabaseHotseatIcons : closestProfile.numHotseatIcons;
+ hotseatColumnSpan = closestProfile.hotseatColumnSpan;
hotseatBorderSpaces = displayOption.hotseatBorderSpaces;
numAllAppsColumns = closestProfile.numAllAppsColumns;
@@ -398,7 +401,8 @@ public class InvariantDeviceProfile {
// We need to ensure that there is enough extra space in the wallpaper
// for the intended parallax effects
float parallaxFactor =
- dpiFromPx(Math.min(displayWidth, displayHeight), displayInfo.densityDpi) < 720
+ dpiFromPx(Math.min(displayWidth, displayHeight), displayInfo.getDensityDpi())
+ < 720
? 2
: wallpaperTravelToScreenWidthRatio(displayWidth, displayHeight);
defaultWallpaperSize.x =
@@ -587,8 +591,8 @@ public class InvariantDeviceProfile {
}
}
- float width = dpiFromPx(minWidthPx, displayInfo.densityDpi);
- float height = dpiFromPx(minHeightPx, displayInfo.densityDpi);
+ float width = dpiFromPx(minWidthPx, displayInfo.getDensityDpi());
+ float height = dpiFromPx(minHeightPx, displayInfo.getDensityDpi());
// Sort the profiles based on the closeness to the device size
Collections.sort(points, (a, b) ->
@@ -735,6 +739,7 @@ public class InvariantDeviceProfile {
private final int numHotseatIcons;
private final int numShrunkenHotseatIcons;
private final int numDatabaseHotseatIcons;
+ private final int[] hotseatColumnSpan = new int[COUNT_SIZES];
private final String dbFile;
@@ -774,6 +779,16 @@ public class InvariantDeviceProfile {
R.styleable.GridDisplayOption_numShrunkenHotseatIcons, numHotseatIcons / 2);
numDatabaseHotseatIcons = a.getInt(
R.styleable.GridDisplayOption_numExtendedHotseatIcons, 2 * numHotseatIcons);
+ hotseatColumnSpan[INDEX_DEFAULT] = a.getInt(
+ R.styleable.GridDisplayOption_hotseatColumnSpan, numColumns);
+ hotseatColumnSpan[INDEX_LANDSCAPE] = a.getInt(
+ R.styleable.GridDisplayOption_hotseatColumnSpanLandscape, numColumns);
+ hotseatColumnSpan[INDEX_TWO_PANEL_LANDSCAPE] = a.getInt(
+ R.styleable.GridDisplayOption_hotseatColumnSpanTwoPanelLandscape,
+ numColumns);
+ hotseatColumnSpan[INDEX_TWO_PANEL_PORTRAIT] = a.getInt(
+ R.styleable.GridDisplayOption_hotseatColumnSpanTwoPanelPortrait,
+ numColumns);
numFolderRows = a.getInt(
R.styleable.GridDisplayOption_numFolderRows, numRows);
@@ -821,6 +836,7 @@ public class InvariantDeviceProfile {
private float folderBorderSpace;
private final PointF[] borderSpaces = new PointF[COUNT_SIZES];
private final float[] horizontalMargin = new float[COUNT_SIZES];
+ //TODO(http://b/228998082) remove this when 3 button spaces are fixed
private final float[] hotseatBorderSpaces = new float[COUNT_SIZES];
private final float[] iconSizes = new float[COUNT_SIZES];
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index ad87451fa9..135b88d5b7 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -1169,6 +1169,7 @@ public class Launcher extends StatefulActivity
}
AbstractFloatingView.closeAllOpenViewsExcept(this, false, TYPE_REBIND_SAFE);
+ DragView.removeAllViews(this);
TraceHelper.INSTANCE.endSection(traceToken);
}
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index fb028b9862..6c091f08c1 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -85,14 +85,12 @@ import com.android.launcher3.logger.LauncherAtom;
import com.android.launcher3.logging.InstanceId;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.logging.StatsLogManager.LauncherEvent;
-import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.FolderInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
-import com.android.launcher3.model.data.SearchActionItemInfo;
+import com.android.launcher3.model.data.WorkspaceItemFactory;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.pageindicators.PageIndicator;
-import com.android.launcher3.popup.PopupContainerWithArrow;
import com.android.launcher3.statemanager.StateManager;
import com.android.launcher3.statemanager.StateManager.StateHandler;
import com.android.launcher3.states.StateAnimationConfig;
@@ -1680,11 +1678,7 @@ public class Workspace extends PagedView
}
if (child instanceof BubbleTextView && !dragOptions.isAccessibleDrag) {
- PopupContainerWithArrow popupContainer = PopupContainerWithArrow
- .showForIcon((BubbleTextView) child);
- if (popupContainer != null) {
- dragOptions.preDragCondition = popupContainer.createPreDragCondition(true);
- }
+ dragOptions.preDragCondition = ((BubbleTextView) child).startLongPressAction();
}
final DragView dv;
@@ -2777,9 +2771,9 @@ public class Workspace extends PagedView
case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT:
case LauncherSettings.Favorites.ITEM_TYPE_SEARCH_ACTION:
- if (info instanceof AppInfo) {
+ if (info instanceof WorkspaceItemFactory) {
// Came from all apps -- make a copy
- info = ((AppInfo) info).makeWorkspaceItem();
+ info = ((WorkspaceItemFactory) info).makeWorkspaceItem(mLauncher);
d.dragInfo = info;
}
if (info instanceof WorkspaceItemInfo
@@ -2788,11 +2782,6 @@ public class Workspace extends PagedView
info = new WorkspaceItemInfo((WorkspaceItemInfo) info);
d.dragInfo = info;
}
- if (info instanceof SearchActionItemInfo) {
- info = ((SearchActionItemInfo) info).createWorkspaceItem(
- mLauncher.getModel());
- d.dragInfo = info;
- }
view = mLauncher.createShortcut(cellLayout, (WorkspaceItemInfo) info);
break;
case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
diff --git a/src/com/android/launcher3/accessibility/BaseAccessibilityDelegate.java b/src/com/android/launcher3/accessibility/BaseAccessibilityDelegate.java
index 14b2431662..19d042147b 100644
--- a/src/com/android/launcher3/accessibility/BaseAccessibilityDelegate.java
+++ b/src/com/android/launcher3/accessibility/BaseAccessibilityDelegate.java
@@ -23,6 +23,7 @@ import android.util.SparseArray;
import android.view.View;
import android.view.accessibility.AccessibilityNodeInfo;
+import com.android.launcher3.BubbleTextView;
import com.android.launcher3.DropTarget;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.dragndrop.DragController;
@@ -31,9 +32,9 @@ import com.android.launcher3.model.data.FolderInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
-import com.android.launcher3.popup.PopupContainerWithArrow;
import com.android.launcher3.util.Thunk;
import com.android.launcher3.views.ActivityContext;
+import com.android.launcher3.views.BubbleTextHolder;
import java.util.ArrayList;
import java.util.List;
@@ -72,7 +73,7 @@ public abstract class BaseAccessibilityDelegate info.addAction(la.accessibilityAction));
- if (!itemSupportsLongClick(host, item)) {
+ if (!itemSupportsLongClick(host)) {
info.setLongClickable(false);
info.removeAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_LONG_CLICK);
}
@@ -84,8 +85,15 @@ public abstract class BaseAccessibilityDelegate out);
- private boolean itemSupportsLongClick(View host, ItemInfo info) {
- return PopupContainerWithArrow.canShow(host, info);
+ private boolean itemSupportsLongClick(View host) {
+ if (host instanceof BubbleTextView) {
+ return ((BubbleTextView) host).canShowLongPressPopup();
+ } else if (host instanceof BubbleTextHolder) {
+ BubbleTextHolder holder = (BubbleTextHolder) host;
+ return holder.getBubbleText() != null && holder.getBubbleText().canShowLongPressPopup();
+ } else {
+ return false;
+ }
}
protected boolean itemSupportsAccessibleDrag(ItemInfo item) {
@@ -113,7 +121,6 @@ public abstract class BaseAccessibilityDelegate {
- if (item instanceof AppInfo) {
- WorkspaceItemInfo info = ((AppInfo) item).makeWorkspaceItem();
+ if (item instanceof WorkspaceItemFactory) {
+ WorkspaceItemInfo info = ((WorkspaceItemFactory) item).makeWorkspaceItem(mContext);
mContext.getModelWriter().addItemToDatabase(info,
LauncherSettings.Favorites.CONTAINER_DESKTOP,
screenId, coordinates[0], coordinates[1]);
diff --git a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
index bdfeada07c..096e2c8d35 100644
--- a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
@@ -228,6 +228,8 @@ public class AllAppsRecyclerView extends BaseRecyclerView {
requestFocus();
mgr.logger().sendToInteractionJankMonitor(
LAUNCHER_ALLAPPS_VERTICAL_SWIPE_BEGIN, this);
+ hideKeyboardAsync(ActivityContext.lookupContext(getContext()),
+ getApplicationWindowToken());
break;
case SCROLL_STATE_IDLE:
mgr.logger().sendToInteractionJankMonitor(
@@ -243,8 +245,6 @@ public class AllAppsRecyclerView extends BaseRecyclerView {
&& mEmptySearchBackground != null && mEmptySearchBackground.getAlpha() > 0) {
mEmptySearchBackground.setHotspot(e.getX(), e.getY());
}
- hideKeyboardAsync(ActivityContext.lookupContext(getContext()),
- getApplicationWindowToken());
return result;
}
diff --git a/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java b/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java
index 72ca5a7db4..95c67ddaa8 100644
--- a/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java
@@ -17,6 +17,7 @@ package com.android.launcher3.allapps;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_TAP_ON_PERSONAL_TAB;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ALLAPPS_TAP_ON_WORK_TAB;
+import static com.android.launcher3.util.UiThreadHelper.hideKeyboardAsync;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -458,6 +459,8 @@ public abstract class BaseAllAppsContainerView {
@@ -465,6 +468,8 @@ public abstract class BaseAllAppsContainerView extends Fram
iv.setImageDrawable(drawable);
return iv;
}
+
+ /**
+ * Removes any stray DragView from the DragLayer.
+ */
+ public static void removeAllViews(ActivityContext activity) {
+ BaseDragLayer dragLayer = activity.getDragLayer();
+ // Iterate in reverse order. DragView is added later to the dragLayer,
+ // and will be one of the last views.
+ for (int i = dragLayer.getChildCount() - 1; i >= 0; i--) {
+ View child = dragLayer.getChildAt(i);
+ if (child instanceof DragView) {
+ dragLayer.removeView(child);
+ }
+ }
+ }
}
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index 891651996b..512fa1c27c 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -88,10 +88,10 @@ import com.android.launcher3.logger.LauncherAtom.FromState;
import com.android.launcher3.logger.LauncherAtom.ToState;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.logging.StatsLogManager.StatsLogger;
-import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.FolderInfo;
import com.android.launcher3.model.data.FolderInfo.FolderListener;
import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.model.data.WorkspaceItemFactory;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.pageindicators.PageIndicatorDots;
import com.android.launcher3.util.Executors;
@@ -1283,9 +1283,9 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
final WorkspaceItemInfo si;
if (pasiSi != null) {
si = pasiSi;
- } else if (d.dragInfo instanceof AppInfo) {
+ } else if (d.dragInfo instanceof WorkspaceItemFactory) {
// Came from all apps -- make a copy.
- si = ((AppInfo) d.dragInfo).makeWorkspaceItem();
+ si = ((WorkspaceItemFactory) d.dragInfo).makeWorkspaceItem(launcher);
} else {
// WorkspaceItemInfo
si = (WorkspaceItemInfo) d.dragInfo;
diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java
index 5fe2435e4a..b1e27019c3 100644
--- a/src/com/android/launcher3/folder/FolderIcon.java
+++ b/src/com/android/launcher3/folder/FolderIcon.java
@@ -68,11 +68,11 @@ import com.android.launcher3.logger.LauncherAtom.FromState;
import com.android.launcher3.logger.LauncherAtom.ToState;
import com.android.launcher3.logging.InstanceId;
import com.android.launcher3.logging.StatsLogManager;
-import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.FolderInfo;
import com.android.launcher3.model.data.FolderInfo.FolderListener;
import com.android.launcher3.model.data.FolderInfo.LabelState;
import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.model.data.WorkspaceItemFactory;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.touch.ItemClickHandler;
import com.android.launcher3.util.Executors;
@@ -284,7 +284,7 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel
mBackground.animateToAccept(cl, lp.cellX, lp.cellY);
mOpenAlarm.setOnAlarmListener(mOnOpenListener);
if (SPRING_LOADING_ENABLED &&
- ((dragInfo instanceof AppInfo)
+ ((dragInfo instanceof WorkspaceItemFactory)
|| (dragInfo instanceof WorkspaceItemInfo)
|| (dragInfo instanceof PendingAddShortcutInfo))) {
mOpenAlarm.setAlarm(ON_OPEN_DELAY);
@@ -486,9 +486,9 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel
public void onDrop(DragObject d, boolean itemReturnedOnFailedDrop) {
WorkspaceItemInfo item;
- if (d.dragInfo instanceof AppInfo) {
+ if (d.dragInfo instanceof WorkspaceItemFactory) {
// Came from all apps -- make a copy
- item = ((AppInfo) d.dragInfo).makeWorkspaceItem();
+ item = ((WorkspaceItemFactory) d.dragInfo).makeWorkspaceItem(getContext());
} else if (d.dragSource instanceof BaseItemDragListener){
// Came from a different window -- make a copy
item = new WorkspaceItemInfo((WorkspaceItemInfo) d.dragInfo);
@@ -637,7 +637,7 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel
// If we are animating to the accepting state, animate the dot out.
mDotParams.scale = Math.max(0, mDotScale - mBackground.getScaleProgress());
- mDotParams.color = mBackground.getDotColor();
+ mDotParams.dotColor = mBackground.getDotColor();
mDotRenderer.draw(canvas, mDotParams);
}
}
diff --git a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
index ca91296ba6..31ef2e5ea6 100644
--- a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
+++ b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
@@ -32,6 +32,7 @@ import com.android.launcher3.model.data.AppInfo;
import com.android.launcher3.model.data.FolderInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.LauncherAppWidgetInfo;
+import com.android.launcher3.model.data.WorkspaceItemFactory;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.pm.InstallSessionHelper;
import com.android.launcher3.pm.PackageInstallInfo;
@@ -107,8 +108,8 @@ public class AddWorkspaceItemsTask extends BaseModelUpdateTask {
}
if (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
- if (item instanceof AppInfo) {
- item = ((AppInfo) item).makeWorkspaceItem();
+ if (item instanceof WorkspaceItemFactory) {
+ item = ((WorkspaceItemFactory) item).makeWorkspaceItem(app.getContext());
}
}
if (item != null) {
@@ -130,8 +131,8 @@ public class AddWorkspaceItemsTask extends BaseModelUpdateTask {
if (item instanceof WorkspaceItemInfo || item instanceof FolderInfo ||
item instanceof LauncherAppWidgetInfo) {
itemInfo = item;
- } else if (item instanceof AppInfo) {
- itemInfo = ((AppInfo) item).makeWorkspaceItem();
+ } else if (item instanceof WorkspaceItemFactory) {
+ itemInfo = ((WorkspaceItemFactory) item).makeWorkspaceItem(app.getContext());
} else {
throw new RuntimeException("Unexpected info type");
}
@@ -180,7 +181,7 @@ public class AddWorkspaceItemsTask extends BaseModelUpdateTask {
// App was installed while launcher was in the background,
// or app was already installed for another user.
itemInfo = new AppInfo(app.getContext(), activities.get(0), item.user)
- .makeWorkspaceItem();
+ .makeWorkspaceItem(app.getContext());
if (shortcutExists(dataModel, itemInfo.getIntent(), itemInfo.user)) {
// We need this additional check here since we treat all auto added
diff --git a/src/com/android/launcher3/model/data/AppInfo.java b/src/com/android/launcher3/model/data/AppInfo.java
index 7f70bade3c..5b2bcf5819 100644
--- a/src/com/android/launcher3/model/data/AppInfo.java
+++ b/src/com/android/launcher3/model/data/AppInfo.java
@@ -35,7 +35,6 @@ import androidx.annotation.VisibleForTesting;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.Utilities;
import com.android.launcher3.pm.PackageInstallInfo;
-import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.PackageManagerHelper;
import java.util.Comparator;
@@ -43,7 +42,7 @@ import java.util.Comparator;
/**
* Represents an app in AllAppsView.
*/
-public class AppInfo extends ItemInfoWithIcon {
+public class AppInfo extends ItemInfoWithIcon implements WorkspaceItemFactory {
public static final AppInfo[] EMPTY_ARRAY = new AppInfo[0];
public static final Comparator COMPONENT_KEY_COMPARATOR = (a, b) -> {
@@ -121,7 +120,8 @@ public class AppInfo extends ItemInfoWithIcon {
return super.dumpProperties() + " componentName=" + componentName;
}
- public WorkspaceItemInfo makeWorkspaceItem() {
+ @Override
+ public WorkspaceItemInfo makeWorkspaceItem(Context context) {
WorkspaceItemInfo workspaceItemInfo = new WorkspaceItemInfo(this);
if ((runtimeStatusFlags & FLAG_INSTALL_SESSION_ACTIVE) != 0) {
@@ -139,10 +139,6 @@ public class AppInfo extends ItemInfoWithIcon {
return workspaceItemInfo;
}
- public ComponentKey toComponentKey() {
- return new ComponentKey(componentName, user);
- }
-
public static Intent makeLaunchIntent(LauncherActivityInfo info) {
return makeLaunchIntent(info.getComponentName());
}
diff --git a/src/com/android/launcher3/model/data/SearchActionItemInfo.java b/src/com/android/launcher3/model/data/SearchActionItemInfo.java
index cc22601a6a..e879313f5e 100644
--- a/src/com/android/launcher3/model/data/SearchActionItemInfo.java
+++ b/src/com/android/launcher3/model/data/SearchActionItemInfo.java
@@ -18,6 +18,7 @@ package com.android.launcher3.model.data;
import static com.android.launcher3.LauncherSettings.Favorites.EXTENDED_CONTAINERS;
import android.app.PendingIntent;
+import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Icon;
import android.os.Process;
@@ -26,18 +27,14 @@ import android.os.UserHandle;
import androidx.annotation.Nullable;
import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.LauncherModel;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.logger.LauncherAtom.ItemInfo;
import com.android.launcher3.logger.LauncherAtom.SearchActionItem;
-import com.android.launcher3.model.AllAppsList;
-import com.android.launcher3.model.BaseModelUpdateTask;
-import com.android.launcher3.model.BgDataModel;
/**
* Represents a SearchAction with in launcher
*/
-public class SearchActionItemInfo extends ItemInfoWithIcon {
+public class SearchActionItemInfo extends ItemInfoWithIcon implements WorkspaceItemFactory {
public static final int FLAG_SHOULD_START = 1 << 1;
public static final int FLAG_SHOULD_START_FOR_RESULT = FLAG_SHOULD_START | 1 << 2;
@@ -158,7 +155,8 @@ public class SearchActionItemInfo extends ItemInfoWithIcon {
/**
* Creates a {@link WorkspaceItemInfo} coorsponding to search action to be stored in launcher db
*/
- public WorkspaceItemInfo createWorkspaceItem(LauncherModel model) {
+ @Override
+ public WorkspaceItemInfo makeWorkspaceItem(Context context) {
WorkspaceItemInfo info = new WorkspaceItemInfo();
info.title = title;
info.bitmap = bitmap;
@@ -167,18 +165,12 @@ public class SearchActionItemInfo extends ItemInfoWithIcon {
if (hasFlags(FLAG_SHOULD_START_FOR_RESULT)) {
info.options |= WorkspaceItemInfo.FLAG_START_FOR_RESULT;
}
-
- model.enqueueModelUpdateTask(new BaseModelUpdateTask() {
- @Override
- public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) {
-
- model.updateAndBindWorkspaceItem(() -> {
- PackageItemInfo pkgInfo = new PackageItemInfo(getIntentPackageName(), user);
- app.getIconCache().getTitleAndIconForApp(pkgInfo, false);
- info.bitmap = info.bitmap.withBadgeInfo(pkgInfo.bitmap);
- return info;
- });
- }
+ LauncherAppState app = LauncherAppState.getInstance(context);
+ app.getModel().updateAndBindWorkspaceItem(() -> {
+ PackageItemInfo pkgInfo = new PackageItemInfo(getIntentPackageName(), user);
+ app.getIconCache().getTitleAndIconForApp(pkgInfo, false);
+ info.bitmap = info.bitmap.withBadgeInfo(pkgInfo.bitmap);
+ return info;
});
return info;
}
diff --git a/src/com/android/launcher3/model/data/WorkspaceItemFactory.java b/src/com/android/launcher3/model/data/WorkspaceItemFactory.java
new file mode 100644
index 0000000000..47b9c6e443
--- /dev/null
+++ b/src/com/android/launcher3/model/data/WorkspaceItemFactory.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.model.data;
+
+import android.content.Context;
+
+/**
+ * Interface to objects capable of generating workspace item
+ */
+public interface WorkspaceItemFactory {
+
+ /**
+ * Called to create a pinnable item info
+ */
+ WorkspaceItemInfo makeWorkspaceItem(Context context);
+}
diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
index 484b879f24..49d97d21c1 100644
--- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java
+++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
@@ -187,7 +187,10 @@ public class PopupContainerWithArrow
/**
* Returns true if we can show the container.
+ *
+ * @deprecated Left here since some dependent projects are using this method
*/
+ @Deprecated
public static boolean canShow(View icon, ItemInfo item) {
return icon instanceof BubbleTextView && ShortcutUtil.supportsShortcuts(item);
}
@@ -204,7 +207,7 @@ public class PopupContainerWithArrow
return null;
}
ItemInfo item = (ItemInfo) icon.getTag();
- if (!canShow(icon, item)) {
+ if (!ShortcutUtil.supportsShortcuts(item)) {
return null;
}
@@ -538,7 +541,7 @@ public class PopupContainerWithArrow
public static void dismissInvalidPopup(BaseDraggingActivity activity) {
PopupContainerWithArrow popup = getOpen(activity);
if (popup != null && (!popup.mOriginalIcon.isAttachedToWindow()
- || !canShow(popup.mOriginalIcon, (ItemInfo) popup.mOriginalIcon.getTag()))) {
+ || !ShortcutUtil.supportsShortcuts((ItemInfo) popup.mOriginalIcon.getTag()))) {
popup.animateClose();
}
}
diff --git a/src/com/android/launcher3/statemanager/StateManager.java b/src/com/android/launcher3/statemanager/StateManager.java
index 2aa9ddeb50..9f50ff9d84 100644
--- a/src/com/android/launcher3/statemanager/StateManager.java
+++ b/src/com/android/launcher3/statemanager/StateManager.java
@@ -335,7 +335,13 @@ public class StateManager> {
@Override
public void onAnimationStart(Animator animation) {
// Change the internal state only when the transition actually starts
- onStateTransitionStart(state);
+ onStateTransitionStart(mCancelled ? mCurrentStableState : state);
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ super.onAnimationCancel(animation);
+ mState = mCurrentStableState;
}
@Override
diff --git a/src/com/android/launcher3/states/SpringLoadedState.java b/src/com/android/launcher3/states/SpringLoadedState.java
index 15cdc20cef..a205ab55ca 100644
--- a/src/com/android/launcher3/states/SpringLoadedState.java
+++ b/src/com/android/launcher3/states/SpringLoadedState.java
@@ -51,7 +51,7 @@ public class SpringLoadedState extends LauncherState {
return super.getWorkspaceScaleAndTranslation(launcher);
}
- float shrunkTop = grid.getWorkspaceSpringLoadShrunkTop();
+ float shrunkTop = grid.getCellLayoutSpringLoadShrunkTop();
float scale = grid.getWorkspaceSpringLoadScale();
float halfHeight = ws.getHeight() / 2;
diff --git a/src/com/android/launcher3/touch/ItemClickHandler.java b/src/com/android/launcher3/touch/ItemClickHandler.java
index cd00f15011..c4d2bc44c8 100644
--- a/src/com/android/launcher3/touch/ItemClickHandler.java
+++ b/src/com/android/launcher3/touch/ItemClickHandler.java
@@ -100,8 +100,7 @@ public class ItemClickHandler {
onClickFolderIcon(v);
}
} else if (tag instanceof AppInfo) {
- startAppShortcutOrInfoActivity(v, (AppInfo) tag, launcher
- );
+ startAppShortcutOrInfoActivity(v, (AppInfo) tag, launcher);
} else if (tag instanceof LauncherAppWidgetInfo) {
if (v instanceof PendingAppWidgetHostView) {
onClickPendingWidget((PendingAppWidgetHostView) v, launcher);
diff --git a/src/com/android/launcher3/touch/ItemLongClickListener.java b/src/com/android/launcher3/touch/ItemLongClickListener.java
index f876dd9230..6bae745ef8 100644
--- a/src/com/android/launcher3/touch/ItemLongClickListener.java
+++ b/src/com/android/launcher3/touch/ItemLongClickListener.java
@@ -37,6 +37,7 @@ import com.android.launcher3.logging.StatsLogManager.StatsLogger;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.TestProtocol;
+import com.android.launcher3.views.BubbleTextHolder;
/**
* Class to handle long-clicks on workspace items and start drag as a result.
@@ -79,9 +80,12 @@ public class ItemLongClickListener {
launcher.getWorkspace().startDrag(longClickCellInfo, dragOptions);
}
- private static boolean onAllAppsItemLongClick(View v) {
+ private static boolean onAllAppsItemLongClick(View view) {
TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "onAllAppsItemLongClick");
- v.cancelLongPress();
+ view.cancelLongPress();
+ View v = (view instanceof BubbleTextHolder)
+ ? ((BubbleTextHolder) view).getBubbleText()
+ : view;
Launcher launcher = Launcher.getLauncher(v.getContext());
if (!canStartDrag(launcher)) return false;
// When we have exited all apps or are in transition, disregard long clicks
diff --git a/src/com/android/launcher3/util/DisplayController.java b/src/com/android/launcher3/util/DisplayController.java
index 777da23e86..7c73be51c6 100644
--- a/src/com/android/launcher3/util/DisplayController.java
+++ b/src/com/android/launcher3/util/DisplayController.java
@@ -290,7 +290,7 @@ public class DisplayController implements ComponentCallbacks, SafeCloseable {
// Configuration property
public final float fontScale;
- public final int densityDpi;
+ private final int densityDpi;
public final NavigationMode navigationMode;
private final PortraitSize mScreenSizeDp;
@@ -357,6 +357,10 @@ public class DisplayController implements ComponentCallbacks, SafeCloseable {
public float smallestSizeDp(WindowBounds bounds) {
return dpiFromPx(Math.min(bounds.bounds.width(), bounds.bounds.height()), densityDpi);
}
+
+ public int getDensityDpi() {
+ return densityDpi;
+ }
}
/**
diff --git a/src/com/android/launcher3/views/BubbleTextHolder.java b/src/com/android/launcher3/views/BubbleTextHolder.java
index 76c465cbc8..84f8049ded 100644
--- a/src/com/android/launcher3/views/BubbleTextHolder.java
+++ b/src/com/android/launcher3/views/BubbleTextHolder.java
@@ -16,8 +16,6 @@
package com.android.launcher3.views;
import com.android.launcher3.BubbleTextView;
-import com.android.launcher3.model.data.ItemInfo;
-import com.android.launcher3.model.data.ItemInfoWithIcon;
/**
* Views that contain {@link BubbleTextView} should implement this interface.
@@ -25,14 +23,6 @@ import com.android.launcher3.model.data.ItemInfoWithIcon;
public interface BubbleTextHolder extends IconLabelDotView {
BubbleTextView getBubbleText();
- /**
- * Called when new {@link ItemInfo} is set to {@link BubbleTextView}
- *
- * @param itemInfo the new itemInfo
- */
- default void onItemInfoUpdated(ItemInfoWithIcon itemInfo) {
- }
-
@Override
default void setIconVisible(boolean visible) {
getBubbleText().setIconVisible(visible);
diff --git a/src/com/android/launcher3/views/RecyclerViewFastScroller.java b/src/com/android/launcher3/views/RecyclerViewFastScroller.java
index a982786972..7a8e9d520e 100644
--- a/src/com/android/launcher3/views/RecyclerViewFastScroller.java
+++ b/src/com/android/launcher3/views/RecyclerViewFastScroller.java
@@ -20,6 +20,8 @@ import static android.view.HapticFeedbackConstants.CLOCK_TICK;
import static androidx.recyclerview.widget.RecyclerView.SCROLL_STATE_IDLE;
+import static com.android.launcher3.util.UiThreadHelper.hideKeyboardAsync;
+
import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.Resources;
@@ -283,6 +285,9 @@ public class RecyclerViewFastScroller extends View {
}
break;
case MotionEvent.ACTION_UP:
+ hideKeyboardAsync(ActivityContext.lookupContext(getContext()),
+ getApplicationWindowToken());
+ break;
case MotionEvent.ACTION_CANCEL:
mRv.onFastScrollCompleted();
mTouchOffsetY = 0;
diff --git a/tests/src/com/android/launcher3/DeviceProfileBaseTest.kt b/tests/src/com/android/launcher3/DeviceProfileBaseTest.kt
index f91f1c4288..6d0fcb6faa 100644
--- a/tests/src/com/android/launcher3/DeviceProfileBaseTest.kt
+++ b/tests/src/com/android/launcher3/DeviceProfileBaseTest.kt
@@ -64,6 +64,7 @@ abstract class DeviceProfileBaseTest {
windowBounds = WindowBounds(x, y, x, y - 100, 0)
whenever(info.isTablet(any())).thenReturn(false)
+ whenever(info.getDensityDpi()).thenReturn(560)
inv = newScalableInvariantDeviceProfile()
}
@@ -77,6 +78,7 @@ abstract class DeviceProfileBaseTest {
windowBounds = WindowBounds(x, y, x, y - 100, 0)
whenever(info.isTablet(any())).thenReturn(true)
+ whenever(info.getDensityDpi()).thenReturn(320)
inv = newScalableInvariantDeviceProfile()
}
@@ -107,6 +109,7 @@ abstract class DeviceProfileBaseTest {
PointF(16f, 16f)
).toTypedArray()
hotseatBorderSpaces = FloatArray(4) { 16f }
+ hotseatColumnSpan = IntArray(4) { 4 }
iconSize = FloatArray(4) { 56f }
allAppsIconSize = FloatArray(4) { 56f }
iconTextSize = FloatArray(4) { 14f }
diff --git a/tests/src/com/android/launcher3/DeviceProfileGridDimensionsTest.kt b/tests/src/com/android/launcher3/DeviceProfileGridDimensionsTest.kt
new file mode 100644
index 0000000000..80259a59b4
--- /dev/null
+++ b/tests/src/com/android/launcher3/DeviceProfileGridDimensionsTest.kt
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3
+
+import android.graphics.PointF
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.launcher3.util.WindowBounds
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers
+import org.mockito.Mockito.`when` as whenever
+
+/**
+ * Test for [DeviceProfile] grid dimensions.
+ *
+ * This includes workspace, cell layout, shortcut and widget container, cell sizes, etc.
+ */
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class DeviceProfileGridDimensionsTest : DeviceProfileBaseTest() {
+
+ @Test
+ fun getCellLayoutWidth_twoPanelLandscapeScalable4By4GridTablet_equalsSinglePanelWidth() {
+ val tabletWidth = 2560
+ val tabletHeight = 1600
+ val availableWidth = 2560
+ val availableHeight = 1500
+ windowBounds = WindowBounds(tabletWidth, tabletHeight, availableWidth, availableHeight, 0)
+ useTwoPanels = true
+ whenever(info.isTablet(ArgumentMatchers.any())).thenReturn(true)
+ whenever(info.densityDpi).thenReturn(320)
+ inv = newScalableInvariantDeviceProfile()
+
+ val dp = newDP()
+
+ val expectedWorkspaceWidth = availableWidth
+ val expectedCellLayoutWidth =
+ (expectedWorkspaceWidth - (dp.workspacePadding.right + dp.workspacePadding.left)) /
+ dp.panelCount
+ assertThat(dp.cellLayoutWidth).isEqualTo(expectedCellLayoutWidth)
+ }
+
+ @Test
+ fun getCellLayoutHeight_twoPanelLandscapeScalable4By4GridTablet_equalsSinglePanelHeight() {
+ val tabletWidth = 2560
+ val tabletHeight = 1600
+ val availableWidth = 2560
+ val availableHeight = 1500
+ windowBounds = WindowBounds(tabletWidth, tabletHeight, availableWidth, availableHeight, 0)
+ useTwoPanels = true
+ whenever(info.isTablet(ArgumentMatchers.any())).thenReturn(true)
+ whenever(info.densityDpi).thenReturn(320)
+ inv = newScalableInvariantDeviceProfile()
+
+ val dp = newDP()
+
+ val expectedWorkspaceHeight = availableHeight
+ val expectedCellLayoutHeight =
+ expectedWorkspaceHeight - (dp.workspacePadding.top + dp.workspacePadding.bottom)
+ assertThat(dp.cellLayoutHeight).isEqualTo(expectedCellLayoutHeight)
+ }
+
+ @Test
+ fun getCellSize_twoPanelLandscapeScalable4By4GridTablet_equalsSinglePanelWidth() {
+ val tabletWidth = 2560
+ val tabletHeight = 1600
+ val availableWidth = 2560
+ val availableHeight = 1500
+ windowBounds = WindowBounds(tabletWidth, tabletHeight, availableWidth, availableHeight, 0)
+ useTwoPanels = true
+ whenever(info.isTablet(ArgumentMatchers.any())).thenReturn(true)
+ whenever(info.densityDpi).thenReturn(320)
+ inv = newScalableInvariantDeviceProfile()
+
+ val dp = newDP()
+
+ val expectedWorkspaceWidth = availableWidth
+ val expectedCellLayoutWidth =
+ (expectedWorkspaceWidth - (dp.workspacePadding.right + dp.workspacePadding.left)) /
+ dp.panelCount
+ val expectedShortcutAndWidgetContainerWidth =
+ expectedCellLayoutWidth -
+ (dp.cellLayoutPaddingPx.left + dp.cellLayoutPaddingPx.right)
+ assertThat(dp.getCellSize().x).isEqualTo(
+ (expectedShortcutAndWidgetContainerWidth -
+ ((inv!!.numColumns - 1) * dp.cellLayoutBorderSpacePx.x)) / inv!!.numColumns)
+ val expectedWorkspaceHeight = availableHeight
+ val expectedCellLayoutHeight =
+ expectedWorkspaceHeight - (dp.workspacePadding.top + dp.workspacePadding.bottom)
+ val expectedShortcutAndWidgetContainerHeight = expectedCellLayoutHeight -
+ (dp.cellLayoutPaddingPx.top + dp.cellLayoutPaddingPx.bottom)
+ assertThat(dp.getCellSize().y).isEqualTo(
+ (expectedShortcutAndWidgetContainerHeight -
+ ((inv!!.numRows - 1) * dp.cellLayoutBorderSpacePx.y)) / inv!!.numRows)
+ }
+
+ @Test
+ fun getPanelCount_twoPanelLandscapeScalable4By4GridTablet_equalsTwoPanels() {
+ val tabletWidth = 2560
+ val tabletHeight = 1600
+ val availableWidth = 2560
+ val availableHeight = 1500
+ windowBounds = WindowBounds(tabletWidth, tabletHeight, availableWidth, availableHeight, 0)
+ useTwoPanels = true
+ whenever(info.isTablet(ArgumentMatchers.any())).thenReturn(true)
+ whenever(info.densityDpi).thenReturn(320)
+ inv = newScalableInvariantDeviceProfile()
+
+ val dp = newDP()
+
+ assertThat(dp.panelCount).isEqualTo(2)
+ }
+}
\ No newline at end of file
diff --git a/tests/src/com/android/launcher3/HotseatSizeTest.kt b/tests/src/com/android/launcher3/HotseatShownIconsTest.kt
similarity index 97%
rename from tests/src/com/android/launcher3/HotseatSizeTest.kt
rename to tests/src/com/android/launcher3/HotseatShownIconsTest.kt
index a44939f4cf..593239d6f7 100644
--- a/tests/src/com/android/launcher3/HotseatSizeTest.kt
+++ b/tests/src/com/android/launcher3/HotseatShownIconsTest.kt
@@ -23,15 +23,13 @@ import com.android.launcher3.InvariantDeviceProfile.TYPE_TABLET
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
-import org.mockito.ArgumentMatchers
-import org.mockito.Mockito.`when` as whenever
/**
* Test for [DeviceProfile]
*/
@SmallTest
@RunWith(AndroidJUnit4::class)
-class HotseatSizeTest : DeviceProfileBaseTest() {
+class HotseatShownIconsTest : DeviceProfileBaseTest() {
@Test
fun hotseat_size_is_normal_for_handhelds() {
diff --git a/tests/src/com/android/launcher3/InlineQsbTest.kt b/tests/src/com/android/launcher3/InlineQsbTest.kt
index e00dca86e2..905c1e1a0f 100644
--- a/tests/src/com/android/launcher3/InlineQsbTest.kt
+++ b/tests/src/com/android/launcher3/InlineQsbTest.kt
@@ -29,17 +29,16 @@ import org.junit.runner.RunWith
class InlineQsbTest : DeviceProfileBaseTest() {
@Test
- fun qsbWidth_is_match_parent_for_phones() {
+ fun qsb_is_not_inline_for_phones() {
initializeVarsForPhone()
val dp = newDP()
assertThat(dp.isQsbInline).isFalse()
- assertThat(dp.qsbWidth).isEqualTo(0)
}
@Test
- fun qsbWidth_is_match_parent_for_tablet_portrait() {
+ fun qsb_is_inline_for_tablet_portrait() {
initializeVarsForTablet()
inv = newScalableInvariantDeviceProfile().apply {
inlineQsb = booleanArrayOf(
@@ -62,11 +61,10 @@ class InlineQsbTest : DeviceProfileBaseTest() {
)
assertThat(dp.isQsbInline).isFalse()
- assertThat(dp.qsbWidth).isEqualTo(0)
}
@Test
- fun qsbWidth_has_size_for_tablet_landscape() {
+ fun qsb_is_inline_for_tablet_landscape() {
initializeVarsForTablet(isLandscape = true)
inv = newScalableInvariantDeviceProfile().apply {
inlineQsb = booleanArrayOf(
@@ -75,16 +73,17 @@ class InlineQsbTest : DeviceProfileBaseTest() {
false,
false
)
+ numColumns = 6
+ numRows = 5
+ numShownHotseatIcons = 6
}
val dp = newDP()
if (dp.hotseatQsbHeight > 0) {
assertThat(dp.isQsbInline).isTrue()
- assertThat(dp.qsbWidth).isGreaterThan(0)
} else { // Launcher3 doesn't have QSB height
assertThat(dp.isQsbInline).isFalse()
- assertThat(dp.qsbWidth).isEqualTo(0)
}
}
@@ -92,14 +91,13 @@ class InlineQsbTest : DeviceProfileBaseTest() {
* This test is to make sure that a tablet doesn't inline the QSB if the layout doesn't support
*/
@Test
- fun qsbWidth_is_match_parent_for_tablet_landscape_without_inline() {
+ fun qsb_is_not_inline_for_tablet_landscape_without_inline() {
initializeVarsForTablet(isLandscape = true)
useTwoPanels = true
val dp = newDP()
assertThat(dp.isQsbInline).isFalse()
- assertThat(dp.qsbWidth).isEqualTo(0)
}
}
\ No newline at end of file
diff --git a/tests/src/com/android/launcher3/deviceemulator/models/DeviceEmulationData.java b/tests/src/com/android/launcher3/deviceemulator/models/DeviceEmulationData.java
index 36235134f5..8d275cc04b 100644
--- a/tests/src/com/android/launcher3/deviceemulator/models/DeviceEmulationData.java
+++ b/tests/src/com/android/launcher3/deviceemulator/models/DeviceEmulationData.java
@@ -135,7 +135,7 @@ public class DeviceEmulationData {
resourceOverrides.put(s, getDimenByName(s, context.getResources(), 0));
}
return new DeviceEmulationData(info.currentSize.x, info.currentSize.y,
- info.densityDpi, info.cutout, code, grids, resourceOverrides);
+ info.getDensityDpi(), info.cutout, code, grids, resourceOverrides);
}
public static DeviceEmulationData getDevice(String deviceCode) throws Exception {
diff --git a/tests/tapl/com/android/launcher3/tapl/Launchable.java b/tests/tapl/com/android/launcher3/tapl/Launchable.java
index 39cd4ffeff..252627238b 100644
--- a/tests/tapl/com/android/launcher3/tapl/Launchable.java
+++ b/tests/tapl/com/android/launcher3/tapl/Launchable.java
@@ -16,8 +16,6 @@
package com.android.launcher3.tapl;
-import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
-
import static com.android.launcher3.testing.TestProtocol.SPRING_LOADED_STATE_ORDINAL;
import android.graphics.Point;
@@ -64,35 +62,25 @@ public abstract class Launchable {
protected abstract String launchableType();
private LaunchedAppState launch(BySelector selector) {
- try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+ try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
"want to launch an app from " + launchableType())) {
LauncherInstrumentation.log("Launchable.launch before click "
+ mObject.getVisibleCenter() + " in " + mLauncher.getVisibleBounds(mObject));
final String label = mObject.getText();
- executeAndWaitForWindowChange(() -> {
- mLauncher.clickLauncherObject(mObject);
- expectActivityStartEvents();
- }, label, "clicking " + launchableType());
+ mLauncher.clickLauncherObject(mObject);
- try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer("clicked")) {
+ try (LauncherInstrumentation.Closable c2 = mLauncher.addContextLayer("clicked")) {
+ expectActivityStartEvents();
return assertAppLaunched(label, selector);
}
}
}
- protected void executeAndWaitForWindowChange(Runnable command, String label, String action) {
- mLauncher.executeAndWaitForEvent(
- command,
- event -> event.getEventType() == TYPE_WINDOW_STATE_CHANGED,
- () -> "Launching an app didn't open a new window: " + label,
- action);
- }
-
protected LaunchedAppState assertAppLaunched(String label, BySelector selector) {
mLauncher.assertTrue(
"App didn't start: " + label + " (" + selector + ")",
- TestHelpers.wait(Until.hasObject(selector),
+ mLauncher.getDevice().wait(Until.hasObject(selector),
LauncherInstrumentation.WAIT_TIME_MS));
return new LaunchedAppState(mLauncher);
}
diff --git a/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java b/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java
index 2033a42798..face02acf5 100644
--- a/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java
+++ b/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java
@@ -129,42 +129,25 @@ public final class LaunchedAppState extends Background {
try (LauncherInstrumentation.Closable c3 = launcher.addContextLayer(
"moved pointer to drop point")) {
- dropDraggedItem(
- launcher,
- launchable,
- expectedNewPackageName,
- endPoint, downTime,
- itemVisibleCenter,
- itemVisibleBounds,
- itemLabel,
- expectedExistingPackageName);
+ LauncherInstrumentation.log("SplitscreenDragSource.dragToSplitscreen: "
+ + "before drop " + itemVisibleCenter + " in " + itemVisibleBounds);
+ launcher.sendPointer(
+ downTime,
+ SystemClock.uptimeMillis(),
+ MotionEvent.ACTION_UP,
+ endPoint,
+ LauncherInstrumentation.GestureScope.INSIDE_TO_OUTSIDE_WITHOUT_PILFER);
+ LauncherInstrumentation.log("SplitscreenDragSource.dragToSplitscreen: "
+ + "after drop");
+
+ try (LauncherInstrumentation.Closable c4 = launcher.addContextLayer(
+ "dropped item")) {
+ launchable.assertAppLaunched(itemLabel, By.pkg(expectedNewPackageName));
+ launchable.assertAppLaunched(
+ itemLabel, By.pkg(expectedExistingPackageName));
+ }
}
}
}
}
-
- private static void dropDraggedItem(
- LauncherInstrumentation launcher, Launchable launchable, String expectedNewPackageName,
- Point endPoint, long downTime, Point itemVisibleCenter, Rect itemVisibleBounds,
- String itemLabel, String expectedExistingPackageName) {
- LauncherInstrumentation.log("SplitscreenDragSource.dragToSplitscreen before drop "
- + itemVisibleCenter + " in " + itemVisibleBounds);
-
- launchable.executeAndWaitForWindowChange(() -> {
- launcher.sendPointer(
- downTime,
- SystemClock.uptimeMillis(),
- MotionEvent.ACTION_UP,
- endPoint,
- LauncherInstrumentation.GestureScope.INSIDE_TO_OUTSIDE_WITHOUT_PILFER);
- LauncherInstrumentation.log("SplitscreenDragSource.dragToSplitscreen: after "
- + "drop");
- }, itemLabel, "dropping taskbar item");
-
- try (LauncherInstrumentation.Closable c = launcher.addContextLayer("dropped item")) {
- launchable.assertAppLaunched(itemLabel, By.pkg(expectedNewPackageName));
- launcher.checkPackagesVisible(
- new String[] {expectedNewPackageName, expectedExistingPackageName});
- }
- }
}
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index 2b3583e5f0..6fcd7d8de6 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -84,7 +84,6 @@ import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
-import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Consumer;
@@ -92,7 +91,6 @@ import java.util.function.Function;
import java.util.function.Supplier;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
-import java.util.stream.Stream;
/**
* The main tapl object. The only object that can be explicitly constructed by the using code. It
@@ -501,29 +499,16 @@ public final class LauncherInstrumentation {
}
}
- void checkPackagesVisible(String[] expectedVisiblePackages) {
- Set actualVisiblePackages =
- getVisiblePackagesStream().collect(Collectors.toSet());
-
- for (String expectedVisible : expectedVisiblePackages) {
- assertTrue("Expected package not visible: " + expectedVisible,
- actualVisiblePackages.contains(expectedVisible));
- }
- }
-
private String getVisiblePackages() {
- final String apps = getVisiblePackagesStream().collect(Collectors.joining(", "));
- return !apps.isEmpty()
- ? "active app: " + apps
- : "the test doesn't see views from any app, including Launcher";
- }
-
- private Stream getVisiblePackagesStream() {
- return mDevice.findObjects(getAnyObjectSelector())
+ final String apps = mDevice.findObjects(getAnyObjectSelector())
.stream()
.map(LauncherInstrumentation::getApplicationPackageSafe)
.distinct()
- .filter(pkg -> pkg != null && !SYSTEMUI_PACKAGE.equals(pkg));
+ .filter(pkg -> pkg != null && !SYSTEMUI_PACKAGE.equals(pkg))
+ .collect(Collectors.joining(", "));
+ return !apps.isEmpty()
+ ? "active app: " + apps
+ : "the test doesn't see views from any app, including Launcher";
}
private static String getApplicationPackageSafe(UiObject2 object) {
diff --git a/tests/tapl/com/android/launcher3/tapl/OptionsPopupMenuItem.java b/tests/tapl/com/android/launcher3/tapl/OptionsPopupMenuItem.java
deleted file mode 100644
index 42b6bc9b3a..0000000000
--- a/tests/tapl/com/android/launcher3/tapl/OptionsPopupMenuItem.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2020 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.annotation.NonNull;
-import androidx.test.uiautomator.By;
-import androidx.test.uiautomator.UiObject2;
-import androidx.test.uiautomator.Until;
-
-import com.android.launcher3.testing.TestProtocol;
-
-public class OptionsPopupMenuItem {
-
- private final LauncherInstrumentation mLauncher;
- private final UiObject2 mObject;
-
- OptionsPopupMenuItem(@NonNull LauncherInstrumentation launcher, @NonNull UiObject2 shortcut) {
- mLauncher = launcher;
- mObject = shortcut;
- }
-
- /**
- * Clicks the option.
- */
- @NonNull
- public void launch(@NonNull String expectedPackageName) {
- try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
- LauncherInstrumentation.log("OptionsPopupMenuItem before click "
- + mObject.getVisibleCenter() + " in " + mLauncher.getVisibleBounds(mObject));
- mLauncher.clickLauncherObject(mObject);
- mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, LauncherInstrumentation.EVENT_START);
- mLauncher.assertTrue(
- "App didn't start: " + By.pkg(expectedPackageName),
- mLauncher.getDevice().wait(Until.hasObject(By.pkg(expectedPackageName)),
- LauncherInstrumentation.WAIT_TIME_MS));
- }
- }
-}