Merge "Fix 3369762: long press should take you into customization mode" into honeycomb
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 6cdf205..f9750ca 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -95,6 +95,8 @@
                 <action android:name="android.intent.action.SET_WALLPAPER" />
                 <category android:name="android.intent.category.DEFAULT" />
             </intent-filter>
+            <meta-data android:name="android.wallpaper.preview"
+                android:resource="@xml/wallpaper_picker_preview" />
         </activity>
 
         <!-- Intent received used to install shortcuts from other applications -->
diff --git a/proguard.flags b/proguard.flags
index 1af3702..699f23e 100644
--- a/proguard.flags
+++ b/proguard.flags
@@ -20,21 +20,15 @@
   public void setHoverAlpha(float);
 }
 
--keep class com.android.launcher2.DimmableBubbleTextView {
-  public float getDimmableProgress();
-  public void setDimmableProgress(float);
-}
-
--keep class com.android.launcher2.DimmableAppWidgetHostView {
-  public float getDimmableProgress();
-  public void setDimmableProgress(float);
-}
-
 -keep class com.android.launcher2.Workspace {
   public float getBackgroundAlpha();
   public void setBackgroundAlpha(float);
   public float getChildrenOutlineAlpha();
   public void setChildrenOutlineAlpha(float);
+  public void setVerticalWallpaperOffset(float);
+  public float getVerticalWallpaperOffset();
+  public void setHorizontalWallpaperOffset(float);
+  public float getHorizontalWallpaperOffset();
 }
 
 -keep class com.android.launcher2.AllApps3D$Defines {
diff --git a/res/drawable-xlarge-nodpi/all_apps_bg_gradient.9.png b/res/drawable-xlarge-nodpi/all_apps_bg_gradient.9.png
index 8d88a7e..3f4b5b5 100644
--- a/res/drawable-xlarge-nodpi/all_apps_bg_gradient.9.png
+++ b/res/drawable-xlarge-nodpi/all_apps_bg_gradient.9.png
Binary files differ
diff --git a/res/drawable/wallpaper_picker_preview.png b/res/drawable/wallpaper_picker_preview.png
new file mode 100644
index 0000000..926a99c
--- /dev/null
+++ b/res/drawable/wallpaper_picker_preview.png
Binary files differ
diff --git a/res/layout-xlarge/all_apps_no_items_placeholder.xml b/res/layout-xlarge/all_apps_no_items_placeholder.xml
index f5ecdec..247870c 100644
--- a/res/layout-xlarge/all_apps_no_items_placeholder.xml
+++ b/res/layout-xlarge/all_apps_no_items_placeholder.xml
@@ -20,7 +20,7 @@
     android:id="@+id/no_items_icon"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:gravity="center_vertical"
+    android:gravity="center"
     android:paddingTop="2dip"
 
     android:textColor="#FFFFFFFF"
@@ -29,7 +29,6 @@
     android:shadowDx="0.0"
     android:shadowDy="1.0"
     android:shadowRadius="1.0"
-    android:drawableLeft="@drawable/ic_no_applications"
     android:drawablePadding="0dip"
 
     android:maxLines="2"
diff --git a/res/values-es-rUS-xlarge/strings.xml b/res/values-es-rUS-xlarge/strings.xml
index 7c8b273..a433f4f 100644
--- a/res/values-es-rUS-xlarge/strings.xml
+++ b/res/values-es-rUS-xlarge/strings.xml
@@ -16,14 +16,10 @@
     <!-- XL -->
     <string name="wallpapers_temp_tab_text" msgid="1406600851510062325">"Ésta será la pestaña para los fondos de pantalla"</string>
     <!-- XL -->
-    <string name="all_apps_tab_apps" msgid="827864997519186499">"Google Apps"</string>
-    <!-- XL -->
     <string name="all_apps_no_downloads" msgid="6687010155766000796">"No se encontraron apps."</string>
     <!-- XL -->
     <string name="group_wallpapers" msgid="5356616257147378618">"Fondos de pantalla"</string>
     <!-- XL -->
-    <string name="all_apps_button_label" msgid="825988103463804114">"Google Apps"</string>
-    <!-- XL -->
     <string name="all_apps_home_button_label" msgid="4573985169183891042">"Pantalla principal"</string>
     <!-- XL -->
     <string name="delete_zone_label_workspace" msgid="7170653385628744300">"Eliminar"</string>
diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml
index d10441b..ef4f0bb 100644
--- a/res/values-sr/strings.xml
+++ b/res/values-sr/strings.xml
@@ -64,8 +64,7 @@
     <string name="title_select_live_folder" msgid="3753447798805166749">"Избор директоријума"</string>
     <string name="all_apps_button_label" msgid="2578400570124163469">"Apps"</string>
     <string name="all_apps_home_button_label" msgid="1022222300329398558">"Почетна"</string>
-    <!-- no translation found for delete_zone_label_workspace (7153615831493049150) -->
-    <skip />
+    <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Уклони"</string>
     <!-- no translation found for delete_zone_label_all_apps (6664588234817475108) -->
     <skip />
     <string name="menu_add" msgid="3065046628354640854">"Додај"</string>
diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml
index e7f638e..63b2450 100644
--- a/res/values-uk/strings.xml
+++ b/res/values-uk/strings.xml
@@ -64,8 +64,7 @@
     <string name="title_select_live_folder" msgid="3753447798805166749">"Виберіть папку"</string>
     <string name="all_apps_button_label" msgid="2578400570124163469">"Прогр."</string>
     <string name="all_apps_home_button_label" msgid="1022222300329398558">"Головна"</string>
-    <!-- no translation found for delete_zone_label_workspace (7153615831493049150) -->
-    <skip />
+    <string name="delete_zone_label_workspace" msgid="7153615831493049150">"Видалити"</string>
     <!-- no translation found for delete_zone_label_all_apps (6664588234817475108) -->
     <skip />
     <string name="menu_add" msgid="3065046628354640854">"Додати"</string>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index addea4b..f473880 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -70,8 +70,8 @@
     <!-- All Apps pane -->
     <!-- Message to show when there are no games [CHAR_LIMIT=25] -->
     <string name="all_apps_no_games">No games found.</string>
-    <!-- Message to show when there are no downloaded apps [CHAR_LIMIT=25] -->
-    <string name="all_apps_no_downloads">No downloaded apps found.</string>
+    <!-- Message to show when there are no downloaded apps [CHAR_LIMIT=50] -->
+    <string name="all_apps_no_downloads">You have no downloaded applications.</string>
 
     <!-- Customization Drawer -->
     <!-- The format string for the dimensions of a widget in the drawer -->
diff --git a/res/xml/wallpaper_picker_preview.xml b/res/xml/wallpaper_picker_preview.xml
new file mode 100644
index 0000000..d52e0e0
--- /dev/null
+++ b/res/xml/wallpaper_picker_preview.xml
@@ -0,0 +1,20 @@
+<?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.
+-->
+
+<wallpaper-preview
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:staticWallpaperPreview="@drawable/wallpaper_picker_preview">
+</wallpaper-preview>
\ No newline at end of file
diff --git a/src/com/android/launcher2/AllAppsPagedView.java b/src/com/android/launcher2/AllAppsPagedView.java
index ef9e3fa..64da1b4 100644
--- a/src/com/android/launcher2/AllAppsPagedView.java
+++ b/src/com/android/launcher2/AllAppsPagedView.java
@@ -511,7 +511,7 @@
             layout.enableCenteredContent(true);
             layout.removeAllViews();
             layout.addViewToCellLayout(icon, -1, 0,
-                    new PagedViewCellLayout.LayoutParams(0, 0, 2, 1));
+                    new PagedViewCellLayout.LayoutParams(0, 0, 4, 1));
         }
     }
 
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index 5ff380e..8255ded 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -2752,8 +2752,6 @@
             toView.setVisibility(View.VISIBLE);
             hideAndShowToolbarButtons(toState, null, null);
         }
-        mWorkspace.setVerticalWallpaperOffset(toAllApps ?
-                Workspace.WallpaperVerticalOffset.TOP  : Workspace.WallpaperVerticalOffset.BOTTOM);
     }
 
     /**
@@ -2828,7 +2826,6 @@
                 hideAndShowToolbarButtons(State.WORKSPACE, null, null);
             }
         }
-        mWorkspace.setVerticalWallpaperOffset(Workspace.WallpaperVerticalOffset.MIDDLE);
     }
 
     /**
@@ -2906,8 +2903,6 @@
             toView.setVisibility(View.VISIBLE);
             hideAndShowToolbarButtons(toState, null, null);
         }
-        mWorkspace.setVerticalWallpaperOffset((toState == State.ALL_APPS) ?
-                Workspace.WallpaperVerticalOffset.TOP : Workspace.WallpaperVerticalOffset.BOTTOM);
     }
 
     void showAllApps(boolean animated) {
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index af7d080..d3d8175 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -206,13 +206,9 @@
     enum WallpaperVerticalOffset { TOP, MIDDLE, BOTTOM };
     int mWallpaperWidth;
     int mWallpaperHeight;
-    float mTargetHorizontalWallpaperOffset = 0.0f;
-    float mTargetVerticalWallpaperOffset = 0.5f;
-    float mHorizontalWallpaperOffset = 0.0f;
-    float mVerticalWallpaperOffset = 0.5f;
-    long mLastWallpaperOffsetUpdateTime;
-    boolean mWallpaperOffsetDirty;
+    WallpaperOffsetInterpolator mWallpaperOffset;
     boolean mUpdateWallpaperOffsetImmediately = false;
+    boolean mSyncWallpaperOffsetWithScroll = true;
 
     /**
      * Used to inflate the Workspace from XML.
@@ -283,6 +279,7 @@
             @Override
             public void onAnimationEnd(Animator animation) {
                 mIsInUnshrinkAnimation = false;
+                mSyncWallpaperOffsetWithScroll = true;
                 if (mShrinkState != ShrinkState.SPRING_LOADED) {
                     mDrawCustomizeTrayBackground = false;
                 }
@@ -302,6 +299,7 @@
             }
         };
         mSnapVelocity = 600;
+        mWallpaperOffset = new WallpaperOffsetInterpolator();
     }
 
     @Override
@@ -610,55 +608,48 @@
         mWallpaperManager.suggestDesiredDimensions(mWallpaperWidth, mWallpaperHeight);
     }
 
-    public void setVerticalWallpaperOffset(WallpaperVerticalOffset offsetPosition) {
-        float offset = 0.5f;
-        Display display = mLauncher.getWindowManager().getDefaultDisplay();
-        int wallpaperTravelHeight = (int) (display.getHeight() *
-                wallpaperTravelToScreenHeightRatio(display.getWidth(), display.getHeight()));
-        float offsetFromCenter = (wallpaperTravelHeight / (float) mWallpaperHeight) / 2f;
-        switch (offsetPosition) {
-            case TOP:
-                offset = 0.5f - offsetFromCenter;
-                break;
-            case MIDDLE:
-                offset = 0.5f;
-                break;
-            case BOTTOM:
-                offset = 0.5f + offsetFromCenter;
-                break;
-        }
-        mTargetVerticalWallpaperOffset = offset;
-        mWallpaperOffsetDirty = true;
+    public void setVerticalWallpaperOffset(float offset) {
+        mWallpaperOffset.setFinalY(offset);
+    }
+    public float getVerticalWallpaperOffset() {
+        return mWallpaperOffset.getCurrY();
+    }
+    public void setHorizontalWallpaperOffset(float offset) {
+        mWallpaperOffset.setFinalX(offset);
+    }
+    public float getHorizontalWallpaperOffset() {
+        return mWallpaperOffset.getCurrX();
     }
 
-    private void updateHorizontalWallpaperOffset() {
+    private float wallpaperOffsetForCurrentScroll() {
+        Display display = mLauncher.getWindowManager().getDefaultDisplay();
+        // The wallpaper travel width is how far, from left to right, the wallpaper will move
+        // at this orientation (for example, in portrait mode we don't move all the way to the
+        // edges of the wallpaper, or otherwise the parallax effect would be too strong)
+        int wallpaperTravelWidth = (int) (display.getWidth() *
+                wallpaperTravelToScreenWidthRatio(display.getWidth(), display.getHeight()));
+
+        // Account for overscroll: you only see the absolute edge of the wallpaper if
+        // you overscroll as far as you can in landscape mode
+        int overscrollOffset = (int) (maxOverScroll() * display.getWidth());
+        float overscrollRatio = overscrollOffset / (float) getScrollRange();
+        int scrollRangeWithOverscroll = getScrollRange() + 2 * overscrollOffset;
+
+        // Set wallpaper offset steps (1 / (number of screens - 1))
+        // We have 3 vertical offset states (centered, and then top/bottom aligned
+        // for all apps/customize)
+        mWallpaperManager.setWallpaperOffsetSteps(1.0f / (getChildCount() - 1), 1.0f / (3 - 1));
+
+        float scrollProgress =
+            mScrollX / (float) scrollRangeWithOverscroll + overscrollRatio;
+        float offsetInDips = wallpaperTravelWidth * scrollProgress +
+            (mWallpaperWidth - wallpaperTravelWidth) / 2;
+        float offset = offsetInDips / (float) mWallpaperWidth;
+        return offset;
+    }
+    private void syncWallpaperOffsetWithScroll() {
         if (LauncherApplication.isScreenXLarge()) {
-            Display display = mLauncher.getWindowManager().getDefaultDisplay();
-            // The wallpaper travel width is how far, from left to right, the wallpaper will move
-            // at this orientation (for example, in portrait mode we don't move all the way to the
-            // edges of the wallpaper, or otherwise the parallax effect would be too strong)
-            int wallpaperTravelWidth = (int) (display.getWidth() *
-                    wallpaperTravelToScreenWidthRatio(display.getWidth(), display.getHeight()));
-
-            // Account for overscroll: you only see the absolute edge of the wallpaper if
-            // you overscroll as far as you can in landscape mode
-            int overscrollOffset = (int) (maxOverScroll() * display.getWidth());
-            float overscrollRatio = overscrollOffset / (float) getScrollRange();
-            int scrollRangeWithOverscroll = getScrollRange() + 2 * overscrollOffset;
-
-            // Set wallpaper offset steps (1 / (number of screens - 1))
-            // We have 3 vertical offset states (centered, and then top/bottom aligned
-            // for all apps/customize)
-            mWallpaperManager.setWallpaperOffsetSteps(1.0f / (getChildCount() - 1), 1.0f / (3 - 1));
-
-            float scrollProgress =
-                mScrollX / (float) scrollRangeWithOverscroll + overscrollRatio;
-            float offsetInDips = wallpaperTravelWidth * scrollProgress +
-                (mWallpaperWidth - wallpaperTravelWidth) / 2;
-            float offset = offsetInDips / (float) mWallpaperWidth;
-
-            mTargetHorizontalWallpaperOffset = Math.max(0f, Math.min(offset, 1.0f));
-            mWallpaperOffsetDirty = true;
+            mWallpaperOffset.setFinalX(wallpaperOffsetForCurrentScroll());
         }
     }
 
@@ -666,48 +657,112 @@
         mUpdateWallpaperOffsetImmediately = true;
     }
 
-    private void updateWallpaperOffsets(boolean immediate) {
-        long currentTime = System.currentTimeMillis();
-        long millisecondsSinceLastUpdate = currentTime - mLastWallpaperOffsetUpdateTime;
-        millisecondsSinceLastUpdate = Math.min((long) (1000/30f), millisecondsSinceLastUpdate);
-        millisecondsSinceLastUpdate = Math.min(1L, millisecondsSinceLastUpdate);
-        final float PERCENT_TO_CATCH_UP_IN_100_MS_HORIZONTAL = 25f;
-        final float PERCENT_TO_CATCH_UP_IN_100_MS_VERTICAL = 25f;
-        final float UPDATE_THRESHOLD = 0.0001f;
-        float hOffsetDelta = mTargetHorizontalWallpaperOffset - mHorizontalWallpaperOffset;
-        float vOffsetDelta = mTargetVerticalWallpaperOffset - mVerticalWallpaperOffset;
-        boolean stopUpdating =
-            Math.abs(hOffsetDelta / mTargetHorizontalWallpaperOffset) < UPDATE_THRESHOLD &&
-            Math.abs(vOffsetDelta / mTargetVerticalWallpaperOffset) < UPDATE_THRESHOLD;
-
-        if (stopUpdating || immediate) {
-            mHorizontalWallpaperOffset = mTargetHorizontalWallpaperOffset;
-            mVerticalWallpaperOffset = mTargetVerticalWallpaperOffset;
+    private void updateWallpaperOffsets() {
+        boolean updateNow = false;
+        boolean keepUpdating = true;
+        if (mUpdateWallpaperOffsetImmediately) {
+            updateNow = true;
+            keepUpdating = false;
+            mWallpaperOffset.jumpToFinal();
+            mUpdateWallpaperOffsetImmediately = false;
         } else {
-            float percentToCatchUpVertical =
-                millisecondsSinceLastUpdate / 100f * PERCENT_TO_CATCH_UP_IN_100_MS_VERTICAL;
-            float percentToCatchUpHorizontal =
-                millisecondsSinceLastUpdate / 100f * PERCENT_TO_CATCH_UP_IN_100_MS_HORIZONTAL;
-            mHorizontalWallpaperOffset += percentToCatchUpHorizontal * hOffsetDelta;
-            mVerticalWallpaperOffset +=
-                percentToCatchUpVertical * (mTargetVerticalWallpaperOffset - mVerticalWallpaperOffset);
+            updateNow = keepUpdating = mWallpaperOffset.computeScrollOffset();
         }
-        IBinder token = getWindowToken();
-        if (token != null) {
-            mWallpaperManager.setWallpaperOffsets(getWindowToken(),
-                    mHorizontalWallpaperOffset, mVerticalWallpaperOffset);
+        if (updateNow) {
+            IBinder token = getWindowToken();
+            if (token != null) {
+                mWallpaperManager.setWallpaperOffsets(getWindowToken(),
+                        mWallpaperOffset.getCurrX(), mWallpaperOffset.getCurrY());
+            }
         }
-        if (!stopUpdating && !immediate) {
+        if (keepUpdating) {
             invalidate();
-            mWallpaperOffsetDirty = true;
         }
-        mLastWallpaperOffsetUpdateTime = System.currentTimeMillis();
+    }
+
+    class WallpaperOffsetInterpolator {
+        float mFinalHorizontalWallpaperOffset = 0.0f;
+        float mFinalVerticalWallpaperOffset = 0.5f;
+        float mHorizontalWallpaperOffset = 0.0f;
+        float mVerticalWallpaperOffset = 0.5f;
+        long mLastWallpaperOffsetUpdateTime;
+
+        public WallpaperOffsetInterpolator() {
+        }
+
+        public boolean computeScrollOffset() {
+            if (Float.compare(mHorizontalWallpaperOffset, mFinalHorizontalWallpaperOffset) == 0 &&
+                    Float.compare(mVerticalWallpaperOffset, mFinalVerticalWallpaperOffset) == 0) {
+                return false;
+            }
+            Display display = mLauncher.getWindowManager().getDefaultDisplay();
+            boolean isLandscape = display.getWidth() > display.getHeight();
+
+            long currentTime = System.currentTimeMillis();
+            long timeSinceLastUpdate = currentTime - mLastWallpaperOffsetUpdateTime;
+            timeSinceLastUpdate = Math.min((long) (1000/30f), timeSinceLastUpdate);
+            timeSinceLastUpdate = Math.max(1L, timeSinceLastUpdate);
+            // ie 75% in 100ms
+            float fractionToCatchUpIn1MsHorizontal = isLandscape ? 0.75f / 100 : 0.75f / 100;
+            float fractionToCatchUpIn1MsVertical = isLandscape ? 1.1f / 100 : 1.1f / 100;
+
+            final float UPDATE_THRESHOLD = 0.00001f;
+            float hOffsetDelta = mFinalHorizontalWallpaperOffset - mHorizontalWallpaperOffset;
+            float vOffsetDelta = mFinalVerticalWallpaperOffset - mVerticalWallpaperOffset;
+            boolean jumpToFinalValue =
+                Math.abs(hOffsetDelta / mFinalHorizontalWallpaperOffset) < UPDATE_THRESHOLD &&
+                Math.abs(vOffsetDelta / mFinalVerticalWallpaperOffset) < UPDATE_THRESHOLD;
+            if (jumpToFinalValue) {
+                mHorizontalWallpaperOffset = mFinalHorizontalWallpaperOffset;
+                mVerticalWallpaperOffset = mFinalVerticalWallpaperOffset;
+            } else {
+                float percentToCatchUpVertical =
+                    timeSinceLastUpdate * fractionToCatchUpIn1MsVertical;
+                float percentToCatchUpHorizontal =
+                    timeSinceLastUpdate * fractionToCatchUpIn1MsHorizontal;
+                mHorizontalWallpaperOffset += percentToCatchUpHorizontal * hOffsetDelta;
+                mVerticalWallpaperOffset += percentToCatchUpVertical * vOffsetDelta;
+            }
+            mLastWallpaperOffsetUpdateTime = System.currentTimeMillis();
+            return true;
+        }
+
+        public float getCurrX() {
+            return mHorizontalWallpaperOffset;
+        }
+
+        public float getFinalX() {
+            return mFinalHorizontalWallpaperOffset;
+        }
+
+        public float getCurrY() {
+            return mVerticalWallpaperOffset;
+        }
+
+        public float getFinalY() {
+            return mFinalVerticalWallpaperOffset;
+        }
+
+        public void setFinalX(float x) {
+            mFinalHorizontalWallpaperOffset = Math.max(0f, Math.min(x, 1.0f));
+        }
+
+        public void setFinalY(float y) {
+            mFinalVerticalWallpaperOffset = Math.max(0f, Math.min(y, 1.0f));
+        }
+
+        public void jumpToFinal() {
+            mHorizontalWallpaperOffset = mFinalHorizontalWallpaperOffset;
+            mVerticalWallpaperOffset = mFinalVerticalWallpaperOffset;
+        }
     }
 
     @Override
     public void computeScroll() {
         super.computeScroll();
-        updateHorizontalWallpaperOffset();
+        if (mSyncWallpaperOffsetWithScroll) {
+            syncWallpaperOffsetWithScroll();
+        }
     }
 
     public void showOutlines() {
@@ -856,7 +911,6 @@
                 } else if (mOverScrollPageIndex != i) {
                     cl.setBackgroundAlphaMultiplier(
                             backgroundAlphaInterpolator(Math.abs(scrollProgress)));
-
                 }
 
                 float rotation = WORKSPACE_ROTATION * scrollProgress;
@@ -919,11 +973,7 @@
 
     @Override
     protected void onDraw(Canvas canvas) {
-        if (mWallpaperOffsetDirty) {
-            updateWallpaperOffsets(mUpdateWallpaperOffsetImmediately);
-            mWallpaperOffsetDirty = false;
-            mUpdateWallpaperOffsetImmediately = false;
-        }
+        updateWallpaperOffsets();
 
         // Draw the background gradient if necessary
         if (mBackground != null && mBackgroundAlpha > 0.0f) {
@@ -1142,25 +1192,30 @@
             mWaitingToShrinkState = shrinkState;
             return;
         }
-        mIsSmall = true;
-        mShrinkState = shrinkState;
-
         // Stop any scrolling, move to the current page right away
         setCurrentPage((mNextPage != INVALID_PAGE) ? mNextPage : mCurrentPage);
         if (!mIsDragInProcess) {
-            updateWhichPagesAcceptDrops(mShrinkState);
+            updateWhichPagesAcceptDrops(shrinkState);
         }
 
-        // we intercept and reject all touch events when we're small, so be sure to reset the state
-        mTouchState = TOUCH_STATE_REST;
-        mActivePointerId = INVALID_POINTER;
-
         CellLayout currentPage = (CellLayout) getChildAt(mCurrentPage);
+        if (currentPage == null) {
+            Log.w(TAG, "currentPage is NULL! mCurrentPage " + mCurrentPage
+                    + " mNextPage " + mNextPage);
+            return;
+        }
         if (currentPage.getBackgroundAlphaMultiplier() < 1.0f) {
             currentPage.setBackgroundAlpha(0.0f);
         }
         currentPage.setBackgroundAlphaMultiplier(1.0f);
 
+        mIsSmall = true;
+        mShrinkState = shrinkState;
+
+        // we intercept and reject all touch events when we're small, so be sure to reset the state
+        mTouchState = TOUCH_STATE_REST;
+        mActivePointerId = INVALID_POINTER;
+
         final Resources res = getResources();
         final int screenWidth = getWidth();
         final int screenHeight = getHeight();
@@ -1186,7 +1241,6 @@
         if (shrinkState == ShrinkState.BOTTOM_VISIBLE) {
              newY = screenHeight - newY - scaledPageHeight;
         } else if (shrinkState == ShrinkState.BOTTOM_HIDDEN) {
-
             // We shrink and disappear to nothing in the case of all apps
             // (which is when we shrink to the bottom)
             newY = screenHeight - newY - scaledPageHeight;
@@ -1258,10 +1312,42 @@
             // increment newX for the next screen
             newX += scaledPageWidth + extraScaledSpacing;
         }
+
+        float wallpaperOffset = 0.5f;
+        Display display = mLauncher.getWindowManager().getDefaultDisplay();
+        int wallpaperTravelHeight = (int) (display.getHeight() *
+                wallpaperTravelToScreenHeightRatio(display.getWidth(), display.getHeight()));
+        float offsetFromCenter = (wallpaperTravelHeight / (float) mWallpaperHeight) / 2f;
+        switch (shrinkState) {
+            case TOP:
+                wallpaperOffset = 0.5f + offsetFromCenter;
+                break;
+            case MIDDLE:
+            case SPRING_LOADED:
+                wallpaperOffset = 0.5f;
+                break;
+            case BOTTOM_HIDDEN:
+            case BOTTOM_VISIBLE:
+                wallpaperOffset = 0.5f - offsetFromCenter;
+                break;
+        }
+
         setLayoutScale(1.0f);
         if (animated) {
+            mSyncWallpaperOffsetWithScroll = false;
+            ObjectAnimator wallpaperAnim = ObjectAnimator.ofPropertyValuesHolder(this,
+                    PropertyValuesHolder.ofFloat("verticalWallpaperOffset", wallpaperOffset),
+                    PropertyValuesHolder.ofFloat("horizontalWallpaperOffset", 0.5f));
+            mAnimator.play(wallpaperAnim);
+
+            wallpaperAnim.setDuration(duration);
+            wallpaperAnim.setInterpolator(mZoomOutInterpolator);
             mAnimator.addListener(mShrinkAnimationListener);
             mAnimator.start();
+        } else {
+            setVerticalWallpaperOffset(wallpaperOffset);
+            setHorizontalWallpaperOffset(0.5f);
+            updateWallpaperOffsetImmediately();
         }
         setChildrenDrawnWithCacheEnabled(true);
 
@@ -1501,6 +1587,20 @@
                     mUnshrinkAnimationListener.onAnimationEnd(null);
                 }
             }
+            if (animated) {
+                ObjectAnimator wallpaperAnim = ObjectAnimator.ofPropertyValuesHolder(this,
+                        PropertyValuesHolder.ofFloat(
+                                "verticalWallpaperOffset", 0.5f),
+                        PropertyValuesHolder.ofFloat(
+                                "horizontalWallpaperOffset", wallpaperOffsetForCurrentScroll()));
+                mAnimator.play(wallpaperAnim);
+                wallpaperAnim.setDuration(duration);
+                wallpaperAnim.setInterpolator(mZoomInInterpolator);
+            } else {
+                setHorizontalWallpaperOffset(wallpaperOffsetForCurrentScroll());
+                setVerticalWallpaperOffset(0.5f);
+                updateWallpaperOffsetImmediately();
+            }
 
             if (animated) {
                 // If we call this when we're not animated, onAnimationEnd is never called on