Merge "Adding additional null checks for instances where the qsb is not defined. (Bug 6940769)" into jb-mr1-dev
diff --git a/res/drawable-sw720dp-hdpi/workspace_bg.9.png b/res/drawable-sw720dp-hdpi/workspace_bg.9.png
new file mode 100644
index 0000000..5bbfa4f
--- /dev/null
+++ b/res/drawable-sw720dp-hdpi/workspace_bg.9.png
Binary files differ
diff --git a/res/drawable-sw720dp-mdpi/workspace_bg.9.png b/res/drawable-sw720dp-mdpi/workspace_bg.9.png
new file mode 100644
index 0000000..2856e09
--- /dev/null
+++ b/res/drawable-sw720dp-mdpi/workspace_bg.9.png
Binary files differ
diff --git a/res/drawable-sw720dp-xhdpi/workspace_bg.9.png b/res/drawable-sw720dp-xhdpi/workspace_bg.9.png
new file mode 100644
index 0000000..72269f2
--- /dev/null
+++ b/res/drawable-sw720dp-xhdpi/workspace_bg.9.png
Binary files differ
diff --git a/res/layout-port/launcher.xml b/res/layout-port/launcher.xml
index 743ec51..a427501 100644
--- a/res/layout-port/launcher.xml
+++ b/res/layout-port/launcher.xml
@@ -63,16 +63,16 @@
         <include android:id="@+id/cell5" layout="@layout/workspace_screen" />
     </com.android.launcher2.Workspace>
 
-    <include
-        android:id="@+id/qsb_bar"
-        layout="@layout/qsb_bar" />
-
     <include layout="@layout/hotseat"
         android:id="@+id/hotseat"
         android:layout_width="match_parent"
         android:layout_height="@dimen/button_bar_height_plus_padding"
         android:layout_gravity="bottom" />
 
+    <include
+        android:id="@+id/qsb_bar"
+        layout="@layout/qsb_bar" />
+
     <com.android.launcher2.DrawableStateProxyView
         android:id="@+id/voice_button_proxy"
         android:layout_width="80dp"
diff --git a/res/layout-sw720dp-port/workspace_cling.xml b/res/layout-sw720dp-port/workspace_cling.xml
deleted file mode 100644
index 29bea81..0000000
--- a/res/layout-sw720dp-port/workspace_cling.xml
+++ /dev/null
@@ -1,52 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2011 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.
--->
-<com.android.launcher2.Cling
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
-    launcher:drawIdentifier="workspace_large">
-    <FrameLayout
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:layout_marginLeft="@dimen/cling_text_block_offset_x"
-        android:layout_marginTop="@dimen/cling_text_block_offset_y">
-        <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:orientation="vertical">
-            <TextView
-                style="@style/ClingTitleText"
-                android:text="@string/workspace_cling_title" />
-            <TextView
-                style="@style/ClingText"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:text="@string/workspace_cling_move_item" />
-            <Button
-                style="@style/ClingButton"
-                android:layout_marginTop="15dp"
-                android:onClick="dismissWorkspaceCling" />
-        </LinearLayout>
-    </FrameLayout>
-    <TextView
-        style="@style/ClingText"
-        android:layout_width="180dp"
-        android:layout_height="wrap_content"
-        android:layout_marginTop="15dp"
-        android:layout_marginRight="150dp"
-        android:layout_gravity="right"
-        android:gravity="right"
-        android:text="@string/workspace_cling_open_all_apps" />
-</com.android.launcher2.Cling>
diff --git a/res/layout-sw720dp/launcher.xml b/res/layout-sw720dp/launcher.xml
index a9c3c8d..9ddb135 100644
--- a/res/layout-sw720dp/launcher.xml
+++ b/res/layout-sw720dp/launcher.xml
@@ -63,16 +63,16 @@
         <include android:id="@+id/cell5" layout="@layout/workspace_screen" />
     </com.android.launcher2.Workspace>
 
-    <include
-        android:id="@+id/qsb_bar"
-        layout="@layout/qsb_bar" />
-
     <include layout="@layout/hotseat"
         android:id="@+id/hotseat"
         android:layout_width="match_parent"
         android:layout_height="@dimen/button_bar_height_plus_padding"
         android:layout_gravity="bottom" />
 
+    <include
+        android:id="@+id/qsb_bar"
+        layout="@layout/qsb_bar" />
+
     <com.android.launcher2.DrawableStateProxyView
         android:id="@+id/voice_button_proxy"
         android:layout_width="80dp"
diff --git a/res/layout-sw720dp/workspace_cling.xml b/res/layout-sw720dp/workspace_cling.xml
index fd7d4f8..10e6976 100644
--- a/res/layout-sw720dp/workspace_cling.xml
+++ b/res/layout-sw720dp/workspace_cling.xml
@@ -16,12 +16,13 @@
 <com.android.launcher2.Cling
     xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
-    launcher:drawIdentifier="workspace_large">
+    launcher:drawIdentifier="workspace_portrait">
     <FrameLayout
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:layout_marginLeft="@dimen/cling_text_block_offset_x"
-        android:layout_marginTop="@dimen/cling_text_block_offset_y">
+        android:layout_marginLeft="20dp"
+        android:layout_marginRight="20dp"
+        android:layout_marginTop="90dp">
         <LinearLayout
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
@@ -34,19 +35,22 @@
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:text="@string/workspace_cling_move_item" />
-            <Button
-                style="@style/ClingButton"
-                android:layout_marginTop="15dp"
-                android:onClick="dismissWorkspaceCling" />
         </LinearLayout>
     </FrameLayout>
     <TextView
         style="@style/ClingText"
-        android:layout_width="180dp"
+        android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_marginTop="90dp"
-        android:layout_marginRight="130dp"
-        android:layout_gravity="right"
-        android:gravity="right"
+        android:layout_marginLeft="20dp"
+        android:layout_marginRight="20dp"
+        android:layout_marginBottom="130dp"
+        android:layout_gravity="bottom"
+        android:gravity="center"
         android:text="@string/workspace_cling_open_all_apps" />
+    <Button
+        style="@style/ClingButton"
+        android:layout_marginBottom="15dp"
+        android:layout_marginRight="10dp"
+        android:layout_gravity="bottom|right"
+        android:onClick="dismissWorkspaceCling" />
 </com.android.launcher2.Cling>
diff --git a/res/values-sw600dp/config.xml b/res/values-sw600dp/config.xml
index 2a8e5df..bbb22c5 100644
--- a/res/values-sw600dp/config.xml
+++ b/res/values-sw600dp/config.xml
@@ -18,4 +18,8 @@
     <!-- Camera distance for the overscroll effect. We use a higher value here because the 
          workspace screens run nearly flush to the edge of the screen-->
     <integer name="config_cameraDistance">14000</integer>
+
+<!-- Hotseat -->
+    <!-- must be between 0 and 100 -->
+    <integer name="hotseat_item_scale_percentage">90</integer>
 </resources>
diff --git a/res/values/config.xml b/res/values/config.xml
index 381ef1b..8717f6a 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -82,4 +82,6 @@
     <bool name="hotseat_transpose_layout_with_orientation">true</bool>
     <integer name="hotseat_cell_count">5</integer>
     <integer name="hotseat_all_apps_index">2</integer>
+    <!-- must be between 0 and 100 -->
+    <integer name="hotseat_item_scale_percentage">100</integer>
 </resources>
diff --git a/src/com/android/launcher2/CellLayout.java b/src/com/android/launcher2/CellLayout.java
index 44944fe..4f4ef4e 100644
--- a/src/com/android/launcher2/CellLayout.java
+++ b/src/com/android/launcher2/CellLayout.java
@@ -137,6 +137,7 @@
     private ShortcutAndWidgetContainer mShortcutsAndWidgets;
 
     private boolean mIsHotseat = false;
+    private float mHotseatScale = 1f;
 
     public static final int MODE_DRAG_OVER = 0;
     public static final int MODE_ON_DROP = 1;
@@ -199,6 +200,7 @@
         setAlwaysDrawnWithCacheEnabled(false);
 
         final Resources res = getResources();
+        mHotseatScale = (res.getInteger(R.integer.hotseat_item_scale_percentage) / 100f);
 
         mNormalBackground = res.getDrawable(R.drawable.homescreen_blue_normal_holo);
         mActiveGlowBackground = res.getDrawable(R.drawable.homescreen_blue_strong_holo);
@@ -316,6 +318,10 @@
         mShortcutsAndWidgets.buildLayer();
     }
 
+    public float getChildrenScale() {
+        return mIsHotseat ? mHotseatScale : 1.0f;
+    }
+
     public void setGridSize(int x, int y) {
         mCountX = x;
         mCountY = y;
@@ -386,6 +392,25 @@
         }
     }
 
+    public void scaleRect(Rect r, float scale) {
+        if (scale != 1.0f) {
+            r.left = (int) (r.left * scale + 0.5f);
+            r.top = (int) (r.top * scale + 0.5f);
+            r.right = (int) (r.right * scale + 0.5f);
+            r.bottom = (int) (r.bottom * scale + 0.5f);
+        }
+    }
+
+    Rect temp = new Rect();
+    void scaleRectAboutCenter(Rect in, Rect out, float scale) {
+        int cx = in.centerX();
+        int cy = in.centerY();
+        out.set(in);
+        out.offset(-cx, -cy);
+        scaleRect(out, scale);
+        out.offset(cx, cy);
+    }
+
     @Override
     protected void onDraw(Canvas canvas) {
         // When we're large, we are either drawn in a "hover" state (ie when dragging an item to
@@ -413,9 +438,10 @@
             final float alpha = mDragOutlineAlphas[i];
             if (alpha > 0) {
                 final Rect r = mDragOutlines[i];
+                scaleRectAboutCenter(r, temp, getChildrenScale());
                 final Bitmap b = (Bitmap) mDragOutlineAnims[i].getTag();
                 paint.setAlpha((int)(alpha + .5f));
-                canvas.drawBitmap(b, null, r, paint);
+                canvas.drawBitmap(b, null, temp, paint);
             }
         }
 
@@ -590,6 +616,9 @@
             }
         }
 
+        child.setScaleX(getChildrenScale());
+        child.setScaleY(getChildrenScale());
+
         // Generate an id for each view, this assumes we have at most 256x256 cells
         // per workspace screen
         if (lp.cellX >= 0 && lp.cellX <= mCountX - 1 && lp.cellY >= 0 && lp.cellY <= mCountY - 1) {
@@ -2071,11 +2100,8 @@
             }
             initDeltaX = child.getTranslationX();
             initDeltaY = child.getTranslationY();
-            finalScale = 1.0f - 4.0f / child.getWidth();
+            finalScale = getChildrenScale() - 4.0f / child.getWidth();
             initScale = child.getScaleX();
-
-            child.setPivotY(child.getMeasuredHeight() * 0.5f);
-            child.setPivotX(child.getMeasuredWidth() * 0.5f);
             this.child = child;
         }
 
@@ -2116,7 +2142,7 @@
                     // We make sure to end only after a full period
                     initDeltaX = 0;
                     initDeltaY = 0;
-                    initScale = 1.0f;
+                    initScale = getChildrenScale();
                 }
             });
             mShakeAnimators.put(child, this);
@@ -2137,8 +2163,8 @@
             AnimatorSet s = LauncherAnimUtils.createAnimatorSet();
             a = s;
             s.playTogether(
-                LauncherAnimUtils.ofFloat(child, "scaleX", 1f),
-                LauncherAnimUtils.ofFloat(child, "scaleY", 1f),
+                LauncherAnimUtils.ofFloat(child, "scaleX", getChildrenScale()),
+                LauncherAnimUtils.ofFloat(child, "scaleY", getChildrenScale()),
                 LauncherAnimUtils.ofFloat(child, "translationX", 0f),
                 LauncherAnimUtils.ofFloat(child, "translationY", 0f)
             );
diff --git a/src/com/android/launcher2/DragLayer.java b/src/com/android/launcher2/DragLayer.java
index 0bcd64c..fed0ad9 100644
--- a/src/com/android/launcher2/DragLayer.java
+++ b/src/com/android/launcher2/DragLayer.java
@@ -274,10 +274,10 @@
         return scale;
     }
 
-    public void getLocationInDragLayer(View child, int[] loc) {
+    public float getLocationInDragLayer(View child, int[] loc) {
         loc[0] = 0;
         loc[1] = 0;
-        getDescendantCoordRelativeToSelf(child, loc);
+        return getDescendantCoordRelativeToSelf(child, loc);
     }
 
     /**
@@ -286,7 +286,9 @@
      *
      * @param descendant The descendant to which the passed coordinate is relative.
      * @param coord The coordinate that we want mapped.
-     * @return The factor by which this descendant is scaled relative to this DragLayer.
+     * @return The factor by which this descendant is scaled relative to this DragLayer. Caution
+     *         this scale factor is assumed to be equal in X and Y, and so if at any point this
+     *         assumption fails, we will need to return a pair of scale factors.
      */
     public float getDescendantCoordRelativeToSelf(View descendant, int[] coord) {
         float scale = 1.0f;
@@ -451,12 +453,16 @@
         getViewRectRelativeToSelf(dragView, r);
 
         int coord[] = new int[2];
-        coord[0] = lp.x;
-        coord[1] = lp.y;
+        float childScale = child.getScaleX();
+        coord[0] = lp.x + (int) (child.getMeasuredWidth() * (1 - childScale) / 2);
+        coord[1] = lp.y + (int) (child.getMeasuredHeight() * (1 - childScale) / 2);
 
         // Since the child hasn't necessarily been laid out, we force the lp to be updated with
         // the correct coordinates (above) and use these to determine the final location
         float scale = getDescendantCoordRelativeToSelf((View) child.getParent(), coord);
+        // We need to account for the scale of the child itself, as the above only accounts for
+        // for the scale in parents.
+        scale *= childScale;
         int toX = coord[0];
         int toY = coord[1];
         if (child instanceof TextView) {
@@ -470,7 +476,8 @@
             toX -= (dragView.getMeasuredWidth() - Math.round(scale * child.getMeasuredWidth())) / 2;
         } else if (child instanceof FolderIcon) {
             // Account for holographic blur padding on the drag view
-            toY -= Workspace.DRAG_BITMAP_PADDING / 2;
+            toY -= scale * Workspace.DRAG_BITMAP_PADDING / 2;
+            toY -= (1 - scale) * dragView.getMeasuredHeight() / 2;
             // Center in the x coordinate about the target's drawable
             toX -= (dragView.getMeasuredWidth() - Math.round(scale * child.getMeasuredWidth())) / 2;
         } else {
@@ -698,13 +705,10 @@
 
     @Override
     protected int getChildDrawingOrder(int childCount, int i) {
-        // We don't want to prioritize the workspace drawing on top of the other children in
-        // landscape for the overscroll event.
-        if (LauncherApplication.isScreenLandscape(getContext())) {
-            return super.getChildDrawingOrder(childCount, i);
-        }
-
-        if (mWorkspaceIndex == -1 || mQsbIndex == -1 || 
+        // TODO: We have turned off this custom drawing order because it now effects touch
+        // dispatch order. We need to sort that issue out and then decide how to go about this.
+        if (true || LauncherApplication.isScreenLandscape(getContext()) ||
+                mWorkspaceIndex == -1 || mQsbIndex == -1 ||
                 mLauncher.getWorkspace().isDrawingBackgroundGradient()) {
             return i;
         }
diff --git a/src/com/android/launcher2/DragView.java b/src/com/android/launcher2/DragView.java
index 389421d..e6b15b8 100644
--- a/src/com/android/launcher2/DragView.java
+++ b/src/com/android/launcher2/DragView.java
@@ -75,6 +75,10 @@
         final float scaleDps = res.getDimensionPixelSize(R.dimen.dragViewScale);
         final float scale = (width + scaleDps) / width;
 
+        // Set the initial scale to avoid any jumps
+        setScaleX(initialScale);
+        setScaleY(initialScale);
+
         // Animate the view into the correct position
         mAnim = LauncherAnimUtils.ofFloat(0.0f, 1.0f);
         mAnim.setDuration(150);
diff --git a/src/com/android/launcher2/Folder.java b/src/com/android/launcher2/Folder.java
index 8aa6e2f..5feac2f 100644
--- a/src/com/android/launcher2/Folder.java
+++ b/src/com/android/launcher2/Folder.java
@@ -805,10 +805,10 @@
                 + mFolderNameHeight;
         DragLayer parent = (DragLayer) mLauncher.findViewById(R.id.drag_layer);
 
-        parent.getDescendantRectRelativeToSelf(mFolderIcon, mTempRect);
+        float scale = parent.getDescendantRectRelativeToSelf(mFolderIcon, mTempRect);
 
-        int centerX = mTempRect.centerX();
-        int centerY = mTempRect.centerY();
+        int centerX = (int) (mTempRect.left + mTempRect.width() * scale / 2);
+        int centerY = (int) (mTempRect.top + mTempRect.height() * scale / 2);
         int centeredLeft = centerX - width / 2;
         int centeredTop = centerY - height / 2;
 
diff --git a/src/com/android/launcher2/Hotseat.java b/src/com/android/launcher2/Hotseat.java
index 38feaa4..c122695 100644
--- a/src/com/android/launcher2/Hotseat.java
+++ b/src/com/android/launcher2/Hotseat.java
@@ -38,7 +38,7 @@
     private int mCellCountX;
     private int mCellCountY;
     private int mAllAppsButtonRank;
-    
+
     private boolean mTransposeLayoutWithOrientation;
     private boolean mIsLandscape;
 
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index e6b237b..1e138f7 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -2134,12 +2134,14 @@
             lp = new DragLayer.LayoutParams(width, height);
         }
 
-        mDragLayer.getViewRectRelativeToSelf(fi, mRectForFolderAnimation);
+        // The layout from which the folder is being opened may be scaled, adjust the starting
+        // view size by this scale factor.
+        float scale = mDragLayer.getDescendantRectRelativeToSelf(fi, mRectForFolderAnimation);
         lp.customPosition = true;
         lp.x = mRectForFolderAnimation.left;
         lp.y = mRectForFolderAnimation.top;
-        lp.width = width;
-        lp.height = height;
+        lp.width = (int) (scale * width);
+        lp.height = (int) (scale * height);
 
         mFolderIconCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
         fi.draw(mFolderIconCanvas);
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index d1d47f5..504f9dc 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -1892,11 +1892,11 @@
         final int bmpWidth = b.getWidth();
         final int bmpHeight = b.getHeight();
 
-        mLauncher.getDragLayer().getLocationInDragLayer(child, mTempXY);
+        float scale = mLauncher.getDragLayer().getLocationInDragLayer(child, mTempXY);
         int dragLayerX =
-                Math.round(mTempXY[0] - (bmpWidth - child.getScaleX() * child.getWidth()) / 2);
+                Math.round(mTempXY[0] - (bmpWidth - scale * child.getWidth()) / 2);
         int dragLayerY =
-                Math.round(mTempXY[1] - (bmpHeight - child.getScaleY() * bmpHeight) / 2
+                Math.round(mTempXY[1] - (bmpHeight - scale * bmpHeight) / 2
                         - DRAG_BITMAP_PADDING / 2);
 
         Point dragVisualizeOffset = null;
@@ -1926,7 +1926,7 @@
         }
 
         mDragController.startDrag(b, dragLayerX, dragLayerY, source, child.getTag(),
-                DragController.DRAG_ACTION_MOVE, dragVisualizeOffset, dragRect, child.getScaleX());
+                DragController.DRAG_ACTION_MOVE, dragVisualizeOffset, dragRect, scale);
         b.recycle();
 
         // Show the scrolling indicator when you pick up an item
@@ -1966,7 +1966,7 @@
 
             // We want the point to be mapped to the dragTarget.
             if (mLauncher.isHotseatLayout(dropTargetLayout)) {
-                mapPointFromSelfToSibling(mLauncher.getHotseat(), mDragViewVisualCenter);
+                mapPointFromSelfToHotseatLayout(mLauncher.getHotseat(), mDragViewVisualCenter);
             } else {
                 mapPointFromSelfToChild(dropTargetLayout, mDragViewVisualCenter, null);
             }
@@ -2577,18 +2577,12 @@
        cachedInverseMatrix.mapPoints(xy);
    }
 
-   /*
-    * Maps a point from the Workspace's coordinate system to another sibling view's. (Workspace
-    * covers the full screen)
-    */
-   void mapPointFromSelfToSibling(View v, float[] xy) {
-       xy[0] = xy[0] - v.getLeft();
-       xy[1] = xy[1] - v.getTop();
-   }
 
    void mapPointFromSelfToHotseatLayout(Hotseat hotseat, float[] xy) {
+       hotseat.getLayout().getMatrix().invert(mTempInverseMatrix);
        xy[0] = xy[0] - hotseat.getLeft() - hotseat.getLayout().getLeft();
        xy[1] = xy[1] - hotseat.getTop() - hotseat.getLayout().getTop();
+       mTempInverseMatrix.mapPoints(xy);
    }
 
    /*