Add touch navigation input source
Bug: 8276741 Change-Id: I674b9804bf9ae76d694ae7073b54a7d43474a43c
This commit is contained in:
@@ -24171,6 +24171,7 @@ package android.view {
|
||||
field public static final int SOURCE_CLASS_BUTTON = 1; // 0x1
|
||||
field public static final int SOURCE_CLASS_JOYSTICK = 16; // 0x10
|
||||
field public static final int SOURCE_CLASS_MASK = 255; // 0xff
|
||||
field public static final int SOURCE_CLASS_NONE = 0; // 0x0
|
||||
field public static final int SOURCE_CLASS_POINTER = 2; // 0x2
|
||||
field public static final int SOURCE_CLASS_POSITION = 8; // 0x8
|
||||
field public static final int SOURCE_CLASS_TRACKBALL = 4; // 0x4
|
||||
@@ -24182,6 +24183,7 @@ package android.view {
|
||||
field public static final int SOURCE_STYLUS = 16386; // 0x4002
|
||||
field public static final int SOURCE_TOUCHPAD = 1048584; // 0x100008
|
||||
field public static final int SOURCE_TOUCHSCREEN = 4098; // 0x1002
|
||||
field public static final int SOURCE_TOUCH_NAVIGATION = 2097152; // 0x200000
|
||||
field public static final int SOURCE_TRACKBALL = 65540; // 0x10004
|
||||
field public static final int SOURCE_UNKNOWN = 0; // 0x0
|
||||
}
|
||||
|
||||
@@ -62,7 +62,14 @@ public final class InputDevice implements Parcelable {
|
||||
* specify the desired interpretation for its input events.
|
||||
*/
|
||||
public static final int SOURCE_CLASS_MASK = 0x000000ff;
|
||||
|
||||
|
||||
/**
|
||||
* The input source has no class.
|
||||
*
|
||||
* It is up to the application to determine how to handle the device based on the device type.
|
||||
*/
|
||||
public static final int SOURCE_CLASS_NONE = 0x00000000;
|
||||
|
||||
/**
|
||||
* The input source has buttons or keys.
|
||||
* Examples: {@link #SOURCE_KEYBOARD}, {@link #SOURCE_DPAD}.
|
||||
@@ -201,6 +208,17 @@ public final class InputDevice implements Parcelable {
|
||||
*/
|
||||
public static final int SOURCE_TOUCHPAD = 0x00100000 | SOURCE_CLASS_POSITION;
|
||||
|
||||
/**
|
||||
* The input source is a touch device whose motions should be interpreted as navigation events.
|
||||
*
|
||||
* For example, an upward swipe should be as an upward focus traversal in the same manner as
|
||||
* pressing up on a D-Pad would be. Swipes to the left, right and down should be treated in a
|
||||
* similar manner.
|
||||
*
|
||||
* @see #SOURCE_CLASS_NONE
|
||||
*/
|
||||
public static final int SOURCE_TOUCH_NAVIGATION = 0x00200000 | SOURCE_CLASS_NONE;
|
||||
|
||||
/**
|
||||
* The input source is a joystick.
|
||||
* (It may also be a {@link #SOURCE_GAMEPAD}).
|
||||
|
||||
@@ -28,7 +28,7 @@ import android.os.UserHandle;
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* This class creates DPAD events from touchpad events.
|
||||
* This class creates DPAD events from TouchNavigation events.
|
||||
*
|
||||
* @see ViewRootImpl
|
||||
*/
|
||||
@@ -47,18 +47,18 @@ class SimulatedDpad {
|
||||
private static final int MSG_FLICK = 313;
|
||||
// TODO: Pass touch slop from the input device
|
||||
private static final int TOUCH_SLOP = 30;
|
||||
// The position of the previous touchpad event
|
||||
private float mLastTouchpadXPosition;
|
||||
private float mLastTouchpadYPosition;
|
||||
// Where the touchpad was initially pressed
|
||||
private float mTouchpadEnterXPosition;
|
||||
private float mTouchpadEnterYPosition;
|
||||
// The position of the previous TouchNavigation event
|
||||
private float mLastTouchNavigationXPosition;
|
||||
private float mLastTouchNavigationYPosition;
|
||||
// Where the Touch Navigation was initially pressed
|
||||
private float mTouchNavigationEnterXPosition;
|
||||
private float mTouchNavigationEnterYPosition;
|
||||
// When the most recent ACTION_HOVER_ENTER occurred
|
||||
private long mLastTouchPadStartTimeMs = 0;
|
||||
private long mLastTouchNavigationStartTimeMs = 0;
|
||||
// When the most recent direction key was sent
|
||||
private long mLastTouchPadKeySendTimeMs = 0;
|
||||
private long mLastTouchNavigationKeySendTimeMs = 0;
|
||||
// When the most recent touch event of any type occurred
|
||||
private long mLastTouchPadEventTimeMs = 0;
|
||||
private long mLastTouchNavigationEventTimeMs = 0;
|
||||
// Did the swipe begin in a valid region
|
||||
private boolean mEdgeSwipePossible;
|
||||
|
||||
@@ -140,7 +140,7 @@ class SimulatedDpad {
|
||||
}
|
||||
};
|
||||
|
||||
public void updateTouchPad(ViewRootImpl viewroot, MotionEvent event,
|
||||
public void updateTouchNavigation(ViewRootImpl viewroot, MotionEvent event,
|
||||
boolean synthesizeNewKeys) {
|
||||
if (!synthesizeNewKeys) {
|
||||
mHandler.removeMessages(MSG_FLICK);
|
||||
@@ -149,14 +149,14 @@ class SimulatedDpad {
|
||||
if (device == null) {
|
||||
return;
|
||||
}
|
||||
// Store what time the touchpad event occurred
|
||||
// Store what time the TouchNavigation event occurred
|
||||
final long time = SystemClock.uptimeMillis();
|
||||
switch (event.getAction()) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
mLastTouchPadStartTimeMs = time;
|
||||
mLastTouchNavigationStartTimeMs = time;
|
||||
mAlwaysInTapRegion = true;
|
||||
mTouchpadEnterXPosition = event.getX();
|
||||
mTouchpadEnterYPosition = event.getY();
|
||||
mTouchNavigationEnterXPosition = event.getX();
|
||||
mTouchNavigationEnterYPosition = event.getY();
|
||||
mAccumulatedX = 0;
|
||||
mAccumulatedY = 0;
|
||||
mLastMoveX = 0;
|
||||
@@ -173,8 +173,8 @@ class SimulatedDpad {
|
||||
break;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
// Determine whether the move is slop or an intentional move
|
||||
float deltaX = event.getX() - mTouchpadEnterXPosition;
|
||||
float deltaY = event.getY() - mTouchpadEnterYPosition;
|
||||
float deltaX = event.getX() - mTouchNavigationEnterXPosition;
|
||||
float deltaY = event.getY() - mTouchNavigationEnterYPosition;
|
||||
if (mTouchSlopSquared < deltaX * deltaX + deltaY * deltaY) {
|
||||
mAlwaysInTapRegion = false;
|
||||
}
|
||||
@@ -199,9 +199,9 @@ class SimulatedDpad {
|
||||
}
|
||||
}
|
||||
// Find the difference in position between the two most recent
|
||||
// touchpad events
|
||||
mLastMoveX = event.getX() - mLastTouchpadXPosition;
|
||||
mLastMoveY = event.getY() - mLastTouchpadYPosition;
|
||||
// TouchNavigation events
|
||||
mLastMoveX = event.getX() - mLastTouchNavigationXPosition;
|
||||
mLastMoveY = event.getY() - mLastTouchNavigationYPosition;
|
||||
mAccumulatedX += mLastMoveX;
|
||||
mAccumulatedY += mLastMoveY;
|
||||
float mAccumulatedXSquared = mAccumulatedX * mAccumulatedX;
|
||||
@@ -251,28 +251,28 @@ class SimulatedDpad {
|
||||
mAccumulatedY = isXAxis ? 0 : dominantAxis;
|
||||
|
||||
mLastKeySent = key;
|
||||
mKeySendRateMs = (int) ((time - mLastTouchPadKeySendTimeMs) / repeatCount);
|
||||
mLastTouchPadKeySendTimeMs = time;
|
||||
mKeySendRateMs = (int) (time - mLastTouchNavigationKeySendTimeMs) / repeatCount;
|
||||
mLastTouchNavigationKeySendTimeMs = time;
|
||||
}
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
if (time - mLastTouchPadStartTimeMs < MAX_TAP_TIME && mAlwaysInTapRegion) {
|
||||
if (time - mLastTouchNavigationStartTimeMs < MAX_TAP_TIME && mAlwaysInTapRegion) {
|
||||
if (synthesizeNewKeys) {
|
||||
viewroot.enqueueInputEvent(new KeyEvent(mLastTouchPadStartTimeMs, time,
|
||||
KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER, 0,
|
||||
event.getMetaState(), event.getDeviceId(), 0,
|
||||
KeyEvent.FLAG_FALLBACK, event.getSource()));
|
||||
viewroot.enqueueInputEvent(new KeyEvent(mLastTouchPadStartTimeMs, time,
|
||||
KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_CENTER, 0,
|
||||
event.getMetaState(), event.getDeviceId(), 0,
|
||||
KeyEvent.FLAG_FALLBACK, event.getSource()));
|
||||
viewroot.enqueueInputEvent(new KeyEvent(mLastTouchNavigationStartTimeMs,
|
||||
time, KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_CENTER, 0,
|
||||
event.getMetaState(), event.getDeviceId(), 0,
|
||||
KeyEvent.FLAG_FALLBACK, event.getSource()));
|
||||
viewroot.enqueueInputEvent(new KeyEvent(mLastTouchNavigationStartTimeMs,
|
||||
time, KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DPAD_CENTER, 0,
|
||||
event.getMetaState(), event.getDeviceId(), 0,
|
||||
KeyEvent.FLAG_FALLBACK, event.getSource()));
|
||||
}
|
||||
} else {
|
||||
float xMoveSquared = mLastMoveX * mLastMoveX;
|
||||
float yMoveSquared = mLastMoveY * mLastMoveY;
|
||||
// Determine whether the last gesture was a fling.
|
||||
if (mMinFlickDistanceSquared <= xMoveSquared + yMoveSquared &&
|
||||
time - mLastTouchPadEventTimeMs <= MAX_TAP_TIME &&
|
||||
time - mLastTouchNavigationEventTimeMs <= MAX_TAP_TIME &&
|
||||
mKeySendRateMs <= mMaxRepeatDelay && mKeySendRateMs > 0) {
|
||||
mLastDeviceId = event.getDeviceId();
|
||||
mLastSource = event.getSource();
|
||||
@@ -291,8 +291,8 @@ class SimulatedDpad {
|
||||
}
|
||||
|
||||
// Store touch event position and time
|
||||
mLastTouchPadEventTimeMs = time;
|
||||
mLastTouchpadXPosition = event.getX();
|
||||
mLastTouchpadYPosition = event.getY();
|
||||
mLastTouchNavigationEventTimeMs = time;
|
||||
mLastTouchNavigationXPosition = event.getX();
|
||||
mLastTouchNavigationYPosition = event.getY();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3559,15 +3559,15 @@ public final class ViewRootImpl implements ViewParent,
|
||||
private int deliverGenericMotionEventPostIme(QueuedInputEvent q) {
|
||||
final MotionEvent event = (MotionEvent) q.mEvent;
|
||||
final int source = event.getSource();
|
||||
final boolean isJoystick = (source & InputDevice.SOURCE_CLASS_JOYSTICK) != 0;
|
||||
final boolean isTouchPad = (source & InputDevice.SOURCE_CLASS_POSITION) != 0;
|
||||
final boolean isJoystick = event.isFromSource(InputDevice.SOURCE_CLASS_JOYSTICK);
|
||||
final boolean isTouchNavigation = event.isFromSource(InputDevice.SOURCE_TOUCH_NAVIGATION);
|
||||
|
||||
// If there is no view, then the event will not be handled.
|
||||
if (mView == null || !mAdded) {
|
||||
if (isJoystick) {
|
||||
updateJoystickDirection(event, false);
|
||||
} else if (isTouchPad) {
|
||||
mSimulatedDpad.updateTouchPad(this, event, false);
|
||||
} else if (isTouchNavigation) {
|
||||
mSimulatedDpad.updateTouchNavigation(this, event, false);
|
||||
}
|
||||
return EVENT_NOT_HANDLED;
|
||||
}
|
||||
@@ -3576,8 +3576,8 @@ public final class ViewRootImpl implements ViewParent,
|
||||
if (mView.dispatchGenericMotionEvent(event)) {
|
||||
if (isJoystick) {
|
||||
updateJoystickDirection(event, false);
|
||||
} else if (isTouchPad) {
|
||||
mSimulatedDpad.updateTouchPad(this, event, false);
|
||||
} else if (isTouchNavigation) {
|
||||
mSimulatedDpad.updateTouchNavigation(this, event, false);
|
||||
}
|
||||
return EVENT_HANDLED;
|
||||
}
|
||||
@@ -3588,8 +3588,8 @@ public final class ViewRootImpl implements ViewParent,
|
||||
updateJoystickDirection(event, true);
|
||||
return EVENT_HANDLED;
|
||||
}
|
||||
if (isTouchPad) {
|
||||
mSimulatedDpad.updateTouchPad(this, event, true);
|
||||
if (isTouchNavigation) {
|
||||
mSimulatedDpad.updateTouchNavigation(this, event, true);
|
||||
return EVENT_HANDLED;
|
||||
}
|
||||
return EVENT_NOT_HANDLED;
|
||||
|
||||
@@ -2788,6 +2788,8 @@ void TouchInputMapper::configureParameters() {
|
||||
mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
|
||||
} else if (deviceTypeString == "touchPad") {
|
||||
mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
|
||||
} else if (deviceTypeString == "touchNavigation") {
|
||||
mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_NAVIGATION;
|
||||
} else if (deviceTypeString == "pointer") {
|
||||
mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
|
||||
} else if (deviceTypeString != "default") {
|
||||
@@ -2832,6 +2834,9 @@ void TouchInputMapper::dumpParameters(String8& dump) {
|
||||
case Parameters::DEVICE_TYPE_TOUCH_PAD:
|
||||
dump.append(INDENT4 "DeviceType: touchPad\n");
|
||||
break;
|
||||
case Parameters::DEVICE_TYPE_TOUCH_NAVIGATION:
|
||||
dump.append(INDENT4 "DeviceType: touchNavigation\n");
|
||||
break;
|
||||
case Parameters::DEVICE_TYPE_POINTER:
|
||||
dump.append(INDENT4 "DeviceType: pointer\n");
|
||||
break;
|
||||
@@ -2885,6 +2890,9 @@ void TouchInputMapper::configureSurface(nsecs_t when, bool* outResetNeeded) {
|
||||
if (hasStylus()) {
|
||||
mSource |= AINPUT_SOURCE_STYLUS;
|
||||
}
|
||||
} else if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_NAVIGATION) {
|
||||
mSource = AINPUT_SOURCE_TOUCH_NAVIGATION;
|
||||
mDeviceMode = DEVICE_MODE_UNSCALED;
|
||||
} else {
|
||||
mSource = AINPUT_SOURCE_TOUCHPAD;
|
||||
mDeviceMode = DEVICE_MODE_UNSCALED;
|
||||
|
||||
@@ -1192,6 +1192,7 @@ protected:
|
||||
enum DeviceType {
|
||||
DEVICE_TYPE_TOUCH_SCREEN,
|
||||
DEVICE_TYPE_TOUCH_PAD,
|
||||
DEVICE_TYPE_TOUCH_NAVIGATION,
|
||||
DEVICE_TYPE_POINTER,
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user