Refactor StylusEventHelper to provide onButtonPress/Release methods

This will enable an easier migration to the new M APIs for identifying
button presses from stylus / other tools.

Bug: 20430722
Change-Id: I41cfa6eff8d76bb83cf1bdaf6623ec1092ed554c
diff --git a/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java b/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java
index e2c008b..ceb51aa 100644
--- a/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java
+++ b/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java
@@ -913,11 +913,12 @@
         v.setOnLongClickListener(mLongClickListener);
 
         // Enable stylus button to also trigger long click.
-        final StylusEventHelper stylusEventHelper = new StylusEventHelper(v);
+        final StylusEventHelper stylusEventHelper =
+                new StylusEventHelper(new SimpleOnStylusPressListener(v), v);
         v.setOnTouchListener(new View.OnTouchListener() {
             @Override
             public boolean onTouch(View view, MotionEvent event) {
-                return stylusEventHelper.checkAndPerformStylusEvent(event);
+                return stylusEventHelper.onMotionEvent(event);
             }
         });
     }
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index 5070878..c8af600 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -144,7 +144,7 @@
         }
 
         mLongPressHelper = new CheckLongPressHelper(this);
-        mStylusEventHelper = new StylusEventHelper(this);
+        mStylusEventHelper = new StylusEventHelper(new SimpleOnStylusPressListener(this), this);
 
         mOutlineHelper = HolographicOutlineHelper.obtain(getContext());
         if (mCustomShadowsEnabled) {
@@ -270,7 +270,7 @@
         boolean result = super.onTouchEvent(event);
 
         // Check for a stylus button press, if it occurs cancel any long press checks.
-        if (mStylusEventHelper.checkAndPerformStylusEvent(event)) {
+        if (mStylusEventHelper.onMotionEvent(event)) {
             mLongPressHelper.cancelLongPress();
             result = true;
         }
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index 772bb7b..b111bee 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -277,7 +277,7 @@
         mShortcutsAndWidgets.setCellDimensions(mCellWidth, mCellHeight, mWidthGap, mHeightGap,
                 mCountX, mCountY);
 
-        mStylusEventHelper = new StylusEventHelper(this);
+        mStylusEventHelper = new StylusEventHelper(new SimpleOnStylusPressListener(this), this);
 
         mTouchFeedbackView = new ClickShadowView(context);
         addView(mTouchFeedbackView);
@@ -339,7 +339,7 @@
         // enabled to allow rearranging the different home screens. So check what mode
         // the workspace is in, and only perform stylus button presses while in overview mode.
         if (mLauncher.mWorkspace.isInOverviewMode()
-                && mStylusEventHelper.checkAndPerformStylusEvent(ev)) {
+                && mStylusEventHelper.onMotionEvent(ev)) {
             return true;
         }
         return handled;
diff --git a/src/com/android/launcher3/FolderIcon.java b/src/com/android/launcher3/FolderIcon.java
index a175d86..c6b2f35 100644
--- a/src/com/android/launcher3/FolderIcon.java
+++ b/src/com/android/launcher3/FolderIcon.java
@@ -131,7 +131,7 @@
 
     private void init() {
         mLongPressHelper = new CheckLongPressHelper(this);
-        mStylusEventHelper = new StylusEventHelper(this);
+        mStylusEventHelper = new StylusEventHelper(new SimpleOnStylusPressListener(this), this);
         setAccessibilityDelegate(LauncherAppState.getInstance().getAccessibilityDelegate());
     }
 
@@ -725,7 +725,7 @@
         boolean result = super.onTouchEvent(event);
 
         // Check for a stylus button press, if it occurs cancel any long press checks.
-        if (mStylusEventHelper.checkAndPerformStylusEvent(event)) {
+        if (mStylusEventHelper.onMotionEvent(event)) {
             mLongPressHelper.cancelLongPress();
             return true;
         }
diff --git a/src/com/android/launcher3/LauncherAppWidgetHostView.java b/src/com/android/launcher3/LauncherAppWidgetHostView.java
index d8cb682..01332fb 100644
--- a/src/com/android/launcher3/LauncherAppWidgetHostView.java
+++ b/src/com/android/launcher3/LauncherAppWidgetHostView.java
@@ -48,7 +48,7 @@
         super(context);
         mContext = context;
         mLongPressHelper = new CheckLongPressHelper(this);
-        mStylusEventHelper = new StylusEventHelper(this);
+        mStylusEventHelper = new StylusEventHelper(new SimpleOnStylusPressListener(this), this);
         mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
         mDragLayer = ((Launcher) context).getDragLayer();
         setAccessibilityDelegate(LauncherAppState.getInstance().getAccessibilityDelegate());
@@ -94,7 +94,7 @@
 
         // Watch for longpress or stylus button press events at this level to
         // make sure users can always pick up this widget
-        if (mStylusEventHelper.checkAndPerformStylusEvent(ev)) {
+        if (mStylusEventHelper.onMotionEvent(ev)) {
             mLongPressHelper.cancelLongPress();
             return true;
         }
diff --git a/src/com/android/launcher3/SimpleOnStylusPressListener.java b/src/com/android/launcher3/SimpleOnStylusPressListener.java
new file mode 100644
index 0000000..6b97dce
--- /dev/null
+++ b/src/com/android/launcher3/SimpleOnStylusPressListener.java
@@ -0,0 +1,25 @@
+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
index 54c5509..d0e3188 100644
--- a/src/com/android/launcher3/StylusEventHelper.java
+++ b/src/com/android/launcher3/StylusEventHelper.java
@@ -6,55 +6,82 @@
 
 /**
  * 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}. On a
- * stylus button press this performs the view's {@link View#performLongClick()} method, if the view
- * is long clickable.
+ * This can occur in {@value MotionEvent#ACTION_DOWN} or {@value MotionEvent#ACTION_MOVE}.
  */
 public class StylusEventHelper {
-    private boolean mIsButtonPressed;
-    private View mView;
-
-    public StylusEventHelper(View view) {
-        mView = view;
-    }
 
     /**
-     * Call this in onTouchEvent method of a view to identify a stylus button press and perform a
-     * long click (if the view is long clickable).
-     *
-     * @param event The event to check for a stylus button press.
-     * @return Whether a stylus event occurred and was handled.
+     * Implement this interface to receive callbacks for a stylus button press and release.
      */
-    public boolean checkAndPerformStylusEvent(MotionEvent event) {
-        final float slop = ViewConfiguration.get(mView.getContext()).getScaledTouchSlop();
+    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);
 
-        if (!mView.isLongClickable()) {
-            // We don't do anything unless the view is long clickable.
-            return false;
+        /**
+         * 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 = false;
-                if (stylusButtonPressed && mView.performLongClick()) {
-                    mIsButtonPressed = true;
-                    return true;
+                mIsButtonPressed = stylusButtonPressed;
+                if (mIsButtonPressed) {
+                    return mListener.onPressed(event);
                 }
                 break;
             case MotionEvent.ACTION_MOVE:
-                if (Utilities.pointInView(mView, event.getX(), event.getY(), slop)) {
-                    if (!mIsButtonPressed && stylusButtonPressed && mView.performLongClick()) {
-                        mIsButtonPressed = true;
-                        return true;
-                    } else if (mIsButtonPressed && !stylusButtonPressed) {
-                        mIsButtonPressed = false;
-                    }
+                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:
-                mIsButtonPressed = false;
+                if (mIsButtonPressed) {
+                    mIsButtonPressed = false;
+                    return mListener.onReleased(event);
+                }
                 break;
         }
         return false;
diff --git a/src/com/android/launcher3/widget/WidgetCell.java b/src/com/android/launcher3/widget/WidgetCell.java
index 94bbd92..70eceb9 100644
--- a/src/com/android/launcher3/widget/WidgetCell.java
+++ b/src/com/android/launcher3/widget/WidgetCell.java
@@ -36,6 +36,7 @@
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherAppState;
 import com.android.launcher3.LauncherAppWidgetProviderInfo;
+import com.android.launcher3.SimpleOnStylusPressListener;
 import com.android.launcher3.R;
 import com.android.launcher3.StylusEventHelper;
 import com.android.launcher3.WidgetPreviewLoader;
@@ -93,7 +94,7 @@
 
         final Resources r = context.getResources();
         mLauncher = (Launcher) context;
-        mStylusEventHelper = new StylusEventHelper(this);
+        mStylusEventHelper = new StylusEventHelper(new SimpleOnStylusPressListener(this), this);
 
         mDimensionsFormatString = r.getString(R.string.widget_dims_format);
         setContainerWidth();
@@ -211,7 +212,7 @@
     @Override
     public boolean onTouchEvent(MotionEvent ev) {
         boolean handled = super.onTouchEvent(ev);
-        if (mStylusEventHelper.checkAndPerformStylusEvent(ev)) {
+        if (mStylusEventHelper.onMotionEvent(ev)) {
             return true;
         }
         return handled;