diff options
Diffstat (limited to 'java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java')
-rw-r--r-- | java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java | 87 |
1 files changed, 54 insertions, 33 deletions
diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java index ba7aa5d1c..9570da7ba 100644 --- a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java +++ b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java @@ -197,7 +197,6 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener private KeyDebouncer mDebouncer; - private int[] mKeyIndices = new int[12]; private GestureDetector mGestureDetector; private int mPopupX; private int mPopupY; @@ -273,6 +272,7 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener } public void popupPreview(int keyIndex, long delay) { + removeMessages(MSG_POPUP_PREVIEW); sendMessageDelayed(obtainMessage(MSG_POPUP_PREVIEW, keyIndex, 0), delay); } @@ -332,12 +332,10 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener private long mLastMoveTime; private long mCurrentKeyTime; - private int mKeyDebounceThreshold; - private static final int KEY_DEBOUNCE_FACTOR = 6; + private final int mKeyDebounceThresholdSquared; - KeyDebouncer(int proximityThreshold) { - // 1/KEY_DEBOUNCE_FACTOR of distance between adjacent keys - mKeyDebounceThreshold = proximityThreshold / KEY_DEBOUNCE_FACTOR; + KeyDebouncer(float hysteresisPixel) { + mKeyDebounceThresholdSquared = (int)(hysteresisPixel * hysteresisPixel); } public int getLastCodeX() { @@ -375,15 +373,23 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener mLastCodeY = mLastY; } - public boolean isMinorMoveBounce(int x, int y, int keyIndex, int currentKey) { - // TODO: Check the coordinate against each key border. The current - // logic is pretty simple. - if (keyIndex == currentKey) + public boolean isMinorMoveBounce(int x, int y, Key newKey, Key curKey) { + if (newKey == curKey) return true; - int dx = x - mLastCodeX; - int dy = y - mLastCodeY; - int delta = dx * dx + dy * dy; - return delta < mKeyDebounceThreshold; + + return getSquareDistanceToKeyEdge(x, y, curKey) < mKeyDebounceThresholdSquared; + } + + private static int getSquareDistanceToKeyEdge(int x, int y, Key key) { + final int left = key.x; + final int right = key.x + key.width; + final int top = key.y; + final int bottom = key.y + key.height; + final int edgeX = x < left ? left : (x > right ? right : x); + final int edgeY = y < top ? top : (y > bottom ? bottom : y); + final int dx = x - edgeX; + final int dy = y - edgeY; + return dx * dx + dy * dy; } public void startTimeDebouncing(long eventTime) { @@ -766,7 +772,9 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener mProximityThreshold = (int) (dimensionSum * 1.4f / length); mProximityThreshold *= mProximityThreshold; // Square it - mDebouncer = new KeyDebouncer(mProximityThreshold); + final float hysteresisPixel = getContext().getResources() + .getDimension(R.dimen.key_debounce_hysteresis_distance); + mDebouncer = new KeyDebouncer(hysteresisPixel); } @Override @@ -903,12 +911,12 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener mDirtyRect.setEmpty(); } - private int getKeyIndices(int x, int y, int[] allKeys) { + private int getKeyIndexAndNearbyCodes(int x, int y, int[] allKeys) { final Key[] keys = mKeys; int primaryIndex = NOT_A_KEY; int closestKey = NOT_A_KEY; int closestKeyDist = mProximityThreshold + 1; - java.util.Arrays.fill(mDistances, Integer.MAX_VALUE); + Arrays.fill(mDistances, Integer.MAX_VALUE); int [] nearestKeyIndices = mKeyboard.getNearestKeys(x, y); final int keyCount = nearestKeyIndices.length; for (int i = 0; i < keyCount; i++) { @@ -939,10 +947,8 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener mDistances.length - j - nCodes); System.arraycopy(allKeys, j, allKeys, j + nCodes, allKeys.length - j - nCodes); - for (int c = 0; c < nCodes; c++) { - allKeys[j + c] = key.codes[c]; - mDistances[j + c] = dist; - } + System.arraycopy(key.codes, 0, allKeys, j, nCodes); + Arrays.fill(mDistances, j, j + nCodes, dist); break; } } @@ -965,7 +971,7 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener //TextEntryState.keyPressedAt(key, x, y); int[] codes = new int[MAX_NEARBY_KEYS]; Arrays.fill(codes, NOT_A_KEY); - getKeyIndices(x, y, codes); + getKeyIndexAndNearbyCodes(x, y, codes); // Multi-tap if (mInMultiTap) { if (mTapCount != -1) { @@ -975,6 +981,15 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener } code = key.codes[mTapCount]; } + /* + * Swap the first and second values in the codes array if the primary code is not + * the first value but the second value in the array. This happens when key + * debouncing is in effect. + */ + if (codes.length >= 2 && codes[0] != code && codes[1] == code) { + codes[1] = codes[0]; + codes[0] = code; + } mKeyboardActionListener.onKey(code, codes); mKeyboardActionListener.onRelease(code); } @@ -1016,13 +1031,12 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener } // If key changed and preview is on ... if (oldKeyIndex != mCurrentKeyIndex && mShowPreview) { - mHandler.cancelPopupPreview(); - if (previewPopup.isShowing()) { - if (keyIndex == NOT_A_KEY) { + if (keyIndex == NOT_A_KEY) { + mHandler.cancelPopupPreview(); + if (previewPopup.isShowing()) { mHandler.dismissPreview(DELAY_AFTER_PREVIEW); } - } - if (keyIndex != NOT_A_KEY) { + } else { if (previewPopup.isShowing() && mPreviewText.getVisibility() == VISIBLE) { // Show right away, if it's already visible and finger is moving around showKey(keyIndex); @@ -1295,7 +1309,7 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener int touchY = (int) me.getY() + mVerticalCorrection - getPaddingTop(); final int action = me.getAction(); final long eventTime = me.getEventTime(); - int keyIndex = getKeyIndices(touchX, touchY, null); + int keyIndex = getKeyIndexAndNearbyCodes(touchX, touchY, null); mPossiblePoly = possiblePoly; // Track the last few movements to look for spurious swipes. @@ -1354,8 +1368,8 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener if (mCurrentKey == NOT_A_KEY) { mCurrentKey = keyIndex; mDebouncer.updateTimeDebouncing(eventTime); - } else if (mDebouncer.isMinorMoveBounce(touchX, touchY, - keyIndex, mCurrentKey)) { + } else if (mDebouncer.isMinorMoveBounce(touchX, touchY, mKeys[keyIndex], + mKeys[mCurrentKey])) { mDebouncer.updateTimeDebouncing(eventTime); continueLongPress = true; } else if (mRepeatKeyIndex == NOT_A_KEY) { @@ -1373,12 +1387,19 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener mHandler.startLongPressTimer(me, LONGPRESS_TIMEOUT); } } - showPreview(mCurrentKey); + /* + * While time debouncing is in effect, mCurrentKey holds the new key and mDebouncer + * holds the last key. At ACTION_UP event if time debouncing will be in effect + * eventually, the last key should be sent as the result. In such case mCurrentKey + * should not be showed as popup preview. + */ + showPreview(mDebouncer.isMinorTimeBounce() ? mDebouncer.getLastKey() : mCurrentKey); break; case MotionEvent.ACTION_UP: mHandler.cancelKeyTimersAndPopupPreview(); - if (keyIndex == mCurrentKey) { + if (mDebouncer.isMinorMoveBounce(touchX, touchY, mKeys[keyIndex], + mKeys[mCurrentKey])) { mDebouncer.updateTimeDebouncing(eventTime); } else { resetMultiTap(); @@ -1391,7 +1412,6 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener touchY = mDebouncer.getLastCodeY(); } showPreview(NOT_A_KEY); - Arrays.fill(mKeyIndices, NOT_A_KEY); // If we're not on a repeating key (which sends on a DOWN event) if (mRepeatKeyIndex == NOT_A_KEY && !mMiniKeyboardOnScreen && !mAbortKey) { detectAndSendKey(mCurrentKey, touchX, touchY, eventTime); @@ -1399,6 +1419,7 @@ public class LatinKeyboardBaseView extends View implements View.OnClickListener invalidateKey(keyIndex); mRepeatKeyIndex = NOT_A_KEY; break; + case MotionEvent.ACTION_CANCEL: mHandler.cancelKeyTimersAndPopupPreview(); dismissPopupKeyboard(); |