Merging stylus click logic in longpress helper for better state-management

Bug: 150825081
Change-Id: I7c507c41e67c09bff5a4ad3abc7a7a62fecf910e
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index 21a8fd4..c8e73ba 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -39,7 +39,6 @@
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.View;
-import android.view.ViewConfiguration;
 import android.view.ViewDebug;
 import android.widget.TextView;
 
@@ -109,8 +108,6 @@
     private final int mDisplay;
 
     private final CheckLongPressHelper mLongPressHelper;
-    private final StylusEventHelper mStylusEventHelper;
-    private final float mSlop;
 
     private final boolean mLayoutHorizontal;
     private final int mIconSize;
@@ -137,9 +134,6 @@
     @ViewDebug.ExportedProperty(category = "launcher")
     private boolean mDisableRelayout = false;
 
-    @ViewDebug.ExportedProperty(category = "launcher")
-    private final boolean mIgnorePaddingTouch;
-
     private IconLoadRequest mIconLoadRequest;
 
     public BubbleTextView(Context context) {
@@ -153,7 +147,6 @@
     public BubbleTextView(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
         mActivity = ActivityContext.lookupContext(context);
-        mSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
 
         TypedArray a = context.obtainStyledAttributes(attrs,
                 R.styleable.BubbleTextView, defStyle, 0);
@@ -166,23 +159,19 @@
             setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.iconTextSizePx);
             setCompoundDrawablePadding(grid.iconDrawablePaddingPx);
             defaultIconSize = grid.iconSizePx;
-            mIgnorePaddingTouch = true;
         } else if (mDisplay == DISPLAY_ALL_APPS) {
             DeviceProfile grid = mActivity.getDeviceProfile();
             setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.allAppsIconTextSizePx);
             setCompoundDrawablePadding(grid.allAppsIconDrawablePaddingPx);
             defaultIconSize = grid.allAppsIconSizePx;
-            mIgnorePaddingTouch = true;
         } else if (mDisplay == DISPLAY_FOLDER) {
             DeviceProfile grid = mActivity.getDeviceProfile();
             setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.folderChildTextSizePx);
             setCompoundDrawablePadding(grid.folderChildDrawablePaddingPx);
             defaultIconSize = grid.folderChildIconSizePx;
-            mIgnorePaddingTouch = true;
         } else {
             // widget_selection or shortcut_popup
             defaultIconSize = mActivity.getDeviceProfile().iconSizePx;
-            mIgnorePaddingTouch = false;
         }
 
         mCenterVertically = a.getBoolean(R.styleable.BubbleTextView_centerVertically, false);
@@ -192,7 +181,6 @@
         a.recycle();
 
         mLongPressHelper = new CheckLongPressHelper(this);
-        mStylusEventHelper = new StylusEventHelper(new SimpleOnStylusPressListener(this), this);
 
         mDotParams = new DotRenderer.DrawParams();
 
@@ -333,42 +321,21 @@
     @Override
     public boolean onTouchEvent(MotionEvent event) {
         // ignore events if they happen in padding area
-        if (event.getAction() == MotionEvent.ACTION_DOWN && mIgnorePaddingTouch
+        if (event.getAction() == MotionEvent.ACTION_DOWN
                 && (event.getY() < getPaddingTop()
                 || event.getX() < getPaddingLeft()
                 || event.getY() > getHeight() - getPaddingBottom()
                 || event.getX() > getWidth() - getPaddingRight())) {
             return false;
         }
-
-        // Call the superclass onTouchEvent first, because sometimes it changes the state to
-        // isPressed() on an ACTION_UP
-        boolean result = super.onTouchEvent(event);
-
-        // Check for a stylus button press, if it occurs cancel any long press checks.
-        if (mStylusEventHelper.onMotionEvent(event)) {
-            mLongPressHelper.cancelLongPress();
-            result = true;
+        if (isLongClickable()) {
+            super.onTouchEvent(event);
+            mLongPressHelper.onTouchEvent(event);
+            // Keep receiving the rest of the events
+            return true;
+        } else {
+            return super.onTouchEvent(event);
         }
-
-        switch (event.getAction()) {
-            case MotionEvent.ACTION_DOWN:
-                // If we're in a stylus button press, don't check for long press.
-                if (!mStylusEventHelper.inStylusButtonPressed()) {
-                    mLongPressHelper.postCheckForLongPress();
-                }
-                break;
-            case MotionEvent.ACTION_CANCEL:
-            case MotionEvent.ACTION_UP:
-                mLongPressHelper.cancelLongPress();
-                break;
-            case MotionEvent.ACTION_MOVE:
-                if (!Utilities.pointInView(this, event.getX(), event.getY(), mSlop)) {
-                    mLongPressHelper.cancelLongPress();
-                }
-                break;
-        }
-        return result;
     }
 
     void setStayPressed(boolean stayPressed) {
@@ -531,7 +498,6 @@
     @Override
     public void cancelLongPress() {
         super.cancelLongPress();
-
         mLongPressHelper.cancelLongPress();
     }
 
diff --git a/src/com/android/launcher3/CheckLongPressHelper.java b/src/com/android/launcher3/CheckLongPressHelper.java
index 639c173..ef353f9 100644
--- a/src/com/android/launcher3/CheckLongPressHelper.java
+++ b/src/com/android/launcher3/CheckLongPressHelper.java
@@ -16,46 +16,68 @@
 
 package com.android.launcher3;
 
+import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewConfiguration;
 
-import com.android.launcher3.util.Thunk;
-
+/**
+ * Utility class to handle tripper long press on a view with custom timeout and stylus event
+ */
 public class CheckLongPressHelper {
 
     public static final float DEFAULT_LONG_PRESS_TIMEOUT_FACTOR = 0.75f;
 
-    @Thunk View mView;
-    @Thunk View.OnLongClickListener mListener;
-    @Thunk boolean mHasPerformedLongPress;
-    private float mLongPressTimeoutFactor = DEFAULT_LONG_PRESS_TIMEOUT_FACTOR;
-    private CheckForLongPress mPendingCheckForLongPress;
+    private final View mView;
+    private final View.OnLongClickListener mListener;
+    private final float mSlop;
 
-    class CheckForLongPress implements Runnable {
-        public void run() {
-            if ((mView.getParent() != null) && mView.hasWindowFocus()
-                    && !mHasPerformedLongPress) {
-                boolean handled;
-                if (mListener != null) {
-                    handled = mListener.onLongClick(mView);
-                } else {
-                    handled = mView.performLongClick();
-                }
-                if (handled) {
-                    mView.setPressed(false);
-                    mHasPerformedLongPress = true;
-                }
-            }
-        }
-    }
+    private float mLongPressTimeoutFactor = DEFAULT_LONG_PRESS_TIMEOUT_FACTOR;
+
+    private boolean mHasPerformedLongPress;
+
+    private Runnable mPendingCheckForLongPress;
 
     public CheckLongPressHelper(View v) {
-        mView = v;
+        this(v, null);
     }
 
     public CheckLongPressHelper(View v, View.OnLongClickListener listener) {
         mView = v;
         mListener = listener;
+        mSlop = ViewConfiguration.get(mView.getContext()).getScaledTouchSlop();
+    }
+
+    /**
+     * Handles the touch event on a view
+     *
+     * @see View#onTouchEvent(MotionEvent)
+     */
+    public void onTouchEvent(MotionEvent ev) {
+        switch (ev.getAction()) {
+            case MotionEvent.ACTION_DOWN: {
+                // Just in case the previous long press hasn't been cleared, we make sure to
+                // start fresh on touch down.
+                cancelLongPress();
+
+                postCheckForLongPress();
+                if (isStylusButtonPressed(ev)) {
+                    triggerLongPress();
+                }
+                break;
+            }
+            case MotionEvent.ACTION_CANCEL:
+            case MotionEvent.ACTION_UP:
+                cancelLongPress();
+                break;
+            case MotionEvent.ACTION_MOVE:
+                if (!Utilities.pointInView(mView, ev.getX(), ev.getY(), mSlop)) {
+                    cancelLongPress();
+                } else if (mPendingCheckForLongPress != null && isStylusButtonPressed(ev)) {
+                    // Only trigger long press if it has not been cancelled before
+                    triggerLongPress();
+                }
+                break;
+        }
     }
 
     /**
@@ -65,25 +87,64 @@
         mLongPressTimeoutFactor = longPressTimeoutFactor;
     }
 
-    public void postCheckForLongPress() {
+    private void postCheckForLongPress() {
         mHasPerformedLongPress = false;
 
         if (mPendingCheckForLongPress == null) {
-            mPendingCheckForLongPress = new CheckForLongPress();
+            mPendingCheckForLongPress = this::triggerLongPress;
         }
         mView.postDelayed(mPendingCheckForLongPress,
                 (long) (ViewConfiguration.getLongPressTimeout() * mLongPressTimeoutFactor));
     }
 
+    /**
+     * Cancels any pending long press
+     */
     public void cancelLongPress() {
         mHasPerformedLongPress = false;
+        clearCallbacks();
+    }
+
+    /**
+     * Returns true if long press has been performed in the current touch gesture
+     */
+    public boolean hasPerformedLongPress() {
+        return mHasPerformedLongPress;
+    }
+
+    private void triggerLongPress() {
+        if ((mView.getParent() != null) && mView.hasWindowFocus() && !mHasPerformedLongPress) {
+            boolean handled;
+            if (mListener != null) {
+                handled = mListener.onLongClick(mView);
+            } else {
+                handled = mView.performLongClick();
+            }
+            if (handled) {
+                mView.setPressed(false);
+                mHasPerformedLongPress = true;
+            }
+            clearCallbacks();
+        }
+    }
+
+    private void clearCallbacks() {
         if (mPendingCheckForLongPress != null) {
             mView.removeCallbacks(mPendingCheckForLongPress);
             mPendingCheckForLongPress = null;
         }
     }
 
-    public boolean hasPerformedLongPress() {
-        return mHasPerformedLongPress;
+
+    /**
+     * Identifies if the provided {@link MotionEvent} is a stylus with the primary stylus button
+     * pressed.
+     *
+     * @param event The event to check.
+     * @return Whether a stylus button press occurred.
+     */
+    private static boolean isStylusButtonPressed(MotionEvent event) {
+        return event.getToolType(0) == MotionEvent.TOOL_TYPE_STYLUS
+                && event.isButtonPressed(MotionEvent.BUTTON_SECONDARY);
     }
 }
diff --git a/src/com/android/launcher3/SimpleOnStylusPressListener.java b/src/com/android/launcher3/SimpleOnStylusPressListener.java
deleted file mode 100644
index 6b97dce..0000000
--- a/src/com/android/launcher3/SimpleOnStylusPressListener.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.android.launcher3;
-
-import android.view.MotionEvent;
-import android.view.View;
-
-import com.android.launcher3.StylusEventHelper.StylusButtonListener;
-
-/**
- * Simple listener that performs a long click on the view after a stylus button press.
- */
-public class SimpleOnStylusPressListener implements StylusButtonListener {
-    private View mView;
-
-    public SimpleOnStylusPressListener(View view) {
-        mView = view;
-    }
-
-    public boolean onPressed(MotionEvent event) {
-        return mView.isLongClickable() && mView.performLongClick();
-    }
-
-    public boolean onReleased(MotionEvent event) {
-        return false;
-    }
-}
\ No newline at end of file
diff --git a/src/com/android/launcher3/StylusEventHelper.java b/src/com/android/launcher3/StylusEventHelper.java
deleted file mode 100644
index d5fc0fa..0000000
--- a/src/com/android/launcher3/StylusEventHelper.java
+++ /dev/null
@@ -1,109 +0,0 @@
-package com.android.launcher3;
-
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewConfiguration;
-
-/**
- * Helper for identifying when a stylus touches a view while the primary stylus button is pressed.
- * This can occur in {@value MotionEvent#ACTION_DOWN} or {@value MotionEvent#ACTION_MOVE}.
- */
-public class StylusEventHelper {
-
-    /**
-     * Implement this interface to receive callbacks for a stylus button press and release.
-     */
-    public interface StylusButtonListener {
-        /**
-         * Called when the stylus button is pressed.
-         *
-         * @param event The MotionEvent that the button press occurred for.
-         * @return Whether the event was handled.
-         */
-        public boolean onPressed(MotionEvent event);
-
-        /**
-         * Called when the stylus button is released after a button press. This is also called if
-         * the event is canceled or the stylus is lifted off the screen.
-         *
-         * @param event The MotionEvent the button release occurred for.
-         * @return Whether the event was handled.
-         */
-        public boolean onReleased(MotionEvent event);
-    }
-
-    private boolean mIsButtonPressed;
-    private View mView;
-    private StylusButtonListener mListener;
-    private final float mSlop;
-
-    /**
-     * Constructs a helper for listening to stylus button presses and releases. Ensure that {
-     * {@link #onMotionEvent(MotionEvent)} and {@link #onGenericMotionEvent(MotionEvent)} are called on
-     * the helper to correctly identify stylus events.
-     *
-     * @param listener The listener to call for stylus events.
-     * @param view Optional view associated with the touch events.
-     */
-    public StylusEventHelper(StylusButtonListener listener, View view) {
-        mListener = listener;
-        mView = view;
-        if (mView != null) {
-            mSlop = ViewConfiguration.get(mView.getContext()).getScaledTouchSlop();
-        } else {
-            mSlop = ViewConfiguration.getTouchSlop();
-        }
-    }
-
-    public boolean onMotionEvent(MotionEvent event) {
-        final boolean stylusButtonPressed = isStylusButtonPressed(event);
-        switch (event.getAction()) {
-            case MotionEvent.ACTION_DOWN:
-                mIsButtonPressed = stylusButtonPressed;
-                if (mIsButtonPressed) {
-                    return mListener.onPressed(event);
-                }
-                break;
-            case MotionEvent.ACTION_MOVE:
-                if (!Utilities.pointInView(mView, event.getX(), event.getY(), mSlop)) {
-                    return false;
-                }
-                if (!mIsButtonPressed && stylusButtonPressed) {
-                    mIsButtonPressed = true;
-                    return mListener.onPressed(event);
-                } else if (mIsButtonPressed && !stylusButtonPressed) {
-                    mIsButtonPressed = false;
-                    return mListener.onReleased(event);
-                }
-                break;
-            case MotionEvent.ACTION_UP:
-            case MotionEvent.ACTION_CANCEL:
-                if (mIsButtonPressed) {
-                    mIsButtonPressed = false;
-                    return mListener.onReleased(event);
-                }
-                break;
-        }
-        return false;
-    }
-
-    /**
-     * Whether a stylus button press is occurring.
-     */
-    public boolean inStylusButtonPressed() {
-        return mIsButtonPressed;
-    }
-
-    /**
-     * Identifies if the provided {@link MotionEvent} is a stylus with the primary stylus button
-     * pressed.
-     *
-     * @param event The event to check.
-     * @return Whether a stylus button press occurred.
-     */
-    private static boolean isStylusButtonPressed(MotionEvent event) {
-        return event.getToolType(0) == MotionEvent.TOOL_TYPE_STYLUS
-                && ((event.getButtonState() & MotionEvent.BUTTON_SECONDARY)
-                        == MotionEvent.BUTTON_SECONDARY);
-    }
-}
\ No newline at end of file
diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java
index f0d18ae..8251d68 100644
--- a/src/com/android/launcher3/folder/FolderIcon.java
+++ b/src/com/android/launcher3/folder/FolderIcon.java
@@ -31,7 +31,6 @@
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
-import android.view.ViewConfiguration;
 import android.view.ViewDebug;
 import android.view.ViewGroup;
 import android.widget.FrameLayout;
@@ -52,8 +51,6 @@
 import com.android.launcher3.LauncherSettings;
 import com.android.launcher3.OnAlarmListener;
 import com.android.launcher3.R;
-import com.android.launcher3.SimpleOnStylusPressListener;
-import com.android.launcher3.StylusEventHelper;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.Workspace;
 import com.android.launcher3.WorkspaceItemInfo;
@@ -87,7 +84,6 @@
     private FolderInfo mInfo;
 
     private CheckLongPressHelper mLongPressHelper;
-    private StylusEventHelper mStylusEventHelper;
 
     static final int DROP_IN_ANIMATION_DURATION = 400;
 
@@ -110,8 +106,6 @@
 
     boolean mAnimating = false;
 
-    private float mSlop;
-
     private Alarm mOpenAlarm = new Alarm();
 
     private boolean mForceHideDot;
@@ -149,9 +143,7 @@
 
     private void init() {
         mLongPressHelper = new CheckLongPressHelper(this);
-        mStylusEventHelper = new StylusEventHelper(new SimpleOnStylusPressListener(this), this);
         mPreviewLayoutRule = new ClippedFolderIconLayoutRule();
-        mSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
         mPreviewItemManager = new PreviewItemManager(this);
         mDotParams = new DotRenderer.DrawParams();
     }
@@ -663,29 +655,10 @@
     public boolean onTouchEvent(MotionEvent event) {
         // Call the superclass onTouchEvent first, because sometimes it changes the state to
         // isPressed() on an ACTION_UP
-        boolean result = super.onTouchEvent(event);
-
-        // Check for a stylus button press, if it occurs cancel any long press checks.
-        if (mStylusEventHelper.onMotionEvent(event)) {
-            mLongPressHelper.cancelLongPress();
-            return true;
-        }
-
-        switch (event.getAction()) {
-            case MotionEvent.ACTION_DOWN:
-                mLongPressHelper.postCheckForLongPress();
-                break;
-            case MotionEvent.ACTION_CANCEL:
-            case MotionEvent.ACTION_UP:
-                mLongPressHelper.cancelLongPress();
-                break;
-            case MotionEvent.ACTION_MOVE:
-                if (!Utilities.pointInView(this, event.getX(), event.getY(), mSlop)) {
-                    mLongPressHelper.cancelLongPress();
-                }
-                break;
-        }
-        return result;
+        super.onTouchEvent(event);
+        mLongPressHelper.onTouchEvent(event);
+        // Keep receiving the rest of the events
+        return true;
     }
 
     @Override
diff --git a/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java b/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
index c1310e3..78acc34 100644
--- a/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
+++ b/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java
@@ -27,7 +27,6 @@
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.View;
-import android.view.ViewConfiguration;
 import android.view.ViewDebug;
 import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityNodeInfo;
@@ -41,8 +40,6 @@
 import com.android.launcher3.LauncherAppWidgetInfo;
 import com.android.launcher3.LauncherAppWidgetProviderInfo;
 import com.android.launcher3.R;
-import com.android.launcher3.SimpleOnStylusPressListener;
-import com.android.launcher3.StylusEventHelper;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.dragndrop.DragLayer;
 import com.android.launcher3.dragndrop.DraggableView;
@@ -66,14 +63,11 @@
     protected final LayoutInflater mInflater;
 
     private final CheckLongPressHelper mLongPressHelper;
-    private final StylusEventHelper mStylusEventHelper;
     protected final Launcher mLauncher;
 
     @ViewDebug.ExportedProperty(category = "launcher")
     private boolean mReinflateOnConfigChange;
 
-    private float mSlop;
-
     private boolean mIsScrollable;
     private boolean mIsAttachedToWindow;
     private boolean mIsAutoAdvanceRegistered;
@@ -93,7 +87,6 @@
         super(context);
         mLauncher = Launcher.getLauncher(context);
         mLongPressHelper = new CheckLongPressHelper(this, this);
-        mStylusEventHelper = new StylusEventHelper(new SimpleOnStylusPressListener(this), this);
         mInflater = LayoutInflater.from(context);
         setAccessibilityDelegate(mLauncher.getAccessibilityDelegate());
         setBackgroundResource(R.drawable.widget_internal_focus_bg);
@@ -157,68 +150,19 @@
     }
 
     public boolean onInterceptTouchEvent(MotionEvent ev) {
-        // Just in case the previous long press hasn't been cleared, we make sure to start fresh
-        // on touch down.
         if (ev.getAction() == MotionEvent.ACTION_DOWN) {
-            mLongPressHelper.cancelLongPress();
-        }
-
-        // Consume any touch events for ourselves after longpress is triggered
-        if (mLongPressHelper.hasPerformedLongPress()) {
-            mLongPressHelper.cancelLongPress();
-            return true;
-        }
-
-        // Watch for longpress or stylus button press events at this level to
-        // make sure users can always pick up this widget
-        if (mStylusEventHelper.onMotionEvent(ev)) {
-            mLongPressHelper.cancelLongPress();
-            return true;
-        }
-
-        switch (ev.getAction()) {
-            case MotionEvent.ACTION_DOWN: {
-                DragLayer dragLayer = Launcher.getLauncher(getContext()).getDragLayer();
-
-                if (mIsScrollable) {
-                     dragLayer.requestDisallowInterceptTouchEvent(true);
-                }
-                if (!mStylusEventHelper.inStylusButtonPressed()) {
-                    mLongPressHelper.postCheckForLongPress();
-                }
-                dragLayer.setTouchCompleteListener(this);
-                break;
+            DragLayer dragLayer = Launcher.getLauncher(getContext()).getDragLayer();
+            if (mIsScrollable) {
+                dragLayer.requestDisallowInterceptTouchEvent(true);
             }
-
-            case MotionEvent.ACTION_UP:
-            case MotionEvent.ACTION_CANCEL:
-                mLongPressHelper.cancelLongPress();
-                break;
-            case MotionEvent.ACTION_MOVE:
-                if (!Utilities.pointInView(this, ev.getX(), ev.getY(), mSlop)) {
-                    mLongPressHelper.cancelLongPress();
-                }
-                break;
+            dragLayer.setTouchCompleteListener(this);
         }
-
-        // Otherwise continue letting touch events fall through to children
-        return false;
+        mLongPressHelper.onTouchEvent(ev);
+        return mLongPressHelper.hasPerformedLongPress();
     }
 
     public boolean onTouchEvent(MotionEvent ev) {
-        // If the widget does not handle touch, then cancel
-        // long press when we release the touch
-        switch (ev.getAction()) {
-            case MotionEvent.ACTION_UP:
-            case MotionEvent.ACTION_CANCEL:
-                mLongPressHelper.cancelLongPress();
-                break;
-            case MotionEvent.ACTION_MOVE:
-                if (!Utilities.pointInView(this, ev.getX(), ev.getY(), mSlop)) {
-                    mLongPressHelper.cancelLongPress();
-                }
-                break;
-        }
+        mLongPressHelper.onTouchEvent(ev);
         // We want to keep receiving though events to be able to cancel long press on ACTION_UP
         return true;
     }
@@ -226,7 +170,6 @@
     @Override
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
-        mSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
 
         mIsAttachedToWindow = true;
         checkIfAutoAdvance();
diff --git a/src/com/android/launcher3/widget/WidgetCell.java b/src/com/android/launcher3/widget/WidgetCell.java
index f055adf..4a0b4ef 100644
--- a/src/com/android/launcher3/widget/WidgetCell.java
+++ b/src/com/android/launcher3/widget/WidgetCell.java
@@ -31,10 +31,9 @@
 import android.widget.TextView;
 
 import com.android.launcher3.BaseActivity;
+import com.android.launcher3.CheckLongPressHelper;
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.R;
-import com.android.launcher3.SimpleOnStylusPressListener;
-import com.android.launcher3.StylusEventHelper;
 import com.android.launcher3.WidgetPreviewLoader;
 import com.android.launcher3.icons.BaseIconFactory;
 import com.android.launcher3.model.WidgetItem;
@@ -71,7 +70,6 @@
     protected WidgetItem mItem;
 
     private WidgetPreviewLoader mWidgetPreviewLoader;
-    private StylusEventHelper mStylusEventHelper;
 
     protected CancellationSignal mActiveRequest;
     private boolean mAnimatePreview = true;
@@ -80,7 +78,8 @@
     private Bitmap mDeferredBitmap;
 
     protected final BaseActivity mActivity;
-    protected DeviceProfile mDeviceProfile;
+    protected final DeviceProfile mDeviceProfile;
+    private final CheckLongPressHelper mLongPressHelper;
 
     public WidgetCell(Context context) {
         this(context, null);
@@ -95,8 +94,9 @@
 
         mActivity = BaseActivity.fromContext(context);
         mDeviceProfile = mActivity.getDeviceProfile();
-        mStylusEventHelper = new StylusEventHelper(new SimpleOnStylusPressListener(this), this);
+        mLongPressHelper = new CheckLongPressHelper(this);
 
+        mLongPressHelper.setLongPressTimeoutFactor(1);
         setContainerWidth();
         setWillNotDraw(false);
         setClipToPadding(false);
@@ -210,11 +210,15 @@
 
     @Override
     public boolean onTouchEvent(MotionEvent ev) {
-        boolean handled = super.onTouchEvent(ev);
-        if (mStylusEventHelper.onMotionEvent(ev)) {
-            return true;
-        }
-        return handled;
+        super.onTouchEvent(ev);
+        mLongPressHelper.onTouchEvent(ev);
+        return true;
+    }
+
+    @Override
+    public void cancelLongPress() {
+        super.cancelLongPress();
+        mLongPressHelper.cancelLongPress();
     }
 
     /**