Add joystick support to framework.
Change-Id: I95374436708752e1a9cff3f85c5b9bc3e0987961
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index ad9e6863..4ed9742 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -128,6 +128,11 @@
final TrackballAxis mTrackballAxisX = new TrackballAxis();
final TrackballAxis mTrackballAxisY = new TrackballAxis();
+ int mLastJoystickXDirection;
+ int mLastJoystickYDirection;
+ int mLastJoystickXKeyCode;
+ int mLastJoystickYKeyCode;
+
final int[] mTmpLocation = new int[2];
final TypedValue mTmpValue = new TypedValue();
@@ -1878,6 +1883,7 @@
public final static int CLOSE_SYSTEM_DIALOGS = 1014;
public final static int DISPATCH_DRAG_EVENT = 1015;
public final static int DISPATCH_DRAG_LOCATION_EVENT = 1016;
+ public final static int DISPATCH_GENERIC_MOTION = 1017;
@Override
public void handleMessage(Message msg) {
@@ -1914,6 +1920,9 @@
case DISPATCH_TRACKBALL:
deliverTrackballEvent((MotionEvent) msg.obj, msg.arg1 != 0);
break;
+ case DISPATCH_GENERIC_MOTION:
+ deliverGenericMotionEvent((MotionEvent) msg.obj, msg.arg1 != 0);
+ break;
case DISPATCH_APP_VISIBILITY:
handleAppVisibility(msg.arg1 != 0);
break;
@@ -2420,6 +2429,102 @@
}
}
+ private void deliverGenericMotionEvent(MotionEvent event, boolean sendDone) {
+ final int source = event.getSource();
+ final boolean isJoystick = (source & InputDevice.SOURCE_CLASS_JOYSTICK) != 0;
+
+ // If there is no view, then the event will not be handled.
+ if (mView == null || !mAdded) {
+ if (isJoystick) {
+ updateJoystickDirection(event, false);
+ }
+ finishGenericMotionEvent(event, sendDone, false);
+ return;
+ }
+
+ // Deliver the event to the view.
+ if (mView.dispatchGenericMotionEvent(event)) {
+ ensureTouchMode(false);
+ if (isJoystick) {
+ updateJoystickDirection(event, false);
+ }
+ finishGenericMotionEvent(event, sendDone, true);
+ return;
+ }
+
+ if (isJoystick) {
+ // Translate the joystick event into DPAD keys and try to deliver those.
+ updateJoystickDirection(event, true);
+ finishGenericMotionEvent(event, sendDone, true);
+ } else {
+ finishGenericMotionEvent(event, sendDone, false);
+ }
+ }
+
+ private void finishGenericMotionEvent(MotionEvent event, boolean sendDone, boolean handled) {
+ event.recycle();
+ if (sendDone) {
+ finishInputEvent(handled);
+ }
+ }
+
+ private void updateJoystickDirection(MotionEvent event, boolean synthesizeNewKeys) {
+ final long time = event.getEventTime();
+ final int metaState = event.getMetaState();
+ final int deviceId = event.getDeviceId();
+ final int source = event.getSource();
+ final int xDirection = joystickAxisValueToDirection(event.getX());
+ final int yDirection = joystickAxisValueToDirection(event.getY());
+
+ if (xDirection != mLastJoystickXDirection) {
+ if (mLastJoystickXKeyCode != 0) {
+ deliverKeyEvent(new KeyEvent(time, time,
+ KeyEvent.ACTION_UP, mLastJoystickXKeyCode, 0, metaState,
+ deviceId, 0, KeyEvent.FLAG_FALLBACK, source), false);
+ mLastJoystickXKeyCode = 0;
+ }
+
+ mLastJoystickXDirection = xDirection;
+
+ if (xDirection != 0 && synthesizeNewKeys) {
+ mLastJoystickXKeyCode = xDirection > 0
+ ? KeyEvent.KEYCODE_DPAD_RIGHT : KeyEvent.KEYCODE_DPAD_LEFT;
+ deliverKeyEvent(new KeyEvent(time, time,
+ KeyEvent.ACTION_DOWN, mLastJoystickXKeyCode, 0, metaState,
+ deviceId, 0, KeyEvent.FLAG_FALLBACK, source), false);
+ }
+ }
+
+ if (yDirection != mLastJoystickYDirection) {
+ if (mLastJoystickYKeyCode != 0) {
+ deliverKeyEvent(new KeyEvent(time, time,
+ KeyEvent.ACTION_UP, mLastJoystickYKeyCode, 0, metaState,
+ deviceId, 0, KeyEvent.FLAG_FALLBACK, source), false);
+ mLastJoystickYKeyCode = 0;
+ }
+
+ mLastJoystickYDirection = yDirection;
+
+ if (yDirection != 0 && synthesizeNewKeys) {
+ mLastJoystickYKeyCode = yDirection > 0
+ ? KeyEvent.KEYCODE_DPAD_DOWN : KeyEvent.KEYCODE_DPAD_UP;
+ deliverKeyEvent(new KeyEvent(time, time,
+ KeyEvent.ACTION_DOWN, mLastJoystickYKeyCode, 0, metaState,
+ deviceId, 0, KeyEvent.FLAG_FALLBACK, source), false);
+ }
+ }
+ }
+
+ private static int joystickAxisValueToDirection(float value) {
+ if (value >= 0.5f) {
+ return 1;
+ } else if (value <= -0.5f) {
+ return -1;
+ } else {
+ return 0;
+ }
+ }
+
/**
* Returns true if the key is used for keyboard navigation.
* @param keyEvent The key event.
@@ -3053,11 +3158,7 @@
} else if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) {
dispatchTrackball(event, sendDone);
} else {
- // TODO
- Log.v(TAG, "Dropping unsupported motion event (unimplemented): " + event);
- if (sendDone) {
- finishInputEvent(false);
- }
+ dispatchGenericMotion(event, sendDone);
}
}
@@ -3082,7 +3183,14 @@
msg.arg1 = sendDone ? 1 : 0;
sendMessageAtTime(msg, event.getEventTime());
}
-
+
+ private void dispatchGenericMotion(MotionEvent event, boolean sendDone) {
+ Message msg = obtainMessage(DISPATCH_GENERIC_MOTION);
+ msg.obj = event;
+ msg.arg1 = sendDone ? 1 : 0;
+ sendMessageAtTime(msg, event.getEventTime());
+ }
+
public void dispatchAppVisibility(boolean visible) {
Message msg = obtainMessage(DISPATCH_APP_VISIBILITY);
msg.arg1 = visible ? 1 : 0;