Adding a horizontal popup when when workspace is longPressed

Change-Id: I5b3c48262c246bfe53e0010ca89c820f42503eef
diff --git a/quickstep/res/layout/longpress_options_menu.xml b/quickstep/res/layout/longpress_options_menu.xml
new file mode 100644
index 0000000..9cf0fcf
--- /dev/null
+++ b/quickstep/res/layout/longpress_options_menu.xml
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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.launcher3.uioverrides.OptionsPopupView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:launcher="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="96dp"
+    android:background="?attr/popupColorPrimary"
+    android:elevation="@dimen/deep_shortcuts_elevation"
+    android:orientation="horizontal"
+    launcher:layout_ignoreInsets="true">
+
+    <FrameLayout
+        android:id="@+id/wallpaper_button"
+        android:layout_width="0dp"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:background="?android:attr/selectableItemBackground">
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center"
+            android:drawablePadding="4dp"
+            android:drawableTint="?android:attr/textColorPrimary"
+            android:drawableTop="@drawable/ic_wallpaper"
+            android:fontFamily="sans-serif-condensed"
+            android:gravity="center"
+            android:paddingLeft="16dp"
+            android:paddingRight="16dp"
+            android:text="@string/wallpaper_button_text"
+            android:textColor="?android:attr/textColorPrimary"
+            android:textSize="12sp"/>
+    </FrameLayout>
+
+    <FrameLayout
+        android:id="@+id/widget_button"
+        android:layout_width="0dp"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:background="?android:attr/selectableItemBackground">
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center"
+            android:drawablePadding="4dp"
+            android:drawableTint="?android:attr/textColorPrimary"
+            android:drawableTop="@drawable/ic_widget"
+            android:fontFamily="sans-serif-condensed"
+            android:gravity="center"
+            android:paddingLeft="16dp"
+            android:paddingRight="16dp"
+            android:text="@string/widget_button_text"
+            android:textColor="?android:attr/textColorPrimary"
+            android:textSize="12sp"/>
+
+    </FrameLayout>
+
+    <FrameLayout
+        android:id="@+id/settings_button"
+        android:layout_width="0dp"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:background="?android:attr/selectableItemBackground">
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center"
+            android:drawablePadding="4dp"
+            android:drawableTint="?android:attr/textColorPrimary"
+            android:drawableTop="@drawable/ic_setting"
+            android:fontFamily="sans-serif-condensed"
+            android:gravity="center"
+            android:paddingLeft="16dp"
+            android:paddingRight="16dp"
+            android:text="@string/settings_button_text"
+            android:textColor="?android:attr/textColorPrimary"
+            android:textSize="12sp"/>
+
+    </FrameLayout>
+
+</com.android.launcher3.uioverrides.OptionsPopupView>
\ No newline at end of file
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index 9ef8e82..40436d1 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -16,11 +16,14 @@
 
 <resources>
 
+    <dimen name="options_menu_icon_size">24dp</dimen>
+
     <dimen name="task_thumbnail_top_margin">24dp</dimen>
     <dimen name="task_thumbnail_icon_size">48dp</dimen>
     <dimen name="task_menu_background_radius">12dp</dimen>
     <dimen name="task_corner_radius">2dp</dimen>
     <dimen name="task_fade_length">20dp</dimen>
+    <dimen name="recents_page_spacing">10dp</dimen>
 
 
     <dimen name="quickstep_fling_threshold_velocity">500dp</dimen>
diff --git a/quickstep/src/com/android/launcher3/uioverrides/OptionsPopupView.java b/quickstep/src/com/android/launcher3/uioverrides/OptionsPopupView.java
new file mode 100644
index 0000000..c089d06
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/uioverrides/OptionsPopupView.java
@@ -0,0 +1,276 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+package com.android.launcher3.uioverrides;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Outline;
+import android.graphics.PointF;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.view.ViewOutlineProvider;
+import android.widget.Toast;
+
+import com.android.launcher3.AbstractFloatingView;
+import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherAnimUtils;
+import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.anim.Interpolators;
+import com.android.launcher3.anim.RevealOutlineAnimation;
+import com.android.launcher3.anim.RoundedRectRevealOutlineProvider;
+import com.android.launcher3.dragndrop.DragLayer;
+import com.android.launcher3.graphics.GradientView;
+import com.android.launcher3.widget.WidgetsFullSheet;
+
+/**
+ * Popup shown on long pressing an empty space in launcher
+ */
+public class OptionsPopupView extends AbstractFloatingView implements OnClickListener {
+
+    private final float mOutlineRadius;
+    private final Launcher mLauncher;
+    private final PointF mTouchPoint = new PointF();
+
+    private final GradientView mGradientView;
+
+    protected Animator mOpenCloseAnimator;
+
+    public OptionsPopupView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public OptionsPopupView(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+
+        mOutlineRadius = getResources().getDimension(R.dimen.bg_round_rect_radius);
+        setClipToOutline(true);
+        setOutlineProvider(new ViewOutlineProvider() {
+            @Override
+            public void getOutline(View view, Outline outline) {
+                outline.setRoundRect(0, 0, view.getWidth(), view.getHeight(), mOutlineRadius);
+            }
+        });
+
+        mLauncher = Launcher.getLauncher(context);
+
+        mGradientView = (GradientView) mLauncher.getLayoutInflater().inflate(
+                R.layout.widgets_bottom_sheet_scrim, mLauncher.getDragLayer(), false);
+        mGradientView.setProgress(1, false);
+        mGradientView.setAlpha(0);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        findViewById(R.id.wallpaper_button).setOnClickListener(this);
+        findViewById(R.id.widget_button).setOnClickListener(this);
+        findViewById(R.id.settings_button).setOnClickListener(this);
+    }
+
+    @Override
+    public void onClick(View view) {
+        if (view.getId() == R.id.wallpaper_button) {
+            mLauncher.onClickWallpaperPicker(null);
+            close(true);
+        } else if (view.getId() == R.id.widget_button) {
+            if (mLauncher.getPackageManager().isSafeMode()) {
+                Toast.makeText(mLauncher, R.string.safemode_widget_error, Toast.LENGTH_SHORT).show();
+            } else {
+                WidgetsFullSheet.show(mLauncher, true /* animated */);
+                close(true);
+            }
+        } else if (view.getId() == R.id.settings_button) {
+            mLauncher.startActivity(new Intent(Intent.ACTION_APPLICATION_PREFERENCES)
+                .setPackage(mLauncher.getPackageName())
+                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
+            close(true);
+        }
+    }
+
+    @Override
+    public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
+        if (ev.getAction() != MotionEvent.ACTION_DOWN) {
+            return false;
+        }
+        if (mLauncher.getDragLayer().isEventOverView(this, ev)) {
+            return false;
+        }
+        close(true);
+        return true;
+    }
+
+    @Override
+    protected void handleClose(boolean animate) {
+        if (animate) {
+            animateClose();
+        } else {
+            closeComplete();
+        }
+    }
+
+    protected void animateClose() {
+        if (!mIsOpen) {
+            return;
+        }
+        mIsOpen = false;
+
+        final AnimatorSet closeAnim = LauncherAnimUtils.createAnimatorSet();
+        closeAnim.setDuration(getResources().getInteger(R.integer.config_popupOpenCloseDuration));
+
+        // Rectangular reveal (reversed).
+        final ValueAnimator revealAnim = createOpenCloseOutlineProvider()
+                .createRevealAnimator(this, true);
+        closeAnim.play(revealAnim);
+
+        Animator fadeOut = ObjectAnimator.ofFloat(this, ALPHA, 0);
+        fadeOut.setInterpolator(Interpolators.DEACCEL);
+        closeAnim.play(fadeOut);
+
+        Animator gradientAlpha = ObjectAnimator.ofFloat(mGradientView, ALPHA, 0);
+        gradientAlpha.setInterpolator(Interpolators.DEACCEL);
+        closeAnim.play(gradientAlpha);
+
+        closeAnim.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                mOpenCloseAnimator = null;
+                closeComplete();
+            }
+        });
+        if (mOpenCloseAnimator != null) {
+            mOpenCloseAnimator.cancel();
+        }
+        mOpenCloseAnimator = closeAnim;
+        closeAnim.start();
+    }
+
+    /**
+     * Closes the popup without animation.
+     */
+    private void closeComplete() {
+        if (mOpenCloseAnimator != null) {
+            mOpenCloseAnimator.cancel();
+            mOpenCloseAnimator = null;
+        }
+        mIsOpen = false;
+        mLauncher.getDragLayer().removeView(this);
+        mLauncher.getDragLayer().removeView(mGradientView);
+    }
+
+    @Override
+    public void logActionCommand(int command) {
+        // TODO:
+    }
+
+    @Override
+    protected boolean isOfType(int type) {
+        return (type & TYPE_OPTIONS_POPUP) != 0;
+    }
+
+    private RoundedRectRevealOutlineProvider createOpenCloseOutlineProvider() {
+        DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams();
+        Rect startRect = new Rect();
+        startRect.offset((int) (mTouchPoint.x - lp.x), (int) (mTouchPoint.y - lp.y));
+
+        Rect endRect = new Rect(0, 0, lp.width, lp.height);
+        if (getOutlineProvider() instanceof RevealOutlineAnimation) {
+            ((RevealOutlineAnimation) getOutlineProvider()).getOutline(endRect);
+        }
+
+        return new RoundedRectRevealOutlineProvider
+                (mOutlineRadius, mOutlineRadius, startRect, endRect);
+    }
+
+    private void animateOpen() {
+        mIsOpen = true;
+        final AnimatorSet openAnim = LauncherAnimUtils.createAnimatorSet();
+        openAnim.setDuration(getResources().getInteger(R.integer.config_popupOpenCloseDuration));
+
+        final ValueAnimator revealAnim = createOpenCloseOutlineProvider()
+                .createRevealAnimator(this, false);
+        openAnim.play(revealAnim);
+
+        Animator gradientAlpha = ObjectAnimator.ofFloat(mGradientView, ALPHA, 1);
+        gradientAlpha.setInterpolator(Interpolators.ACCEL);
+        openAnim.play(gradientAlpha);
+
+        mOpenCloseAnimator = openAnim;
+
+        openAnim.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                mOpenCloseAnimator = null;
+            }
+        });
+        openAnim.start();
+    }
+
+    public static void show(Launcher launcher, float x, float y) {
+        DragLayer dl = launcher.getDragLayer();
+        OptionsPopupView view = (OptionsPopupView) launcher.getLayoutInflater()
+                .inflate(R.layout.longpress_options_menu, dl, false);
+        DragLayer.LayoutParams lp = (DragLayer.LayoutParams) view.getLayoutParams();
+
+        int maxWidth = dl.getWidth();
+        int maxHeight = dl.getHeight();
+        if (x <= 0 || y <= 0 || x >= maxWidth || y >= maxHeight) {
+            x = maxWidth / 2;
+            y = maxHeight / 2;
+        }
+        view.mTouchPoint.set(x, y);
+
+        int height = lp.height;
+
+        // Find a good width;
+        int childCount = view.getChildCount();
+        int heightSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST);
+        int widthSpec = MeasureSpec.makeMeasureSpec(maxWidth / childCount, MeasureSpec.AT_MOST);
+        int maxChildWidth = 0;
+
+        for (int i = 0; i < childCount; i ++) {
+            View child = ((ViewGroup) view.getChildAt(i)).getChildAt(0);
+            child.measure(widthSpec, heightSpec);
+            maxChildWidth = Math.max(maxChildWidth, child.getMeasuredWidth());
+        }
+        Rect insets = dl.getInsets();
+        int margin = (int) (2 * view.getElevation());
+
+        int width = Math.min(maxWidth - insets.left - insets.right - 2 * margin,
+                maxChildWidth * childCount);
+        lp.width = width;
+
+        // Position is towards the finger
+        lp.customPosition = true;
+        lp.x = Utilities.boundToRange((int) (x - width / 2), insets.left + margin,
+                maxWidth - insets.right - width - margin);
+        lp.y = Utilities.boundToRange((int) (y - height / 2), insets.top + margin,
+                maxHeight - insets.bottom - height - margin);
+
+        launcher.getDragLayer().addView(view.mGradientView);
+        launcher.getDragLayer().addView(view);
+        view.animateOpen();
+    }
+}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java b/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java
index 67a7d6a..92f6514 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java
@@ -16,23 +16,19 @@
 
 package com.android.launcher3.uioverrides;
 
-import android.content.Intent;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
+import android.graphics.PointF;
 import android.os.Bundle;
 import android.view.View;
 import android.view.View.AccessibilityDelegate;
-import android.widget.PopupMenu;
-import android.widget.Toast;
 
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherAppTransitionManager;
 import com.android.launcher3.LauncherStateManager.StateHandler;
-import com.android.launcher3.R;
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.graphics.BitmapRenderer;
 import com.android.launcher3.util.TouchController;
-import com.android.launcher3.widget.WidgetsFullSheet;
 import com.android.quickstep.RecentsView;
 import com.android.systemui.shared.recents.view.RecentsTransition;
 
@@ -63,31 +59,8 @@
                 new RecentsViewStateController(launcher)};
     }
 
-    public static void onWorkspaceLongPress(Launcher launcher) {
-        PopupMenu menu = new PopupMenu(launcher.getApplicationContext(),
-                launcher.getWorkspace().getPageIndicator());
-
-        menu.getMenu().add(R.string.wallpaper_button_text).setOnMenuItemClickListener((i) -> {
-            launcher.onClickWallpaperPicker(null);
-            return true;
-        });
-        menu.getMenu().add(R.string.widget_button_text).setOnMenuItemClickListener((i) -> {
-            if (launcher.getPackageManager().isSafeMode()) {
-                Toast.makeText(launcher, R.string.safemode_widget_error, Toast.LENGTH_SHORT).show();
-            } else {
-                WidgetsFullSheet.show(launcher, true /* animated */);
-            }
-            return true;
-        });
-        if (launcher.hasSettings()) {
-            menu.getMenu().add(R.string.settings_button_text).setOnMenuItemClickListener((i) -> {
-                launcher.startActivity(new Intent(Intent.ACTION_APPLICATION_PREFERENCES)
-                        .setPackage(launcher.getPackageName())
-                        .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
-                return true;
-            });
-        }
-        menu.show();
+    public static void onWorkspaceLongPress(Launcher launcher, PointF touchPoint) {
+        OptionsPopupView.show(launcher, touchPoint.x, touchPoint.y);
     }
 
     public static Bitmap createFromRenderer(int width, int height, boolean forceSoftwareRenderer,
diff --git a/res/drawable/ic_setting.xml b/res/drawable/ic_setting.xml
index 1bab189..08eba25 100644
--- a/res/drawable/ic_setting.xml
+++ b/res/drawable/ic_setting.xml
@@ -14,8 +14,8 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="48dp"
-        android:height="48dp"
+        android:width="@dimen/options_menu_icon_size"
+        android:height="@dimen/options_menu_icon_size"
         android:viewportWidth="48.0"
         android:viewportHeight="48.0">
     <path
diff --git a/res/drawable/ic_wallpaper.xml b/res/drawable/ic_wallpaper.xml
index 9e9222f..0c5a125 100644
--- a/res/drawable/ic_wallpaper.xml
+++ b/res/drawable/ic_wallpaper.xml
@@ -14,8 +14,8 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="48dp"
-        android:height="48dp"
+        android:width="@dimen/options_menu_icon_size"
+        android:height="@dimen/options_menu_icon_size"
         android:viewportWidth="48.0"
         android:viewportHeight="48.0">
     <path
diff --git a/res/drawable/ic_widget.xml b/res/drawable/ic_widget.xml
index de2980f..4bb23b3 100644
--- a/res/drawable/ic_widget.xml
+++ b/res/drawable/ic_widget.xml
@@ -14,12 +14,12 @@
     limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="48dp"
-        android:height="48dp"
+        android:width="@dimen/options_menu_icon_size"
+        android:height="@dimen/options_menu_icon_size"
         android:viewportWidth="48.0"
         android:viewportHeight="48.0">
     <path
-        android:fillColor="#FFFFFFFF"
+        android:fillColor="?android:attr/textColorPrimary"
         android:pathData="M26,28v12c0,1,0.8,2,2,2h12c1,0,2-1,2-2V28c0-1.2-1-2-2-2H28C26.8,26,26,26.8,26,28z M8,42h12c1.2,0,2-1,2-2V28
         c0-1.2-0.8-2-2-2H8c-1,0-2,0.8-2,2v12C6,41,7,42,8,42z M6,8v12c0,1.2,1,2,2,2h12c1.2,0,2-0.8,2-2V8c0-1-0.8-2-2-2H8C7,6,6,7,6,8z
         M32.6,4.6l-8,8c-0.8,0.8-0.8,2,0,2.8l8,8c0.8,0.8,2,0.8,2.8,0l8-8c0.8-0.8,0.8-2,0-2.8l-8-8C34.6,3.8,33.4,3.8,32.6,4.6z"/>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index f53fe79..60ee43d 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -228,6 +228,6 @@
     <dimen name="popup_item_divider_height">0.5dp</dimen>
     <dimen name="swipe_helper_falsing_threshold">70dp</dimen>
 
-<!-- Recents -->
-    <dimen name="recents_page_spacing">10dp</dimen>
+<!-- Overview -->
+    <dimen name="options_menu_icon_size">48dp</dimen>
 </resources>
diff --git a/src/com/android/launcher3/AbstractFloatingView.java b/src/com/android/launcher3/AbstractFloatingView.java
index 824040a..12f022f 100644
--- a/src/com/android/launcher3/AbstractFloatingView.java
+++ b/src/com/android/launcher3/AbstractFloatingView.java
@@ -42,9 +42,11 @@
             TYPE_WIDGETS_BOTTOM_SHEET,
             TYPE_WIDGET_RESIZE_FRAME,
             TYPE_WIDGETS_FULL_SHEET,
-            TYPE_QUICKSTEP_PREVIEW,
             TYPE_ON_BOARD_POPUP,
-            TYPE_TASK_MENU
+
+            TYPE_QUICKSTEP_PREVIEW,
+            TYPE_TASK_MENU,
+            TYPE_OPTIONS_POPUP
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface FloatingViewType {}
@@ -53,17 +55,20 @@
     public static final int TYPE_WIDGETS_BOTTOM_SHEET = 1 << 2;
     public static final int TYPE_WIDGET_RESIZE_FRAME = 1 << 3;
     public static final int TYPE_WIDGETS_FULL_SHEET = 1 << 4;
-    public static final int TYPE_QUICKSTEP_PREVIEW = 1 << 5;
-    public static final int TYPE_ON_BOARD_POPUP = 1 << 6;
+    public static final int TYPE_ON_BOARD_POPUP = 1 << 5;
+
+    // Popups related to quickstep UI
+    public static final int TYPE_QUICKSTEP_PREVIEW = 1 << 6;
     public static final int TYPE_TASK_MENU = 1 << 7;
+    public static final int TYPE_OPTIONS_POPUP = 1 << 8;
 
     public static final int TYPE_ALL = TYPE_FOLDER | TYPE_ACTION_POPUP
             | TYPE_WIDGETS_BOTTOM_SHEET | TYPE_WIDGET_RESIZE_FRAME | TYPE_WIDGETS_FULL_SHEET
-            | TYPE_QUICKSTEP_PREVIEW | TYPE_ON_BOARD_POPUP | TYPE_TASK_MENU;
+            | TYPE_QUICKSTEP_PREVIEW | TYPE_ON_BOARD_POPUP | TYPE_TASK_MENU | TYPE_OPTIONS_POPUP;
 
     // Type of popups which should be kept open during launcher rebind
     public static final int TYPE_REBIND_SAFE = TYPE_WIDGETS_FULL_SHEET
-            | TYPE_QUICKSTEP_PREVIEW | TYPE_ON_BOARD_POPUP;
+            | TYPE_QUICKSTEP_PREVIEW | TYPE_ON_BOARD_POPUP | TYPE_OPTIONS_POPUP;
 
     protected boolean mIsOpen;
 
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 38a3044..32342b2 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -56,6 +56,7 @@
 import android.content.pm.PackageManager;
 import android.database.sqlite.SQLiteDatabase;
 import android.graphics.Point;
+import android.graphics.PointF;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.os.AsyncTask;
@@ -268,7 +269,7 @@
      */
     private PendingRequestArgs mPendingRequestArgs;
 
-    private float mLastDispatchTouchEventX = 0.0f;
+    private final PointF mLastDispatchTouchEvent = new PointF();
 
     public ViewGroupFocusHelper mFocusHandler;
     private boolean mRotationEnabled = false;
@@ -2013,7 +2014,7 @@
 
     @Override
     public boolean dispatchTouchEvent(MotionEvent ev) {
-        mLastDispatchTouchEventX = ev.getX();
+        mLastDispatchTouchEvent.set(ev.getX(), ev.getY());
         return super.dispatchTouchEvent(ev);
     }
 
@@ -2024,7 +2025,7 @@
         if (!isInState(NORMAL) && !isInState(OVERVIEW)) return false;
 
         boolean ignoreLongPressToOverview =
-                mDeviceProfile.shouldIgnoreLongPressToOverview(mLastDispatchTouchEventX);
+                mDeviceProfile.shouldIgnoreLongPressToOverview(mLastDispatchTouchEvent.x);
 
         if (v instanceof Workspace) {
             if (!isInState(OVERVIEW)) {
@@ -2032,7 +2033,7 @@
                     getUserEventDispatcher().logActionOnContainer(Action.Touch.LONGPRESS,
                             Action.Direction.NONE, ContainerType.WORKSPACE,
                             mWorkspace.getCurrentPage());
-                    UiFactory.onWorkspaceLongPress(this);
+                    UiFactory.onWorkspaceLongPress(this, mLastDispatchTouchEvent);
                     mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
                             HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
                     return true;
@@ -2069,7 +2070,7 @@
                     getUserEventDispatcher().logActionOnContainer(Action.Touch.LONGPRESS,
                             Action.Direction.NONE, ContainerType.WORKSPACE,
                             mWorkspace.getCurrentPage());
-                    UiFactory.onWorkspaceLongPress(this);
+                    UiFactory.onWorkspaceLongPress(this, mLastDispatchTouchEvent);
                 }
                 mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
                         HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
diff --git a/src/com/android/launcher3/anim/RevealOutlineAnimation.java b/src/com/android/launcher3/anim/RevealOutlineAnimation.java
index c6b62fa..afb8875 100644
--- a/src/com/android/launcher3/anim/RevealOutlineAnimation.java
+++ b/src/com/android/launcher3/anim/RevealOutlineAnimation.java
@@ -80,4 +80,8 @@
     public float getRadius() {
         return mOutlineRadius;
     }
+
+    public void getOutline(Rect out) {
+        out.set(mOutline);
+    }
 }
diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
index f90abb4..b3ef7bb 100644
--- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java
+++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
@@ -62,6 +62,7 @@
 import com.android.launcher3.Utilities;
 import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
 import com.android.launcher3.accessibility.ShortcutMenuAccessibilityDelegate;
+import com.android.launcher3.anim.RevealOutlineAnimation;
 import com.android.launcher3.anim.RoundedRectRevealOutlineProvider;
 import com.android.launcher3.badge.BadgeInfo;
 import com.android.launcher3.dragndrop.DragController;
@@ -810,10 +811,10 @@
             return;
         }
         mEndRect.setEmpty();
+        if (getOutlineProvider() instanceof RevealOutlineAnimation) {
+            ((RevealOutlineAnimation) getOutlineProvider()).getOutline(mEndRect);
+        }
         if (mOpenCloseAnimator != null) {
-            Outline outline = new Outline();
-            getOutlineProvider().getOutline(this, outline);
-            outline.getRect(mEndRect);
             mOpenCloseAnimator.cancel();
         }
         mIsOpen = false;
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java b/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java
index 9819d71..0488fae 100644
--- a/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java
+++ b/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java
@@ -21,6 +21,7 @@
 import android.app.ActivityOptions;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
+import android.graphics.PointF;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.os.Bundle;
@@ -54,7 +55,7 @@
                 launcher.getAllAppsController(), launcher.getWorkspace() };
     }
 
-    public static void onWorkspaceLongPress(Launcher launcher) {
+    public static void onWorkspaceLongPress(Launcher launcher, PointF touchPoint) {
         launcher.getStateManager().goToState(OVERVIEW);
     }