Detect bogus down-move-up event and add workaround
Bug: 7032858 Change-Id: I2e76bf49f1e07b436d05c19881e2f2c4fed21621main
parent
9d42353611
commit
b0952888eb
|
@ -71,7 +71,7 @@
|
||||||
false -->
|
false -->
|
||||||
<bool name="config_show_more_keys_keyboard_at_touched_point">false</bool>
|
<bool name="config_show_more_keys_keyboard_at_touched_point">false</bool>
|
||||||
<!-- Static threshold for gesture after fast typing (msec) -->
|
<!-- Static threshold for gesture after fast typing (msec) -->
|
||||||
<integer name="config_gesture_static_time_threshold_after_fast_typing">1000</integer>
|
<integer name="config_gesture_static_time_threshold_after_fast_typing">500</integer>
|
||||||
<!-- Static threshold for starting gesture detection (keyWidth%/sec) -->
|
<!-- Static threshold for starting gesture detection (keyWidth%/sec) -->
|
||||||
<fraction name="config_gesture_detect_fast_move_speed_threshold">150%</fraction>
|
<fraction name="config_gesture_detect_fast_move_speed_threshold">150%</fraction>
|
||||||
<!-- Dynamic threshold for gesture after fast typing (msec) -->
|
<!-- Dynamic threshold for gesture after fast typing (msec) -->
|
||||||
|
|
|
@ -40,7 +40,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
|
||||||
private static final boolean DEBUG_EVENT = false;
|
private static final boolean DEBUG_EVENT = false;
|
||||||
private static final boolean DEBUG_MOVE_EVENT = false;
|
private static final boolean DEBUG_MOVE_EVENT = false;
|
||||||
private static final boolean DEBUG_LISTENER = false;
|
private static final boolean DEBUG_LISTENER = false;
|
||||||
private static boolean DEBUG_MODE = LatinImeLogger.sDBG;
|
private static boolean DEBUG_MODE = LatinImeLogger.sDBG || DEBUG_EVENT;
|
||||||
|
|
||||||
/** True if {@link PointerTracker}s should handle gesture events. */
|
/** True if {@link PointerTracker}s should handle gesture events. */
|
||||||
private static boolean sShouldHandleGesture = false;
|
private static boolean sShouldHandleGesture = false;
|
||||||
|
@ -121,8 +121,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
|
||||||
static final class PointerTrackerParams {
|
static final class PointerTrackerParams {
|
||||||
public final boolean mSlidingKeyInputEnabled;
|
public final boolean mSlidingKeyInputEnabled;
|
||||||
public final int mTouchNoiseThresholdTime;
|
public final int mTouchNoiseThresholdTime;
|
||||||
public final float mTouchNoiseThresholdDistance;
|
public final int mTouchNoiseThresholdDistance;
|
||||||
public final int mTouchNoiseThresholdDistanceSquared;
|
|
||||||
public final int mSuppressKeyPreviewAfterBatchInputDuration;
|
public final int mSuppressKeyPreviewAfterBatchInputDuration;
|
||||||
|
|
||||||
public static final PointerTrackerParams DEFAULT = new PointerTrackerParams();
|
public static final PointerTrackerParams DEFAULT = new PointerTrackerParams();
|
||||||
|
@ -130,8 +129,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
|
||||||
private PointerTrackerParams() {
|
private PointerTrackerParams() {
|
||||||
mSlidingKeyInputEnabled = false;
|
mSlidingKeyInputEnabled = false;
|
||||||
mTouchNoiseThresholdTime = 0;
|
mTouchNoiseThresholdTime = 0;
|
||||||
mTouchNoiseThresholdDistance = 0.0f;
|
mTouchNoiseThresholdDistance = 0;
|
||||||
mTouchNoiseThresholdDistanceSquared = 0;
|
|
||||||
mSuppressKeyPreviewAfterBatchInputDuration = 0;
|
mSuppressKeyPreviewAfterBatchInputDuration = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,11 +138,8 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
|
||||||
R.styleable.MainKeyboardView_slidingKeyInputEnable, false);
|
R.styleable.MainKeyboardView_slidingKeyInputEnable, false);
|
||||||
mTouchNoiseThresholdTime = mainKeyboardViewAttr.getInt(
|
mTouchNoiseThresholdTime = mainKeyboardViewAttr.getInt(
|
||||||
R.styleable.MainKeyboardView_touchNoiseThresholdTime, 0);
|
R.styleable.MainKeyboardView_touchNoiseThresholdTime, 0);
|
||||||
final float touchNouseThresholdDistance = mainKeyboardViewAttr.getDimension(
|
mTouchNoiseThresholdDistance = mainKeyboardViewAttr.getDimensionPixelSize(
|
||||||
R.styleable.MainKeyboardView_touchNoiseThresholdDistance, 0);
|
R.styleable.MainKeyboardView_touchNoiseThresholdDistance, 0);
|
||||||
mTouchNoiseThresholdDistance = touchNouseThresholdDistance;
|
|
||||||
mTouchNoiseThresholdDistanceSquared =
|
|
||||||
(int)(touchNouseThresholdDistance * touchNouseThresholdDistance);
|
|
||||||
mSuppressKeyPreviewAfterBatchInputDuration = mainKeyboardViewAttr.getInt(
|
mSuppressKeyPreviewAfterBatchInputDuration = mainKeyboardViewAttr.getInt(
|
||||||
R.styleable.MainKeyboardView_suppressKeyPreviewAfterBatchInputDuration, 0);
|
R.styleable.MainKeyboardView_suppressKeyPreviewAfterBatchInputDuration, 0);
|
||||||
}
|
}
|
||||||
|
@ -154,6 +149,11 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
|
||||||
private static PointerTrackerParams sParams;
|
private static PointerTrackerParams sParams;
|
||||||
private static GestureStrokeParams sGestureStrokeParams;
|
private static GestureStrokeParams sGestureStrokeParams;
|
||||||
private static boolean sNeedsPhantomSuddenMoveEventHack;
|
private static boolean sNeedsPhantomSuddenMoveEventHack;
|
||||||
|
// Move this threshold to resource.
|
||||||
|
// TODO: Device specific parameter would be better for device specific hack?
|
||||||
|
private static final float PHANTOM_SUDDEN_MOVE_THRESHOLD = 0.25f; // in keyWidth
|
||||||
|
// This hack might be device specific.
|
||||||
|
private static final boolean sNeedsProximateBogusDownMoveUpEventHack = true;
|
||||||
|
|
||||||
private static final ArrayList<PointerTracker> sTrackers = CollectionUtils.newArrayList();
|
private static final ArrayList<PointerTracker> sTrackers = CollectionUtils.newArrayList();
|
||||||
private static PointerTrackerQueue sPointerTrackerQueue;
|
private static PointerTrackerQueue sPointerTrackerQueue;
|
||||||
|
@ -166,7 +166,8 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
|
||||||
private KeyboardActionListener mListener = EMPTY_LISTENER;
|
private KeyboardActionListener mListener = EMPTY_LISTENER;
|
||||||
|
|
||||||
private Keyboard mKeyboard;
|
private Keyboard mKeyboard;
|
||||||
private int mKeyQuarterWidthSquared;
|
private int mPhantonSuddenMoveThreshold;
|
||||||
|
private final BogusMoveEventDetector mBogusMoveEventDetector = new BogusMoveEventDetector();
|
||||||
|
|
||||||
private boolean mIsDetectingGesture = false; // per PointerTracker.
|
private boolean mIsDetectingGesture = false; // per PointerTracker.
|
||||||
private static boolean sInGesture = false;
|
private static boolean sInGesture = false;
|
||||||
|
@ -177,6 +178,51 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
|
||||||
private static int sLastRecognitionPointSize = 0; // synchronized using sAggregratedPointers
|
private static int sLastRecognitionPointSize = 0; // synchronized using sAggregratedPointers
|
||||||
private static long sLastRecognitionTime = 0; // synchronized using sAggregratedPointers
|
private static long sLastRecognitionTime = 0; // synchronized using sAggregratedPointers
|
||||||
|
|
||||||
|
static final class BogusMoveEventDetector {
|
||||||
|
// Move these thresholds to resource.
|
||||||
|
private static final float BOGUS_MOVE_ACCUMULATED_DISTANCE_THRESHOLD = 0.70f; // in keyWidth
|
||||||
|
private static final float BOGUS_MOVE_RADIUS_THRESHOLD = 1.50f; // in keyWidth
|
||||||
|
|
||||||
|
private int mAccumulatedDistanceThreshold;
|
||||||
|
private int mRadiusThreshold;
|
||||||
|
|
||||||
|
// Accumulated distance from actual and artificial down keys.
|
||||||
|
/* package */ int mAccumulatedDistanceFromDownKey;
|
||||||
|
private int mActualDownX;
|
||||||
|
private int mActualDownY;
|
||||||
|
|
||||||
|
public void setKeyboardGeometry(final int keyWidth) {
|
||||||
|
mAccumulatedDistanceThreshold = (int)(
|
||||||
|
keyWidth * BOGUS_MOVE_ACCUMULATED_DISTANCE_THRESHOLD);
|
||||||
|
mRadiusThreshold = (int)(keyWidth * BOGUS_MOVE_RADIUS_THRESHOLD);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onActualDownEvent(final int x, final int y) {
|
||||||
|
mActualDownX = x;
|
||||||
|
mActualDownY = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onDownKey() {
|
||||||
|
mAccumulatedDistanceFromDownKey = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onMoveKey(final int distance) {
|
||||||
|
mAccumulatedDistanceFromDownKey += distance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasTraveledLongDistance() {
|
||||||
|
return mAccumulatedDistanceFromDownKey >= mAccumulatedDistanceThreshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* package */ int getDistanceFromDownEvent(final int x, final int y) {
|
||||||
|
return getDistance(x, y, mActualDownX, mActualDownY);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCloseToActualDownEvent(final int x, final int y) {
|
||||||
|
return getDistanceFromDownEvent(x, y) < mRadiusThreshold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static final class TimeRecorder {
|
static final class TimeRecorder {
|
||||||
private final int mSuppressKeyPreviewAfterBatchInputDuration;
|
private final int mSuppressKeyPreviewAfterBatchInputDuration;
|
||||||
private final int mStaticTimeThresholdAfterFastTyping; // msec
|
private final int mStaticTimeThresholdAfterFastTyping; // msec
|
||||||
|
@ -192,6 +238,11 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
|
||||||
gestureStrokeParams.mStaticTimeThresholdAfterFastTyping;
|
gestureStrokeParams.mStaticTimeThresholdAfterFastTyping;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isInFastTyping(final long eventTime) {
|
||||||
|
final long elapsedTimeSinceLastLetterTyping = eventTime - mLastLetterTypingTime;
|
||||||
|
return elapsedTimeSinceLastLetterTyping < mStaticTimeThresholdAfterFastTyping;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean wasLastInputTyping() {
|
private boolean wasLastInputTyping() {
|
||||||
return mLastTypingTime >= mLastBatchInputTime;
|
return mLastTypingTime >= mLastBatchInputTime;
|
||||||
}
|
}
|
||||||
|
@ -471,8 +522,9 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
|
||||||
}
|
}
|
||||||
// Keep {@link #mCurrentKey} that comes from previous keyboard.
|
// Keep {@link #mCurrentKey} that comes from previous keyboard.
|
||||||
}
|
}
|
||||||
final int keyQuarterWidth = mKeyboard.mMostCommonKeyWidth / 4;
|
final int keyWidth = mKeyboard.mMostCommonKeyWidth;
|
||||||
mKeyQuarterWidthSquared = keyQuarterWidth * keyQuarterWidth;
|
mPhantonSuddenMoveThreshold = (int)(keyWidth * PHANTOM_SUDDEN_MOVE_THRESHOLD);
|
||||||
|
mBogusMoveEventDetector.setKeyboardGeometry(keyWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -596,10 +648,16 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
|
||||||
|
|
||||||
private Key onDownKey(final int x, final int y, final long eventTime) {
|
private Key onDownKey(final int x, final int y, final long eventTime) {
|
||||||
mDownTime = eventTime;
|
mDownTime = eventTime;
|
||||||
|
mBogusMoveEventDetector.onDownKey();
|
||||||
return onMoveToNewKey(onMoveKeyInternal(x, y), x, y);
|
return onMoveToNewKey(onMoveKeyInternal(x, y), x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int getDistance(final int x1, final int y1, final int x2, final int y2) {
|
||||||
|
return (int)Math.hypot(x1 - x2, y1 - y2);
|
||||||
|
}
|
||||||
|
|
||||||
private Key onMoveKeyInternal(final int x, final int y) {
|
private Key onMoveKeyInternal(final int x, final int y) {
|
||||||
|
mBogusMoveEventDetector.onMoveKey(getDistance(x, y, mLastX, mLastY));
|
||||||
mLastX = x;
|
mLastX = x;
|
||||||
mLastY = y;
|
mLastY = y;
|
||||||
return mKeyDetector.detectHitKey(x, y);
|
return mKeyDetector.detectHitKey(x, y);
|
||||||
|
@ -713,15 +771,14 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
|
||||||
// Naive up-to-down noise filter.
|
// Naive up-to-down noise filter.
|
||||||
final long deltaT = eventTime - mUpTime;
|
final long deltaT = eventTime - mUpTime;
|
||||||
if (deltaT < sParams.mTouchNoiseThresholdTime) {
|
if (deltaT < sParams.mTouchNoiseThresholdTime) {
|
||||||
final int dx = x - mLastX;
|
final int distance = getDistance(x, y, mLastX, mLastY);
|
||||||
final int dy = y - mLastY;
|
if (distance < sParams.mTouchNoiseThresholdDistance) {
|
||||||
final int distanceSquared = (dx * dx + dy * dy);
|
|
||||||
if (distanceSquared < sParams.mTouchNoiseThresholdDistanceSquared) {
|
|
||||||
if (DEBUG_MODE)
|
if (DEBUG_MODE)
|
||||||
Log.w(TAG, "onDownEvent: ignore potential noise: time=" + deltaT
|
Log.w(TAG, String.format("[%d] onDownEvent:"
|
||||||
+ " distance=" + distanceSquared);
|
+ " ignore potential noise: time=%d distance=%d",
|
||||||
|
mPointerId, deltaT, distance));
|
||||||
if (ProductionFlag.IS_EXPERIMENTAL) {
|
if (ProductionFlag.IS_EXPERIMENTAL) {
|
||||||
ResearchLogger.pointerTracker_onDownEvent(deltaT, distanceSquared);
|
ResearchLogger.pointerTracker_onDownEvent(deltaT, distance * distance);
|
||||||
}
|
}
|
||||||
mKeyAlreadyProcessed = true;
|
mKeyAlreadyProcessed = true;
|
||||||
return;
|
return;
|
||||||
|
@ -729,6 +786,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
|
||||||
}
|
}
|
||||||
|
|
||||||
final Key key = getKeyOn(x, y);
|
final Key key = getKeyOn(x, y);
|
||||||
|
mBogusMoveEventDetector.onActualDownEvent(x, y);
|
||||||
final PointerTrackerQueue queue = sPointerTrackerQueue;
|
final PointerTrackerQueue queue = sPointerTrackerQueue;
|
||||||
if (queue != null) {
|
if (queue != null) {
|
||||||
if (key != null && key.isModifier()) {
|
if (key != null && key.isModifier()) {
|
||||||
|
@ -856,7 +914,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
|
||||||
onMoveToNewKey(key, x, y);
|
onMoveToNewKey(key, x, y);
|
||||||
startLongPressTimer(key);
|
startLongPressTimer(key);
|
||||||
setPressedKeyGraphics(key, eventTime);
|
setPressedKeyGraphics(key, eventTime);
|
||||||
} else if (isMajorEnoughMoveToBeOnNewKey(x, y, key)) {
|
} else if (isMajorEnoughMoveToBeOnNewKey(x, y, eventTime, key)) {
|
||||||
// The pointer has been slid in to the new key from the previous key, we must call
|
// The pointer has been slid in to the new key from the previous key, we must call
|
||||||
// onRelease() first to notify that the previous key has been released, then call
|
// onRelease() first to notify that the previous key has been released, then call
|
||||||
// onPress() to notify that the new key is being pressed.
|
// onPress() to notify that the new key is being pressed.
|
||||||
|
@ -876,20 +934,19 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
|
||||||
startLongPressTimer(key);
|
startLongPressTimer(key);
|
||||||
setPressedKeyGraphics(key, eventTime);
|
setPressedKeyGraphics(key, eventTime);
|
||||||
} else {
|
} else {
|
||||||
// HACK: On some devices, quick successive touches may be translated to sudden
|
// HACK: On some devices, quick successive touches may be reported as a sudden
|
||||||
// move by touch panel firmware. This hack detects the case and translates the
|
// move by touch panel firmware. This hack detects such cases and translates the
|
||||||
// move event to successive up and down events.
|
// move event to successive up and down events.
|
||||||
final int dx = x - lastX;
|
|
||||||
final int dy = y - lastY;
|
|
||||||
final int lastMoveSquared = dx * dx + dy * dy;
|
|
||||||
// TODO: Should find a way to balance gesture detection and this hack.
|
// TODO: Should find a way to balance gesture detection and this hack.
|
||||||
if (sNeedsPhantomSuddenMoveEventHack
|
if (sNeedsPhantomSuddenMoveEventHack
|
||||||
&& lastMoveSquared >= mKeyQuarterWidthSquared
|
&& getDistance(x, y, lastX, lastY) >= mPhantonSuddenMoveThreshold) {
|
||||||
&& !mIsDetectingGesture) {
|
|
||||||
if (DEBUG_MODE) {
|
if (DEBUG_MODE) {
|
||||||
Log.w(TAG, String.format("onMoveEvent:"
|
Log.w(TAG, String.format("[%d] onMoveEvent:"
|
||||||
+ " phantom sudden move event is translated to "
|
+ " phantom sudden move event (distance=%d) is translated to "
|
||||||
+ "up[%d,%d]/down[%d,%d] events", lastX, lastY, x, y));
|
+ "up[%d,%d,%s]/down[%d,%d,%s] events", mPointerId,
|
||||||
|
getDistance(x, y, lastX, lastY),
|
||||||
|
lastX, lastY, Keyboard.printableCode(oldKey.mCode),
|
||||||
|
x, y, Keyboard.printableCode(key.mCode)));
|
||||||
}
|
}
|
||||||
// TODO: This should be moved to outside of this nested if-clause?
|
// TODO: This should be moved to outside of this nested if-clause?
|
||||||
if (ProductionFlag.IS_EXPERIMENTAL) {
|
if (ProductionFlag.IS_EXPERIMENTAL) {
|
||||||
|
@ -897,6 +954,26 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
|
||||||
}
|
}
|
||||||
onUpEventInternal(eventTime);
|
onUpEventInternal(eventTime);
|
||||||
onDownEventInternal(x, y, eventTime);
|
onDownEventInternal(x, y, eventTime);
|
||||||
|
}
|
||||||
|
// HACK: On some devices, quick successive proximate touches may be reported as
|
||||||
|
// a bogus down-move-up event by touch panel firmware. This hack detects such
|
||||||
|
// cases and breaks these events into separate up and down events.
|
||||||
|
else if (sNeedsProximateBogusDownMoveUpEventHack
|
||||||
|
&& sTimeRecorder.isInFastTyping(eventTime)
|
||||||
|
&& mBogusMoveEventDetector.isCloseToActualDownEvent(x, y)) {
|
||||||
|
if (DEBUG_MODE) {
|
||||||
|
final float radiusRatio =
|
||||||
|
(float)mBogusMoveEventDetector.getDistanceFromDownEvent(x, y)
|
||||||
|
/ mKeyboard.mMostCommonKeyWidth;
|
||||||
|
Log.w(TAG, String.format("[%d] onMoveEvent:"
|
||||||
|
+ " bogus down-move-up event (raidus=%.2f keyWidth) is "
|
||||||
|
+ " translated to up[%d,%d,%s]/down[%d,%d,%s] events",
|
||||||
|
mPointerId, radiusRatio,
|
||||||
|
lastX, lastY, Keyboard.printableCode(oldKey.mCode),
|
||||||
|
x, y, Keyboard.printableCode(key.mCode)));
|
||||||
|
}
|
||||||
|
onUpEventInternal(eventTime);
|
||||||
|
onDownEventInternal(x, y, eventTime);
|
||||||
} else {
|
} else {
|
||||||
// HACK: If there are currently multiple touches, register the key even if
|
// HACK: If there are currently multiple touches, register the key even if
|
||||||
// the finger slides off the key. This defends against noise from some
|
// the finger slides off the key. This defends against noise from some
|
||||||
|
@ -905,7 +982,13 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
|
||||||
// this hack.
|
// this hack.
|
||||||
if (getActivePointerTrackerCount() > 1 && sPointerTrackerQueue != null
|
if (getActivePointerTrackerCount() > 1 && sPointerTrackerQueue != null
|
||||||
&& !sPointerTrackerQueue.hasModifierKeyOlderThan(this)) {
|
&& !sPointerTrackerQueue.hasModifierKeyOlderThan(this)) {
|
||||||
onUpEventInternal(eventTime);
|
if (DEBUG_MODE) {
|
||||||
|
Log.w(TAG, String.format("[%d] onMoveEvent:"
|
||||||
|
+ " detected sliding finger while multi touching",
|
||||||
|
mPointerId));
|
||||||
|
}
|
||||||
|
onUpEvent(x, y, eventTime);
|
||||||
|
mKeyAlreadyProcessed = true;
|
||||||
}
|
}
|
||||||
if (!mIsDetectingGesture) {
|
if (!mIsDetectingGesture) {
|
||||||
mKeyAlreadyProcessed = true;
|
mKeyAlreadyProcessed = true;
|
||||||
|
@ -915,7 +998,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (oldKey != null && isMajorEnoughMoveToBeOnNewKey(x, y, key)) {
|
if (oldKey != null && isMajorEnoughMoveToBeOnNewKey(x, y, eventTime, key)) {
|
||||||
// The pointer has been slid out from the previous key, we must call onRelease() to
|
// The pointer has been slid out from the previous key, we must call onRelease() to
|
||||||
// notify that the previous key has been released.
|
// notify that the previous key has been released.
|
||||||
setReleasedKeyGraphics(oldKey);
|
setReleasedKeyGraphics(oldKey);
|
||||||
|
@ -1049,7 +1132,8 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isMajorEnoughMoveToBeOnNewKey(final int x, final int y, final Key newKey) {
|
private boolean isMajorEnoughMoveToBeOnNewKey(final int x, final int y, final long eventTime,
|
||||||
|
final Key newKey) {
|
||||||
if (mKeyDetector == null) {
|
if (mKeyDetector == null) {
|
||||||
throw new NullPointerException("keyboard and/or key detector not set");
|
throw new NullPointerException("keyboard and/or key detector not set");
|
||||||
}
|
}
|
||||||
|
@ -1059,8 +1143,33 @@ public final class PointerTracker implements PointerTrackerQueue.Element {
|
||||||
} else if (curKey != null) {
|
} else if (curKey != null) {
|
||||||
final int keyHysteresisDistanceSquared = mKeyDetector.getKeyHysteresisDistanceSquared(
|
final int keyHysteresisDistanceSquared = mKeyDetector.getKeyHysteresisDistanceSquared(
|
||||||
mIsInSlidingKeyInputFromModifier);
|
mIsInSlidingKeyInputFromModifier);
|
||||||
return curKey.squaredDistanceToEdge(x, y) >= keyHysteresisDistanceSquared;
|
final int distanceFromKeyEdgeSquared = curKey.squaredDistanceToEdge(x, y);
|
||||||
} else {
|
if (distanceFromKeyEdgeSquared >= keyHysteresisDistanceSquared) {
|
||||||
|
if (DEBUG_MODE) {
|
||||||
|
final int keyWidth = mKeyboard.mMostCommonKeyWidth;
|
||||||
|
final float distanceToEdgeRatio = (float)distanceFromKeyEdgeSquared
|
||||||
|
/ (keyWidth * keyWidth);
|
||||||
|
Log.d(TAG, String.format("[%d] isMajorEnoughMoveToBeOnNewKey:"
|
||||||
|
+" %.2f keyWidth from key edge",
|
||||||
|
mPointerId, distanceToEdgeRatio));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (sNeedsProximateBogusDownMoveUpEventHack && !mIsAllowedSlidingKeyInput
|
||||||
|
&& sTimeRecorder.isInFastTyping(eventTime)
|
||||||
|
&& mBogusMoveEventDetector.hasTraveledLongDistance()) {
|
||||||
|
if (DEBUG_MODE) {
|
||||||
|
final float lengthFromDownRatio =
|
||||||
|
(float)mBogusMoveEventDetector.mAccumulatedDistanceFromDownKey
|
||||||
|
/ mKeyboard.mMostCommonKeyWidth;
|
||||||
|
Log.d(TAG, String.format("[%d] isMajorEnoughMoveToBeOnNewKey:"
|
||||||
|
+ " %.2f keyWidth from virtual down point",
|
||||||
|
mPointerId, lengthFromDownRatio));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} else { // curKey == null && newKey != null
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue