Merge "Adding the avility to add icons on multiple CellLayouts on tests." into tm-qpr-dev

This commit is contained in:
Sebastián Franco
2023-01-24 20:02:35 +00:00
committed by Android (Google) Code Review
11 changed files with 363 additions and 88 deletions

View File

@@ -201,6 +201,13 @@ public class TestInformationHandler implements ResourceBasedOverride {
});
}
case TestProtocol.REQUEST_WORKSPACE_COLUMNS_ROWS: {
return getLauncherUIProperty(Bundle::putParcelable, launcher -> new Point(
InvariantDeviceProfile.INSTANCE.get(mContext).numColumns,
InvariantDeviceProfile.INSTANCE.get(mContext).numRows)
);
}
case TestProtocol.REQUEST_HOTSEAT_CELL_CENTER: {
final HotseatCellCenterRequest request = extra.getParcelable(
TestProtocol.TEST_INFO_REQUEST_FIELD);

View File

@@ -123,6 +123,7 @@ public final class TestProtocol {
public static final String REQUEST_WORKSPACE_CELL_LAYOUT_SIZE = "workspace-cell-layout-size";
public static final String REQUEST_WORKSPACE_CELL_CENTER = "workspace-cell-center";
public static final String REQUEST_WORKSPACE_COLUMNS_ROWS = "workspace-columns-rows";
public static final String REQUEST_HOTSEAT_CELL_CENTER = "hotseat-cell-center";

View File

@@ -124,7 +124,7 @@ public class WorkspaceCellCenterRequest implements TestInformationRequest {
* Set span Height in cells
*/
public WorkspaceCellCenterRequest.Builder setSpanY(int y) {
this.mCellY = y;
this.mSpanY = y;
return this;
}

View File

@@ -29,7 +29,73 @@ import java.util.Set;
import java.util.stream.Collectors;
public class CellLayoutBoard {
public class CellLayoutBoard implements Comparable<CellLayoutBoard> {
private boolean intersects(Rect r1, Rect r2) {
// If one rectangle is on left side of other
if (r1.left > r2.right || r2.left > r1.right) {
return false;
}
// If one rectangle is above other
if (r1.bottom > r2.top || r2.bottom > r1.top) {
return false;
}
return true;
}
private boolean overlapsWithIgnored(Set<Rect> ignoredRectangles, Rect rect) {
for (Rect ignoredRect : ignoredRectangles) {
// Using the built in intersects doesn't work because it doesn't account for area 0
if (intersects(ignoredRect, rect)) {
return true;
}
}
return false;
}
@Override
public int compareTo(CellLayoutBoard cellLayoutBoard) {
// to be equal they need to have the same number of widgets and the same dimensions
// their order can be different
Set<Rect> widgetsSet = new HashSet<>();
Set<Rect> ignoredRectangles = new HashSet<>();
for (WidgetRect rect : mWidgetsRects) {
if (rect.shouldIgnore()) {
ignoredRectangles.add(rect.mBounds);
} else {
widgetsSet.add(rect.mBounds);
}
}
for (WidgetRect rect : cellLayoutBoard.mWidgetsRects) {
// ignore rectangles overlapping with the area marked by x
if (overlapsWithIgnored(ignoredRectangles, rect.mBounds)) {
continue;
}
if (!widgetsSet.contains(rect.mBounds)) {
return -1;
}
widgetsSet.remove(rect.mBounds);
}
if (!widgetsSet.isEmpty()) {
return 1;
}
// to be equal they need to have the same number of icons their order can be different
Set<Point> iconsSet = new HashSet<>();
mIconPoints.forEach(icon -> iconsSet.add(icon.getCoord()));
for (IconPoint icon : cellLayoutBoard.mIconPoints) {
if (!iconsSet.contains(icon.getCoord())) {
return -1;
}
iconsSet.remove(icon.getCoord());
}
if (!iconsSet.isEmpty()) {
return 1;
}
return 0;
}
public static class CellType {
// The cells marked by this will be filled by 1x1 widgets and will be ignored when
@@ -115,7 +181,7 @@ public class CellLayoutBoard {
List<IconPoint> mIconPoints = new ArrayList<>();
Map<Character, IconPoint> mIconsMap = new HashMap<>();
Point mMain = new Point();
WidgetRect mMain = null;
CellLayoutBoard() {
for (int x = 0; x < mWidget.length; x++) {
@@ -133,7 +199,7 @@ public class CellLayoutBoard {
return mIconPoints;
}
public Point getMain() {
public WidgetRect getMain() {
return mMain;
}
@@ -273,6 +339,16 @@ public class CellLayoutBoard {
return iconPoints;
}
public static WidgetRect getMainFromList(List<CellLayoutBoard> boards) {
for (CellLayoutBoard board : boards) {
WidgetRect main = board.getMain();
if (main != null) {
return main;
}
}
return null;
}
public static CellLayoutBoard boardFromString(String boardStr) {
String[] lines = boardStr.split("\n");
CellLayoutBoard board = new CellLayoutBoard();
@@ -281,17 +357,18 @@ public class CellLayoutBoard {
String line = lines[y];
for (int x = 0; x < line.length(); x++) {
char c = line.charAt(x);
if (c == CellType.MAIN_WIDGET) {
board.mMain = new Point(x, y);
}
if (c != CellType.EMPTY) {
board.mWidget[x][y] = line.charAt(x);
}
}
}
board.mWidgetsRects = getRects(board.mWidget);
board.mWidgetsRects.forEach(
widgetRect -> board.mWidgetsMap.put(widgetRect.mType, widgetRect));
board.mWidgetsRects.forEach(widgetRect -> {
if (widgetRect.mType == CellType.MAIN_WIDGET) {
board.mMain = widgetRect;
}
board.mWidgetsMap.put(widgetRect.mType, widgetRect);
});
board.mIconPoints = getIconPoints(board.mWidget);
return board;
}
@@ -308,4 +385,24 @@ public class CellLayoutBoard {
}
return s.toString();
}
public static List<CellLayoutBoard> boardListFromString(String boardsStr) {
String[] lines = boardsStr.split("\n");
ArrayList<String> individualBoards = new ArrayList<>();
ArrayList<CellLayoutBoard> boards = new ArrayList<>();
for (String line : lines) {
String[] boardSegment = line.split("\\|");
for (int i = 0; i < boardSegment.length; i++) {
if (i >= individualBoards.size()) {
individualBoards.add(boardSegment[i]);
} else {
individualBoards.set(i, individualBoards.get(i) + "\n" + boardSegment[i]);
}
}
}
for (String board : individualBoards) {
boards.add(CellLayoutBoard.boardFromString(board));
}
return boards;
}
}

View File

@@ -0,0 +1,88 @@
/*
* 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.celllayout.testcases;
import android.graphics.Point;
import java.util.Map;
/**
* The grids represent the workspace to be build by TestWorkspaceBuilder, to see what each character
* in the board mean refer to {@code CellType}
*/
public class MultipleCellLayoutsSimpleReorder {
/** 5x5 Test
**/
private static final String START_BOARD_STR_5x5 = ""
+ "xxxxx|-----\n"
+ "--mm-|-----\n"
+ "--mm-|-----\n"
+ "-----|-----\n"
+ "-----|-----";
private static final Point MOVE_TO_5x5 = new Point(8, 3);
private static final String END_BOARD_STR_5x5 = ""
+ "xxxxx|-----\n"
+ "-----|-----\n"
+ "-----|-----\n"
+ "-----|---mm\n"
+ "-----|---mm";
private static final ReorderTestCase TEST_CASE_5x5 = new ReorderTestCase(START_BOARD_STR_5x5,
MOVE_TO_5x5,
END_BOARD_STR_5x5);
/** 4x4 Test
**/
private static final String START_BOARD_STR_4x4 = ""
+ "xxxx|----\n"
+ "--mm|----\n"
+ "--mm|----\n"
+ "----|----";
private static final Point MOVE_TO_4x4 = new Point(5, 3);
private static final String END_BOARD_STR_4x4 = ""
+ "xxxx|----\n"
+ "----|----\n"
+ "----|-mm-\n"
+ "----|-mm-";
private static final ReorderTestCase TEST_CASE_4x4 = new ReorderTestCase(START_BOARD_STR_4x4,
MOVE_TO_4x4,
END_BOARD_STR_4x4);
/** 6x5 Test
**/
private static final String START_BOARD_STR_6x5 = ""
+ "xxxxxx|------\n"
+ "--m---|------\n"
+ "------|------\n"
+ "------|------\n"
+ "------|------";
private static final Point MOVE_TO_6x5 = new Point(10, 4);
private static final String END_BOARD_STR_6x5 = ""
+ "xxxxxx|------\n"
+ "------|------\n"
+ "------|------\n"
+ "------|------\n"
+ "------|----m-";
private static final ReorderTestCase TEST_CASE_6x5 = new ReorderTestCase(START_BOARD_STR_6x5,
MOVE_TO_6x5,
END_BOARD_STR_6x5);
public static final Map<Point, ReorderTestCase> TEST_BY_GRID_SIZE =
Map.of(new Point(5, 5), TEST_CASE_5x5,
new Point(4, 4), TEST_CASE_4x4,
new Point(6, 5), TEST_CASE_6x5);
}

View File

@@ -29,6 +29,7 @@ import com.android.launcher3.CellLayout;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.celllayout.testcases.FullReorderCase;
import com.android.launcher3.celllayout.testcases.MoveOutReorderCase;
import com.android.launcher3.celllayout.testcases.MultipleCellLayoutsSimpleReorder;
import com.android.launcher3.celllayout.testcases.PushReorderCase;
import com.android.launcher3.celllayout.testcases.ReorderTestCase;
import com.android.launcher3.celllayout.testcases.SimpleReorderCase;
@@ -38,7 +39,6 @@ import com.android.launcher3.ui.AbstractLauncherUiTest;
import com.android.launcher3.ui.TaplTestsLauncher3;
import com.android.launcher3.util.rule.ShellCommandRule;
import com.android.launcher3.views.DoubleShadowBubbleTextView;
import com.android.launcher3.widget.LauncherAppWidgetHostView;
import org.junit.Assume;
import org.junit.Before;
@@ -48,6 +48,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
@@ -62,20 +63,6 @@ public class ReorderWidgets extends AbstractLauncherUiTest {
TestWorkspaceBuilder mWorkspaceBuilder;
private View getViewAt(int cellX, int cellY) {
return getFromLauncher(l -> l.getWorkspace().getScreenWithId(
l.getWorkspace().getScreenIdForPageIndex(0)).getChildAt(cellX, cellY));
}
private Point getCellDimensions() {
return getFromLauncher(l -> {
CellLayout cellLayout = l.getWorkspace().getScreenWithId(
l.getWorkspace().getScreenIdForPageIndex(0));
return new Point(cellLayout.getWidth() / cellLayout.getCountX(),
cellLayout.getHeight() / cellLayout.getCountY());
});
}
@Before
public void setup() throws Throwable {
mWorkspaceBuilder = new TestWorkspaceBuilder(this, mTargetContext);
@@ -86,28 +73,26 @@ public class ReorderWidgets extends AbstractLauncherUiTest {
/**
* Validate if the given board represent the current CellLayout
**/
private boolean validateBoard(CellLayoutBoard board) {
boolean match = true;
Point cellDimensions = getCellDimensions();
for (CellLayoutBoard.WidgetRect widgetRect : board.getWidgets()) {
if (widgetRect.shouldIgnore()) {
continue;
private boolean validateBoard(List<CellLayoutBoard> testBoards) {
ArrayList<CellLayoutBoard> workspaceBoards = workspaceToBoards();
if (workspaceBoards.size() < testBoards.size()) {
return false;
}
for (int i = 0; i < testBoards.size(); i++) {
if (testBoards.get(i).compareTo(workspaceBoards.get(i)) != 0) {
return false;
}
View widget = getViewAt(widgetRect.getCellX(), widgetRect.getCellY());
assertTrue("The view selected at " + board + " is not a widget",
widget instanceof LauncherAppWidgetHostView);
match &= widgetRect.getSpanX()
== Math.round(widget.getWidth() / (float) cellDimensions.x);
match &= widgetRect.getSpanY()
== Math.round(widget.getHeight() / (float) cellDimensions.y);
if (!match) return match;
}
for (CellLayoutBoard.IconPoint iconPoint : board.getIcons()) {
View icon = getViewAt(iconPoint.getCoord().x, iconPoint.getCoord().y);
assertTrue("The view selected at " + iconPoint.coord + " is not an Icon",
icon instanceof DoubleShadowBubbleTextView);
return true;
}
private FavoriteItemsTransaction buildWorkspaceFromBoards(List<CellLayoutBoard> boards,
FavoriteItemsTransaction transaction) {
for (int i = 0; i < boards.size(); i++) {
CellLayoutBoard board = boards.get(i);
mWorkspaceBuilder.buildFromBoard(board, transaction, i);
}
return match;
return transaction;
}
private void printCurrentWorkspace() {
@@ -148,22 +133,25 @@ public class ReorderWidgets extends AbstractLauncherUiTest {
private void runTestCase(ReorderTestCase testCase)
throws ExecutionException, InterruptedException {
Point mainWidgetCellPos = testCase.mStart.getMain();
CellLayoutBoard.WidgetRect mainWidgetCellPos = CellLayoutBoard.getMainFromList(
testCase.mStart);
FavoriteItemsTransaction transaction =
new FavoriteItemsTransaction(mTargetContext, this);
mWorkspaceBuilder.buildFromBoard(testCase.mStart, transaction).commit();
transaction = buildWorkspaceFromBoards(testCase.mStart, transaction);
transaction.commit();
waitForLauncherCondition("Workspace didn't finish loading", l -> !l.isWorkspaceLoading());
Widget widget = mLauncher.getWorkspace().getWidgetAtCell(mainWidgetCellPos.x,
mainWidgetCellPos.y);
Widget widget = mLauncher.getWorkspace().getWidgetAtCell(mainWidgetCellPos.getCellX(),
mainWidgetCellPos.getCellY());
assertNotNull(widget);
WidgetResizeFrame resizeFrame = widget.dragWidgetToWorkspace(testCase.moveMainTo.x,
testCase.moveMainTo.y);
testCase.moveMainTo.y, mainWidgetCellPos.getSpanX(), mainWidgetCellPos.getSpanY());
resizeFrame.dismiss();
boolean isValid = false;
for (CellLayoutBoard board : testCase.mEnd) {
isValid |= validateBoard(board);
for (List<CellLayoutBoard> boards : testCase.mEnd) {
isValid |= validateBoard(boards);
if (isValid) break;
}
printCurrentWorkspace();
assertTrue("Non of the valid boards match with the current state", isValid);
@@ -207,4 +195,11 @@ public class ReorderWidgets extends AbstractLauncherUiTest {
runTestCaseMap(MoveOutReorderCase.TEST_BY_GRID_SIZE,
MoveOutReorderCase.class.getSimpleName());
}
@Test
public void multipleCellLayoutsSimpleReorder() throws ExecutionException, InterruptedException {
Assume.assumeTrue("Test doesn't support foldables", !mLauncher.isTwoPanels());
runTestCaseMap(MultipleCellLayoutsSimpleReorder.TEST_BY_GRID_SIZE,
MultipleCellLayoutsSimpleReorder.class.getSimpleName());
}
}

View File

@@ -15,7 +15,6 @@
*/
package com.android.launcher3.celllayout;
import static com.android.launcher3.WorkspaceLayoutManager.FIRST_SCREEN_ID;
import static com.android.launcher3.util.WidgetUtils.createWidgetInfo;
import android.content.ComponentName;
@@ -62,7 +61,7 @@ public class TestWorkspaceBuilder {
* Fills the given rect in WidgetRect with 1x1 widgets. This is useful to equalize cases.
*/
private FavoriteItemsTransaction fillWithWidgets(CellLayoutBoard.WidgetRect widgetRect,
FavoriteItemsTransaction transaction) {
FavoriteItemsTransaction transaction, int screenId) {
int initX = widgetRect.getCellX();
int initY = widgetRect.getCellY();
for (int x = initX; x < initX + widgetRect.getSpanX(); x++) {
@@ -71,8 +70,7 @@ public class TestWorkspaceBuilder {
// this widgets are filling, we don't care if we can't place them
ItemInfo item = createWidgetInCell(
new CellLayoutBoard.WidgetRect(CellLayoutBoard.CellType.IGNORE,
new Rect(x, y, x, y))
);
new Rect(x, y, x, y)), screenId);
transaction.addItem(item);
} catch (Exception e) {
Log.d(TAG, "Unable to place filling widget at " + x + "," + y);
@@ -94,11 +92,11 @@ public class TestWorkspaceBuilder {
}
private void addCorrespondingWidgetRect(CellLayoutBoard.WidgetRect widgetRect,
FavoriteItemsTransaction transaction) {
FavoriteItemsTransaction transaction, int screenId) {
if (widgetRect.mType == 'x') {
fillWithWidgets(widgetRect, transaction);
fillWithWidgets(widgetRect, transaction, screenId);
} else {
transaction.addItem(createWidgetInCell(widgetRect));
transaction.addItem(createWidgetInCell(widgetRect, screenId));
}
}
@@ -106,11 +104,11 @@ public class TestWorkspaceBuilder {
* Builds the given board into the transaction
*/
public FavoriteItemsTransaction buildFromBoard(CellLayoutBoard board,
FavoriteItemsTransaction transaction) {
FavoriteItemsTransaction transaction, final int screenId) {
board.getWidgets().forEach(
(widgetRect) -> addCorrespondingWidgetRect(widgetRect, transaction));
(widgetRect) -> addCorrespondingWidgetRect(widgetRect, transaction, screenId));
board.getIcons().forEach((iconPoint) ->
transaction.addItem(createIconInCell(iconPoint))
transaction.addItem(createIconInCell(iconPoint, screenId))
);
return transaction;
}
@@ -127,7 +125,7 @@ public class TestWorkspaceBuilder {
return transaction;
}
private ItemInfo createWidgetInCell(CellLayoutBoard.WidgetRect widgetRect) {
private ItemInfo createWidgetInCell(CellLayoutBoard.WidgetRect widgetRect, int screenId) {
LauncherAppWidgetProviderInfo info = TestViewHelpers.findWidgetProvider(mTest, false);
LauncherAppWidgetInfo item = createWidgetInfo(info,
ApplicationProvider.getApplicationContext(), true);
@@ -136,14 +134,14 @@ public class TestWorkspaceBuilder {
item.cellY = widgetRect.getCellY();
item.spanX = widgetRect.getSpanX();
item.spanY = widgetRect.getSpanY();
item.screenId = FIRST_SCREEN_ID;
item.screenId = screenId;
return item;
}
private ItemInfo createIconInCell(CellLayoutBoard.IconPoint iconPoint) {
private ItemInfo createIconInCell(CellLayoutBoard.IconPoint iconPoint, int screenId) {
WorkspaceItemInfo item = new WorkspaceItemInfo(getApp());
item.id = getID();
item.screenId = FIRST_SCREEN_ID;
item.screenId = screenId;
item.cellX = iconPoint.getCoord().x;
item.cellY = iconPoint.getCoord().y;
item.minSpanY = item.minSpanX = item.spanX = item.spanY = 1;

View File

@@ -24,23 +24,23 @@ import java.util.List;
import java.util.stream.Collectors;
public class ReorderTestCase {
public CellLayoutBoard mStart;
public List<CellLayoutBoard> mStart;
public Point moveMainTo;
public List<CellLayoutBoard> mEnd;
public List<List<CellLayoutBoard>> mEnd;
ReorderTestCase(CellLayoutBoard start, Point moveMainTo, CellLayoutBoard ... end) {
ReorderTestCase(List<CellLayoutBoard> start, Point moveMainTo, List<CellLayoutBoard> ... end) {
mStart = start;
this.moveMainTo = moveMainTo;
mEnd = Arrays.asList(end);
}
ReorderTestCase(String start, Point moveMainTo, String ... end) {
mStart = CellLayoutBoard.boardFromString(start);
mStart = CellLayoutBoard.boardListFromString(start);
this.moveMainTo = moveMainTo;
mEnd = Arrays
.asList(end)
.stream()
.map(CellLayoutBoard::boardFromString)
.map(CellLayoutBoard::boardListFromString)
.collect(Collectors.toList());
}
}

View File

@@ -33,13 +33,13 @@ public class SimpleReorderCase {
+ "--mm-\n"
+ "-----\n"
+ "-----";
private static final Point MOVE_TO_5x5 = new Point(4, 4);
private static final Point MOVE_TO_5x5 = new Point(0, 4);
private static final String END_BOARD_STR_5x5 = ""
+ "xxxxx\n"
+ "-----\n"
+ "-----\n"
+ "---mm\n"
+ "---mm";
+ "mm---\n"
+ "mm---";
private static final ReorderTestCase TEST_CASE_5x5 = new ReorderTestCase(START_BOARD_STR_5x5,
MOVE_TO_5x5,
END_BOARD_STR_5x5);
@@ -61,7 +61,27 @@ public class SimpleReorderCase {
MOVE_TO_4x4,
END_BOARD_STR_4x4);
/** 6x5 Test
**/
private static final String START_BOARD_STR_6x5 = ""
+ "xxxxxx\n"
+ "-mm---\n"
+ "-mm---\n"
+ "------\n"
+ "------";
private static final Point MOVE_TO_6x5 = new Point(4, 3);
private static final String END_BOARD_STR_6x5 = ""
+ "xxxxxx\n"
+ "------\n"
+ "------\n"
+ "----mm\n"
+ "----mm";
private static final ReorderTestCase TEST_CASE_6x5 = new ReorderTestCase(START_BOARD_STR_6x5,
MOVE_TO_6x5,
END_BOARD_STR_6x5);
public static final Map<Point, ReorderTestCase> TEST_BY_GRID_SIZE =
Map.of(new Point(5, 5), TEST_CASE_5x5,
new Point(4, 4), TEST_CASE_4x4);
new Point(4, 4), TEST_CASE_4x4,
new Point(6, 5), TEST_CASE_6x5);
}

View File

@@ -71,7 +71,7 @@ public final class Widget extends Launchable implements WorkspaceDragSource {
public WidgetResizeFrame dragWidgetToWorkspace() {
try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
return dragWidgetToWorkspace(/* configurable= */ false, /* acceptsConfig= */ false, -1,
-1);
-1, 1, 1);
}
}
@@ -80,12 +80,12 @@ public final class Widget extends Launchable implements WorkspaceDragSource {
* cellY and returns the resize frame that is shown after the widget is added.
*/
@NonNull
public WidgetResizeFrame dragWidgetToWorkspace(int cellX, int cellY) {
public WidgetResizeFrame dragWidgetToWorkspace(int cellX, int cellY, int spanX, int spanY) {
try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
"Dragging widget to workspace cell " + cellX + "," + cellY)) {
return dragWidgetToWorkspace(/* configurable= */ false, /* acceptsConfig= */ false,
cellX, cellY);
cellX, cellY, spanX, spanY);
}
}
@@ -98,7 +98,7 @@ public final class Widget extends Launchable implements WorkspaceDragSource {
public WidgetResizeFrame dragConfigWidgetToWorkspace(boolean acceptsConfig) {
// TODO(b/239438337, fransebas) add correct event checking for this case
//try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
return dragWidgetToWorkspace(/* configurable= */ true, acceptsConfig, -1, -1);
return dragWidgetToWorkspace(/* configurable= */ true, acceptsConfig, -1, -1, 1, 1);
//}
}
@@ -110,18 +110,17 @@ public final class Widget extends Launchable implements WorkspaceDragSource {
* @param cellX X position in the CellLayout
* @param cellY Y position in the CellLayout
*/
private void dragToWorkspace(boolean startsActivity, boolean isWidgetShortcut, int cellX,
int cellY) {
private void dragToWorkspaceCellPosition(boolean startsActivity, boolean isWidgetShortcut,
int cellX, int cellY, int spanX, int spanY) {
Launchable launchable = getLaunchable();
LauncherInstrumentation launcher = launchable.mLauncher;
Workspace.dragIconToWorkspace(
Workspace.dragIconToWorkspaceCellPosition(
launcher,
launchable,
() -> Workspace.getCellCenter(launchable.mLauncher, cellX, cellY),
cellX, cellY, spanX, spanY,
startsActivity,
isWidgetShortcut,
launchable::addExpectedEventsForLongClick);
}
/**
@@ -144,13 +143,13 @@ public final class Widget extends Launchable implements WorkspaceDragSource {
*/
@Nullable
private WidgetResizeFrame dragWidgetToWorkspace(boolean configurable, boolean acceptsConfig,
int cellX, int cellY) {
int cellX, int cellY, int spanX, int spanY) {
if (cellX == -1 || cellY == -1) {
internalDragToWorkspace(/* startsActivity= */ configurable, /* isWidgetShortcut= */
false);
} else {
dragToWorkspace(/* startsActivity= */ configurable, /* isWidgetShortcut= */ false,
cellX, cellY);
dragToWorkspaceCellPosition(/* startsActivity= */ configurable, /* isWidgetShortcut= */
false, cellX, cellY, spanX, spanY);
}
if (configurable) {

View File

@@ -409,9 +409,15 @@ public final class Workspace extends Home {
}
static Point getCellCenter(LauncherInstrumentation launcher, int cellX, int cellY) {
return launcher.getTestInfo(WorkspaceCellCenterRequest.builder().setCellX(
cellX).setCellY(cellY).build()).getParcelable(
TestProtocol.TEST_INFO_RESPONSE_FIELD);
return launcher.getTestInfo(WorkspaceCellCenterRequest.builder().setCellX(cellX).setCellY(
cellY).build()).getParcelable(TestProtocol.TEST_INFO_RESPONSE_FIELD);
}
static Point getCellCenter(LauncherInstrumentation launcher, int cellX, int cellY, int spanX,
int spanY) {
return launcher.getTestInfo(WorkspaceCellCenterRequest.builder().setCellX(cellX)
.setCellY(cellY).setSpanX(spanX).setSpanY(spanY).build())
.getParcelable(TestProtocol.TEST_INFO_RESPONSE_FIELD);
}
static Point getHotseatCellCenter(LauncherInstrumentation launcher, int cellInd) {
@@ -419,6 +425,12 @@ public final class Workspace extends Home {
.setCellInd(cellInd).build()).getParcelable(TestProtocol.TEST_INFO_RESPONSE_FIELD);
}
/** Returns the number of rows and columns in the workspace */
public Point getRowsAndCols() {
return mLauncher.getTestInfo(TestProtocol.REQUEST_WORKSPACE_COLUMNS_ROWS).getParcelable(
TestProtocol.TEST_INFO_RESPONSE_FIELD);
}
/**
* Finds folder icons in the current workspace.
*
@@ -457,6 +469,19 @@ public final class Workspace extends Home {
launcher, launchable, dest, expectLongClickEvents, expectDropEvents);
}
static void dragIconToWorkspaceCellPosition(LauncherInstrumentation launcher,
Launchable launchable, int cellX, int cellY, int spanX, int spanY,
boolean startsActivity, boolean isWidgetShortcut, Runnable expectLongClickEvents) {
Runnable expectDropEvents = null;
if (startsActivity || isWidgetShortcut) {
expectDropEvents = () -> launcher.expectEvent(TestProtocol.SEQUENCE_MAIN,
LauncherInstrumentation.EVENT_START);
}
dragIconToWorkspaceCellPosition(
launcher, launchable, cellX, cellY, spanX, spanY, true, expectLongClickEvents,
expectDropEvents);
}
/**
* Drag icon in workspace to else where and drop it immediately.
* (There is no slow down time before drop event)
@@ -526,6 +551,51 @@ public final class Workspace extends Home {
}
}
static void dragIconToWorkspaceCellPosition(
LauncherInstrumentation launcher,
Launchable launchable,
int cellX, int cellY, int spanX, int spanY,
boolean isDecelerating,
Runnable expectLongClickEvents,
@Nullable Runnable expectDropEvents) {
try (LauncherInstrumentation.Closable ignored = launcher.addContextLayer(
"want to drag icon to workspace")) {
Point rowsAndCols = launcher.getWorkspace().getRowsAndCols();
int destinationWorkspace = cellX / rowsAndCols.x;
cellX = cellX % rowsAndCols.x;
final long downTime = SystemClock.uptimeMillis();
Point dragStart = launchable.startDrag(
downTime,
expectLongClickEvents,
/* runToSpringLoadedState= */ true);
Point targetDest = getCellCenter(launcher, cellX, cellY, spanX, spanY);
int displayX = launcher.getRealDisplaySize().x;
// Since the destination can be on another page, we need to drag to the edge first
// until we reach the target page
for (int i = 0; i < destinationWorkspace; i++) {
// Don't drag all the way to the edge to prevent touch events from getting out of
//screen bounds.
Point screenEdge = new Point(displayX - 1, targetDest.y);
Point finalDragStart = dragStart;
executeAndWaitForPageScroll(launcher,
() -> launcher.movePointer(finalDragStart, screenEdge, DEFAULT_DRAG_STEPS,
true, downTime, downTime, true,
LauncherInstrumentation.GestureScope.INSIDE));
dragStart = screenEdge;
}
// targetDest.x is now between 0 and displayX so we found the target page,
// we just have to put move the icon to the destination and drop it
launcher.movePointer(dragStart, targetDest, DEFAULT_DRAG_STEPS, isDecelerating,
downTime, SystemClock.uptimeMillis(), false,
LauncherInstrumentation.GestureScope.INSIDE);
launcher.runCallbackIfActive(CALLBACK_HOLD_BEFORE_DROP);
dropDraggedIcon(launcher, targetDest, downTime, expectDropEvents);
}
}
private static void executeAndWaitForPageScroll(LauncherInstrumentation launcher,
Runnable command) {
launcher.executeAndWaitForEvent(command,