diff options
Diffstat (limited to 'core/java/android/view/MotionEvent.java')
-rw-r--r-- | core/java/android/view/MotionEvent.java | 1020 |
1 files changed, 852 insertions, 168 deletions
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java index 7611b08..82fd581 100644 --- a/core/java/android/view/MotionEvent.java +++ b/core/java/android/view/MotionEvent.java @@ -23,53 +23,60 @@ import android.os.SystemClock; import android.util.SparseArray; /** - * Object used to report movement (mouse, pen, finger, trackball) events. This - * class may hold either absolute or relative movements, depending on what - * it is being used for. + * Object used to report movement (mouse, pen, finger, trackball) events. + * Motion events may hold either absolute or relative movements and other data, + * depending on the type of device. + * + * <h3>Overview</h3> * <p> - * On pointing devices with source class {@link InputDevice#SOURCE_CLASS_POINTER} - * such as touch screens, the pointer coordinates specify absolute - * positions such as view X/Y coordinates. Each complete gesture is represented - * by a sequence of motion events with actions that describe pointer state transitions - * and movements. A gesture starts with a motion event with {@link #ACTION_DOWN} - * that provides the location of the first pointer down. As each additional - * pointer that goes down or up, the framework will generate a motion event with - * {@link #ACTION_POINTER_DOWN} or {@link #ACTION_POINTER_UP} accordingly. - * Pointer movements are described by motion events with {@link #ACTION_MOVE}. - * Finally, a gesture end either when the final pointer goes up as represented - * by a motion event with {@link #ACTION_UP} or when gesture is canceled - * with {@link #ACTION_CANCEL}. + * Motion events describe movements in terms of an action code and a set of axis values. + * The action code specifies the state change that occurred such as a pointer going + * down or up. The axis values describe the position and other movement properties. * </p><p> - * Some pointing devices such as mice may support vertical and/or horizontal scrolling. - * A scroll event is reported as a generic motion event with {@link #ACTION_SCROLL} that - * includes the relative scroll offset in the {@link #AXIS_VSCROLL} and - * {@link #AXIS_HSCROLL} axes. See {@link #getAxisValue(int)} for information - * about retrieving these additional axes. + * For example, when the user first touches the screen, the system delivers a touch + * event to the appropriate {@link View} with the action code {@link #ACTION_DOWN} + * and a set of axis values that include the X and Y coordinates of the touch and + * information about the pressure, size and orientation of the contact area. * </p><p> - * On trackball devices with source class {@link InputDevice#SOURCE_CLASS_TRACKBALL}, - * the pointer coordinates specify relative movements as X/Y deltas. - * A trackball gesture consists of a sequence of movements described by motion - * events with {@link #ACTION_MOVE} interspersed with occasional {@link #ACTION_DOWN} - * or {@link #ACTION_UP} motion events when the trackball button is pressed or released. + * Some devices can report multiple movement traces at the same time. Multi-touch + * screens emit one movement trace for each finger. The individual fingers or + * other objects that generate movement traces are referred to as <em>pointers</em>. + * Motion events contain information about all of the pointers that are currently active + * even if some of them have not moved since the last event was delivered. * </p><p> - * On joystick devices with source class {@link InputDevice#SOURCE_CLASS_JOYSTICK}, - * the pointer coordinates specify the absolute position of the joystick axes. - * The joystick axis values are normalized to a range of -1.0 to 1.0 where 0.0 corresponds - * to the center position. More information about the set of available axes and the - * range of motion can be obtained using {@link InputDevice#getMotionRange}. - * Some common joystick axes are {@link #AXIS_X}, {@link #AXIS_Y}, - * {@link #AXIS_HAT_X}, {@link #AXIS_HAT_Y}, {@link #AXIS_Z} and {@link #AXIS_RZ}. - * </p><p> - * Motion events always report movements for all pointers at once. The number - * of pointers only ever changes by one as individual pointers go up and down, + * The number of pointers only ever changes by one as individual pointers go up and down, * except when the gesture is canceled. * </p><p> - * The order in which individual pointers appear within a motion event can change - * from one event to the next. Use the {@link #getPointerId(int)} method to obtain a - * pointer id to track pointers across motion events in a gesture. Then for - * successive motion events, use the {@link #findPointerIndex(int)} method to obtain - * the pointer index for a given pointer id in that motion event. + * Each pointer has a unique id that is assigned when it first goes down + * (indicated by {@link #ACTION_DOWN} or {@link #ACTION_POINTER_DOWN}). A pointer id + * remains valid until the pointer eventually goes up (indicated by {@link #ACTION_UP} + * or {@link #ACTION_POINTER_UP}) or when the gesture is canceled (indicated by + * {@link #ACTION_CANCEL}). + * </p><p> + * The MotionEvent class provides many methods to query the position and other properties of + * pointers, such as {@link #getX(int)}, {@link #getY(int)}, {@link #getAxisValue}, + * {@link #getPointerId(int)}, {@link #getToolType(int)}, and many others. Most of these + * methods accept the pointer index as a parameter rather than the pointer id. + * The pointer index of each pointer in the event ranges from 0 to one less than the value + * returned by {@link #getPointerCount()}. * </p><p> + * The order in which individual pointers appear within a motion event is undefined. + * Thus the pointer index of a pointer can change from one event to the next but + * the pointer id of a pointer is guaranteed to remain constant as long as the pointer + * remains active. Use the {@link #getPointerId(int)} method to obtain the + * pointer id of a pointer to track it across all subsequent motion events in a gesture. + * Then for successive motion events, use the {@link #findPointerIndex(int)} method + * to obtain the pointer index for a given pointer id in that motion event. + * </p><p> + * Mouse and stylus buttons can be retrieved using {@link #getButtonState()}. It is a + * good idea to check the button state while handling {@link #ACTION_DOWN} as part + * of a touch event. The application may choose to perform some different action + * if the touch event starts due to a secondary button click, such as presenting a + * context menu. + * </p> + * + * <h3>Batching</h3> + * <p> * For efficiency, motion events with {@link #ACTION_MOVE} may batch together * multiple movement samples within a single object. The most current * pointer coordinates are available using {@link #getX(int)} and {@link #getY(int)}. @@ -98,42 +105,104 @@ import android.util.SparseArray; * ev.getPointerId(p), ev.getX(p), ev.getY(p)); * } * } - * </code></pre></p><p> - * In general, the framework cannot guarantee that the motion events it delivers - * to a view always constitute a complete motion sequences since some events may be dropped - * or modified by containing views before they are delivered. The view implementation - * should be prepared to handle {@link #ACTION_CANCEL} and should tolerate anomalous - * situations such as receiving a new {@link #ACTION_DOWN} without first having - * received an {@link #ACTION_UP} for the prior gesture. + * </code></pre></p> + * + * <h3>Device Types</h3> + * <p> + * The interpretation of the contents of a MotionEvent varies significantly depending + * on the source class of the device. + * </p><p> + * On pointing devices with source class {@link InputDevice#SOURCE_CLASS_POINTER} + * such as touch screens, the pointer coordinates specify absolute + * positions such as view X/Y coordinates. Each complete gesture is represented + * by a sequence of motion events with actions that describe pointer state transitions + * and movements. A gesture starts with a motion event with {@link #ACTION_DOWN} + * that provides the location of the first pointer down. As each additional + * pointer that goes down or up, the framework will generate a motion event with + * {@link #ACTION_POINTER_DOWN} or {@link #ACTION_POINTER_UP} accordingly. + * Pointer movements are described by motion events with {@link #ACTION_MOVE}. + * Finally, a gesture end either when the final pointer goes up as represented + * by a motion event with {@link #ACTION_UP} or when gesture is canceled + * with {@link #ACTION_CANCEL}. + * </p><p> + * Some pointing devices such as mice may support vertical and/or horizontal scrolling. + * A scroll event is reported as a generic motion event with {@link #ACTION_SCROLL} that + * includes the relative scroll offset in the {@link #AXIS_VSCROLL} and + * {@link #AXIS_HSCROLL} axes. See {@link #getAxisValue(int)} for information + * about retrieving these additional axes. + * </p><p> + * On trackball devices with source class {@link InputDevice#SOURCE_CLASS_TRACKBALL}, + * the pointer coordinates specify relative movements as X/Y deltas. + * A trackball gesture consists of a sequence of movements described by motion + * events with {@link #ACTION_MOVE} interspersed with occasional {@link #ACTION_DOWN} + * or {@link #ACTION_UP} motion events when the trackball button is pressed or released. + * </p><p> + * On joystick devices with source class {@link InputDevice#SOURCE_CLASS_JOYSTICK}, + * the pointer coordinates specify the absolute position of the joystick axes. + * The joystick axis values are normalized to a range of -1.0 to 1.0 where 0.0 corresponds + * to the center position. More information about the set of available axes and the + * range of motion can be obtained using {@link InputDevice#getMotionRange}. + * Some common joystick axes are {@link #AXIS_X}, {@link #AXIS_Y}, + * {@link #AXIS_HAT_X}, {@link #AXIS_HAT_Y}, {@link #AXIS_Z} and {@link #AXIS_RZ}. * </p><p> * Refer to {@link InputDevice} for more information about how different kinds of * input devices and sources represent pointer coordinates. * </p> + * + * <h3>Consistency Guarantees</h3> + * <p> + * Motion events are always delivered to views as a consistent stream of events. + * What constitutes a consistent stream varies depending on the type of device. + * For touch events, consistency implies that pointers go down one at a time, + * move around as a group and then go up one at a time or are canceled. + * </p><p> + * While the framework tries to deliver consistent streams of motion events to + * views, it cannot guarantee it. Some events may be dropped or modified by + * containing views in the application before they are delivered thereby making + * the stream of events inconsistent. Views should always be prepared to + * handle {@link #ACTION_CANCEL} and should tolerate anomalous + * situations such as receiving a new {@link #ACTION_DOWN} without first having + * received an {@link #ACTION_UP} for the prior gesture. + * </p> */ public final class MotionEvent extends InputEvent implements Parcelable { private static final long NS_PER_MS = 1000000; private static final boolean TRACK_RECYCLED_LOCATION = false; - + + /** + * An invalid pointer id. + * + * This value (-1) can be used as a placeholder to indicate that a pointer id + * has not been assigned or is not available. It cannot appear as + * a pointer id inside a {@link MotionEvent}. + */ + public static final int INVALID_POINTER_ID = -1; + /** * Bit mask of the parts of the action code that are the action itself. */ public static final int ACTION_MASK = 0xff; /** - * Constant for {@link #getAction}: A pressed gesture has started, the + * Constant for {@link #getActionMasked}: A pressed gesture has started, the * motion contains the initial starting location. + * <p> + * This is also a good time to check the button state to distinguish + * secondary and tertiary button clicks and handle them appropriately. + * Use {@link #getButtonState} to retrieve the button state. + * </p> */ public static final int ACTION_DOWN = 0; /** - * Constant for {@link #getAction}: A pressed gesture has finished, the + * Constant for {@link #getActionMasked}: A pressed gesture has finished, the * motion contains the final release location as well as any intermediate * points since the last down or move event. */ public static final int ACTION_UP = 1; /** - * Constant for {@link #getAction}: A change has happened during a + * Constant for {@link #getActionMasked}: A change has happened during a * press gesture (between {@link #ACTION_DOWN} and {@link #ACTION_UP}). * The motion contains the most recent point, as well as any intermediate * points since the last down or move event. @@ -141,33 +210,43 @@ public final class MotionEvent extends InputEvent implements Parcelable { public static final int ACTION_MOVE = 2; /** - * Constant for {@link #getAction}: The current gesture has been aborted. + * Constant for {@link #getActionMasked}: The current gesture has been aborted. * You will not receive any more points in it. You should treat this as * an up event, but not perform any action that you normally would. */ public static final int ACTION_CANCEL = 3; /** - * Constant for {@link #getAction}: A movement has happened outside of the + * Constant for {@link #getActionMasked}: A movement has happened outside of the * normal bounds of the UI element. This does not provide a full gesture, * but only the initial location of the movement/touch. */ public static final int ACTION_OUTSIDE = 4; /** - * A non-primary pointer has gone down. The bits in - * {@link #ACTION_POINTER_ID_MASK} indicate which pointer changed. + * Constant for {@link #getActionMasked}: A non-primary pointer has gone down. + * <p> + * Use {@link #getActionIndex} to retrieve the index of the pointer that changed. + * </p><p> + * The index is encoded in the {@link #ACTION_POINTER_INDEX_MASK} bits of the + * unmasked action returned by {@link #getAction}. + * </p> */ public static final int ACTION_POINTER_DOWN = 5; /** - * A non-primary pointer has gone up. The bits in - * {@link #ACTION_POINTER_ID_MASK} indicate which pointer changed. + * Constant for {@link #getActionMasked}: A non-primary pointer has gone up. + * <p> + * Use {@link #getActionIndex} to retrieve the index of the pointer that changed. + * </p><p> + * The index is encoded in the {@link #ACTION_POINTER_INDEX_MASK} bits of the + * unmasked action returned by {@link #getAction}. + * </p> */ public static final int ACTION_POINTER_UP = 6; /** - * Constant for {@link #getAction}: A change happened but the pointer + * Constant for {@link #getActionMasked}: A change happened but the pointer * is not down (unlike {@link #ACTION_MOVE}). The motion contains the most * recent point, as well as any intermediate points since the last * hover move event. @@ -182,14 +261,14 @@ public final class MotionEvent extends InputEvent implements Parcelable { public static final int ACTION_HOVER_MOVE = 7; /** - * Constant for {@link #getAction}: The motion event contains relative + * Constant for {@link #getActionMasked}: The motion event contains relative * vertical and/or horizontal scroll offsets. Use {@link #getAxisValue(int)} * to retrieve the information from {@link #AXIS_VSCROLL} and {@link #AXIS_HSCROLL}. * The pointer may or may not be down when this event is dispatched. - * <p></p> + * <p> * This action is always delivered to the window or view under the pointer, which * may not be the window or view currently touched. - * <p> + * </p><p> * This action is not a touch event so it is delivered to * {@link View#onGenericMotionEvent(MotionEvent)} rather than * {@link View#onTouchEvent(MotionEvent)}. @@ -198,7 +277,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { public static final int ACTION_SCROLL = 8; /** - * Constant for {@link #getAction}: The pointer is not down but has entered the + * Constant for {@link #getActionMasked}: The pointer is not down but has entered the * boundaries of a window or view. * <p> * This action is always delivered to the window or view under the pointer. @@ -211,7 +290,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { public static final int ACTION_HOVER_ENTER = 9; /** - * Constant for {@link #getAction}: The pointer is not down but has exited the + * Constant for {@link #getActionMasked}: The pointer is not down but has exited the * boundaries of a window or view. * <p> * This action is always delivered to the window or view that was previously under the pointer. @@ -230,15 +309,19 @@ public final class MotionEvent extends InputEvent implements Parcelable { * index where the data for the pointer going up or down can be found; you can * get its identifier with {@link #getPointerId(int)} and the actual * data with {@link #getX(int)} etc. + * + * @see #getActionIndex */ public static final int ACTION_POINTER_INDEX_MASK = 0xff00; /** * Bit shift for the action bits holding the pointer index as * defined by {@link #ACTION_POINTER_INDEX_MASK}. + * + * @see #getActionIndex */ public static final int ACTION_POINTER_INDEX_SHIFT = 8; - + /** * @deprecated Use {@link #ACTION_POINTER_INDEX_MASK} to retrieve the * data index associated with {@link #ACTION_POINTER_DOWN}. @@ -339,7 +422,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { public static final int EDGE_RIGHT = 0x00000008; /** - * Constant used to identify the X axis of a motion event. + * Axis constant: X axis of a motion event. * <p> * <ul> * <li>For a touch screen, reports the absolute X screen position of the center of @@ -364,7 +447,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { public static final int AXIS_X = 0; /** - * Constant used to identify the Y axis of a motion event. + * Axis constant: Y axis of a motion event. * <p> * <ul> * <li>For a touch screen, reports the absolute Y screen position of the center of @@ -389,7 +472,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { public static final int AXIS_Y = 1; /** - * Constant used to identify the Pressure axis of a motion event. + * Axis constant: Pressure axis of a motion event. * <p> * <ul> * <li>For a touch screen or touch pad, reports the approximate pressure applied to the surface @@ -411,7 +494,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { public static final int AXIS_PRESSURE = 2; /** - * Constant used to identify the Size axis of a motion event. + * Axis constant: Size axis of a motion event. * <p> * <ul> * <li>For a touch screen or touch pad, reports the approximate size of the contact area in @@ -431,7 +514,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { public static final int AXIS_SIZE = 3; /** - * Constant used to identify the TouchMajor axis of a motion event. + * Axis constant: TouchMajor axis of a motion event. * <p> * <ul> * <li>For a touch screen, reports the length of the major axis of an ellipse that @@ -452,7 +535,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { public static final int AXIS_TOUCH_MAJOR = 4; /** - * Constant used to identify the TouchMinor axis of a motion event. + * Axis constant: TouchMinor axis of a motion event. * <p> * <ul> * <li>For a touch screen, reports the length of the minor axis of an ellipse that @@ -475,7 +558,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { public static final int AXIS_TOUCH_MINOR = 5; /** - * Constant used to identify the ToolMajor axis of a motion event. + * Axis constant: ToolMajor axis of a motion event. * <p> * <ul> * <li>For a touch screen, reports the length of the major axis of an ellipse that @@ -500,7 +583,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { public static final int AXIS_TOOL_MAJOR = 6; /** - * Constant used to identify the ToolMinor axis of a motion event. + * Axis constant: ToolMinor axis of a motion event. * <p> * <ul> * <li>For a touch screen, reports the length of the minor axis of an ellipse that @@ -525,7 +608,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { public static final int AXIS_TOOL_MINOR = 7; /** - * Constant used to identify the Orientation axis of a motion event. + * Axis constant: Orientation axis of a motion event. * <p> * <ul> * <li>For a touch screen or touch pad, reports the orientation of the finger @@ -547,7 +630,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { public static final int AXIS_ORIENTATION = 8; /** - * Constant used to identify the Vertical Scroll axis of a motion event. + * Axis constant: Vertical Scroll axis of a motion event. * <p> * <ul> * <li>For a mouse, reports the relative movement of the vertical scroll wheel. @@ -565,7 +648,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { public static final int AXIS_VSCROLL = 9; /** - * Constant used to identify the Horizontal Scroll axis of a motion event. + * Axis constant: Horizontal Scroll axis of a motion event. * <p> * <ul> * <li>For a mouse, reports the relative movement of the horizontal scroll wheel. @@ -583,7 +666,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { public static final int AXIS_HSCROLL = 10; /** - * Constant used to identify the Z axis of a motion event. + * Axis constant: Z axis of a motion event. * <p> * <ul> * <li>For a joystick, reports the absolute Z position of the joystick. @@ -601,7 +684,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { public static final int AXIS_Z = 11; /** - * Constant used to identify the X Rotation axis of a motion event. + * Axis constant: X Rotation axis of a motion event. * <p> * <ul> * <li>For a joystick, reports the absolute rotation angle about the X axis. @@ -617,7 +700,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { public static final int AXIS_RX = 12; /** - * Constant used to identify the Y Rotation axis of a motion event. + * Axis constant: Y Rotation axis of a motion event. * <p> * <ul> * <li>For a joystick, reports the absolute rotation angle about the Y axis. @@ -633,7 +716,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { public static final int AXIS_RY = 13; /** - * Constant used to identify the Z Rotation axis of a motion event. + * Axis constant: Z Rotation axis of a motion event. * <p> * <ul> * <li>For a joystick, reports the absolute rotation angle about the Z axis. @@ -651,7 +734,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { public static final int AXIS_RZ = 14; /** - * Constant used to identify the Hat X axis of a motion event. + * Axis constant: Hat X axis of a motion event. * <p> * <ul> * <li>For a joystick, reports the absolute X position of the directional hat control. @@ -667,7 +750,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { public static final int AXIS_HAT_X = 15; /** - * Constant used to identify the Hat Y axis of a motion event. + * Axis constant: Hat Y axis of a motion event. * <p> * <ul> * <li>For a joystick, reports the absolute Y position of the directional hat control. @@ -683,7 +766,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { public static final int AXIS_HAT_Y = 16; /** - * Constant used to identify the Left Trigger axis of a motion event. + * Axis constant: Left Trigger axis of a motion event. * <p> * <ul> * <li>For a joystick, reports the absolute position of the left trigger control. @@ -699,7 +782,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { public static final int AXIS_LTRIGGER = 17; /** - * Constant used to identify the Right Trigger axis of a motion event. + * Axis constant: Right Trigger axis of a motion event. * <p> * <ul> * <li>For a joystick, reports the absolute position of the right trigger control. @@ -715,7 +798,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { public static final int AXIS_RTRIGGER = 18; /** - * Constant used to identify the Throttle axis of a motion event. + * Axis constant: Throttle axis of a motion event. * <p> * <ul> * <li>For a joystick, reports the absolute position of the throttle control. @@ -731,7 +814,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { public static final int AXIS_THROTTLE = 19; /** - * Constant used to identify the Rudder axis of a motion event. + * Axis constant: Rudder axis of a motion event. * <p> * <ul> * <li>For a joystick, reports the absolute position of the rudder control. @@ -747,7 +830,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { public static final int AXIS_RUDDER = 20; /** - * Constant used to identify the Wheel axis of a motion event. + * Axis constant: Wheel axis of a motion event. * <p> * <ul> * <li>For a joystick, reports the absolute position of the steering wheel control. @@ -763,7 +846,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { public static final int AXIS_WHEEL = 21; /** - * Constant used to identify the Gas axis of a motion event. + * Axis constant: Gas axis of a motion event. * <p> * <ul> * <li>For a joystick, reports the absolute position of the gas (accelerator) control. @@ -780,7 +863,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { public static final int AXIS_GAS = 22; /** - * Constant used to identify the Brake axis of a motion event. + * Axis constant: Brake axis of a motion event. * <p> * <ul> * <li>For a joystick, reports the absolute position of the brake control. @@ -796,7 +879,24 @@ public final class MotionEvent extends InputEvent implements Parcelable { public static final int AXIS_BRAKE = 23; /** - * Constant used to identify the Generic 1 axis of a motion event. + * Axis constant: Distance axis of a motion event. + * <p> + * <ul> + * <li>For a stylus, reports the distance of the stylus from the screen. + * The value is normalized to a range from 0.0 (direct contact) to 1.0 (furthest measurable + * distance). + * </ul> + * </p> + * + * @see #getAxisValue(int, int) + * @see #getHistoricalAxisValue(int, int, int) + * @see MotionEvent.PointerCoords#getAxisValue(int) + * @see InputDevice#getMotionRange + */ + public static final int AXIS_DISTANCE = 24; + + /** + * Axis constant: Generic 1 axis of a motion event. * The interpretation of a generic axis is device-specific. * * @see #getAxisValue(int, int) @@ -807,7 +907,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { public static final int AXIS_GENERIC_1 = 32; /** - * Constant used to identify the Generic 2 axis of a motion event. + * Axis constant: Generic 2 axis of a motion event. * The interpretation of a generic axis is device-specific. * * @see #getAxisValue(int, int) @@ -818,7 +918,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { public static final int AXIS_GENERIC_2 = 33; /** - * Constant used to identify the Generic 3 axis of a motion event. + * Axis constant: Generic 3 axis of a motion event. * The interpretation of a generic axis is device-specific. * * @see #getAxisValue(int, int) @@ -829,7 +929,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { public static final int AXIS_GENERIC_3 = 34; /** - * Constant used to identify the Generic 4 axis of a motion event. + * Axis constant: Generic 4 axis of a motion event. * The interpretation of a generic axis is device-specific. * * @see #getAxisValue(int, int) @@ -840,7 +940,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { public static final int AXIS_GENERIC_4 = 35; /** - * Constant used to identify the Generic 5 axis of a motion event. + * Axis constant: Generic 5 axis of a motion event. * The interpretation of a generic axis is device-specific. * * @see #getAxisValue(int, int) @@ -851,7 +951,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { public static final int AXIS_GENERIC_5 = 36; /** - * Constant used to identify the Generic 6 axis of a motion event. + * Axis constant: Generic 6 axis of a motion event. * The interpretation of a generic axis is device-specific. * * @see #getAxisValue(int, int) @@ -862,7 +962,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { public static final int AXIS_GENERIC_6 = 37; /** - * Constant used to identify the Generic 7 axis of a motion event. + * Axis constant: Generic 7 axis of a motion event. * The interpretation of a generic axis is device-specific. * * @see #getAxisValue(int, int) @@ -873,7 +973,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { public static final int AXIS_GENERIC_7 = 38; /** - * Constant used to identify the Generic 8 axis of a motion event. + * Axis constant: Generic 8 axis of a motion event. * The interpretation of a generic axis is device-specific. * * @see #getAxisValue(int, int) @@ -884,7 +984,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { public static final int AXIS_GENERIC_8 = 39; /** - * Constant used to identify the Generic 9 axis of a motion event. + * Axis constant: Generic 9 axis of a motion event. * The interpretation of a generic axis is device-specific. * * @see #getAxisValue(int, int) @@ -895,7 +995,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { public static final int AXIS_GENERIC_9 = 40; /** - * Constant used to identify the Generic 10 axis of a motion event. + * Axis constant: Generic 10 axis of a motion event. * The interpretation of a generic axis is device-specific. * * @see #getAxisValue(int, int) @@ -906,7 +1006,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { public static final int AXIS_GENERIC_10 = 41; /** - * Constant used to identify the Generic 11 axis of a motion event. + * Axis constant: Generic 11 axis of a motion event. * The interpretation of a generic axis is device-specific. * * @see #getAxisValue(int, int) @@ -917,7 +1017,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { public static final int AXIS_GENERIC_11 = 42; /** - * Constant used to identify the Generic 12 axis of a motion event. + * Axis constant: Generic 12 axis of a motion event. * The interpretation of a generic axis is device-specific. * * @see #getAxisValue(int, int) @@ -928,7 +1028,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { public static final int AXIS_GENERIC_12 = 43; /** - * Constant used to identify the Generic 13 axis of a motion event. + * Axis constant: Generic 13 axis of a motion event. * The interpretation of a generic axis is device-specific. * * @see #getAxisValue(int, int) @@ -939,7 +1039,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { public static final int AXIS_GENERIC_13 = 44; /** - * Constant used to identify the Generic 14 axis of a motion event. + * Axis constant: Generic 14 axis of a motion event. * The interpretation of a generic axis is device-specific. * * @see #getAxisValue(int, int) @@ -950,7 +1050,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { public static final int AXIS_GENERIC_14 = 45; /** - * Constant used to identify the Generic 15 axis of a motion event. + * Axis constant: Generic 15 axis of a motion event. * The interpretation of a generic axis is device-specific. * * @see #getAxisValue(int, int) @@ -961,7 +1061,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { public static final int AXIS_GENERIC_15 = 46; /** - * Constant used to identify the Generic 16 axis of a motion event. + * Axis constant: Generic 16 axis of a motion event. * The interpretation of a generic axis is device-specific. * * @see #getAxisValue(int, int) @@ -977,7 +1077,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { // Symbolic names of all axes. private static final SparseArray<String> AXIS_SYMBOLIC_NAMES = new SparseArray<String>(); - private static void populateAxisSymbolicNames() { + static { SparseArray<String> names = AXIS_SYMBOLIC_NAMES; names.append(AXIS_X, "AXIS_X"); names.append(AXIS_Y, "AXIS_Y"); @@ -1003,6 +1103,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { names.append(AXIS_WHEEL, "AXIS_WHEEL"); names.append(AXIS_GAS, "AXIS_GAS"); names.append(AXIS_BRAKE, "AXIS_BRAKE"); + names.append(AXIS_DISTANCE, "AXIS_DISTANCE"); names.append(AXIS_GENERIC_1, "AXIS_GENERIC_1"); names.append(AXIS_GENERIC_2, "AXIS_GENERIC_2"); names.append(AXIS_GENERIC_3, "AXIS_GENERIC_3"); @@ -1021,8 +1122,169 @@ public final class MotionEvent extends InputEvent implements Parcelable { names.append(AXIS_GENERIC_16, "AXIS_GENERIC_16"); } + /** + * Button constant: Primary button (left mouse button, stylus tip). + * + * @see #getButtonState + */ + public static final int BUTTON_PRIMARY = 1 << 0; + + /** + * Button constant: Secondary button (right mouse button, stylus barrel). + * + * @see #getButtonState + */ + public static final int BUTTON_SECONDARY = 1 << 1; + + /** + * Button constant: Tertiary button (middle mouse button). + * + * @see #getButtonState + */ + public static final int BUTTON_TERTIARY = 1 << 2; + + /** + * Button constant: Back button pressed (mouse back button). + * <p> + * The system may send a {@link KeyEvent#KEYCODE_BACK} key press to the application + * when this button is pressed. + * </p> + * + * @see #getButtonState + */ + public static final int BUTTON_BACK = 1 << 3; + + /** + * Button constant: Forward button pressed (mouse forward button). + * <p> + * The system may send a {@link KeyEvent#KEYCODE_FORWARD} key press to the application + * when this button is pressed. + * </p> + * + * @see #getButtonState + */ + public static final int BUTTON_FORWARD = 1 << 4; + + /** + * Button constant: Eraser button pressed (stylus end). + * + * @see #getButtonState + */ + public static final int BUTTON_ERASER = 1 << 5; + + // NOTE: If you add a new axis here you must also add it to: + // native/include/android/input.h + + // Symbolic names of all button states in bit order from least significant + // to most significant. + private static final String[] BUTTON_SYMBOLIC_NAMES = new String[] { + "BUTTON_PRIMARY", + "BUTTON_SECONDARY", + "BUTTON_TERTIARY", + "BUTTON_BACK", + "BUTTON_FORWARD", + "BUTTON_ERASER", + "0x00000040", + "0x00000080", + "0x00000100", + "0x00000200", + "0x00000400", + "0x00000800", + "0x00001000", + "0x00002000", + "0x00004000", + "0x00008000", + "0x00010000", + "0x00020000", + "0x00040000", + "0x00080000", + "0x00100000", + "0x00200000", + "0x00400000", + "0x00800000", + "0x01000000", + "0x02000000", + "0x04000000", + "0x08000000", + "0x10000000", + "0x20000000", + "0x40000000", + "0x80000000", + }; + + /** + * Tool type constant: Unknown tool type. + * This constant is used when the tool type is not known or is not relevant, + * such as for a trackball or other non-pointing device. + * + * @see #getToolType + */ + public static final int TOOL_TYPE_UNKNOWN = 0; + + /** + * Tool type constant: The tool is a finger directly touching the display. + * + * This is a <em>direct</em> positioning tool. + * + * @see #getToolType + */ + public static final int TOOL_TYPE_FINGER = 1; + + /** + * Tool type constant: The tool is a stylus directly touching the display + * or hovering slightly above it. + * + * This is a <em>direct</em> positioning tool. + * + * @see #getToolType + */ + public static final int TOOL_TYPE_STYLUS = 2; + + /** + * Tool type constant: The tool is a mouse or trackpad that translates + * relative motions into cursor movements on the display. + * + * This is an <em>indirect</em> positioning tool. + * + * @see #getToolType + */ + public static final int TOOL_TYPE_MOUSE = 3; + + /** + * Tool type constant: The tool is a finger on a touch pad that is not + * directly attached to the display. Finger movements on the touch pad + * may be translated into touches on the display, possibly with visual feedback. + * + * This is an <em>indirect</em> positioning tool. + * + * @see #getToolType + */ + public static final int TOOL_TYPE_INDIRECT_FINGER = 4; + + /** + * Tool type constant: The tool is a stylus on a digitizer tablet that is not + * attached to the display. Stylus movements on the digitizer may be translated + * into touches on the display, possibly with visual feedback. + * + * This is an <em>indirect</em> positioning tool. + * + * @see #getToolType + */ + public static final int TOOL_TYPE_INDIRECT_STYLUS = 5; + + // NOTE: If you add a new tool type here you must also add it to: + // native/include/android/input.h + + // Symbolic names of all tool types. + private static final SparseArray<String> TOOL_TYPE_SYMBOLIC_NAMES = new SparseArray<String>(); static { - populateAxisSymbolicNames(); + SparseArray<String> names = TOOL_TYPE_SYMBOLIC_NAMES; + names.append(TOOL_TYPE_UNKNOWN, "TOOL_TYPE_UNKNOWN"); + names.append(TOOL_TYPE_FINGER, "TOOL_TYPE_FINGER"); + names.append(TOOL_TYPE_STYLUS, "TOOL_TYPE_STYLUS"); + names.append(TOOL_TYPE_MOUSE, "TOOL_TYPE_MOUSE"); + names.append(TOOL_TYPE_INDIRECT_FINGER, "TOOL_TYPE_INDIRECT_FINGER"); + names.append(TOOL_TYPE_INDIRECT_STYLUS, "TOOL_TYPE_INDIRECT_STYLUS"); } // Private value for history pos that obtains the current sample. @@ -1035,10 +1297,23 @@ public final class MotionEvent extends InputEvent implements Parcelable { // Shared temporary objects used when translating coordinates supplied by // the caller into single element PointerCoords and pointer id arrays. - // Must lock gTmpPointerCoords prior to use. - private static final PointerCoords[] gTmpPointerCoords = - new PointerCoords[] { new PointerCoords() }; - private static final int[] gTmpPointerIds = new int[] { 0 /*always 0*/ }; + private static final Object gSharedTempLock = new Object(); + private static PointerCoords[] gSharedTempPointerCoords; + private static PointerProperties[] gSharedTempPointerProperties; + private static int[] gSharedTempPointerIndexMap; + + private static final void ensureSharedTempPointerCapacity(int desiredCapacity) { + if (gSharedTempPointerCoords == null + || gSharedTempPointerCoords.length < desiredCapacity) { + int capacity = gSharedTempPointerCoords != null ? gSharedTempPointerCoords.length : 8; + while (capacity < desiredCapacity) { + capacity *= 2; + } + gSharedTempPointerCoords = PointerCoords.createArray(capacity); + gSharedTempPointerProperties = PointerProperties.createArray(capacity); + gSharedTempPointerIndexMap = new int[capacity]; + } + } // Pointer to the native MotionEvent object that contains the actual data. private int mNativePtr; @@ -1048,10 +1323,11 @@ public final class MotionEvent extends InputEvent implements Parcelable { private boolean mRecycled; private static native int nativeInitialize(int nativePtr, - int deviceId, int source, int action, int flags, int edgeFlags, int metaState, + int deviceId, int source, int action, int flags, int edgeFlags, + int metaState, int buttonState, float xOffset, float yOffset, float xPrecision, float yPrecision, long downTimeNanos, long eventTimeNanos, - int pointerCount, int[] pointerIds, PointerCoords[] pointerCoords); + int pointerCount, PointerProperties[] pointerIds, PointerCoords[] pointerCoords); private static native int nativeCopy(int destNativePtr, int sourceNativePtr, boolean keepHistory); private static native void nativeDispose(int nativePtr); @@ -1069,13 +1345,18 @@ public final class MotionEvent extends InputEvent implements Parcelable { private static native int nativeGetEdgeFlags(int nativePtr); private static native void nativeSetEdgeFlags(int nativePtr, int action); private static native int nativeGetMetaState(int nativePtr); + private static native int nativeGetButtonState(int nativePtr); private static native void nativeOffsetLocation(int nativePtr, float deltaX, float deltaY); + private static native float nativeGetXOffset(int nativePtr); + private static native float nativeGetYOffset(int nativePtr); private static native float nativeGetXPrecision(int nativePtr); private static native float nativeGetYPrecision(int nativePtr); private static native long nativeGetDownTimeNanos(int nativePtr); + private static native void nativeSetDownTimeNanos(int nativePtr, long downTime); private static native int nativeGetPointerCount(int nativePtr); private static native int nativeGetPointerId(int nativePtr, int pointerIndex); + private static native int nativeGetToolType(int nativePtr, int pointerIndex); private static native int nativeFindPointerIndex(int nativePtr, int pointerId); private static native int nativeGetHistorySize(int nativePtr); @@ -1086,6 +1367,8 @@ public final class MotionEvent extends InputEvent implements Parcelable { int axis, int pointerIndex, int historyPos); private static native void nativeGetPointerCoords(int nativePtr, int pointerIndex, int historyPos, PointerCoords outPointerCoords); + private static native void nativeGetPointerProperties(int nativePtr, + int pointerIndex, PointerProperties outPointerProperties); private static native void nativeScale(int nativePtr, float scale); private static native void nativeTransform(int nativePtr, Matrix matrix); @@ -1127,19 +1410,21 @@ public final class MotionEvent extends InputEvent implements Parcelable { /** * Create a new MotionEvent, filling in all of the basic values that * define the motion. - * + * * @param downTime The time (in ms) when the user originally pressed down to start * a stream of position events. This must be obtained from {@link SystemClock#uptimeMillis()}. * @param eventTime The the time (in ms) when this specific event was generated. This * must be obtained from {@link SystemClock#uptimeMillis()}. * @param action The kind of action being performed, such as {@link #ACTION_DOWN}. - * @param pointers The number of points that will be in this event. - * @param pointerIds An array of <em>pointers</em> values providing - * an identifier for each pointer. - * @param pointerCoords An array of <em>pointers</em> values providing + * @param pointerCount The number of pointers that will be in this event. + * @param pointerProperties An array of <em>pointerCount</em> values providing + * a {@link PointerProperties} property object for each pointer, which must + * include the pointer identifier. + * @param pointerCoords An array of <em>pointerCount</em> values providing * a {@link PointerCoords} coordinate object for each pointer. * @param metaState The state of any meta / modifier keys that were in effect when * the event was generated. + * @param buttonState The state of buttons that are pressed. * @param xPrecision The precision of the X coordinate being reported. * @param yPrecision The precision of the Y coordinate being reported. * @param deviceId The id for the device that this event came from. An id of @@ -1151,21 +1436,69 @@ public final class MotionEvent extends InputEvent implements Parcelable { * @param flags The motion event flags. */ static public MotionEvent obtain(long downTime, long eventTime, - int action, int pointers, int[] pointerIds, PointerCoords[] pointerCoords, - int metaState, float xPrecision, float yPrecision, int deviceId, + int action, int pointerCount, PointerProperties[] pointerProperties, + PointerCoords[] pointerCoords, int metaState, int buttonState, + float xPrecision, float yPrecision, int deviceId, int edgeFlags, int source, int flags) { MotionEvent ev = obtain(); ev.mNativePtr = nativeInitialize(ev.mNativePtr, - deviceId, source, action, flags, edgeFlags, metaState, + deviceId, source, action, flags, edgeFlags, metaState, buttonState, 0, 0, xPrecision, yPrecision, downTime * NS_PER_MS, eventTime * NS_PER_MS, - pointers, pointerIds, pointerCoords); + pointerCount, pointerProperties, pointerCoords); return ev; } /** * Create a new MotionEvent, filling in all of the basic values that * define the motion. + * + * @param downTime The time (in ms) when the user originally pressed down to start + * a stream of position events. This must be obtained from {@link SystemClock#uptimeMillis()}. + * @param eventTime The the time (in ms) when this specific event was generated. This + * must be obtained from {@link SystemClock#uptimeMillis()}. + * @param action The kind of action being performed, such as {@link #ACTION_DOWN}. + * @param pointerCount The number of pointers that will be in this event. + * @param pointerIds An array of <em>pointerCount</em> values providing + * an identifier for each pointer. + * @param pointerCoords An array of <em>pointerCount</em> values providing + * a {@link PointerCoords} coordinate object for each pointer. + * @param metaState The state of any meta / modifier keys that were in effect when + * the event was generated. + * @param xPrecision The precision of the X coordinate being reported. + * @param yPrecision The precision of the Y coordinate being reported. + * @param deviceId The id for the device that this event came from. An id of + * zero indicates that the event didn't come from a physical device; other + * numbers are arbitrary and you shouldn't depend on the values. + * @param edgeFlags A bitfield indicating which edges, if any, were touched by this + * MotionEvent. + * @param source The source of this event. + * @param flags The motion event flags. + * + * @deprecated Use {@link #obtain(long, long, int, int, PointerProperties[], PointerCoords[], int, int, float, float, int, int, int, int)} + * instead. + */ + @Deprecated + static public MotionEvent obtain(long downTime, long eventTime, + int action, int pointerCount, int[] pointerIds, PointerCoords[] pointerCoords, + int metaState, float xPrecision, float yPrecision, int deviceId, + int edgeFlags, int source, int flags) { + synchronized (gSharedTempLock) { + ensureSharedTempPointerCapacity(pointerCount); + final PointerProperties[] pp = gSharedTempPointerProperties; + for (int i = 0; i < pointerCount; i++) { + pp[i].clear(); + pp[i].id = pointerIds[i]; + } + return obtain(downTime, eventTime, action, pointerCount, pp, + pointerCoords, metaState, 0, xPrecision, yPrecision, deviceId, + edgeFlags, source, flags); + } + } + + /** + * Create a new MotionEvent, filling in all of the basic values that + * define the motion. * * @param downTime The time (in ms) when the user originally pressed down to start * a stream of position events. This must be obtained from {@link SystemClock#uptimeMillis()}. @@ -1195,20 +1528,25 @@ public final class MotionEvent extends InputEvent implements Parcelable { static public MotionEvent obtain(long downTime, long eventTime, int action, float x, float y, float pressure, float size, int metaState, float xPrecision, float yPrecision, int deviceId, int edgeFlags) { - synchronized (gTmpPointerCoords) { - final PointerCoords pc = gTmpPointerCoords[0]; - pc.clear(); - pc.x = x; - pc.y = y; - pc.pressure = pressure; - pc.size = size; - - MotionEvent ev = obtain(); + MotionEvent ev = obtain(); + synchronized (gSharedTempLock) { + ensureSharedTempPointerCapacity(1); + final PointerProperties[] pp = gSharedTempPointerProperties; + pp[0].clear(); + pp[0].id = 0; + + final PointerCoords pc[] = gSharedTempPointerCoords; + pc[0].clear(); + pc[0].x = x; + pc[0].y = y; + pc[0].pressure = pressure; + pc[0].size = size; + ev.mNativePtr = nativeInitialize(ev.mNativePtr, - deviceId, InputDevice.SOURCE_UNKNOWN, action, 0, edgeFlags, metaState, + deviceId, InputDevice.SOURCE_UNKNOWN, action, 0, edgeFlags, metaState, 0, 0, 0, xPrecision, yPrecision, downTime * NS_PER_MS, eventTime * NS_PER_MS, - 1, gTmpPointerIds, gTmpPointerCoords); + 1, pp, pc); return ev; } } @@ -1222,7 +1560,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { * @param eventTime The the time (in ms) when this specific event was generated. This * must be obtained from {@link SystemClock#uptimeMillis()}. * @param action The kind of action being performed, such as {@link #ACTION_DOWN}. - * @param pointers The number of pointers that are active in this event. + * @param pointerCount The number of pointers that are active in this event. * @param x The X coordinate of this event. * @param y The Y coordinate of this event. * @param pressure The current pressure of this event. The pressure generally @@ -1248,7 +1586,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { */ @Deprecated static public MotionEvent obtain(long downTime, long eventTime, int action, - int pointers, float x, float y, float pressure, float size, int metaState, + int pointerCount, float x, float y, float pressure, float size, int metaState, float xPrecision, float yPrecision, int deviceId, int edgeFlags) { return obtain(downTime, eventTime, action, x, y, pressure, size, metaState, xPrecision, yPrecision, deviceId, edgeFlags); @@ -1444,6 +1782,16 @@ public final class MotionEvent extends InputEvent implements Parcelable { } /** + * Sets the time (in ms) when the user originally pressed down to start + * a stream of position events. + * + * @hide + */ + public final void setDownTime(long downTime) { + nativeSetDownTimeNanos(mNativePtr, downTime * NS_PER_MS); + } + + /** * Returns the time (in ms) when this specific event was generated. */ public final long getEventTime() { @@ -1582,7 +1930,27 @@ public final class MotionEvent extends InputEvent implements Parcelable { public final int getPointerId(int pointerIndex) { return nativeGetPointerId(mNativePtr, pointerIndex); } - + + /** + * Gets the tool type of a pointer for the given pointer index. + * The tool type indicates the type of tool used to make contact such + * as a finger or stylus, if known. + * + * @param pointerIndex Raw index of pointer to retrieve. Value may be from 0 + * (the first pointer that is down) to {@link #getPointerCount()}-1. + * @return The tool type of the pointer. + * + * @see #TOOL_TYPE_UNKNOWN + * @see #TOOL_TYPE_FINGER + * @see #TOOL_TYPE_STYLUS + * @see #TOOL_TYPE_MOUSE + * @see #TOOL_TYPE_INDIRECT_FINGER + * @see #TOOL_TYPE_INDIRECT_STYLUS + */ + public final int getToolType(int pointerIndex) { + return nativeGetToolType(mNativePtr, pointerIndex); + } + /** * Given a pointer identifier, find the index of its data in the event. * @@ -1594,7 +1962,7 @@ public final class MotionEvent extends InputEvent implements Parcelable { public final int findPointerIndex(int pointerId) { return nativeFindPointerIndex(mNativePtr, pointerId); } - + /** * Returns the X coordinate of this event for the given pointer * <em>index</em> (use {@link #getPointerId(int)} to find the pointer @@ -1770,6 +2138,21 @@ public final class MotionEvent extends InputEvent implements Parcelable { } /** + * Populates a {@link PointerProperties} object with pointer properties for + * the specified pointer index. + * + * @param pointerIndex Raw index of pointer to retrieve. Value may be from 0 + * (the first pointer that is down) to {@link #getPointerCount()}-1. + * @param outPointerProperties The pointer properties object to populate. + * + * @see PointerProperties + */ + public final void getPointerProperties(int pointerIndex, + PointerProperties outPointerProperties) { + nativeGetPointerProperties(mNativePtr, pointerIndex, outPointerProperties); + } + + /** * Returns the state of any meta / modifier keys that were in effect when * the event was generated. This is the same values as those * returned by {@link KeyEvent#getMetaState() KeyEvent.getMetaState}. @@ -1784,6 +2167,22 @@ public final class MotionEvent extends InputEvent implements Parcelable { } /** + * Gets the state of all buttons that are pressed such as a mouse or stylus button. + * + * @return The button state. + * + * @see #BUTTON_PRIMARY + * @see #BUTTON_SECONDARY + * @see #BUTTON_TERTIARY + * @see #BUTTON_FORWARD + * @see #BUTTON_BACK + * @see #BUTTON_ERASER + */ + public final int getButtonState() { + return nativeGetButtonState(mNativePtr); + } + + /** * Returns the original raw X coordinate of this event. For touch * events on the screen, this is the original location of the event * on the screen, before it had been adjusted for the containing window @@ -2297,14 +2696,16 @@ public final class MotionEvent extends InputEvent implements Parcelable { */ public final void addBatch(long eventTime, float x, float y, float pressure, float size, int metaState) { - synchronized (gTmpPointerCoords) { - final PointerCoords pc = gTmpPointerCoords[0]; - pc.clear(); - pc.x = x; - pc.y = y; - pc.pressure = pressure; - pc.size = size; - nativeAddBatch(mNativePtr, eventTime * NS_PER_MS, gTmpPointerCoords, metaState); + synchronized (gSharedTempLock) { + ensureSharedTempPointerCapacity(1); + final PointerCoords[] pc = gSharedTempPointerCoords; + pc[0].clear(); + pc[0].x = x; + pc[0].y = y; + pc[0].pressure = pressure; + pc[0].size = size; + + nativeAddBatch(mNativePtr, eventTime * NS_PER_MS, pc, metaState); } } @@ -2323,30 +2724,187 @@ public final class MotionEvent extends InputEvent implements Parcelable { nativeAddBatch(mNativePtr, eventTime * NS_PER_MS, pointerCoords, metaState); } + /** + * Returns true if all points in the motion event are completely within the specified bounds. + * @hide + */ + public final boolean isWithinBoundsNoHistory(float left, float top, + float right, float bottom) { + final int pointerCount = nativeGetPointerCount(mNativePtr); + for (int i = 0; i < pointerCount; i++) { + final float x = nativeGetAxisValue(mNativePtr, AXIS_X, i, HISTORY_CURRENT); + final float y = nativeGetAxisValue(mNativePtr, AXIS_Y, i, HISTORY_CURRENT); + if (x < left || x > right || y < top || y > bottom) { + return false; + } + } + return true; + } + + private static final float clamp(float value, float low, float high) { + if (value < low) { + return low; + } else if (value > high) { + return high; + } + return value; + } + + /** + * Returns a new motion events whose points have been clamped to the specified bounds. + * @hide + */ + public final MotionEvent clampNoHistory(float left, float top, float right, float bottom) { + MotionEvent ev = obtain(); + synchronized (gSharedTempLock) { + final int pointerCount = nativeGetPointerCount(mNativePtr); + + ensureSharedTempPointerCapacity(pointerCount); + final PointerProperties[] pp = gSharedTempPointerProperties; + final PointerCoords[] pc = gSharedTempPointerCoords; + + for (int i = 0; i < pointerCount; i++) { + nativeGetPointerProperties(mNativePtr, i, pp[i]); + nativeGetPointerCoords(mNativePtr, i, HISTORY_CURRENT, pc[i]); + pc[i].x = clamp(pc[i].x, left, right); + pc[i].y = clamp(pc[i].y, top, bottom); + } + ev.mNativePtr = nativeInitialize(ev.mNativePtr, + nativeGetDeviceId(mNativePtr), nativeGetSource(mNativePtr), + nativeGetAction(mNativePtr), nativeGetFlags(mNativePtr), + nativeGetEdgeFlags(mNativePtr), nativeGetMetaState(mNativePtr), + nativeGetButtonState(mNativePtr), + nativeGetXOffset(mNativePtr), nativeGetYOffset(mNativePtr), + nativeGetXPrecision(mNativePtr), nativeGetYPrecision(mNativePtr), + nativeGetDownTimeNanos(mNativePtr), + nativeGetEventTimeNanos(mNativePtr, HISTORY_CURRENT), + pointerCount, pp, pc); + return ev; + } + } + + /** + * Gets an integer where each pointer id present in the event is marked as a bit. + * @hide + */ + public final int getPointerIdBits() { + int idBits = 0; + final int pointerCount = nativeGetPointerCount(mNativePtr); + for (int i = 0; i < pointerCount; i++) { + idBits |= 1 << nativeGetPointerId(mNativePtr, i); + } + return idBits; + } + + /** + * Splits a motion event such that it includes only a subset of pointer ids. + * @hide + */ + public final MotionEvent split(int idBits) { + MotionEvent ev = obtain(); + synchronized (gSharedTempLock) { + final int oldPointerCount = nativeGetPointerCount(mNativePtr); + ensureSharedTempPointerCapacity(oldPointerCount); + final PointerProperties[] pp = gSharedTempPointerProperties; + final PointerCoords[] pc = gSharedTempPointerCoords; + final int[] map = gSharedTempPointerIndexMap; + + final int oldAction = nativeGetAction(mNativePtr); + final int oldActionMasked = oldAction & ACTION_MASK; + final int oldActionPointerIndex = (oldAction & ACTION_POINTER_INDEX_MASK) + >> ACTION_POINTER_INDEX_SHIFT; + int newActionPointerIndex = -1; + int newPointerCount = 0; + int newIdBits = 0; + for (int i = 0; i < oldPointerCount; i++) { + nativeGetPointerProperties(mNativePtr, i, pp[newPointerCount]); + final int idBit = 1 << pp[newPointerCount].id; + if ((idBit & idBits) != 0) { + if (i == oldActionPointerIndex) { + newActionPointerIndex = newPointerCount; + } + map[newPointerCount] = i; + newPointerCount += 1; + newIdBits |= idBit; + } + } + + if (newPointerCount == 0) { + throw new IllegalArgumentException("idBits did not match any ids in the event"); + } + + final int newAction; + if (oldActionMasked == ACTION_POINTER_DOWN || oldActionMasked == ACTION_POINTER_UP) { + if (newActionPointerIndex < 0) { + // An unrelated pointer changed. + newAction = ACTION_MOVE; + } else if (newPointerCount == 1) { + // The first/last pointer went down/up. + newAction = oldActionMasked == ACTION_POINTER_DOWN + ? ACTION_DOWN : ACTION_UP; + } else { + // A secondary pointer went down/up. + newAction = oldActionMasked + | (newActionPointerIndex << ACTION_POINTER_INDEX_SHIFT); + } + } else { + // Simple up/down/cancel/move or other motion action. + newAction = oldAction; + } + + final int historySize = nativeGetHistorySize(mNativePtr); + for (int h = 0; h <= historySize; h++) { + final int historyPos = h == historySize ? HISTORY_CURRENT : h; + + for (int i = 0; i < newPointerCount; i++) { + nativeGetPointerCoords(mNativePtr, map[i], historyPos, pc[i]); + } + + final long eventTimeNanos = nativeGetEventTimeNanos(mNativePtr, historyPos); + if (h == 0) { + ev.mNativePtr = nativeInitialize(ev.mNativePtr, + nativeGetDeviceId(mNativePtr), nativeGetSource(mNativePtr), + newAction, nativeGetFlags(mNativePtr), + nativeGetEdgeFlags(mNativePtr), nativeGetMetaState(mNativePtr), + nativeGetButtonState(mNativePtr), + nativeGetXOffset(mNativePtr), nativeGetYOffset(mNativePtr), + nativeGetXPrecision(mNativePtr), nativeGetYPrecision(mNativePtr), + nativeGetDownTimeNanos(mNativePtr), eventTimeNanos, + newPointerCount, pp, pc); + } else { + nativeAddBatch(ev.mNativePtr, eventTimeNanos, pc, 0); + } + } + return ev; + } + } + @Override public String toString() { - return "MotionEvent{" + Integer.toHexString(System.identityHashCode(this)) - + " pointerId=" + getPointerId(0) - + " action=" + actionToString(getAction()) - + " x=" + getX() - + " y=" + getY() - + " pressure=" + getPressure() - + " size=" + getSize() - + " touchMajor=" + getTouchMajor() - + " touchMinor=" + getTouchMinor() - + " toolMajor=" + getToolMajor() - + " toolMinor=" + getToolMinor() - + " orientation=" + getOrientation() - + " meta=" + KeyEvent.metaStateToString(getMetaState()) - + " pointerCount=" + getPointerCount() - + " historySize=" + getHistorySize() - + " flags=0x" + Integer.toHexString(getFlags()) - + " edgeFlags=0x" + Integer.toHexString(getEdgeFlags()) - + " device=" + getDeviceId() - + " source=0x" + Integer.toHexString(getSource()) - + (getPointerCount() > 1 ? - " pointerId2=" + getPointerId(1) + " x2=" + getX(1) + " y2=" + getY(1) : "") - + "}"; + StringBuilder msg = new StringBuilder(); + msg.append("MotionEvent { action=").append(actionToString(getAction())); + + final int pointerCount = getPointerCount(); + for (int i = 0; i < pointerCount; i++) { + msg.append(", id[").append(i).append("]=").append(getPointerId(i)); + msg.append(", x[").append(i).append("]=").append(getX(i)); + msg.append(", y[").append(i).append("]=").append(getY(i)); + msg.append(", toolType[").append(i).append("]=").append( + toolTypeToString(getToolType(i))); + } + + msg.append(", buttonState=").append(KeyEvent.metaStateToString(getButtonState())); + msg.append(", metaState=").append(KeyEvent.metaStateToString(getMetaState())); + msg.append(", flags=0x").append(Integer.toHexString(getFlags())); + msg.append(", edgeFlags=0x").append(Integer.toHexString(getEdgeFlags())); + msg.append(", pointerCount=").append(pointerCount); + msg.append(", historySize=").append(getHistorySize()); + msg.append(", eventTime=").append(getEventTime()); + msg.append(", downTime=").append(getDownTime()); + msg.append(", deviceId=").append(getDeviceId()); + msg.append(", source=0x").append(Integer.toHexString(getSource())); + msg.append(" }"); + return msg.toString(); } /** @@ -2429,6 +2987,55 @@ public final class MotionEvent extends InputEvent implements Parcelable { } } + /** + * Returns a string that represents the symbolic name of the specified combined + * button state flags such as "0", "BUTTON_PRIMARY", + * "BUTTON_PRIMARY|BUTTON_SECONDARY" or an equivalent numeric constant such as "0x10000000" + * if unknown. + * + * @param buttonState The button state. + * @return The symbolic name of the specified combined button state flags. + * @hide + */ + public static String buttonStateToString(int buttonState) { + if (buttonState == 0) { + return "0"; + } + StringBuilder result = null; + int i = 0; + while (buttonState != 0) { + final boolean isSet = (buttonState & 1) != 0; + buttonState >>>= 1; // unsigned shift! + if (isSet) { + final String name = BUTTON_SYMBOLIC_NAMES[i]; + if (result == null) { + if (buttonState == 0) { + return name; + } + result = new StringBuilder(name); + } else { + result.append('|'); + result.append(name); + } + } + i += 1; + } + return result.toString(); + } + + /** + * Returns a string that represents the symbolic name of the specified tool type + * such as "TOOL_TYPE_FINGER" or an equivalent numeric constant such as "42" if unknown. + * + * @param toolType The tool type. + * @return The symbolic name of the specified tool type. + * @hide + */ + public static String toolTypeToString(int toolType) { + String symbolicName = TOOL_TYPE_SYMBOLIC_NAMES.get(toolType); + return symbolicName != null ? symbolicName : Integer.toString(toolType); + } + public static final Parcelable.Creator<MotionEvent> CREATOR = new Parcelable.Creator<MotionEvent>() { public MotionEvent createFromParcel(Parcel in) { @@ -2456,8 +3063,9 @@ public final class MotionEvent extends InputEvent implements Parcelable { /** * Transfer object for pointer coordinates. * - * Objects of this type can be used to manufacture new {@link MotionEvent} objects - * and to query pointer coordinate information in bulk. + * Objects of this type can be used to specify the pointer coordinates when + * creating new {@link MotionEvent} objects and to query pointer coordinates + * in bulk. * * Refer to {@link InputDevice} for information about how different kinds of * input devices and sources represent pointer coordinates. @@ -2483,6 +3091,15 @@ public final class MotionEvent extends InputEvent implements Parcelable { copyFrom(other); } + /** @hide */ + public static PointerCoords[] createArray(int size) { + PointerCoords[] array = new PointerCoords[size]; + for (int i = 0; i < size; i++) { + array[i] = new PointerCoords(); + } + return array; + } + /** * The X component of the pointer movement. * @@ -2743,4 +3360,71 @@ public final class MotionEvent extends InputEvent implements Parcelable { } } } + + /** + * Transfer object for pointer properties. + * + * Objects of this type can be used to specify the pointer id and tool type + * when creating new {@link MotionEvent} objects and to query pointer properties in bulk. + */ + public static final class PointerProperties { + /** + * Creates a pointer properties object with an invalid pointer id. + */ + public PointerProperties() { + clear(); + } + + /** + * Creates a pointer properties object as a copy of the contents of + * another pointer properties object. + * @param other + */ + public PointerProperties(PointerProperties other) { + copyFrom(other); + } + + /** @hide */ + public static PointerProperties[] createArray(int size) { + PointerProperties[] array = new PointerProperties[size]; + for (int i = 0; i < size; i++) { + array[i] = new PointerProperties(); + } + return array; + } + + /** + * The pointer id. + * Initially set to {@link #INVALID_POINTER_ID} (-1). + * + * @see MotionEvent#getPointerId(int) + */ + public int id; + + /** + * The pointer tool type. + * Initially set to 0. + * + * @see MotionEvent#getToolType(int) + */ + public int toolType; + + /** + * Resets the pointer properties to their initial values. + */ + public void clear() { + id = INVALID_POINTER_ID; + toolType = TOOL_TYPE_UNKNOWN; + } + + /** + * Copies the contents of another pointer properties object. + * + * @param other The pointer properties object to copy. + */ + public void copyFrom(PointerProperties other) { + id = other.id; + toolType = other.toolType; + } + } } |