Merge branch 'master' into honeycomb-release
diff --git a/res/drawable-hdpi/hotseat_browser_normal.png b/res/drawable-hdpi/hotseat_browser_normal.png
index ebdab62..c7f902a 100644
--- a/res/drawable-hdpi/hotseat_browser_normal.png
+++ b/res/drawable-hdpi/hotseat_browser_normal.png
Binary files differ
diff --git a/res/drawable-hdpi/hotseat_phone_normal.png b/res/drawable-hdpi/hotseat_phone_normal.png
index 2a16f9c..391802e 100644
--- a/res/drawable-hdpi/hotseat_phone_normal.png
+++ b/res/drawable-hdpi/hotseat_phone_normal.png
Binary files differ
diff --git a/res/drawable-mdpi/hotseat_browser_normal.png b/res/drawable-mdpi/hotseat_browser_normal.png
index 4c662fd..4a4a6e3 100644
--- a/res/drawable-mdpi/hotseat_browser_normal.png
+++ b/res/drawable-mdpi/hotseat_browser_normal.png
Binary files differ
diff --git a/res/drawable-mdpi/hotseat_phone_normal.png b/res/drawable-mdpi/hotseat_phone_normal.png
index d759b1f..7f20428 100644
--- a/res/drawable-mdpi/hotseat_phone_normal.png
+++ b/res/drawable-mdpi/hotseat_phone_normal.png
Binary files differ
diff --git a/src/com/android/launcher2/CellLayout.java b/src/com/android/launcher2/CellLayout.java
index 164d7c5..369f0d2 100644
--- a/src/com/android/launcher2/CellLayout.java
+++ b/src/com/android/launcher2/CellLayout.java
@@ -91,13 +91,13 @@
private Rect[] mDragRects = new Rect[8];
private int[] mDragRectAlphas = new int[mDragRects.length];
private InterruptibleInOutAnimator[] mDragRectAnims =
- new InterruptibleInOutAnimator[mDragRects.length];
+ new InterruptibleInOutAnimator[mDragRects.length];
// Used as an index into the above 3 arrays; indicates which is the most current value.
private int mDragRectCurrent = 0;
private Drawable mCrosshairsDrawable = null;
- private ValueAnimator mCrosshairsAnimator = null;
+ private InterruptibleInOutAnimator mCrosshairsAnimator = null;
private float mCrosshairsVisibility = 0.0f;
// When a drag operation is in progress, holds the nearest cell to the touch point
@@ -165,7 +165,7 @@
// Set up the animation for fading the crosshairs in and out
int animDuration = res.getInteger(R.integer.config_crosshairsFadeInTime);
- mCrosshairsAnimator = new ValueAnimator<Float>(animDuration);
+ mCrosshairsAnimator = new InterruptibleInOutAnimator(animDuration, 0.0f, 1.0f);
mCrosshairsAnimator.addUpdateListener(new AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator animation) {
mCrosshairsVisibility = ((Float) animation.getAnimatedValue()).floatValue();
@@ -207,15 +207,6 @@
mHover = value;
}
- private void animateCrosshairsTo(float value) {
- final ValueAnimator anim = mCrosshairsAnimator;
- long fullDuration = getResources().getInteger(R.integer.config_crosshairsFadeInTime);
- anim.setDuration(fullDuration - anim.getCurrentPlayTime());
- anim.setValues(mCrosshairsVisibility, value);
- anim.cancel();
- anim.start();
- }
-
public void drawChildren(Canvas canvas) {
super.dispatchDraw(canvas);
}
@@ -809,6 +800,11 @@
mDragRectAnims[mDragRectCurrent].animateIn();
}
}
+
+ // If we are drawing crosshairs, the entire CellLayout needs to be invalidated
+ if (mCrosshairsDrawable != null) {
+ invalidate();
+ }
}
/**
@@ -1020,7 +1016,7 @@
// Fade out the drag indicators
if (mCrosshairsAnimator != null) {
- animateCrosshairsTo(0.0f);
+ mCrosshairsAnimator.animateOut();
}
mDragRectAnims[mDragRectCurrent].animateOut();
@@ -1070,7 +1066,7 @@
void onDragEnter(View dragView) {
// Fade in the drag indicators
if (mCrosshairsAnimator != null) {
- animateCrosshairsTo(1.0f);
+ mCrosshairsAnimator.animateIn();
}
}
@@ -1110,9 +1106,12 @@
* @param result An array of length 2 in which to store the result (may be null).
*/
public int[] rectToCell(int width, int height, int[] result) {
+ return rectToCell(getResources(), width, height, result);
+ }
+
+ public static int[] rectToCell(Resources resources, int width, int height, int[] result) {
// Always assume we're working with the smallest span to make sure we
// reserve enough space in both orientations.
- final Resources resources = getResources();
int actualWidth = resources.getDimensionPixelSize(R.dimen.workspace_cell_width);
int actualHeight = resources.getDimensionPixelSize(R.dimen.workspace_cell_height);
int smallerSize = Math.min(actualWidth, actualHeight);
diff --git a/src/com/android/launcher2/CustomizePagedView.java b/src/com/android/launcher2/CustomizePagedView.java
index b7e5dcd..f3de74b 100644
--- a/src/com/android/launcher2/CustomizePagedView.java
+++ b/src/com/android/launcher2/CustomizePagedView.java
@@ -624,8 +624,10 @@
l.setOnLongClickListener(this);
final Drawable icon = getWidgetIcon(info);
- final int hSpan = mWorkspaceWidgetLayout.estimateCellHSpan(info.minWidth);
- final int vSpan = mWorkspaceWidgetLayout.estimateCellHSpan(info.minHeight);
+
+ int[] spans = CellLayout.rectToCell(getResources(), info.minWidth, info.minHeight, null);
+ final int hSpan = spans[0];
+ final int vSpan = spans[1];
ImageView image = (ImageView) l.findViewById(R.id.widget_preview);
image.setMaxWidth(mMaxWidgetWidth);
diff --git a/src/com/android/launcher2/DragController.java b/src/com/android/launcher2/DragController.java
index 68dfb35..3c956f0 100644
--- a/src/com/android/launcher2/DragController.java
+++ b/src/com/android/launcher2/DragController.java
@@ -16,8 +16,11 @@
package com.android.launcher2;
+import com.android.launcher.R;
+
import android.content.Context;
import android.graphics.Bitmap;
+import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Handler;
@@ -28,13 +31,12 @@
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
+import android.view.ViewConfiguration;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import java.util.ArrayList;
-import com.android.launcher.R;
-
/**
* Class for initiating a drag within a view or across multiple views.
*/
@@ -124,6 +126,9 @@
private InputMethodManager mInputMethodManager;
+ private int mLastTouch[] = new int[2];
+ private int mDistanceSinceScroll = 0;
+
/**
* Interface to receive notifications when a drag starts or stops
*/
@@ -486,15 +491,24 @@
if (mDeleteRegion != null) {
inDeleteRegion = mDeleteRegion.contains(x, y);
}
+
+ // After a scroll, the touch point will still be in the scroll region.
+ // Rather than scrolling immediately, require a bit of twiddling to scroll again
+ final int slop = ViewConfiguration.get(mContext).getScaledWindowTouchSlop();
+ mDistanceSinceScroll +=
+ Math.sqrt(Math.pow(mLastTouch[0] - x, 2) + Math.pow(mLastTouch[1] - y, 2));
+ mLastTouch[0] = x;
+ mLastTouch[1] = y;
+
if (!inDeleteRegion && x < mScrollZone) {
- if (mScrollState == SCROLL_OUTSIDE_ZONE) {
+ if (mScrollState == SCROLL_OUTSIDE_ZONE && mDistanceSinceScroll > slop) {
mScrollState = SCROLL_WAITING_IN_ZONE;
mScrollRunnable.setDirection(SCROLL_LEFT);
mHandler.postDelayed(mScrollRunnable, SCROLL_DELAY);
mDragScroller.onEnterScrollArea(SCROLL_LEFT);
}
} else if (!inDeleteRegion && x > mScrollView.getWidth() - mScrollZone) {
- if (mScrollState == SCROLL_OUTSIDE_ZONE) {
+ if (mScrollState == SCROLL_OUTSIDE_ZONE && mDistanceSinceScroll > slop) {
mScrollState = SCROLL_WAITING_IN_ZONE;
mScrollRunnable.setDirection(SCROLL_RIGHT);
mHandler.postDelayed(mScrollRunnable, SCROLL_DELAY);
@@ -696,6 +710,8 @@
mDragScroller.scrollRight();
}
mScrollState = SCROLL_OUTSIDE_ZONE;
+ mDistanceSinceScroll = 0;
+ mDragScroller.onExitScrollArea();
}
}
diff --git a/src/com/android/launcher2/LauncherModel.java b/src/com/android/launcher2/LauncherModel.java
index 2800605..d46ea07 100644
--- a/src/com/android/launcher2/LauncherModel.java
+++ b/src/com/android/launcher2/LauncherModel.java
@@ -414,8 +414,10 @@
}
} else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) {
- // When everything comes back, just reload everything. We might not
- // have the right icons for apps on external storage.
+ // First, schedule to add these apps back in.
+ String[] packages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+ enqueuePackageUpdated(new PackageUpdatedTask(PackageUpdatedTask.OP_ADD, packages));
+ // Then, rebind everything.
startLoader(mApp, false);
} else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index 6802966..97c54c4 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -110,10 +110,14 @@
private IconCache mIconCache;
private DragController mDragController;
+ // These are temporary variables to prevent having to allocate a new object just to
+ // return an (x, y) value from helper functions. Do NOT use them to maintain other state.
private int[] mTempCell = new int[2];
private int[] mTempEstimate = new int[2];
private float[] mTempOriginXY = new float[2];
private float[] mTempDragCoordinates = new float[2];
+ private float[] mTempTouchCoordinates = new float[2];
+ private float[] mTempCellLayoutCenterCoordinates = new float[2];
private float[] mTempDragBottomRightCoordinates = new float[2];
private Matrix mTempInverseMatrix = new Matrix();
@@ -855,7 +859,7 @@
int originX = x - xOffset;
int originY = y - yOffset;
if (mIsSmall || mIsInUnshrinkAnimation) {
- cellLayout = findMatchingPageForDragOver(dragView, originX, originY);
+ cellLayout = findMatchingPageForDragOver(dragView, originX, originY, xOffset, yOffset);
if (cellLayout == null) {
// cancel the drag if we're not over a mini-screen at time of drop
// TODO: maybe add a nice fade here?
@@ -864,7 +868,7 @@
// get originX and originY in the local coordinate system of the screen
mTempOriginXY[0] = originX;
mTempOriginXY[1] = originY;
- mapPointGlobalToLocal(cellLayout, mTempOriginXY);
+ mapPointFromSelfToChild(cellLayout, mTempOriginXY);
originX = (int)mTempOriginXY[0];
originY = (int)mTempOriginXY[1];
} else {
@@ -954,73 +958,146 @@
return null;
}
- private void mapPointGlobalToLocal(View v, float[] xy) {
- xy[0] = xy[0] + mScrollX - v.getLeft();
- xy[1] = xy[1] + mScrollY - v.getTop();
- v.getMatrix().invert(mTempInverseMatrix);
- mTempInverseMatrix.mapPoints(xy);
+ /*
+ *
+ * Convert the 2D coordinate xy from the parent View's coordinate space to this CellLayout's
+ * coordinate space. The argument xy is modified with the return result.
+ *
+ */
+ void mapPointFromSelfToChild(View v, float[] xy) {
+ mapPointFromSelfToChild(v, xy, null);
+ }
+
+ /*
+ *
+ * Convert the 2D coordinate xy from the parent View's coordinate space to this CellLayout's
+ * coordinate space. The argument xy is modified with the return result.
+ *
+ * if cachedInverseMatrix is not null, this method will just use that matrix instead of
+ * computing it itself; we use this to avoid redudant matrix inversions in
+ * findMatchingPageForDragOver
+ *
+ */
+ void mapPointFromSelfToChild(View v, float[] xy, Matrix cachedInverseMatrix) {
+ if (cachedInverseMatrix == null) {
+ v.getMatrix().invert(mTempInverseMatrix);
+ cachedInverseMatrix = mTempInverseMatrix;
+ }
+ xy[0] = xy[0] + mScrollX - v.getLeft();
+ xy[1] = xy[1] + mScrollY - v.getTop();
+ cachedInverseMatrix.mapPoints(xy);
+ }
+
+ /*
+ *
+ * Convert the 2D coordinate xy from this CellLayout's coordinate space to
+ * the parent View's coordinate space. The argument xy is modified with the return result.
+ *
+ */
+ void mapPointFromChildToSelf(View v, float[] xy) {
+ v.getMatrix().mapPoints(xy);
+ xy[0] -= (mScrollX - v.getLeft());
+ xy[1] -= (mScrollY - v.getTop());
+ }
+
+ static private float squaredDistance(float[] point1, float[] point2) {
+ float distanceX = point1[0] - point2[0];
+ float distanceY = point2[1] - point2[1];
+ return distanceX * distanceX + distanceY * distanceY;
}
- // xy = upper left corner of item being dragged
- // bottomRightXy = lower right corner of item being dragged
- // This method will see which mini-screen is most overlapped by the item being dragged, and
- // return it. It will also transform the parameters xy and bottomRightXy into the local
- // coordinate space of the returned screen
- private CellLayout findMatchingPageForDragOver(DragView dragView, int originX, int originY) {
- float x = originX + dragView.getScaledDragRegionXOffset();
- float y = originY + dragView.getScaledDragRegionYOffset();
- float right = x + dragView.getScaledDragRegionWidth();
- float bottom = y + dragView.getScaledDragRegionHeight();
+ /*
+ *
+ * Returns true if the passed CellLayout cl overlaps with dragView
+ *
+ */
+ boolean overlaps(CellLayout cl, DragView dragView,
+ int dragViewX, int dragViewY, Matrix cachedInverseMatrix) {
+ // Transform the coordinates of the item being dragged to the CellLayout's coordinates
+ final float[] draggedItemTopLeft = mTempDragCoordinates;
+ draggedItemTopLeft[0] = dragViewX + dragView.getScaledDragRegionXOffset();
+ draggedItemTopLeft[1] = dragViewY + dragView.getScaledDragRegionYOffset();
+ final float[] draggedItemBottomRight = mTempDragBottomRightCoordinates;
+ draggedItemBottomRight[0] = draggedItemTopLeft[0] + dragView.getScaledDragRegionWidth();
+ draggedItemBottomRight[1] = draggedItemTopLeft[1] + dragView.getScaledDragRegionHeight();
- // We loop through all the screens (ie CellLayouts) and see which one overlaps the most
- // with the item being dragged.
+ // Transform the dragged item's top left coordinates
+ // to the CellLayout's local coordinates
+ mapPointFromSelfToChild(cl, draggedItemTopLeft, cachedInverseMatrix);
+ float overlapRegionLeft = Math.max(0f, draggedItemTopLeft[0]);
+ float overlapRegionTop = Math.max(0f, draggedItemTopLeft[1]);
+
+ if (overlapRegionLeft <= cl.getWidth() && overlapRegionTop >= 0) {
+ // Transform the dragged item's bottom right coordinates
+ // to the CellLayout's local coordinates
+ mapPointFromSelfToChild(cl, draggedItemBottomRight, cachedInverseMatrix);
+ float overlapRegionRight = Math.min(cl.getWidth(), draggedItemBottomRight[0]);
+ float overlapRegionBottom = Math.min(cl.getHeight(), draggedItemBottomRight[1]);
+
+ if (overlapRegionRight >= 0 && overlapRegionBottom <= cl.getHeight()) {
+ float overlap = (overlapRegionRight - overlapRegionLeft) *
+ (overlapRegionBottom - overlapRegionTop);
+ if (overlap > 0) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /*
+ *
+ * This method returns the CellLayout that is currently being dragged to. In order to drag
+ * to a CellLayout, either the touch point must be directly over the CellLayout, or as a second
+ * strategy, we see if the dragView is overlapping any CellLayout and choose the closest one
+ *
+ * Return null if no CellLayout is currently being dragged over
+ *
+ */
+ private CellLayout findMatchingPageForDragOver(
+ DragView dragView, int originX, int originY, int offsetX, int offsetY) {
+ // We loop through all the screens (ie CellLayouts) and see which ones overlap
+ // with the item being dragged and then choose the one that's closest to the touch point
final int screenCount = getChildCount();
CellLayout bestMatchingScreen = null;
float smallestDistSoFar = Float.MAX_VALUE;
- final float[] xy = mTempDragCoordinates;
- final float[] bottomRightXy = mTempDragBottomRightCoordinates;
+
for (int i = 0; i < screenCount; i++) {
CellLayout cl = (CellLayout)getChildAt(i);
- // Transform the coordinates of the item being dragged to the CellLayout's coordinates
- float left = cl.getLeft();
- float top = cl.getTop();
- xy[0] = x + mScrollX - left;
- xy[1] = y + mScrollY - top;
- bottomRightXy[0] = right + mScrollX - left;
- bottomRightXy[1] = bottom + mScrollY - top;
+ final float[] touchXy = mTempTouchCoordinates;
+ touchXy[0] = originX + offsetX;
+ touchXy[1] = originY + offsetY;
+ // Transform the touch coordinates to the CellLayout's local coordinates
+ // If the touch point is within the bounds of the cell layout, we can return immediately
cl.getMatrix().invert(mTempInverseMatrix);
- mTempInverseMatrix.mapPoints(xy);
- mTempInverseMatrix.mapPoints(bottomRightXy);
+ mapPointFromSelfToChild(cl, touchXy, mTempInverseMatrix);
- float dragRegionX = xy[0];
- float dragRegionY = xy[1];
- float dragRegionRight = bottomRightXy[0];
- float dragRegionBottom = bottomRightXy[1];
- float dragRegionCenterX = (dragRegionX + dragRegionRight) / 2.0f;
- float dragRegionCenterY = (dragRegionY + dragRegionBottom) / 2.0f;
+ if (touchXy[0] >= 0 && touchXy[0] <= cl.getWidth() &&
+ touchXy[1] >= 0 && touchXy[1] <= cl.getHeight()) {
+ return cl;
+ }
- // Find the overlapping region
- float overlapLeft = Math.max(0f, dragRegionX);
- float overlapTop = Math.max(0f, dragRegionY);
- float overlapBottom = Math.min(cl.getHeight(), dragRegionBottom);
- float overlapRight = Math.min(cl.getWidth(), dragRegionRight);
- if (overlapRight >= 0 && overlapLeft <= cl.getWidth() &&
- (overlapTop >= 0 && overlapBottom <= cl.getHeight())) {
- // Calculate the distance between the two centers
- float distX = dragRegionCenterX - cl.getWidth()/2;
- float distY = dragRegionCenterY - cl.getHeight()/2;
- float dist = distX * distX + distY * distY;
+ if (overlaps(cl, dragView, originX, originY, mTempInverseMatrix)) {
+ // Get the center of the cell layout in screen coordinates
+ final float[] cellLayoutCenter = mTempCellLayoutCenterCoordinates;
+ cellLayoutCenter[0] = cl.getWidth()/2;
+ cellLayoutCenter[1] = cl.getHeight()/2;
+ mapPointFromChildToSelf(cl, cellLayoutCenter);
- float overlap = (overlapRight - overlapLeft) * (overlapBottom - overlapTop);
+ touchXy[0] = originX + offsetX;
+ touchXy[1] = originY + offsetY;
- // Calculate the closest overlapping region
- if (overlap > 0 && dist < smallestDistSoFar) {
+ // Calculate the distance between the center of the CellLayout
+ // and the touch point
+ float dist = squaredDistance(touchXy, cellLayoutCenter);
+
+ if (dist < smallestDistSoFar) {
smallestDistSoFar = dist;
bestMatchingScreen = cl;
}
- }
+ }
}
if (bestMatchingScreen != mDragTargetLayout) {
@@ -1039,7 +1116,8 @@
int originX = x - xOffset;
int originY = y - yOffset;
if (mIsSmall || mIsInUnshrinkAnimation) {
- currentLayout = findMatchingPageForDragOver(dragView, originX, originY);
+ currentLayout = findMatchingPageForDragOver(
+ dragView, originX, originY, xOffset, yOffset);
if (currentLayout == null) {
return;
@@ -1049,7 +1127,7 @@
// get originX and originY in the local coordinate system of the screen
mTempOriginXY[0] = originX;
mTempOriginXY[1] = originY;
- mapPointGlobalToLocal(currentLayout, mTempOriginXY);
+ mapPointFromSelfToChild(currentLayout, mTempOriginXY);
originX = (int)mTempOriginXY[0];
originY = (int)mTempOriginXY[1];
} else {
@@ -1069,7 +1147,7 @@
}
}
- if (source != this) {
+ if (source instanceof AllAppsPagedView) {
// This is a hack to fix the point used to determine which cell an icon from the all
// apps screen is over
if (item != null && item.spanX == 1 && currentLayout != null) {
@@ -1233,7 +1311,8 @@
int xOffset, int yOffset, DragView dragView, Object dragInfo) {
CellLayout layout;
if (mIsSmall || mIsInUnshrinkAnimation) {
- layout = findMatchingPageForDragOver(dragView, x - xOffset, y - yOffset);
+ layout = findMatchingPageForDragOver(
+ dragView, x - xOffset, y - yOffset, xOffset, yOffset);
if (layout == null) {
// cancel the drag if we're not over a mini-screen at time of drop
return false;
diff --git a/src/com/android/launcher2/allapps.rs b/src/com/android/launcher2/allapps.rs
index acee82b..a9727fb 100644
--- a/src/com/android/launcher2/allapps.rs
+++ b/src/com/android/launcher2/allapps.rs
@@ -37,7 +37,6 @@
VpConsts_t *vpConstants;
-#pragma rs export_var(COLUMNS_PER_PAGE_PORTRAIT, ROWS_PER_PAGE_PORTRAIT, COLUMNS_PER_PAGE_LANDSCAPE, ROWS_PER_PAGE_LANDSCAPE, gIconCount, gSelectedIconIndex, gSelectedIconTexture, gHomeButton, gTargetPos, gPFTexNearest, gPFTexMip, gPFTexMipAlpha, gPVCurve, gPS, gSMCell, gIconIDs, gLabelIDs, vpConstants)
#pragma rs export_func(move, moveTo, setZoom, fling)
@@ -47,7 +46,7 @@
static float g_PhysicsTableSize = 7;
static float gZoomTarget;
-static float gTargetPos;
+float gTargetPos;
static float g_PosPage = 0.f;
static float g_PosVelocity = 0.f;
static float g_LastPositionX = 0.f;