summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/com/android/launcher3/FocusHelper.java22
-rw-r--r--src/com/android/launcher3/Hotseat.java2
-rw-r--r--src/com/android/launcher3/util/FocusLogic.java108
-rw-r--r--tests/src/com/android/launcher3/util/FocusLogicTest.java150
4 files changed, 232 insertions, 50 deletions
diff --git a/src/com/android/launcher3/FocusHelper.java b/src/com/android/launcher3/FocusHelper.java
index 8516afb4e..3d12aa3e2 100644
--- a/src/com/android/launcher3/FocusHelper.java
+++ b/src/com/android/launcher3/FocusHelper.java
@@ -223,20 +223,18 @@ public class FocusHelper {
if (keyCode == KeyEvent.KEYCODE_DPAD_UP &&
!profile.isVerticalBarLayout()) {
matrix = FocusLogic.createSparseMatrix(iconLayout, hotseatLayout,
- true /* hotseat horizontal */, profile.inv.hotseatAllAppsRank,
- iconRank == profile.inv.hotseatAllAppsRank /* include all apps icon */);
+ true /* hotseat horizontal */, profile.inv.hotseatAllAppsRank);
iconIndex += iconParent.getChildCount();
- countX = iconLayout.getCountX();
+ countX = hotseatLayout.getCountX();
countY = iconLayout.getCountY() + hotseatLayout.getCountY();
parent = iconParent;
} else if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT &&
profile.isVerticalBarLayout()) {
matrix = FocusLogic.createSparseMatrix(iconLayout, hotseatLayout,
- false /* hotseat horizontal */, profile.inv.hotseatAllAppsRank,
- iconRank == profile.inv.hotseatAllAppsRank /* include all apps icon */);
+ false /* hotseat horizontal */, profile.inv.hotseatAllAppsRank);
iconIndex += iconParent.getChildCount();
countX = iconLayout.getCountX() + hotseatLayout.getCountX();
- countY = iconLayout.getCountY();
+ countY = hotseatLayout.getCountY();
parent = iconParent;
} else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT &&
profile.isVerticalBarLayout()) {
@@ -326,15 +324,15 @@ public class FocusHelper {
// with the hotseat.
if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN && !profile.isVerticalBarLayout()) {
matrix = FocusLogic.createSparseMatrix(iconLayout, hotseatLayout, true /* horizontal */,
- profile.inv.hotseatAllAppsRank,
- !hotseat.hasIcons() /* ignore all apps icon, unless there are no other icons */);
- countY = countY + 1;
+ profile.inv.hotseatAllAppsRank);
+ countX = hotseatLayout.getCountX();
+ countY = countY + hotseatLayout.getCountY();
} else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT &&
profile.isVerticalBarLayout()) {
matrix = FocusLogic.createSparseMatrix(iconLayout, hotseatLayout, false /* horizontal */,
- profile.inv.hotseatAllAppsRank,
- !hotseat.hasIcons() /* ignore all apps icon, unless there are no other icons */);
- countX = countX + 1;
+ profile.inv.hotseatAllAppsRank);
+ countX = countX + hotseatLayout.getCountX();
+ countY = hotseatLayout.getCountY();
} else if (isUninstallKeyChord(e)) {
matrix = FocusLogic.createSparseMatrix(iconLayout);
if (UninstallDropTarget.supportsDrop(launcher, itemInfo)) {
diff --git a/src/com/android/launcher3/Hotseat.java b/src/com/android/launcher3/Hotseat.java
index 902b6ec61..3e838760e 100644
--- a/src/com/android/launcher3/Hotseat.java
+++ b/src/com/android/launcher3/Hotseat.java
@@ -70,7 +70,7 @@ public class Hotseat extends FrameLayout
public void setOnLongClickListener(OnLongClickListener l) {
mContent.setOnLongClickListener(l);
}
-
+
/* Get the orientation invariant order of the item in the hotseat for persistence. */
int getOrderInHotseat(int x, int y) {
return mHasVerticalHotseat ? (mContent.getCountY() - y - 1) : x;
diff --git a/src/com/android/launcher3/util/FocusLogic.java b/src/com/android/launcher3/util/FocusLogic.java
index 2aae3c089..f56d16222 100644
--- a/src/com/android/launcher3/util/FocusLogic.java
+++ b/src/com/android/launcher3/util/FocusLogic.java
@@ -63,6 +63,8 @@ public class FocusLogic {
public static final int NEXT_PAGE_LEFT_COLUMN = -9;
public static final int NEXT_PAGE_RIGHT_COLUMN = -10;
+ public static final int ALL_APPS_COLUMN = -11;
+
// Matrix related constant.
public static final int EMPTY = -1;
public static final int PIVOT = 100;
@@ -186,22 +188,36 @@ public class FocusLogic {
*/
// TODO: get rid of the dynamic matrix creation
public static int[][] createSparseMatrix(CellLayout iconLayout, CellLayout hotseatLayout,
- boolean isHorizontal, int allappsiconRank, boolean includeAllappsicon) {
+ boolean isHotseatHorizontal, int allappsiconRank) {
ViewGroup iconParent = iconLayout.getShortcutsAndWidgets();
ViewGroup hotseatParent = hotseatLayout.getShortcutsAndWidgets();
+ boolean moreIconsInHotseatThanWorkspace = isHotseatHorizontal ?
+ hotseatLayout.getCountX() > iconLayout.getCountX() :
+ hotseatLayout.getCountY() > iconLayout.getCountY();
+
int m, n;
- if (isHorizontal) {
- m = iconLayout.getCountX();
+ if (isHotseatHorizontal) {
+ m = hotseatLayout.getCountX();
n = iconLayout.getCountY() + hotseatLayout.getCountY();
} else {
m = iconLayout.getCountX() + hotseatLayout.getCountX();
- n = iconLayout.getCountY();
+ n = hotseatLayout.getCountY();
}
int[][] matrix = createFullMatrix(m, n);
-
- // Iterate thru the children of the top parent.
+ if (moreIconsInHotseatThanWorkspace) {
+ if (isHotseatHorizontal) {
+ for (int j = 0; j < n; j++) {
+ matrix[allappsiconRank][j] = ALL_APPS_COLUMN;
+ }
+ } else {
+ for (int j = 0; j < m; j++) {
+ matrix[j][allappsiconRank] = ALL_APPS_COLUMN;
+ }
+ }
+ }
+ // Iterate thru the children of the workspace.
for (int i = 0; i < iconParent.getChildCount(); i++) {
View cell = iconParent.getChildAt(i);
if (!cell.isFocusable()) {
@@ -209,31 +225,29 @@ public class FocusLogic {
}
int cx = ((CellLayout.LayoutParams) cell.getLayoutParams()).cellX;
int cy = ((CellLayout.LayoutParams) cell.getLayoutParams()).cellY;
+ if (moreIconsInHotseatThanWorkspace) {
+ if (isHotseatHorizontal && cx >= allappsiconRank) {
+ // Add 1 to account for the All Apps button.
+ cx++;
+ }
+ if (!isHotseatHorizontal && cy >= allappsiconRank) {
+ // Add 1 to account for the All Apps button.
+ cy++;
+ }
+ }
matrix[cx][cy] = i;
}
- // Iterate thru the children of the bottom parent
- // The hotseat view group contains one more item than iconLayout column count.
- // If {@param allappsiconRank} not negative, then the last icon in the hotseat
- // is truncated. If it is negative, then all apps icon index is not inserted.
- for(int i = hotseatParent.getChildCount() - 1; i >= (includeAllappsicon ? 0 : 1); i--) {
- int delta = 0;
- if (isHorizontal) {
+ // Iterate thru the children of the hotseat.
+ for (int i = hotseatParent.getChildCount() - 1; i >= 0; i--) {
+ if (isHotseatHorizontal) {
int cx = ((CellLayout.LayoutParams)
hotseatParent.getChildAt(i).getLayoutParams()).cellX;
- if ((includeAllappsicon && cx >= allappsiconRank) ||
- (!includeAllappsicon && cx > allappsiconRank)) {
- delta = -1;
- }
- matrix[cx + delta][iconLayout.getCountY()] = iconParent.getChildCount() + i;
+ matrix[cx][iconLayout.getCountY()] = iconParent.getChildCount() + i;
} else {
int cy = ((CellLayout.LayoutParams)
hotseatParent.getChildAt(i).getLayoutParams()).cellY;
- if ((includeAllappsicon && cy >= allappsiconRank) ||
- (!includeAllappsicon && cy > allappsiconRank)) {
- delta = -1;
- }
- matrix[iconLayout.getCountX()][cy + delta] = iconParent.getChildCount() + i;
+ matrix[iconLayout.getCountX()][cy] = iconParent.getChildCount() + i;
}
}
if (DEBUG) {
@@ -323,8 +337,9 @@ public class FocusLogic {
}
// Rule1: check first in the horizontal direction
- for (int i = xPos + increment; 0 <= i && i < cntX; i = i + increment) {
- if ((newIconIndex = inspectMatrix(i, yPos, cntX, cntY, matrix)) != NOOP) {
+ for (int x = xPos + increment; 0 <= x && x < cntX; x += increment) {
+ if ((newIconIndex = inspectMatrix(x, yPos, cntX, cntY, matrix)) != NOOP
+ && newIconIndex != ALL_APPS_COLUMN) {
return newIconIndex;
}
}
@@ -333,15 +348,23 @@ public class FocusLogic {
// (x2-n, yPos + 2*increment), (x2-n, yPos - 2*increment)
int nextYPos1;
int nextYPos2;
- int i = -1;
+ int x = -1;
for (int coeff = 1; coeff < cntY; coeff++) {
nextYPos1 = yPos + coeff * increment;
nextYPos2 = yPos - coeff * increment;
- for (i = xPos + increment * coeff; 0 <= i && i < cntX; i = i + increment) {
- if ((newIconIndex = inspectMatrix(i, nextYPos1, cntX, cntY, matrix)) != NOOP) {
+ x = xPos + increment * coeff;
+ if (inspectMatrix(x, nextYPos1, cntX, cntY, matrix) == ALL_APPS_COLUMN) {
+ nextYPos1 += increment;
+
+ }
+ if (inspectMatrix(x, nextYPos2, cntX, cntY, matrix) == ALL_APPS_COLUMN) {
+ nextYPos2 -= increment;
+ }
+ for (; 0 <= x && x < cntX; x += increment) {
+ if ((newIconIndex = inspectMatrix(x, nextYPos1, cntX, cntY, matrix)) != NOOP) {
return newIconIndex;
}
- if ((newIconIndex = inspectMatrix(i, nextYPos2, cntX, cntY, matrix)) != NOOP) {
+ if ((newIconIndex = inspectMatrix(x, nextYPos2, cntX, cntY, matrix)) != NOOP) {
return newIconIndex;
}
}
@@ -350,9 +373,10 @@ public class FocusLogic {
// Rule 3: if switching between pages, do a brute-force search to find an item that was
// missed by rules 1 and 2 (such as when going from a bottom right icon to top left)
if (iconIdx == PIVOT) {
- for (int x = xPos + increment; 0 <= x && x < cntX; x = x + increment) {
+ for (x = xPos + increment; 0 <= x && x < cntX; x += increment) {
for (int y = 0; y < cntY; y++) {
- if ((newIconIndex = inspectMatrix(x, y, cntX, cntY, matrix)) != NOOP) {
+ if ((newIconIndex = inspectMatrix(x, y, cntX, cntY, matrix)) != NOOP
+ && newIconIndex != ALL_APPS_COLUMN) {
return newIconIndex;
}
}
@@ -396,8 +420,9 @@ public class FocusLogic {
}
// Rule1: check first in the dpad direction
- for (int j = yPos + increment; 0 <= j && j <cntY && 0 <= j; j = j + increment) {
- if ((newIconIndex = inspectMatrix(xPos, j, cntX, cntY, matrix)) != NOOP) {
+ for (int y = yPos + increment; 0 <= y && y <cntY && 0 <= y; y += increment) {
+ if ((newIconIndex = inspectMatrix(xPos, y, cntX, cntY, matrix)) != NOOP
+ && newIconIndex != ALL_APPS_COLUMN) {
return newIconIndex;
}
}
@@ -406,15 +431,23 @@ public class FocusLogic {
// (xPos + 2*increment, y_(2-n))), (xPos - 2*increment, y_(2-n))
int nextXPos1;
int nextXPos2;
- int j = -1;
+ int y = -1;
for (int coeff = 1; coeff < cntX; coeff++) {
nextXPos1 = xPos + coeff * increment;
nextXPos2 = xPos - coeff * increment;
- for (j = yPos + increment * coeff; 0 <= j && j < cntY; j = j + increment) {
- if ((newIconIndex = inspectMatrix(nextXPos1, j, cntX, cntY, matrix)) != NOOP) {
+ y = yPos + increment * coeff;
+ if (inspectMatrix(nextXPos1, y, cntX, cntY, matrix) == ALL_APPS_COLUMN) {
+ nextXPos1 += increment;
+
+ }
+ if (inspectMatrix(nextXPos2, y, cntX, cntY, matrix) == ALL_APPS_COLUMN) {
+ nextXPos2 -= increment;
+ }
+ for (; 0 <= y && y < cntY; y = y + increment) {
+ if ((newIconIndex = inspectMatrix(nextXPos1, y, cntX, cntY, matrix)) != NOOP) {
return newIconIndex;
}
- if ((newIconIndex = inspectMatrix(nextXPos2, j, cntX, cntY, matrix)) != NOOP) {
+ if ((newIconIndex = inspectMatrix(nextXPos2, y, cntX, cntY, matrix)) != NOOP) {
return newIconIndex;
}
}
@@ -481,6 +514,7 @@ public class FocusLogic {
case CURRENT_PAGE_LAST_ITEM: return "CURRENT_PAGE_LAST";
case NEXT_PAGE_FIRST_ITEM: return "NEXT_PAGE_FIRST";
case NEXT_PAGE_LEFT_COLUMN: return "NEXT_PAGE_LEFT_COLUMN";
+ case ALL_APPS_COLUMN: return "ALL_APPS_COLUMN";
default:
return Integer.toString(index);
}
diff --git a/tests/src/com/android/launcher3/util/FocusLogicTest.java b/tests/src/com/android/launcher3/util/FocusLogicTest.java
index 2c2f0d3df..f93e91313 100644
--- a/tests/src/com/android/launcher3/util/FocusLogicTest.java
+++ b/tests/src/com/android/launcher3/util/FocusLogicTest.java
@@ -19,6 +19,7 @@ package com.android.launcher3;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
import android.view.KeyEvent;
+import android.view.View;
import com.android.launcher3.util.FocusLogic;
@@ -82,6 +83,155 @@ public final class FocusLogicTest extends AndroidTestCase {
assertEquals(0, i);
}
+ public void testMoveIntoHotseatWithEqualHotseatAndWorkspaceColumns() {
+ // Test going from an icon right above the All Apps button to the All Apps button.
+ int[][] map = transpose(new int[][] {
+ {-1, -1, -1, -1, -1},
+ {-1, -1, -1, -1, -1},
+ {-1, -1, -1, -1, -1},
+ {-1, -1, 0, -1, -1},
+ { 2, 3, 1, 4, 5},
+ });
+ int i = FocusLogic.handleKeyEvent(KeyEvent.KEYCODE_DPAD_DOWN, 5, 5, map, 0, 1, 1, true);
+ assertEquals(1, i);
+ // Test going from an icon above and to the right of the All Apps
+ // button to an icon to the right of the All Apps button.
+ map = transpose(new int[][] {
+ {-1, -1, -1, -1, -1},
+ {-1, -1, -1, -1, -1},
+ {-1, -1, -1, -1, -1},
+ {-1, -1, -1, 0, -1},
+ { 2, 3, 1, 4, 5},
+ });
+ i = FocusLogic.handleKeyEvent(KeyEvent.KEYCODE_DPAD_DOWN, 5, 5, map, 0, 1, 1, true);
+ assertEquals(4, i);
+ }
+
+ public void testMoveIntoHotseatWithExtraColumnForAllApps() {
+ // Test going from an icon above and to the left
+ // of the All Apps button to the All Apps button.
+ int[][] map = transpose(new int[][] {
+ {-1, -1, -1,-11, -1, -1, -1},
+ {-1, -1, -1,-11, -1, -1, -1},
+ {-1, -1, -1,-11, -1, -1, -1},
+ {-1, -1, -1,-11, -1, -1, -1},
+ {-1, -1, 0,-11, -1, -1, -1},
+ {-1, -1, -1, 1, 1, -1, -1},
+ });
+ int i = FocusLogic.handleKeyEvent(KeyEvent.KEYCODE_DPAD_DOWN, 7, 6, map, 0, 1, 1, true);
+ assertEquals(1, i);
+ // Test going from an icon above and to the right
+ // of the All Apps button to the All Apps button.
+ map = transpose(new int[][] {
+ {-1, -1, -1,-11, -1, -1, -1},
+ {-1, -1, -1,-11, -1, -1, -1},
+ {-1, -1, -1,-11, -1, -1, -1},
+ {-1, -1, -1,-11, -1, -1, -1},
+ {-1, -1, -1,-11, 0, -1, -1},
+ {-1, -1, -1, 1, -1, -1, -1},
+ });
+ i = FocusLogic.handleKeyEvent(KeyEvent.KEYCODE_DPAD_DOWN, 7, 6, map, 0, 1, 1, true);
+ assertEquals(1, i);
+ // Test going from the All Apps button to an icon
+ // above and to the right of the All Apps button.
+ map = transpose(new int[][] {
+ {-1, -1, -1,-11, -1, -1, -1},
+ {-1, -1, -1,-11, -1, -1, -1},
+ {-1, -1, -1,-11, -1, -1, -1},
+ {-1, -1, -1,-11, -1, -1, -1},
+ {-1, -1, -1,-11, 0, -1, -1},
+ {-1, -1, -1, 1, -1, -1, -1},
+ });
+ i = FocusLogic.handleKeyEvent(KeyEvent.KEYCODE_DPAD_UP, 7, 6, map, 1, 1, 1, true);
+ assertEquals(0, i);
+ // Test going from an icon above and to the left of the
+ // All Apps button in landscape to the All Apps button.
+ map = transpose(new int[][] {
+ { -1, -1, -1, -1, -1},
+ { -1, -1, -1, 0, -1},
+ {-11,-11,-11,-11, 1},
+ { -1, -1, -1, -1, -1},
+ { -1, -1, -1, -1, -1},
+ });
+ i = FocusLogic.handleKeyEvent(KeyEvent.KEYCODE_DPAD_RIGHT, 5, 5, map, 0, 1, 1, true);
+ assertEquals(1, i);
+ // Test going from the All Apps button in landscape to
+ // an icon above and to the left of the All Apps button.
+ map = transpose(new int[][] {
+ { -1, -1, -1, -1, -1},
+ { -1, -1, -1, 0, -1},
+ {-11,-11,-11,-11, 1},
+ { -1, -1, -1, -1, -1},
+ { -1, -1, -1, -1, -1},
+ });
+ i = FocusLogic.handleKeyEvent(KeyEvent.KEYCODE_DPAD_LEFT, 5, 5, map, 1, 1, 1, true);
+ assertEquals(0, i);
+ // Test that going to the hotseat always goes to the same row as the original icon.
+ map = transpose(new int[][]{
+ { 0, 1, 2,-11, 3, 4, 5},
+ {-1, -1, -1,-11, -1, -1, -1},
+ {-1, -1, -1,-11, -1, -1, -1},
+ {-1, -1, -1,-11, -1, -1, -1},
+ {-1, -1, -1,-11, -1, -1, -1},
+ { 7, 8, 9, 6, 10, 11, 12},
+ });
+ i = FocusLogic.handleKeyEvent(KeyEvent.KEYCODE_DPAD_DOWN, 7, 6, map, 0, 1, 1, true);
+ assertEquals(7, i);
+ i = FocusLogic.handleKeyEvent(KeyEvent.KEYCODE_DPAD_DOWN, 7, 6, map, 1, 1, 1, true);
+ assertEquals(8, i);
+ i = FocusLogic.handleKeyEvent(KeyEvent.KEYCODE_DPAD_DOWN, 7, 6, map, 2, 1, 1, true);
+ assertEquals(9, i);
+ i = FocusLogic.handleKeyEvent(KeyEvent.KEYCODE_DPAD_DOWN, 7, 6, map, 3, 1, 1, true);
+ assertEquals(10, i);
+ i = FocusLogic.handleKeyEvent(KeyEvent.KEYCODE_DPAD_DOWN, 7, 6, map, 4, 1, 1, true);
+ assertEquals(11, i);
+ i = FocusLogic.handleKeyEvent(KeyEvent.KEYCODE_DPAD_DOWN, 7, 6, map, 5, 1, 1, true);
+ assertEquals(12, i);
+ }
+
+ public void testCrossingAllAppsColumn() {
+ // Test crossing from left to right in portrait.
+ int[][] map = transpose(new int[][] {
+ {-1, -1,-11, -1, -1},
+ {-1, 0,-11, -1, -1},
+ {-1, -1,-11, 1, -1},
+ {-1, -1,-11, -1, -1},
+ {-1, -1, 2, -1, -1},
+ });
+ int i = FocusLogic.handleKeyEvent(KeyEvent.KEYCODE_DPAD_DOWN, 5, 5, map, 0, 1, 1, true);
+ assertEquals(1, i);
+ // Test crossing from right to left in portrait.
+ map = transpose(new int[][] {
+ {-1, -1,-11, -1, -1},
+ {-1, -1,-11, 0, -1},
+ {-1, 1,-11, -1, -1},
+ {-1, -1,-11, -1, -1},
+ {-1, -1, 2, -1, -1},
+ });
+ i = FocusLogic.handleKeyEvent(KeyEvent.KEYCODE_DPAD_DOWN, 5, 5, map, 0, 1, 1, true);
+ assertEquals(1, i);
+ // Test crossing from left to right in landscape.
+ map = transpose(new int[][] {
+ { -1, -1, -1, -1, -1},
+ { -1, -1, -1, 0, -1},
+ {-11,-11,-11,-11, 2},
+ { -1, 1, -1, -1, -1},
+ { -1, -1, -1, -1, -1},
+ });
+ i = FocusLogic.handleKeyEvent(KeyEvent.KEYCODE_DPAD_LEFT, 5, 5, map, 0, 1, 1, true);
+ assertEquals(1, i);
+ // Test crossing from right to left in landscape.
+ map = transpose(new int[][] {
+ { -1, -1, -1, -1, -1},
+ { -1, 0, -1, -1, -1},
+ {-11,-11,-11,-11, 2},
+ { -1, -1, 1, -1, -1},
+ { -1, -1, -1, -1, -1},
+ });
+ i = FocusLogic.handleKeyEvent(KeyEvent.KEYCODE_DPAD_RIGHT, 5, 5, map, 0, 1, 1, true);
+ assertEquals(1, i);
+ }
+
/** Transposes the matrix so that we can write it in human-readable format in the tests. */
private int[][] transpose(int[][] m) {
int[][] t = new int[m[0].length][m.length];