diff options
| -rw-r--r-- | api/current.txt | 2 | ||||
| -rw-r--r-- | core/java/android/view/KeyEvent.java | 27 | ||||
| -rw-r--r-- | core/java/android/view/MotionEvent.java | 8 | ||||
| -rw-r--r-- | core/java/android/view/View.java | 4 | ||||
| -rw-r--r-- | core/java/android/view/ViewRootImpl.java | 16 | ||||
| -rw-r--r-- | core/java/android/widget/AbsListView.java | 2 | ||||
| -rw-r--r-- | core/java/android/widget/Gallery.java | 2 | ||||
| -rw-r--r-- | core/java/android/widget/ListPopupWindow.java | 4 | ||||
| -rw-r--r-- | libs/input/InputDispatcher.cpp | 33 | 
9 files changed, 76 insertions, 22 deletions
diff --git a/api/current.txt b/api/current.txt index b8e8a05962b8..4d49e79390ee 100644 --- a/api/current.txt +++ b/api/current.txt @@ -26836,8 +26836,10 @@ package android.view {      method public final boolean hasModifiers(int);      method public final boolean hasNoModifiers();      method public final boolean isAltPressed(); +    method public final boolean isCancelKey();      method public final boolean isCanceled();      method public final boolean isCapsLockOn(); +    method public final boolean isConfirmKey();      method public final boolean isCtrlPressed();      method public final boolean isFunctionPressed();      method public static final boolean isGamepadButton(int); diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java index 6a6c1271a823..437ccfb29176 100644 --- a/core/java/android/view/KeyEvent.java +++ b/core/java/android/view/KeyEvent.java @@ -1847,13 +1847,32 @@ public class KeyEvent extends InputEvent implements Parcelable {          }      } -    /** Whether key will, by default, trigger a click on the focused view. -     * @hide +    /** +     * Returns true if the key event should be treated as a confirming action. +     * @return True for a confirmation key, such as {@link #KEYCODE_DPAD_CENTER}, +     * {@link #KEYCODE_ENTER}, or {@link #KEYCODE_BUTTON_A}.       */ -    public static final boolean isConfirmKey(int keyCode) { -        switch (keyCode) { +    public final boolean isConfirmKey() { +        switch (mKeyCode) {              case KeyEvent.KEYCODE_DPAD_CENTER:              case KeyEvent.KEYCODE_ENTER: +            case KeyEvent.KEYCODE_BUTTON_A: +                return true; +            default: +                return false; +        } +    } + +    /** +     * Returns true if the key event should be treated as a cancelling action. +     * @return True for a cancellation key, such as {@link #KEYCODE_ESCAPE}, +     * {@link #KEYCODE_BACK}, or {@link #KEYCODE_BUTTON_B}. +     */ +    public final boolean isCancelKey() { +        switch (mKeyCode) { +            case KeyEvent.KEYCODE_BUTTON_B: +            case KeyEvent.KEYCODE_ESCAPE: +            case KeyEvent.KEYCODE_BACK:                  return true;              default:                  return false; diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java index ddce3ceef753..6378ffd99749 100644 --- a/core/java/android/view/MotionEvent.java +++ b/core/java/android/view/MotionEvent.java @@ -3372,11 +3372,11 @@ public final class MotionEvent extends InputEvent implements Parcelable {                          throw new IllegalArgumentException("Axis out of range.");                      }                      final long bits = mPackedAxisBits; -                    final long axisBit = 1L << axis; +                    final long axisBit = 0x8000000000000000L >>> axis;                      if ((bits & axisBit) == 0) {                          return 0;                      } -                    final int index = Long.bitCount(bits & (axisBit - 1L)); +                    final int index = Long.bitCount(bits & ~(0xFFFFFFFFFFFFFFFFL >>> axis));                      return mPackedAxisValues[index];                  }              } @@ -3425,8 +3425,8 @@ public final class MotionEvent extends InputEvent implements Parcelable {                          throw new IllegalArgumentException("Axis out of range.");                      }                      final long bits = mPackedAxisBits; -                    final long axisBit = 1L << axis; -                    final int index = Long.bitCount(bits & (axisBit - 1L)); +                    final long axisBit = 0x8000000000000000L >>> axis; +                    final int index = Long.bitCount(bits & ~(0xFFFFFFFFFFFFFFFFL >>> axis));                      float[] values = mPackedAxisValues;                      if ((bits & axisBit) == 0) {                          if (values == null) { diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 6b73ae7bbab4..80725dc68475 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -8186,7 +8186,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,      public boolean onKeyDown(int keyCode, KeyEvent event) {          boolean result = false; -        if (KeyEvent.isConfirmKey(keyCode)) { +        if (event.isConfirmKey()) {              if ((mViewFlags & ENABLED_MASK) == DISABLED) {                  return true;              } @@ -8228,7 +8228,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,       * @param event   The KeyEvent object that defines the button action.       */      public boolean onKeyUp(int keyCode, KeyEvent event) { -        if (KeyEvent.isConfirmKey(keyCode)) { +        if (event.isConfirmKey()) {              if ((mViewFlags & ENABLED_MASK) == DISABLED) {                  return true;              } diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index d779628571bf..1848a8f976af 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -4319,6 +4319,7 @@ public final class ViewRootImpl implements ViewParent,       * Creates dpad events from unhandled joystick movements.       */      final class SyntheticJoystickHandler extends Handler { +        private final static String TAG = "SyntheticJoystickHandler";          private final static int MSG_ENQUEUE_X_AXIS_KEY_REPEAT = 1;          private final static int MSG_ENQUEUE_Y_AXIS_KEY_REPEAT = 2; @@ -4351,10 +4352,21 @@ public final class ViewRootImpl implements ViewParent,          }          public void process(MotionEvent event) { -            update(event, true); +            switch(event.getActionMasked()) { +            case MotionEvent.ACTION_CANCEL: +                cancel(event); +                break; +            case MotionEvent.ACTION_MOVE: +                update(event, true); +                break; +            default: +                Log.w(TAG, "Unexpected action: " + event.getActionMasked()); +            }          } -        public void cancel(MotionEvent event) { +        private void cancel(MotionEvent event) { +            removeMessages(MSG_ENQUEUE_X_AXIS_KEY_REPEAT); +            removeMessages(MSG_ENQUEUE_Y_AXIS_KEY_REPEAT);              update(event, false);          } diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index 25a43a6a2969..bbaa33d0dabd 100644 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -3039,7 +3039,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te      @Override      public boolean onKeyUp(int keyCode, KeyEvent event) { -        if (KeyEvent.isConfirmKey(keyCode)) { +        if (event.isConfirmKey()) {              if (!isEnabled()) {                  return true;              } diff --git a/core/java/android/widget/Gallery.java b/core/java/android/widget/Gallery.java index 78ba6e0db2b3..6dd93a7fb9f3 100644 --- a/core/java/android/widget/Gallery.java +++ b/core/java/android/widget/Gallery.java @@ -1228,7 +1228,7 @@ public class Gallery extends AbsSpinner implements GestureDetector.OnGestureList      @Override      public boolean onKeyUp(int keyCode, KeyEvent event) { -        if (KeyEvent.isConfirmKey(keyCode)) { +        if (event.isConfirmKey()) {              if (mReceivedInvokeKeyDown) {                  if (mItemCount > 0) {                      dispatchPress(mSelectedChild); diff --git a/core/java/android/widget/ListPopupWindow.java b/core/java/android/widget/ListPopupWindow.java index 66fe46f29fce..13f3eb64188f 100644 --- a/core/java/android/widget/ListPopupWindow.java +++ b/core/java/android/widget/ListPopupWindow.java @@ -843,7 +843,7 @@ public class ListPopupWindow {              // to select one of its items              if (keyCode != KeyEvent.KEYCODE_SPACE                      && (mDropDownList.getSelectedItemPosition() >= 0 -                            || !KeyEvent.isConfirmKey(keyCode))) { +                            || !event.isConfirmKey())) {                  int curIndex = mDropDownList.getSelectedItemPosition();                  boolean consumed; @@ -931,7 +931,7 @@ public class ListPopupWindow {      public boolean onKeyUp(int keyCode, KeyEvent event) {          if (isShowing() && mDropDownList.getSelectedItemPosition() >= 0) {              boolean consumed = mDropDownList.onKeyUp(keyCode, event); -            if (consumed && KeyEvent.isConfirmKey(keyCode)) { +            if (consumed && event.isConfirmKey()) {                  // if the list accepts the key events and the key event was a click, the text view                  // gets the selected item from the drop down as its content                  dismiss(); diff --git a/libs/input/InputDispatcher.cpp b/libs/input/InputDispatcher.cpp index 4d447878da4b..70ff0851b1f8 100644 --- a/libs/input/InputDispatcher.cpp +++ b/libs/input/InputDispatcher.cpp @@ -4105,18 +4105,39 @@ bool InputDispatcher::InputState::trackMotion(const MotionEntry* entry,      case AMOTION_EVENT_ACTION_POINTER_UP:      case AMOTION_EVENT_ACTION_POINTER_DOWN:      case AMOTION_EVENT_ACTION_MOVE: { +        if (entry->source & AINPUT_SOURCE_CLASS_NAVIGATION) { +            // Trackballs can send MOVE events with a corresponding DOWN or UP. There's no need to +            // generate cancellation events for these since they're based in relative rather than +            // absolute units. +            return true; +        } +          ssize_t index = findMotionMemento(entry, false /*hovering*/); + +        if (entry->source & AINPUT_SOURCE_CLASS_JOYSTICK) { +            // Joysticks can send MOVE events without a corresponding DOWN or UP. Since all +            // joystick axes are normalized to [-1, 1] we can trust that 0 means it's neutral. Any +            // other value and we need to track the motion so we can send cancellation events for +            // anything generating fallback events (e.g. DPad keys for joystick movements). +            if (index >= 0) { +                if (entry->pointerCoords[0].isEmpty()) { +                    mMotionMementos.removeAt(index); +                } else { +                    MotionMemento& memento = mMotionMementos.editItemAt(index); +                    memento.setPointers(entry); +                } +            } else if (!entry->pointerCoords[0].isEmpty()) { +                addMotionMemento(entry, flags, false /*hovering*/); +            } + +            // Joysticks and trackballs can send MOVE events without corresponding DOWN or UP. +            return true; +        }          if (index >= 0) {              MotionMemento& memento = mMotionMementos.editItemAt(index);              memento.setPointers(entry);              return true;          } -        if (actionMasked == AMOTION_EVENT_ACTION_MOVE -                && (entry->source & (AINPUT_SOURCE_CLASS_JOYSTICK -                        | AINPUT_SOURCE_CLASS_NAVIGATION))) { -            // Joysticks and trackballs can send MOVE events without corresponding DOWN or UP. -            return true; -        }  #if DEBUG_OUTBOUND_EVENT_DETAILS          ALOGD("Dropping inconsistent motion pointer up/down or move event: "                  "deviceId=%d, source=%08x, actionMasked=%d",  |