Merge "Fix 3099036: Drag visualization appears in wrong spot" into honeycomb
diff --git a/src/com/android/launcher2/AllAppsPagedView.java b/src/com/android/launcher2/AllAppsPagedView.java
index c9c069f..8ed1f46 100644
--- a/src/com/android/launcher2/AllAppsPagedView.java
+++ b/src/com/android/launcher2/AllAppsPagedView.java
@@ -221,11 +221,13 @@
             public void run() {
                 DeleteZone allAppsDeleteZone =
                         (DeleteZone) mLauncher.findViewById(R.id.all_apps_delete_zone);
-                allAppsDeleteZone.setDragAndDropEnabled(false);
+                // if onDestroy was called on Launcher, we might have already deleted the
+                // all apps delete zone / info button, so check if they are null
+                if (allAppsDeleteZone != null) allAppsDeleteZone.setDragAndDropEnabled(false);
 
                 ApplicationInfoDropTarget allAppsInfoButton =
                     (ApplicationInfoDropTarget) mLauncher.findViewById(R.id.all_apps_info_target);
-                allAppsInfoButton.setDragAndDropEnabled(false);
+                if (allAppsInfoButton != null) allAppsInfoButton.setDragAndDropEnabled(false);
             }
         });
         resetCheckedGrandchildren();
@@ -269,6 +271,7 @@
         }
 
         // Start the drag
+        mLauncher.lockScreenOrientation();
         mLauncher.getWorkspace().onDragStartedWithItemSpans(1, 1, b);
         mDragController.startDrag(v, b, this, app, DragController.DRAG_ACTION_COPY, null);
         b.recycle();
@@ -287,6 +290,7 @@
         }
         tearDownDragMode();
         mLauncher.getWorkspace().onDragStopped();
+        mLauncher.unlockScreenOrientation();
     }
 
     @Override
diff --git a/src/com/android/launcher2/AllAppsTabbed.java b/src/com/android/launcher2/AllAppsTabbed.java
index 2cc0a6b..47a5bf7 100644
--- a/src/com/android/launcher2/AllAppsTabbed.java
+++ b/src/com/android/launcher2/AllAppsTabbed.java
@@ -48,6 +48,7 @@
     private AllAppsPagedView mAllApps;
     private Context mContext;
     private final LayoutInflater mInflater;
+    private boolean mFirstLayout = true;
 
     public AllAppsTabbed(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -135,6 +136,11 @@
 
     @Override
     public void setVisibility(int visibility) {
+        if (visibility == View.GONE && mFirstLayout) {
+            // It needs to be INVISIBLE so that it will be measured in the layout.
+            // Otherwise the animations is messed up when we show it for the first time.
+            visibility = View.INVISIBLE;
+        }
         final boolean isVisible = (visibility == View.VISIBLE); 
         super.setVisibility(visibility);
         float zoom = (isVisible ? 1.0f : 0.0f);
@@ -147,6 +153,12 @@
     }
 
     @Override
+    protected void onLayout(boolean changed, int l, int t, int r, int b) {
+        mFirstLayout = false;
+        super.onLayout(changed, l, t, r, b);
+    }
+
+    @Override
     public boolean isAnimating() {
         return (getAnimation() != null);
     }
diff --git a/src/com/android/launcher2/CustomizePagedView.java b/src/com/android/launcher2/CustomizePagedView.java
index 6a563f2..d9a6612 100644
--- a/src/com/android/launcher2/CustomizePagedView.java
+++ b/src/com/android/launcher2/CustomizePagedView.java
@@ -308,8 +308,8 @@
     }
 
     public void setCustomizationFilter(CustomizationType filterType) {
-        mCustomizationType = filterType;
         cancelDragging();
+        mCustomizationType = filterType;
         if (getChildCount() > 0) {
             setCurrentPage(0);
             updateCurrentPageScroll();
@@ -328,6 +328,7 @@
     public void onDropCompleted(View target, boolean success) {
         resetCheckedGrandchildren();
         mLauncher.getWorkspace().onDragStopped();
+        mLauncher.unlockScreenOrientation();
     }
 
     @Override
@@ -500,60 +501,67 @@
             endChoiceMode();
         }
         boolean result = false;
+        mLauncher.lockScreenOrientation();
         switch (mCustomizationType) {
         case WidgetCustomization: {
-            // Get the widget preview as the drag representation
-            final LinearLayout l = (LinearLayout) v;
-            final ImageView i = (ImageView) l.findViewById(R.id.widget_preview);
-            final Drawable icon = i.getDrawable();
-            Bitmap b = drawableToBitmap(icon, i);
-            PendingAddWidgetInfo createWidgetInfo = (PendingAddWidgetInfo) v.getTag();
+            if (v instanceof PagedViewWidget) {
+                // Get the widget preview as the drag representation
+                final LinearLayout l = (LinearLayout) v;
+                final ImageView i = (ImageView) l.findViewById(R.id.widget_preview);
+                final Drawable icon = i.getDrawable();
+                Bitmap b = drawableToBitmap(icon, i);
+                PendingAddWidgetInfo createWidgetInfo = (PendingAddWidgetInfo) v.getTag();
 
-            int[] spanXY = CellLayout.rectToCell(
-                    getResources(), createWidgetInfo.minWidth, createWidgetInfo.minHeight, null);
-            createWidgetInfo.spanX = spanXY[0];
-            createWidgetInfo.spanY = spanXY[1];
-            mLauncher.getWorkspace().onDragStartedWithItemSpans(spanXY[0], spanXY[1], b);
-            mDragController.startDrag(
-                    i, b, this, createWidgetInfo, DragController.DRAG_ACTION_COPY, null);
-            b.recycle();
-            result = true;
+                int[] spanXY = CellLayout.rectToCell(
+                        getResources(), createWidgetInfo.minWidth, createWidgetInfo.minHeight, null);
+                createWidgetInfo.spanX = spanXY[0];
+                createWidgetInfo.spanY = spanXY[1];
+                mLauncher.getWorkspace().onDragStartedWithItemSpans(spanXY[0], spanXY[1], b);
+                mDragController.startDrag(
+                        i, b, this, createWidgetInfo, DragController.DRAG_ACTION_COPY, null);
+                b.recycle();
+                result = true;
+            }
             break;
         }
         case ShortcutCustomization: {
-            // get icon (top compound drawable, index is 1)
-            final TextView tv = (TextView) v;
-            final Drawable icon = tv.getCompoundDrawables()[1];
-            Bitmap b = drawableToBitmap(icon, tv);
-            PendingAddItemInfo createItemInfo = (PendingAddItemInfo) v.getTag();
+            if (v instanceof PagedViewIcon) {
+                // get icon (top compound drawable, index is 1)
+                final TextView tv = (TextView) v;
+                final Drawable icon = tv.getCompoundDrawables()[1];
+                Bitmap b = drawableToBitmap(icon, tv);
+                PendingAddItemInfo createItemInfo = (PendingAddItemInfo) v.getTag();
 
-            mLauncher.getWorkspace().onDragStartedWithItemSpans(1, 1, b);
-            mDragController.startDrag(v, b, this, createItemInfo, DragController.DRAG_ACTION_COPY,
-                    null);
-            b.recycle();
-            result = true;
+                mLauncher.getWorkspace().onDragStartedWithItemSpans(1, 1, b);
+                mDragController.startDrag(v, b, this, createItemInfo, DragController.DRAG_ACTION_COPY,
+                        null);
+                b.recycle();
+                result = true;
+            }
             break;
         }
         case ApplicationCustomization: {
-            // Pick up the application for dropping
-            // get icon (top compound drawable, index is 1)
-            final TextView tv = (TextView) v;
-            final Drawable icon = tv.getCompoundDrawables()[1];
-            Bitmap b = drawableToBitmap(icon, tv);
-            ApplicationInfo app = (ApplicationInfo) v.getTag();
-            app = new ApplicationInfo(app);
+            if (v instanceof PagedViewIcon) {
+                // Pick up the application for dropping
+                // get icon (top compound drawable, index is 1)
+                final TextView tv = (TextView) v;
+                final Drawable icon = tv.getCompoundDrawables()[1];
+                Bitmap b = drawableToBitmap(icon, tv);
+                ApplicationInfo app = (ApplicationInfo) v.getTag();
+                app = new ApplicationInfo(app);
 
-            mLauncher.getWorkspace().onDragStartedWithItemSpans(1, 1, b);
-            mDragController.startDrag(v, b, this, app, DragController.DRAG_ACTION_COPY, null);
-            b.recycle();
-            result = true;
+                mLauncher.getWorkspace().onDragStartedWithItemSpans(1, 1, b);
+                mDragController.startDrag(v, b, this, app, DragController.DRAG_ACTION_COPY, null);
+                b.recycle();
+                result = true;
+            }
             break;
         }
         }
 
         // We toggle the checked state _after_ we create the view for the drag in case toggling the
         // checked state changes the view's look
-        if (v instanceof Checkable) {
+        if (result && (v instanceof Checkable)) {
             // In preparation for drag, we always reset the checked grand children regardless of
             // what choice mode we are in
             resetCheckedGrandchildren();
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index bef4e84..9b5dac7 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -17,17 +17,19 @@
 
 package com.android.launcher2;
 
-import com.android.common.Search;
-import com.android.launcher.R;
-import com.android.launcher2.CustomizePagedView.CustomizationType;
-import com.android.launcher2.Workspace.ShrinkState;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
 import android.animation.PropertyValuesHolder;
-import android.animation.TimeInterpolator;
 import android.animation.ValueAnimator;
 import android.app.Activity;
 import android.app.AlertDialog;
@@ -45,12 +47,12 @@
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
-import android.content.IntentFilter;
 import android.content.Intent.ShortcutIconResource;
+import android.content.IntentFilter;
 import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
@@ -77,16 +79,18 @@
 import android.text.TextUtils;
 import android.text.method.TextKeyListener;
 import android.util.Log;
+import android.view.Display;
 import android.view.HapticFeedbackConstants;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.MotionEvent;
+import android.view.Surface;
 import android.view.View;
+import android.view.View.OnLongClickListener;
 import android.view.ViewGroup;
 import android.view.WindowManager;
-import android.view.View.OnLongClickListener;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.animation.DecelerateInterpolator;
 import android.view.inputmethod.InputMethodManager;
@@ -96,20 +100,16 @@
 import android.widget.LinearLayout;
 import android.widget.PopupWindow;
 import android.widget.TabHost;
+import android.widget.TabHost.OnTabChangeListener;
+import android.widget.TabHost.TabContentFactory;
 import android.widget.TabWidget;
 import android.widget.TextView;
 import android.widget.Toast;
-import android.widget.TabHost.OnTabChangeListener;
-import android.widget.TabHost.TabContentFactory;
 
-import java.io.DataInputStream;
-import java.io.DataOutputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
+import com.android.common.Search;
+import com.android.launcher.R;
+import com.android.launcher2.CustomizePagedView.CustomizationType;
+import com.android.launcher2.Workspace.ShrinkState;
 
 
 /**
@@ -264,6 +264,10 @@
     private HashMap<View, AppWidgetProviderInfo> mWidgetsToAdvance =
         new HashMap<View, AppWidgetProviderInfo>();
 
+    // Determines how long to wait after a rotation before restoring the screen orientation to
+    // match the sensor state.
+    private final int mRestoreScreenOrientationDelay = 500;
+
     // External icons saved in case of resource changes, orientation, etc.
     private static Drawable.ConstantState sGlobalSearchIcon;
     private static Drawable.ConstantState sVoiceSearchIcon;
@@ -1710,7 +1714,7 @@
                     final ClipDescription clipDesc = clipData.getDescription();
                     for (int i = 0; i < clipDesc.getMimeTypeCount(); ++i) {
                         if (clipDesc.getMimeType(i).equals(mimeType)) {
-                            final ClipData.Item item = clipData.getItem(i);
+                            final ClipData.Item item = clipData.getItemAt(i);
                             final CharSequence stringData = item.getText();
                             final Uri uriData = item.getUri();
                             final Intent intentData = item.getIntent();
@@ -3576,6 +3580,49 @@
         }
     }
 
+    private int mapConfigurationOriActivityInfoOri(int configOri) {
+        final Display d = getWindowManager().getDefaultDisplay();
+        int naturalOri = Configuration.ORIENTATION_LANDSCAPE;
+        switch (d.getRotation()) {
+        case Surface.ROTATION_0:
+        case Surface.ROTATION_180:
+            // We are currently in the same basic orientation as the natural orientation
+            naturalOri = configOri;
+            break;
+        case Surface.ROTATION_90:
+        case Surface.ROTATION_270:
+            // We are currently in the other basic orientation to the natural orientation
+            naturalOri = (configOri == Configuration.ORIENTATION_LANDSCAPE) ?
+                    Configuration.ORIENTATION_PORTRAIT : Configuration.ORIENTATION_LANDSCAPE;
+            break;
+        }
+
+        int[] oriMap = {
+                ActivityInfo.SCREEN_ORIENTATION_PORTRAIT,
+                ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE,
+                ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT,
+                ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE
+        };
+        // Since the map starts at portrait, we need to offset if this device's natural orientation
+        // is landscape.
+        int indexOffset = 0;
+        if (naturalOri == Configuration.ORIENTATION_LANDSCAPE) {
+            indexOffset = 1;
+        }
+        return oriMap[(d.getRotation() + indexOffset) % 4];
+    }
+    public void lockScreenOrientation() {
+        setRequestedOrientation(mapConfigurationOriActivityInfoOri(getResources()
+                .getConfiguration().orientation));
+    }
+    public void unlockScreenOrientation() {
+        mHandler.postDelayed(new Runnable() {
+            public void run() {
+                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
+            }
+        }, mRestoreScreenOrientationDelay);
+    }
+
     /**
      * Prints out out state for debugging.
      */
diff --git a/src/com/android/launcher2/PagedViewWidget.java b/src/com/android/launcher2/PagedViewWidget.java
index 07a59ee..9b83f48 100644
--- a/src/com/android/launcher2/PagedViewWidget.java
+++ b/src/com/android/launcher2/PagedViewWidget.java
@@ -33,6 +33,7 @@
 import android.os.Message;
 import android.util.AttributeSet;
 import android.view.MotionEvent;
+import android.view.View;
 import android.widget.Checkable;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
@@ -159,8 +160,10 @@
         image.setImageDrawable(preview);
         final TextView name = (TextView) findViewById(R.id.widget_name);
         name.setText(info.label);
+        name.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
         final TextView dims = (TextView) findViewById(R.id.widget_dims);
         dims.setText(mContext.getString(R.string.widget_dims_format, cellSpan[0], cellSpan[1]));
+        dims.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
 
         if (createHolographicOutline) {
             mIconCache = cache;
@@ -178,6 +181,7 @@
         image.setImageDrawable(preview);
         TextView name = (TextView) findViewById(R.id.wallpaper_name);
         name.setText(info.loadLabel(packageManager));
+        name.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
 
         if (createHolographicOutline) {
             mIconCache = cache;
diff --git a/src/com/android/launcher2/PagedViewWithDraggableItems.java b/src/com/android/launcher2/PagedViewWithDraggableItems.java
index 3f72292..5fa7be7 100644
--- a/src/com/android/launcher2/PagedViewWithDraggableItems.java
+++ b/src/com/android/launcher2/PagedViewWithDraggableItems.java
@@ -35,6 +35,7 @@
     implements View.OnLongClickListener, View.OnTouchListener {
     private View mLastTouchedItem;
     private boolean mIsDragging;
+    private boolean mIsDragEnabled;
     private float mDragSlopeThreshold;
 
     public PagedViewWithDraggableItems(Context context) {
@@ -58,6 +59,7 @@
     protected void cancelDragging() {
         mIsDragging = false;
         mLastTouchedItem = null;
+        mIsDragEnabled = false;
     }
 
     private void handleTouchEvent(MotionEvent ev) {
@@ -65,9 +67,10 @@
         switch (action & MotionEvent.ACTION_MASK) {
             case MotionEvent.ACTION_DOWN:
                 cancelDragging();
+                mIsDragEnabled = true;
                 break;
             case MotionEvent.ACTION_MOVE:
-                if (mTouchState != TOUCH_STATE_SCROLLING && !mIsDragging) {
+                if (mTouchState != TOUCH_STATE_SCROLLING && !mIsDragging && mIsDragEnabled) {
                     determineDraggingStart(ev);
                 }
                 break;
@@ -89,6 +92,7 @@
     @Override
     public boolean onTouch(View v, MotionEvent event) {
         mLastTouchedItem = v;
+        mIsDragEnabled = true;
         return false;
     }
 
@@ -153,7 +157,7 @@
 
     @Override
     protected void onDetachedFromWindow() {
-        mLastTouchedItem = null;
+        cancelDragging();
         super.onDetachedFromWindow();
     }
 }
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index 2e2c441..a25db39 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -1439,6 +1439,7 @@
     }
 
     void unshrink(boolean animated, boolean springLoaded) {
+        mWaitingToShrink = false;
         if (mIsSmall) {
             float finalScaleFactor = 1.0f;
             float finalBackgroundAlpha = 0.0f;
@@ -1647,6 +1648,7 @@
         child.getLocationOnScreen(mTempXY);
         final int screenX = (int) mTempXY[0] + (child.getWidth() - bmpWidth) / 2;
         final int screenY = (int) mTempXY[1] + (child.getHeight() - bmpHeight) / 2;
+        mLauncher.lockScreenOrientation();
         mDragController.startDrag(b, screenX, screenY, 0, 0, bmpWidth, bmpHeight, this,
                 child.getTag(), DragController.DRAG_ACTION_MOVE, null);
         b.recycle();
@@ -2010,7 +2012,7 @@
                 final boolean isShortcut = (widgets == null);
                 final String mimeType = desc.getMimeType(index);
                 if (isShortcut) {
-                    final Intent intent = data.getItem(index).getIntent();
+                    final Intent intent = data.getItemAt(index).getIntent();
                     Object info = model.infoFromShortcutIntent(mContext, intent, data.getIcon());
                     onDropExternal(x, y, info, layout, false);
                 } else {
@@ -2453,7 +2455,7 @@
             boolean animateDrop = !mWasSpringLoadedOnDragExit;
             ((CellLayout) getChildAt(mDragInfo.screen)).onDropChild(mDragInfo.cell, animateDrop);
         }
-
+        mLauncher.unlockScreenOrientation();
         mDragOutline = null;
         mDragInfo = null;
     }