summaryrefslogtreecommitdiffstats
path: root/src/com/android/launcher3/StylusEventHelper.java
blob: d5fc0fad474b6a30dd9466a9a801e92cd91dfcc0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
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);
    }
}