Close the shortcuts container in various places.

- Mostly everywhere folders are closed
- Implements DragListener so we can close the container when dragging
  the original icon or shortcuts from the container. We actually just
  hide the container in onDragStart() and really remove it in
  onDragEnd(). This avoids interfering with touch events and thus
  allows us to remove the hack of explicitly setting the DragLayer's
  controller when dragging shortcuts (since it will do it on intercept).

Bug: 30080537

Change-Id: Iccc2afba2a990a613bc588d57c4d8c1b7c65224b
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 763daf4..717b059 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -116,6 +116,7 @@
 import com.android.launcher3.model.WidgetsModel;
 import com.android.launcher3.pageindicators.PageIndicator;
 import com.android.launcher3.shortcuts.DeepShortcutManager;
+import com.android.launcher3.shortcuts.DeepShortcutsContainer;
 import com.android.launcher3.util.ComponentKey;
 import com.android.launcher3.util.MultiHashMap;
 import com.android.launcher3.util.PackageManagerHelper;
@@ -1245,6 +1246,9 @@
                 // Close any open folders
                 closeFolder();
 
+                // Close any shortcuts containers
+                closeShortcutsContainer();
+
                 // Stop resizing any widgets
                 mWorkspace.exitWidgetResizeMode();
 
@@ -1840,6 +1844,7 @@
             mWorkspace.exitWidgetResizeMode();
 
             closeFolder(alreadyOnHome);
+            closeShortcutsContainer();
             exitSpringLoadedDragMode();
 
             // If we are already on home, then just animate back to the workspace,
@@ -1927,6 +1932,8 @@
         // TODO: Move folderInfo.isOpened out of the model and make it a UI state.
         closeFolder(false);
 
+        closeShortcutsContainer();
+
         if (mPendingAddInfo.container != ItemInfo.NO_ID && mPendingAddInfo.screenId > -1 &&
                 mWaitingForResult) {
             ContentValues itemValues = new ContentValues();
@@ -2423,7 +2430,9 @@
             return;
         }
 
-        if (isAppsViewVisible()) {
+        if (getOpenShortcutsContainer() != null) {
+            closeShortcutsContainer();
+        } else if (isAppsViewVisible()) {
             showWorkspace(true);
         } else if (isWidgetsViewVisible())  {
             showOverviewMode(true);
@@ -3090,6 +3099,21 @@
         getDragLayer().sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
     }
 
+    public void closeShortcutsContainer() {
+        DeepShortcutsContainer deepShortcutsContainer = getOpenShortcutsContainer();
+        if (deepShortcutsContainer != null) {
+            mDragController.removeDragListener(deepShortcutsContainer);
+            mDragLayer.removeView(deepShortcutsContainer);
+        }
+    }
+
+    /**
+     * @return The open shortcuts container, or null if there is none
+     */
+    public DeepShortcutsContainer getOpenShortcutsContainer() {
+        return (DeepShortcutsContainer) mDragLayer.findViewById(R.id.deep_shortcuts_container);
+    }
+
     @Override
     public boolean onLongClick(View v) {
         if (!isDraggingEnabled()) return false;
@@ -3351,6 +3375,7 @@
         mUserPresent = false;
         updateAutoAdvanceState();
         closeFolder();
+        closeShortcutsContainer();
 
         // Send an accessibility event to announce the context change
         getWindow().getDecorView()
diff --git a/src/com/android/launcher3/dragndrop/DragLayer.java b/src/com/android/launcher3/dragndrop/DragLayer.java
index ce97536..82b5dd3 100644
--- a/src/com/android/launcher3/dragndrop/DragLayer.java
+++ b/src/com/android/launcher3/dragndrop/DragLayer.java
@@ -231,8 +231,7 @@
         }
 
         // Remove the shortcuts container when touching outside of it.
-        DeepShortcutsContainer deepShortcutsContainer = (DeepShortcutsContainer)
-                findViewById(R.id.deep_shortcuts_container);
+        DeepShortcutsContainer deepShortcutsContainer = mLauncher.getOpenShortcutsContainer();
         if (deepShortcutsContainer != null) {
             if (isEventOverView(deepShortcutsContainer, ev)) {
                 // Let the container handle the event.
@@ -244,7 +243,7 @@
                         return true;
                     }
                 } else {
-                    removeView(deepShortcutsContainer);
+                    mLauncher.closeShortcutsContainer();
                     // We let touches on the original icon go through so that users can launch
                     // the app with one tap if they don't find a shortcut they want.
                     return !isEventOverView(deepShortcutsContainer.getDeferredDragIcon(), ev);
@@ -547,10 +546,6 @@
         return new LayoutParams(p);
     }
 
-    public void setController(TouchController controller) {
-        mActiveController = controller;
-    }
-
     public static class LayoutParams extends InsettableFrameLayout.LayoutParams {
         public int x, y;
         public boolean customPosition = false;
diff --git a/src/com/android/launcher3/shortcuts/DeepShortcutsContainer.java b/src/com/android/launcher3/shortcuts/DeepShortcutsContainer.java
index 6f3875c..31440ff 100644
--- a/src/com/android/launcher3/shortcuts/DeepShortcutsContainer.java
+++ b/src/com/android/launcher3/shortcuts/DeepShortcutsContainer.java
@@ -27,12 +27,12 @@
 import com.android.launcher3.Utilities;
 import com.android.launcher3.Workspace;
 import com.android.launcher3.compat.UserHandleCompat;
+import com.android.launcher3.dragndrop.DragController;
 import com.android.launcher3.dragndrop.DragLayer;
 import com.android.launcher3.dragndrop.DragView;
 import com.android.launcher3.logging.UserEventDispatcher;
 import com.android.launcher3.userevent.nano.LauncherLogProto;
 import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
-import com.android.launcher3.util.TouchController;
 import com.android.launcher3.util.UiThreadCircularReveal;
 
 import java.util.ArrayList;
@@ -42,9 +42,9 @@
  * A container for shortcuts to deep links within apps.
  */
 @TargetApi(Build.VERSION_CODES.N)
-public class DeepShortcutsContainer extends LinearLayout implements  View.OnClickListener,
-        View.OnLongClickListener, View.OnTouchListener, DragSource,
-        UserEventDispatcher.LaunchSourceProvider, TouchController {
+public class DeepShortcutsContainer extends LinearLayout implements View.OnLongClickListener,
+        View.OnTouchListener, DragSource, DragController.DragListener,
+        UserEventDispatcher.LaunchSourceProvider {
     private static final String TAG = "ShortcutsContainer";
 
     private Launcher mLauncher;
@@ -121,7 +121,7 @@
                     ShortcutInfo launcherShortcutInfo = shortcuts.get(i);
                     iconAndText.applyFromShortcutInfo(launcherShortcutInfo,
                             LauncherAppState.getInstance().getIconCache());
-                    iconAndText.setOnClickListener(DeepShortcutsContainer.this);
+                    iconAndText.setOnClickListener(mLauncher);
                     iconAndText.setOnLongClickListener(DeepShortcutsContainer.this);
                     iconAndText.setOnTouchListener(DeepShortcutsContainer.this);
                     int viewId = mLauncher.getViewIdForItem(originalInfo);
@@ -194,6 +194,7 @@
     private void deferDrag(BubbleTextView originalIcon) {
         mDeferredDragIcon = originalIcon;
         showDragView(originalIcon);
+        mLauncher.getDragController().addDragListener(this);
     }
 
     public BubbleTextView getDeferredDragIcon() {
@@ -231,7 +232,6 @@
             return false;
         }
 
-
         final int activePointerIndex = ev.findPointerIndex(mActivePointerId);
         if (activePointerIndex < 0) {
             return false;
@@ -256,12 +256,10 @@
 
             boolean containerContainsTouch = x >= 0 && y >= 0 && x < getWidth() && y < getHeight();
             if (shouldStartDeferredDrag((int) x, (int) y, containerContainsTouch)) {
-                mDeferredDragIcon.getParent().requestDisallowInterceptTouchEvent(false);
-                mDeferredDragIcon.setVisibility(VISIBLE);
-                mDeferredDragIcon.getOnLongClickListener().onLongClick(mDeferredDragIcon);
-                mLauncher.getDragLayer().removeView(this);
-                mLauncher.getDragController().onTouchEvent(ev);
                 cleanupDeferredDrag();
+                mDeferredDragIcon.getParent().requestDisallowInterceptTouchEvent(false);
+                mDeferredDragIcon.getOnLongClickListener().onLongClick(mDeferredDragIcon);
+                mLauncher.getDragController().onTouchEvent(ev);
                 return true;
             } else {
                 // Determine whether touch is over a shortcut.
@@ -288,7 +286,6 @@
                 }
             }
         } else if (action == MotionEvent.ACTION_UP) {
-            mDeferredDragIcon.setVisibility(VISIBLE);
             cleanupDeferredDrag();
             // Launch a shortcut if user was hovering over it.
             for (int i = 0; i < childCount; i++) {
@@ -326,6 +323,7 @@
         if (mDragView != null) {
             mDragView.remove();
         }
+        mDeferredDragIcon.setVisibility(VISIBLE);
     }
 
     @Override
@@ -340,13 +338,6 @@
         return false;
     }
 
-    @Override
-    public void onClick(View view) {
-        // Clicked on a shortcut.
-        mLauncher.onClick(view);
-        ((DragLayer) getParent()).removeView(this);
-    }
-
     public boolean onLongClick(View v) {
         // Return early if this is not initiated from a touch
         if (!v.isInTouchMode()) return false;
@@ -354,11 +345,7 @@
         if (!mLauncher.isDraggingEnabled()) return false;
 
         // Long clicked on a shortcut.
-        // TODO remove this hack; it required because DragLayer isn't intercepting touch, so
-        // the controller is not updated from what it was previously.
-        mLauncher.getDragLayer().setController(mLauncher.getDragController());
         mLauncher.getWorkspace().beginDragShared(v, mIconLastTouchPos, this, false);
-        ((DragLayer) getParent()).removeView(this);
         // TODO: support dragging from within folder without having to close it
         mLauncher.closeFolder();
         return false;
@@ -401,6 +388,19 @@
     }
 
     @Override
+    public void onDragStart(DragSource source, ItemInfo info, int dragAction) {
+        // Either the original icon or one of the shortcuts was dragged.
+        // Hide the container, but don't remove it yet because that interferes with touch events.
+        setVisibility(INVISIBLE);
+    }
+
+    @Override
+    public void onDragEnd() {
+        // Now remove the container.
+        mLauncher.closeShortcutsContainer();
+    }
+
+    @Override
     public void fillInLaunchSourceData(View v, ItemInfo info, Target target, Target targetParent) {
         target.itemType = LauncherLogProto.SHORTCUT; // TODO: change to DYNAMIC_SHORTCUT
         target.gridX = info.cellX;
diff --git a/src/com/android/launcher3/shortcuts/ShortcutsContainerListener.java b/src/com/android/launcher3/shortcuts/ShortcutsContainerListener.java
index 956623e..efb5be5 100644
--- a/src/com/android/launcher3/shortcuts/ShortcutsContainerListener.java
+++ b/src/com/android/launcher3/shortcuts/ShortcutsContainerListener.java
@@ -243,8 +243,7 @@
     private boolean onTouchForwarded(MotionEvent srcEvent) {
         final View src = mSrcIcon;
 
-        final DeepShortcutsContainer dst = (DeepShortcutsContainer)
-                mDragLayer.findViewById(R.id.deep_shortcuts_container);
+        final DeepShortcutsContainer dst = mLauncher.getOpenShortcutsContainer();
         if (dst == null) {
             return false;
         }