diff --git a/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java b/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java index a7b695eb3..0db204ed8 100644 --- a/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java +++ b/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java @@ -82,10 +82,6 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha R.xml.kbd_symbols_shift, R.xml.kbd_symbols_shift_black}; private static final int[] KBD_QWERTY = new int[] {R.xml.kbd_qwerty, R.xml.kbd_qwerty_black}; - private static final int SYMBOLS_MODE_STATE_NONE = 0; - private static final int SYMBOLS_MODE_STATE_BEGIN = 1; - private static final int SYMBOLS_MODE_STATE_SYMBOL = 2; - private LatinKeyboardView mInputView; private static final int[] ALPHABET_MODES = { KEYBOARDMODE_NORMAL, @@ -99,13 +95,14 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha KEYBOARDMODE_IM_WITH_SETTINGS_KEY, KEYBOARDMODE_WEB_WITH_SETTINGS_KEY }; - private final LatinIME mInputMethodService; + private LatinIME mInputMethodService; private KeyboardId mSymbolsId; private KeyboardId mSymbolsShiftedId; private KeyboardId mCurrentId; - private final HashMap> mKeyboards; + private final HashMap> mKeyboards = + new HashMap>(); private int mMode = MODE_NONE; /** One of the MODE_XXX values */ private int mImeOptions; @@ -116,7 +113,14 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha private boolean mHasVoice; private boolean mVoiceOnPrimary; private boolean mPreferSymbols; - private int mSymbolsModeState = SYMBOLS_MODE_STATE_NONE; + + private static final int AUTO_MODE_SWITCH_STATE_ALPHA = 0; + private static final int AUTO_MODE_SWITCH_STATE_SYMBOL_BEGIN = 1; + private static final int AUTO_MODE_SWITCH_STATE_SYMBOL = 2; + // The following states are used only on the distinct multi-touch panel devices. + private static final int AUTO_MODE_SWITCH_STATE_MOMENTARY = 3; + private static final int AUTO_MODE_SWITCH_STATE_CHORDING = 4; + private int mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_ALPHA; // Indicates whether or not we have the settings key private boolean mHasSettingsKey; @@ -133,17 +137,27 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha private int mLayoutId; - public KeyboardSwitcher(LatinIME ims) { - mInputMethodService = ims; + private static final KeyboardSwitcher sInstance = new KeyboardSwitcher(); + + public static KeyboardSwitcher getInstance() { + return sInstance; + } + + private KeyboardSwitcher() { + // Intentional empty constructor for singleton. + } + + public static void init(LatinIME ims) { + sInstance.mInputMethodService = ims; final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ims); - mLayoutId = Integer.valueOf(prefs.getString(PREF_KEYBOARD_LAYOUT, DEFAULT_LAYOUT_ID)); - updateSettingsKeyState(prefs); - prefs.registerOnSharedPreferenceChangeListener(this); + sInstance.mLayoutId = Integer.valueOf( + prefs.getString(PREF_KEYBOARD_LAYOUT, DEFAULT_LAYOUT_ID)); + sInstance.updateSettingsKeyState(prefs); + prefs.registerOnSharedPreferenceChangeListener(sInstance); - mKeyboards = new HashMap>(); - mSymbolsId = makeSymbolsId(false); - mSymbolsShiftedId = makeSymbolsShiftedId(false); + sInstance.mSymbolsId = sInstance.makeSymbolsId(false); + sInstance.mSymbolsShiftedId = sInstance.makeSymbolsShiftedId(false); } /** @@ -243,7 +257,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha } public void setKeyboardMode(int mode, int imeOptions, boolean enableVoice) { - mSymbolsModeState = SYMBOLS_MODE_STATE_NONE; + mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_ALPHA; mPreferSymbols = mode == MODE_SYMBOLS; if (mode == MODE_SYMBOLS) { mode = MODE_TEXT; @@ -410,12 +424,18 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha } } + public void onCancelInput() { + // Snap back to the previous keyboard mode if the user cancels sliding input. + if (mAutoModeSwitchState == AUTO_MODE_SWITCH_STATE_MOMENTARY && getPointerCount() == 1) + mInputMethodService.changeKeyboardMode(); + } + public void toggleSymbols() { setKeyboardMode(mMode, mImeOptions, mHasVoice, !mIsSymbols); if (mIsSymbols && !mPreferSymbols) { - mSymbolsModeState = SYMBOLS_MODE_STATE_BEGIN; + mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_SYMBOL_BEGIN; } else { - mSymbolsModeState = SYMBOLS_MODE_STATE_NONE; + mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_ALPHA; } } @@ -423,24 +443,72 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha return mInputView != null && mInputView.hasDistinctMultitouch(); } + public void setAutoModeSwitchStateMomentary() { + mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_MOMENTARY; + } + + public boolean isInMomentaryAutoModeSwitchState() { + return mAutoModeSwitchState == AUTO_MODE_SWITCH_STATE_MOMENTARY; + } + + public boolean isInChordingAutoModeSwitchState() { + return mAutoModeSwitchState == AUTO_MODE_SWITCH_STATE_CHORDING; + } + + public boolean isVibrateAndSoundFeedbackRequired() { + return mInputView != null && !mInputView.isInSlidingKeyInput(); + } + + private int getPointerCount() { + return mInputView == null ? 0 : mInputView.getPointerCount(); + } + /** - * Updates state machine to figure out when to automatically switch back to alpha mode. - * Returns true if the keyboard needs to switch back + * Updates state machine to figure out when to automatically snap back to the previous mode. */ - public boolean onKey(int key) { + public void onKey(int key) { // Switch back to alpha mode if user types one or more non-space/enter characters // followed by a space/enter - switch (mSymbolsModeState) { - case SYMBOLS_MODE_STATE_BEGIN: - if (key != LatinIME.KEYCODE_SPACE && key != LatinIME.KEYCODE_ENTER && key > 0) { - mSymbolsModeState = SYMBOLS_MODE_STATE_SYMBOL; + switch (mAutoModeSwitchState) { + case AUTO_MODE_SWITCH_STATE_MOMENTARY: + // Only distinct multi touch devices can be in this state. + // On non-distinct multi touch devices, mode change key is handled by {@link onKey}, + // not by {@link onPress} and {@link onRelease}. So, on such devices, + // {@link mAutoModeSwitchState} starts from {@link AUTO_MODE_SWITCH_STATE_SYMBOL_BEGIN}, + // or {@link AUTO_MODE_SWITCH_STATE_ALPHA}, not from + // {@link AUTO_MODE_SWITCH_STATE_MOMENTARY}. + if (key == LatinKeyboard.KEYCODE_MODE_CHANGE) { + // Detected only the mode change key has been pressed, and then released. + if (mIsSymbols) { + mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_SYMBOL_BEGIN; + } else { + mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_ALPHA; } - break; - case SYMBOLS_MODE_STATE_SYMBOL: - if (key == LatinIME.KEYCODE_ENTER || key == LatinIME.KEYCODE_SPACE) return true; - break; + } else if (getPointerCount() == 1) { + // Snap back to the previous keyboard mode if the user pressed the mode change key + // and slid to other key, then released the finger. + // If the user cancels the sliding input, snapping back to the previous keyboard + // mode is handled by {@link #onCancelInput}. + mInputMethodService.changeKeyboardMode(); + } else { + // Chording input is being started. The keyboard mode will be snapped back to the + // previous mode in {@link onReleaseSymbol} when the mode change key is released. + mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_CHORDING; + } + break; + case AUTO_MODE_SWITCH_STATE_SYMBOL_BEGIN: + if (key != LatinIME.KEYCODE_SPACE && key != LatinIME.KEYCODE_ENTER && key >= 0) { + mAutoModeSwitchState = AUTO_MODE_SWITCH_STATE_SYMBOL; + } + break; + case AUTO_MODE_SWITCH_STATE_SYMBOL: + // Snap back to alpha keyboard mode if user types one or more non-space/enter + // characters followed by a space/enter. + if (key == LatinIME.KEYCODE_ENTER || key == LatinIME.KEYCODE_SPACE) { + mInputMethodService.changeKeyboardMode(); + } + break; } - return false; } public LatinKeyboardView getInputView() { diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index ffca22e45..b1689f886 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -342,6 +342,7 @@ public class LatinIME extends InputMethodService @Override public void onCreate() { LatinImeLogger.init(this); + KeyboardSwitcher.init(this); super.onCreate(); //setStatusIcon(R.drawable.ime_qwerty); mResources = getResources(); @@ -349,7 +350,7 @@ public class LatinIME extends InputMethodService final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); mLanguageSwitcher = new LanguageSwitcher(this); mLanguageSwitcher.loadLocales(prefs); - mKeyboardSwitcher = new KeyboardSwitcher(this); + mKeyboardSwitcher = KeyboardSwitcher.getInstance(); mKeyboardSwitcher.setLanguageSwitcher(mLanguageSwitcher); mSystemLocale = conf.locale.toString(); mLanguageSwitcher.setSystemLocale(conf.locale); @@ -1247,9 +1248,7 @@ public class LatinIME extends InputMethodService // Cancel the just reverted state mJustRevertedSeparator = null; } - if (mKeyboardSwitcher.onKey(primaryCode)) { - changeKeyboardMode(); - } + mKeyboardSwitcher.onKey(primaryCode); // Reset after any single keystroke mEnteredText = null; } @@ -1269,6 +1268,7 @@ public class LatinIME extends InputMethodService ic.commitText(text, 1); ic.endBatchEdit(); updateShiftKeyState(getCurrentInputEditorInfo()); + mKeyboardSwitcher.onKey(0); // dummy key code. mJustRevertedSeparator = null; mJustAddedAutoSpace = false; mEnteredText = text; @@ -1276,6 +1276,7 @@ public class LatinIME extends InputMethodService public void onCancel() { // User released a finger outside any key + mKeyboardSwitcher.onCancelInput(); } private void handleBackspace() { @@ -2283,15 +2284,18 @@ public class LatinIME extends InputMethodService } public void onPress(int primaryCode) { - vibrate(); - playKeyClick(primaryCode); + if (mKeyboardSwitcher.isVibrateAndSoundFeedbackRequired()) { + vibrate(); + playKeyClick(primaryCode); + } final boolean distinctMultiTouch = mKeyboardSwitcher.hasDistinctMultitouch(); if (distinctMultiTouch && primaryCode == Keyboard.KEYCODE_SHIFT) { mShiftKeyState.onPress(); handleShift(); } else if (distinctMultiTouch && primaryCode == Keyboard.KEYCODE_MODE_CHANGE) { - mSymbolKeyState.onPress(); changeKeyboardMode(); + mSymbolKeyState.onPress(); + mKeyboardSwitcher.setAutoModeSwitchStateMomentary(); } else { mShiftKeyState.onOtherKeyPressed(); mSymbolKeyState.onOtherKeyPressed(); @@ -2308,7 +2312,9 @@ public class LatinIME extends InputMethodService resetShift(); mShiftKeyState.onRelease(); } else if (distinctMultiTouch && primaryCode == Keyboard.KEYCODE_MODE_CHANGE) { - if (mSymbolKeyState.isMomentary()) + // Snap back to the previous keyboard mode if the user chords the mode change key and + // other key, then released the mode change key. + if (mKeyboardSwitcher.isInChordingAutoModeSwitchState()) changeKeyboardMode(); mSymbolKeyState.onRelease(); } @@ -2562,7 +2568,7 @@ public class LatinIME extends InputMethodService mOptionsDialog.show(); } - private void changeKeyboardMode() { + public void changeKeyboardMode() { mKeyboardSwitcher.toggleSymbols(); if (mCapsLock && mKeyboardSwitcher.isAlphabetMode()) { mKeyboardSwitcher.setShiftLocked(mCapsLock); diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java index b1ef08573..008d37202 100644 --- a/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java +++ b/java/src/com/android/inputmethod/latin/LatinKeyboardBaseView.java @@ -343,7 +343,7 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx cancelPopupPreview(); cancelDismissPreview(); } - }; + } static class PointerQueue { private LinkedList mQueue = new LinkedList(); @@ -391,6 +391,14 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx public void remove(PointerTracker tracker) { mQueue.remove(tracker); } + + public boolean isInSlidingKeyInput() { + for (final PointerTracker tracker : mQueue) { + if (tracker.isInSlidingKeyInput()) + return true; + } + return false; + } } public LatinKeyboardBaseView(Context context, AttributeSet attrs) { @@ -1086,6 +1094,7 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx } public void onCancel() { + mKeyboardActionListener.onCancel(); dismissPopupKeyboard(); } @@ -1294,15 +1303,29 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx return pointers.get(id); } + public boolean isInSlidingKeyInput() { + if (mMiniKeyboard != null) { + return mMiniKeyboard.isInSlidingKeyInput(); + } else { + return mPointerQueue.isInSlidingKeyInput(); + } + } + + public int getPointerCount() { + return mOldPointerCount; + } + @Override public boolean onTouchEvent(MotionEvent me) { - final int pointerCount = me.getPointerCount(); final int action = me.getActionMasked(); + final int pointerCount = me.getPointerCount(); + final int oldPointerCount = mOldPointerCount; + mOldPointerCount = pointerCount; // TODO: cleanup this code into a multi-touch to single-touch event converter class? // If the device does not have distinct multi-touch support panel, ignore all multi-touch // events except a transition from/to single-touch. - if (!mHasDistinctMultitouch && pointerCount > 1 && mOldPointerCount > 1) { + if (!mHasDistinctMultitouch && pointerCount > 1 && oldPointerCount > 1) { return true; } @@ -1358,7 +1381,6 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx if (!mHasDistinctMultitouch) { // Use only main (id=0) pointer tracker. PointerTracker tracker = getPointerTracker(0); - int oldPointerCount = mOldPointerCount; if (pointerCount == 1 && oldPointerCount == 2) { // Multi-touch to single touch transition. // Send a down event for the latest pointer. @@ -1373,7 +1395,6 @@ public class LatinKeyboardBaseView extends View implements PointerTracker.UIProx Log.w(TAG, "Unknown touch panel behavior: pointer count is " + pointerCount + " (old " + oldPointerCount + ")"); } - mOldPointerCount = pointerCount; return true; } diff --git a/java/src/com/android/inputmethod/latin/PointerTracker.java b/java/src/com/android/inputmethod/latin/PointerTracker.java index 90218e4ab..b23b4d7b8 100644 --- a/java/src/com/android/inputmethod/latin/PointerTracker.java +++ b/java/src/com/android/inputmethod/latin/PointerTracker.java @@ -51,6 +51,7 @@ public class PointerTracker { private final UIHandler mHandler; private final KeyDetector mKeyDetector; private OnKeyboardActionListener mListener; + private final KeyboardSwitcher mKeyboardSwitcher; private final boolean mHasDistinctMultitouch; private Key[] mKeys; @@ -58,12 +59,18 @@ public class PointerTracker { private final KeyState mKeyState; + // true if keyboard layout has been changed. + private boolean mKeyboardLayoutHasBeenChanged; + // true if event is already translated to a key action (long press or mini-keyboard) private boolean mKeyAlreadyProcessed; // true if this pointer is repeatable key private boolean mIsRepeatableKey; + // true if this pointer is in sliding key input + private boolean mIsInSlidingKeyInput; + // For multi-tap private int mLastSentIndex; private int mTapCount; @@ -157,10 +164,6 @@ public class PointerTracker { public int onUpKey(int x, int y) { return onMoveKeyInternal(x, y); } - - public void onSetKeyboard() { - mKeyIndex = mKeyDetector.getKeyIndexAndNearbyCodes(mKeyX, mKeyY, null); - } } public PointerTracker(int id, UIHandler handler, KeyDetector keyDetector, UIProxy proxy, @@ -171,6 +174,7 @@ public class PointerTracker { mProxy = proxy; mHandler = handler; mKeyDetector = keyDetector; + mKeyboardSwitcher = KeyboardSwitcher.getInstance(); mKeyState = new KeyState(keyDetector); mHasDistinctMultitouch = proxy.hasDistinctMultitouch(); mDelayBeforeKeyRepeatStart = res.getInteger(R.integer.config_delay_before_key_repeat_start); @@ -188,8 +192,12 @@ public class PointerTracker { throw new IllegalArgumentException(); mKeys = keys; mKeyHysteresisDistanceSquared = (int)(keyHysteresisDistance * keyHysteresisDistance); - // Update current key index because keyboard layout has been changed. - mKeyState.onSetKeyboard(); + // Mark that keyboard layout has been changed. + mKeyboardLayoutHasBeenChanged = true; + } + + public boolean isInSlidingKeyInput() { + return mIsInSlidingKeyInput; } private boolean isValidKeyIndex(int keyIndex) { @@ -268,15 +276,21 @@ public class PointerTracker { if (DEBUG) debugLog("onDownEvent:", x, y); int keyIndex = mKeyState.onDownKey(x, y, eventTime); + mKeyboardLayoutHasBeenChanged = false; mKeyAlreadyProcessed = false; mIsRepeatableKey = false; + mIsInSlidingKeyInput = false; checkMultiTap(eventTime, keyIndex); if (mListener != null) { if (isValidKeyIndex(keyIndex)) { mListener.onPress(mKeys[keyIndex].codes[0]); - // This onPress call may have changed keyboard layout and have updated mKeyIndex. - // If that's the case, mKeyIndex has been updated in setKeyboard(). - keyIndex = mKeyState.getKeyIndex(); + // This onPress call may have changed keyboard layout. Those cases are detected at + // {@link #setKeyboard}. In those cases, we should update keyIndex according to the + // new keyboard layout. + if (mKeyboardLayoutHasBeenChanged) { + mKeyboardLayoutHasBeenChanged = false; + keyIndex = mKeyState.onDownKey(x, y, eventTime); + } } } if (isValidKeyIndex(keyIndex)) { @@ -285,7 +299,7 @@ public class PointerTracker { mHandler.startKeyRepeatTimer(mDelayBeforeKeyRepeatStart, keyIndex, this); mIsRepeatableKey = true; } - mHandler.startLongPressTimer(mLongPressKeyTimeout, keyIndex, this); + startLongPressTimer(keyIndex); } showKeyPreviewAndUpdateKey(keyIndex); } @@ -295,42 +309,70 @@ public class PointerTracker { debugLog("onMoveEvent:", x, y); if (mKeyAlreadyProcessed) return; - KeyState keyState = mKeyState; - final int keyIndex = keyState.onMoveKey(x, y); + final KeyState keyState = mKeyState; + int keyIndex = keyState.onMoveKey(x, y); final Key oldKey = getKey(keyState.getKeyIndex()); if (isValidKeyIndex(keyIndex)) { if (oldKey == null) { + // The pointer has been slid in to the new key, but the finger was not on any keys. + // In this case, we must call onPress() to notify that the new key is being pressed. + if (mListener != null) { + mListener.onPress(getKey(keyIndex).codes[0]); + // This onPress call may have changed keyboard layout. Those cases are detected + // at {@link #setKeyboard}. In those cases, we should update keyIndex according + // to the new keyboard layout. + if (mKeyboardLayoutHasBeenChanged) { + mKeyboardLayoutHasBeenChanged = false; + keyIndex = keyState.onMoveKey(x, y); + } + } keyState.onMoveToNewKey(keyIndex, x, y); - mHandler.startLongPressTimer(mLongPressKeyTimeout, keyIndex, this); + startLongPressTimer(keyIndex); } else if (!isMinorMoveBounce(x, y, keyIndex)) { + // 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 + // onPress() to notify that the new key is being pressed. + mIsInSlidingKeyInput = true; if (mListener != null) mListener.onRelease(oldKey.codes[0]); resetMultiTap(); + if (mListener != null) { + mListener.onPress(getKey(keyIndex).codes[0]); + // This onPress call may have changed keyboard layout. Those cases are detected + // at {@link #setKeyboard}. In those cases, we should update keyIndex according + // to the new keyboard layout. + if (mKeyboardLayoutHasBeenChanged) { + mKeyboardLayoutHasBeenChanged = false; + keyIndex = keyState.onMoveKey(x, y); + } + } keyState.onMoveToNewKey(keyIndex, x, y); - mHandler.startLongPressTimer(mLongPressKeyTimeout, keyIndex, this); + startLongPressTimer(keyIndex); } } else { - if (oldKey != null) { + if (oldKey != null && !isMinorMoveBounce(x, y, keyIndex)) { + // The pointer has been slid out from the previous key, we must call onRelease() to + // notify that the previous key has been released. + mIsInSlidingKeyInput = true; if (mListener != null) mListener.onRelease(oldKey.codes[0]); - keyState.onMoveToNewKey(keyIndex, x ,y); - mHandler.cancelLongPressTimer(); - } else if (!isMinorMoveBounce(x, y, keyIndex)) { resetMultiTap(); keyState.onMoveToNewKey(keyIndex, x ,y); mHandler.cancelLongPressTimer(); } } - showKeyPreviewAndUpdateKey(mKeyState.getKeyIndex()); + showKeyPreviewAndUpdateKey(keyState.getKeyIndex()); } public void onUpEvent(int x, int y, long eventTime) { if (DEBUG) debugLog("onUpEvent :", x, y); - if (mKeyAlreadyProcessed) - return; mHandler.cancelKeyTimers(); mHandler.cancelPopupPreview(); + showKeyPreviewAndUpdateKey(NOT_A_KEY); + mIsInSlidingKeyInput = false; + if (mKeyAlreadyProcessed) + return; int keyIndex = mKeyState.onUpKey(x, y); if (isMinorMoveBounce(x, y, keyIndex)) { // Use previous fixed key index and coordinates. @@ -338,7 +380,6 @@ public class PointerTracker { x = mKeyState.getKeyX(); y = mKeyState.getKeyY(); } - showKeyPreviewAndUpdateKey(NOT_A_KEY); if (!mIsRepeatableKey) { detectAndSendKey(keyIndex, x, y, eventTime); } @@ -353,6 +394,7 @@ public class PointerTracker { mHandler.cancelKeyTimers(); mHandler.cancelPopupPreview(); showKeyPreviewAndUpdateKey(NOT_A_KEY); + mIsInSlidingKeyInput = false; int keyIndex = mKeyState.getKeyIndex(); if (isValidKeyIndex(keyIndex)) mProxy.invalidateKey(mKeys[keyIndex]); @@ -425,6 +467,15 @@ public class PointerTracker { } } + private void startLongPressTimer(int keyIndex) { + if (mKeyboardSwitcher.isInMomentaryAutoModeSwitchState()) { + // We use longer timeout for sliding finger input started from the symbols mode key. + mHandler.startLongPressTimer(mLongPressKeyTimeout * 3, keyIndex, this); + } else { + mHandler.startLongPressTimer(mLongPressKeyTimeout, keyIndex, this); + } + } + private void detectAndSendKey(int index, int x, int y, long eventTime) { final OnKeyboardActionListener listener = mListener; final Key key = getKey(index); @@ -436,11 +487,10 @@ public class PointerTracker { if (key.text != null) { if (listener != null) { listener.onText(key.text); - listener.onRelease(NOT_A_KEY); + listener.onRelease(0); // dummy key code } } else { int code = key.codes[0]; - //TextEntryState.keyPressedAt(key, x, y); int[] codes = mKeyDetector.newCodeArray(); mKeyDetector.getKeyIndexAndNearbyCodes(x, y, codes); // Multi-tap