aboutsummaryrefslogtreecommitdiffstats
path: root/java/src/com/android/inputmethod/latin/LatinIME.java
diff options
context:
space:
mode:
authorSatoshi Kataoka <satok@google.com>2012-11-06 12:49:53 +0900
committerSatoshi Kataoka <satok@google.com>2012-11-06 12:49:53 +0900
commit555e15a96a00e8829981557d96e9fa7fc5a74f8c (patch)
tree9750c7af9777b63c176cc780c2a6de4849931434 /java/src/com/android/inputmethod/latin/LatinIME.java
parent9381ab669f12664f7e2debea846d3ce71f89b256 (diff)
parent5f2fa6b82cbb6714ab2996aebc16f10c62d0e673 (diff)
downloadlatinime-555e15a96a00e8829981557d96e9fa7fc5a74f8c.tar.gz
latinime-555e15a96a00e8829981557d96e9fa7fc5a74f8c.tar.xz
latinime-555e15a96a00e8829981557d96e9fa7fc5a74f8c.zip
Merge remote-tracking branch 'goog/master' into mergescriptpackage
Conflicts: java/res/values-ca/strings.xml java/res/values-cs/strings.xml java/res/values-de/strings.xml java/res/values-es/strings.xml java/res/values-hr/strings.xml java/res/values-hu/strings.xml java/res/values-it/strings.xml java/res/values-lv/strings.xml java/res/values-nb/strings.xml java/res/values-nl/strings.xml java/res/values-pl/strings.xml java/res/values-pt/strings.xml java/res/values-ro/strings.xml java/res/values-ru/strings.xml java/res/values-sv/strings.xml java/res/values-sw/strings.xml java/res/values-tr/strings.xml java/res/values-uk/strings.xml java/res/values-zh-rCN/strings.xml java/res/values-zh-rTW/strings.xml java/src/com/android/inputmethod/latin/RichInputConnection.java Change-Id: Iba00dd5b86cb16d72968bc7e40d75853845b6dcb
Diffstat (limited to 'java/src/com/android/inputmethod/latin/LatinIME.java')
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java321
1 files changed, 183 insertions, 138 deletions
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 9252b0980..2af7b1d61 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -60,6 +60,7 @@ import android.view.inputmethod.InputMethodSubtype;
import com.android.inputmethod.accessibility.AccessibilityUtils;
import com.android.inputmethod.accessibility.AccessibleKeyboardViewProxy;
+import com.android.inputmethod.annotations.UsedForTesting;
import com.android.inputmethod.compat.CompatUtils;
import com.android.inputmethod.compat.InputMethodManagerCompatWrapper;
import com.android.inputmethod.compat.InputMethodServiceCompatUtils;
@@ -85,7 +86,7 @@ import java.util.Locale;
/**
* Input method implementation for Qwerty'ish keyboard.
*/
-public class LatinIME extends InputMethodService implements KeyboardActionListener,
+public final class LatinIME extends InputMethodService implements KeyboardActionListener,
SuggestionStripView.Listener, TargetApplicationGetter.OnTargetApplicationKnownListener,
Suggest.SuggestInitializationListener {
private static final String TAG = LatinIME.class.getSimpleName();
@@ -132,14 +133,14 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private View mKeyPreviewBackingView;
private View mSuggestionsContainer;
private SuggestionStripView mSuggestionStripView;
- /* package for tests */ Suggest mSuggest;
+ @UsedForTesting Suggest mSuggest;
private CompletionInfo[] mApplicationSpecifiedCompletions;
private ApplicationInfo mTargetApplicationInfo;
private InputMethodManagerCompatWrapper mImm;
private Resources mResources;
private SharedPreferences mPrefs;
- /* package for tests */ final KeyboardSwitcher mKeyboardSwitcher;
+ @UsedForTesting final KeyboardSwitcher mKeyboardSwitcher;
private final SubtypeSwitcher mSubtypeSwitcher;
private boolean mShouldSwitchToLastSubtype = true;
@@ -163,8 +164,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private int mDeleteCount;
private long mLastKeyTime;
- private AudioAndHapticFeedbackManager mFeedbackManager;
-
// Member variables for remembering the current device orientation.
private int mDisplayOrientation;
@@ -173,7 +172,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
new DictionaryPackInstallBroadcastReceiver(this);
// Keeps track of most recently inserted text (multi-character key) for reverting
- private CharSequence mEnteredText;
+ private String mEnteredText;
private boolean mIsAutoCorrectionIndicatorOn;
@@ -183,7 +182,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
public final UIHandler mHandler = new UIHandler(this);
- public static class UIHandler extends StaticInnerHandlerWrapper<LatinIME> {
+ public static final class UIHandler extends StaticInnerHandlerWrapper<LatinIME> {
private static final int MSG_UPDATE_SHIFT_STATE = 0;
private static final int MSG_PENDING_IMS_CALLBACK = 1;
private static final int MSG_UPDATE_SUGGESTION_STRIP = 2;
@@ -424,7 +423,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
// Has to be package-visible for unit tests
- /* package for test */
+ @UsedForTesting
void loadSettings() {
// Note that the calling sequence of onCreate() and onCurrentInputMethodSubtypeChanged()
// is not guaranteed. It may even be called at the same time on a different thread.
@@ -438,7 +437,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
};
mCurrentSettings = job.runInLocale(mResources, mSubtypeSwitcher.getCurrentSubtypeLocale());
- mFeedbackManager = new AudioAndHapticFeedbackManager(this, mCurrentSettings);
resetContactsDictionary(null == mSuggest ? null : mSuggest.getContactsDictionary());
}
@@ -715,11 +713,13 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mSpaceState = SPACE_STATE_NONE;
if (mSuggestionStripView != null) {
- mSuggestionStripView.clear();
+ // This will set the punctuation suggestions if next word suggestion is off;
+ // otherwise it will clear the suggestion strip.
+ setPunctuationSuggestions();
}
}
- mConnection.resetCachesUponCursorMove(mLastSelectionStart);
+ mConnection.resetCachesUponCursorMove(editorInfo.initialSelStart);
if (isDifferentTextField) {
mainKeyboardView.closing();
@@ -856,16 +856,25 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// TODO: the following is probably better done in resetEntireInputState().
// it should only happen when the cursor moved, and the very purpose of the
// test below is to narrow down whether this happened or not. Likewise with
- // the call to postUpdateShiftState.
+ // the call to updateShiftState.
// We set this to NONE because after a cursor move, we don't want the space
// state-related special processing to kick in.
mSpaceState = SPACE_STATE_NONE;
if ((!mWordComposer.isComposingWord()) || selectionChanged || noComposingSpan) {
+ // If we are composing a word and moving the cursor, we would want to set a
+ // suggestion span for recorrection to work correctly. Unfortunately, that
+ // would involve the keyboard committing some new text, which would move the
+ // cursor back to where it was. Latin IME could then fix the position of the cursor
+ // again, but the asynchronous nature of the calls results in this wreaking havoc
+ // with selection on double tap and the like.
+ // Another option would be to send suggestions each time we set the composing
+ // text, but that is probably too expensive to do, so we decided to leave things
+ // as is.
resetEntireInputState(newSelStart);
}
- mHandler.postUpdateShiftState();
+ mKeyboardSwitcher.updateShiftState();
}
mExpectingUpdateSelection = false;
// TODO: Decide to call restartSuggestionsOnWordBeforeCursorIfAtEndOfWord() or not
@@ -1052,7 +1061,16 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// Reread resource value here, because this method is called by framework anytime as needed.
final boolean isFullscreenModeAllowed =
mCurrentSettings.isFullscreenModeAllowed(getResources());
- return super.onEvaluateFullscreenMode() && isFullscreenModeAllowed;
+ if (super.onEvaluateFullscreenMode() && isFullscreenModeAllowed) {
+ // TODO: Remove this hack. Actually we should not really assume NO_EXTRACT_UI
+ // implies NO_FULLSCREEN. However, the framework mistakenly does. i.e. NO_EXTRACT_UI
+ // without NO_FULLSCREEN doesn't work as expected. Because of this we need this
+ // hack for now. Let's get rid of this once the framework gets fixed.
+ final EditorInfo ei = getCurrentInputEditorInfo();
+ return !(ei != null && ((ei.imeOptions & EditorInfo.IME_FLAG_NO_EXTRACT_UI) != 0));
+ } else {
+ return false;
+ }
}
@Override
@@ -1085,13 +1103,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private void commitTyped(final String separatorString) {
if (!mWordComposer.isComposingWord()) return;
- final CharSequence typedWord = mWordComposer.getTypedWord();
+ final String typedWord = mWordComposer.getTypedWord();
if (typedWord.length() > 0) {
- mConnection.commitText(typedWord, 1);
- final CharSequence prevWord = addToUserHistoryDictionary(typedWord);
- mLastComposedWord = mWordComposer.commitWord(
- LastComposedWord.COMMIT_TYPE_USER_TYPED_WORD, typedWord.toString(),
- separatorString, prevWord);
+ commitChosenWord(typedWord, LastComposedWord.COMMIT_TYPE_USER_TYPED_WORD,
+ separatorString);
}
}
@@ -1111,8 +1126,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// Factor in auto-caps and manual caps and compute the current caps mode.
private int getActualCapsMode() {
- final int manual = mKeyboardSwitcher.getManualCapsMode();
- if (manual != WordComposer.CAPS_MODE_OFF) return manual;
+ final int keyboardShiftMode = mKeyboardSwitcher.getKeyboardShiftMode();
+ if (keyboardShiftMode != WordComposer.CAPS_MODE_AUTO_SHIFTED) return keyboardShiftMode;
final int auto = getCurrentAutoCapsState();
if (0 != (auto & TextUtils.CAP_MODE_CHARACTERS)) {
return WordComposer.CAPS_MODE_AUTO_SHIFT_LOCKED;
@@ -1125,7 +1140,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
CharSequence lastTwo = mConnection.getTextBeforeCursor(2, 0);
// It is guaranteed lastTwo.charAt(1) is a swapper - else this method is not called.
if (lastTwo != null && lastTwo.length() == 2
- && lastTwo.charAt(0) == Keyboard.CODE_SPACE) {
+ && lastTwo.charAt(0) == Constants.CODE_SPACE) {
mConnection.deleteSurroundingText(2, 0);
mConnection.commitText(lastTwo.charAt(1) + " ", 1);
if (ProductionFlag.IS_EXPERIMENTAL) {
@@ -1141,8 +1156,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
final CharSequence lastThree = mConnection.getTextBeforeCursor(3, 0);
if (lastThree != null && lastThree.length() == 3
&& canBeFollowedByPeriod(lastThree.charAt(0))
- && lastThree.charAt(1) == Keyboard.CODE_SPACE
- && lastThree.charAt(2) == Keyboard.CODE_SPACE) {
+ && lastThree.charAt(1) == Constants.CODE_SPACE
+ && lastThree.charAt(2) == Constants.CODE_SPACE) {
mHandler.cancelDoubleSpacesTimer();
mConnection.deleteSurroundingText(2, 0);
mConnection.commitText(". ", 1);
@@ -1156,12 +1171,12 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// TODO: Check again whether there really ain't a better way to check this.
// TODO: This should probably be language-dependant...
return Character.isLetterOrDigit(codePoint)
- || codePoint == Keyboard.CODE_SINGLE_QUOTE
- || codePoint == Keyboard.CODE_DOUBLE_QUOTE
- || codePoint == Keyboard.CODE_CLOSING_PARENTHESIS
- || codePoint == Keyboard.CODE_CLOSING_SQUARE_BRACKET
- || codePoint == Keyboard.CODE_CLOSING_CURLY_BRACKET
- || codePoint == Keyboard.CODE_CLOSING_ANGLE_BRACKET;
+ || codePoint == Constants.CODE_SINGLE_QUOTE
+ || codePoint == Constants.CODE_DOUBLE_QUOTE
+ || codePoint == Constants.CODE_CLOSING_PARENTHESIS
+ || codePoint == Constants.CODE_CLOSING_SQUARE_BRACKET
+ || codePoint == Constants.CODE_CLOSING_CURLY_BRACKET
+ || codePoint == Constants.CODE_CLOSING_ANGLE_BRACKET;
}
// Callback for the {@link SuggestionStripView}, to call when the "add to dictionary" hint is
@@ -1211,22 +1226,25 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mConnection.performEditorAction(actionId);
}
+ // TODO: Revise the language switch key behavior to make it much smarter and more reasonable.
private void handleLanguageSwitchKey() {
- final boolean includesOtherImes = mCurrentSettings.mIncludesOtherImesInLanguageSwitchList;
final IBinder token = getWindow().getWindow().getAttributes().token;
+ if (mCurrentSettings.mIncludesOtherImesInLanguageSwitchList) {
+ mImm.switchToNextInputMethod(token, false /* onlyCurrentIme */);
+ return;
+ }
if (mShouldSwitchToLastSubtype) {
final InputMethodSubtype lastSubtype = mImm.getLastInputMethodSubtype();
final boolean lastSubtypeBelongsToThisIme =
ImfUtils.checkIfSubtypeBelongsToThisImeAndEnabled(this, lastSubtype);
- if ((includesOtherImes || lastSubtypeBelongsToThisIme)
- && mImm.switchToLastInputMethod(token)) {
+ if (lastSubtypeBelongsToThisIme && mImm.switchToLastInputMethod(token)) {
mShouldSwitchToLastSubtype = false;
} else {
- mImm.switchToNextInputMethod(token, !includesOtherImes);
+ mImm.switchToNextInputMethod(token, true /* onlyCurrentIme */);
mShouldSwitchToLastSubtype = true;
}
} else {
- mImm.switchToNextInputMethod(token, !includesOtherImes);
+ mImm.switchToNextInputMethod(token, true /* onlyCurrentIme */);
}
}
@@ -1253,7 +1271,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// 16 is android.os.Build.VERSION_CODES.JELLY_BEAN but we can't write it because
// we want to be able to compile against the Ice Cream Sandwich SDK.
- if (Keyboard.CODE_ENTER == code && mTargetApplicationInfo != null
+ if (Constants.CODE_ENTER == code && mTargetApplicationInfo != null
&& mTargetApplicationInfo.targetSdkVersion < 16) {
// Backward compatibility mode. Before Jelly bean, the keyboard would simulate
// a hardware keyboard event on pressing enter or delete. This is bad for many
@@ -1270,7 +1288,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
@Override
public void onCodeInput(final int primaryCode, final int x, final int y) {
final long when = SystemClock.uptimeMillis();
- if (primaryCode != Keyboard.CODE_DELETE || when > mLastKeyTime + QUICK_PRESS) {
+ if (primaryCode != Constants.CODE_DELETE || when > mLastKeyTime + QUICK_PRESS) {
mDeleteCount = 0;
}
mLastKeyTime = when;
@@ -1285,13 +1303,13 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (!mWordComposer.isComposingWord()) mIsAutoCorrectionIndicatorOn = false;
// TODO: Consolidate the double space timer, mLastKeyTime, and the space state.
- if (primaryCode != Keyboard.CODE_SPACE) {
+ if (primaryCode != Constants.CODE_SPACE) {
mHandler.cancelDoubleSpacesTimer();
}
boolean didAutoCorrect = false;
switch (primaryCode) {
- case Keyboard.CODE_DELETE:
+ case Constants.CODE_DELETE:
mSpaceState = SPACE_STATE_NONE;
handleBackspace(spaceState);
mDeleteCount++;
@@ -1299,29 +1317,29 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mShouldSwitchToLastSubtype = true;
LatinImeLogger.logOnDelete(x, y);
break;
- case Keyboard.CODE_SHIFT:
- case Keyboard.CODE_SWITCH_ALPHA_SYMBOL:
+ case Constants.CODE_SHIFT:
+ case Constants.CODE_SWITCH_ALPHA_SYMBOL:
// Shift and symbol key is handled in onPressKey() and onReleaseKey().
break;
- case Keyboard.CODE_SETTINGS:
+ case Constants.CODE_SETTINGS:
onSettingsKeyPressed();
break;
- case Keyboard.CODE_SHORTCUT:
+ case Constants.CODE_SHORTCUT:
mSubtypeSwitcher.switchToShortcutIME(this);
break;
- case Keyboard.CODE_ACTION_ENTER:
+ case Constants.CODE_ACTION_ENTER:
performEditorAction(getActionId(switcher.getKeyboard()));
break;
- case Keyboard.CODE_ACTION_NEXT:
+ case Constants.CODE_ACTION_NEXT:
performEditorAction(EditorInfo.IME_ACTION_NEXT);
break;
- case Keyboard.CODE_ACTION_PREVIOUS:
+ case Constants.CODE_ACTION_PREVIOUS:
performEditorAction(EditorInfo.IME_ACTION_PREVIOUS);
break;
- case Keyboard.CODE_LANGUAGE_SWITCH:
+ case Constants.CODE_LANGUAGE_SWITCH:
handleLanguageSwitchKey();
break;
- case Keyboard.CODE_RESEARCH:
+ case Constants.CODE_RESEARCH:
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.getInstance().onResearchKeySelected(this);
}
@@ -1357,10 +1375,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
switcher.onCodeInput(primaryCode);
// Reset after any single keystroke, except shift and symbol-shift
- if (!didAutoCorrect && primaryCode != Keyboard.CODE_SHIFT
- && primaryCode != Keyboard.CODE_SWITCH_ALPHA_SYMBOL)
+ if (!didAutoCorrect && primaryCode != Constants.CODE_SHIFT
+ && primaryCode != Constants.CODE_SWITCH_ALPHA_SYMBOL)
mLastComposedWord.deactivate();
- if (Keyboard.CODE_DELETE != primaryCode) {
+ if (Constants.CODE_DELETE != primaryCode) {
mEnteredText = null;
}
mConnection.endBatchEdit();
@@ -1371,7 +1389,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// Called from PointerTracker through the KeyboardActionListener interface
@Override
- public void onTextInput(final CharSequence rawText) {
+ public void onTextInput(final String rawText) {
mConnection.beginBatchEdit();
if (mWordComposer.isComposingWord()) {
commitCurrentAutoCorrection(rawText.toString());
@@ -1379,21 +1397,22 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
resetComposingState(true /* alsoResetLastComposedWord */);
}
mHandler.postUpdateSuggestionStrip();
- final CharSequence text = specificTldProcessingOnTextInput(rawText);
+ final String text = specificTldProcessingOnTextInput(rawText);
if (SPACE_STATE_PHANTOM == mSpaceState) {
- sendKeyCodePoint(Keyboard.CODE_SPACE);
+ sendKeyCodePoint(Constants.CODE_SPACE);
}
mConnection.commitText(text, 1);
mConnection.endBatchEdit();
// Space state must be updated before calling updateShiftState
mSpaceState = SPACE_STATE_NONE;
mKeyboardSwitcher.updateShiftState();
- mKeyboardSwitcher.onCodeInput(Keyboard.CODE_OUTPUT_TEXT);
+ mKeyboardSwitcher.onCodeInput(Constants.CODE_OUTPUT_TEXT);
mEnteredText = text;
}
@Override
public void onStartBatchInput() {
+ BatchInputUpdater.getInstance().onStartBatchInput();
mConnection.beginBatchEdit();
if (mWordComposer.isComposingWord()) {
if (ProductionFlag.IS_INTERNAL) {
@@ -1417,6 +1436,16 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// The following is necessary for the case where the user typed something but didn't
// manual pick it and didn't input any separator.
mSpaceState = SPACE_STATE_PHANTOM;
+ } else {
+ final int codePointBeforeCursor = mConnection.getCodePointBeforeCursor();
+ // TODO: reverse this logic. We should have the means to determine whether a character
+ // should usually be followed by a space, and it should be more readable.
+ if (Constants.NOT_A_CODE != codePointBeforeCursor
+ && !Character.isWhitespace(codePointBeforeCursor)
+ && !mCurrentSettings.isPhantomSpacePromotingSymbol(codePointBeforeCursor)
+ && !mCurrentSettings.isWeakSpaceStripper(codePointBeforeCursor)) {
+ mSpaceState = SPACE_STATE_PHANTOM;
+ }
}
mConnection.endBatchEdit();
mWordComposer.setCapitalizedModeAtStartComposingTime(getActualCapsMode());
@@ -1425,6 +1454,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private static final class BatchInputUpdater implements Handler.Callback {
private final Handler mHandler;
private LatinIME mLatinIme;
+ private boolean mInBatchInput; // synchornized using "this".
private BatchInputUpdater() {
final HandlerThread handlerThread = new HandlerThread(
@@ -1448,17 +1478,32 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
public boolean handleMessage(final Message msg) {
switch (msg.what) {
case MSG_UPDATE_GESTURE_PREVIEW_AND_SUGGESTION_STRIP:
- final SuggestedWords suggestedWords = getSuggestedWordsGesture(
- (InputPointers)msg.obj, mLatinIme);
- showGesturePreviewAndSuggestionStrip(
- suggestedWords, false /* dismissGestureFloatingPreviewText */, mLatinIme);
+ updateBatchInput((InputPointers)msg.obj, mLatinIme);
break;
}
return true;
}
- public void updateGesturePreviewAndSuggestionStrip(final InputPointers batchPointers,
+ // Run in the UI thread.
+ public synchronized void onStartBatchInput() {
+ mInBatchInput = true;
+ }
+
+ // Run in the Handler thread.
+ private synchronized void updateBatchInput(final InputPointers batchPointers,
final LatinIME latinIme) {
+ if (!mInBatchInput) {
+ // Batch input has ended while the message was being delivered.
+ return;
+ }
+ final SuggestedWords suggestedWords = getSuggestedWordsGestureLocked(
+ batchPointers, latinIme);
+ latinIme.mHandler.showGesturePreviewAndSuggestionStrip(
+ suggestedWords, false /* dismissGestureFloatingPreviewText */);
+ }
+
+ // Run in the UI thread.
+ public void onUpdateBatchInput(final InputPointers batchPointers, final LatinIME latinIme) {
mLatinIme = latinIme;
if (mHandler.hasMessages(MSG_UPDATE_GESTURE_PREVIEW_AND_SUGGESTION_STRIP)) {
return;
@@ -1468,15 +1513,20 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
.sendToTarget();
}
- public void showGesturePreviewAndSuggestionStrip(final SuggestedWords suggestedWords,
- final boolean dismissGestureFloatingPreviewText, final LatinIME latinIme) {
+ // Run in the UI thread.
+ public synchronized SuggestedWords onEndBatchInput(final InputPointers batchPointers,
+ final LatinIME latinIme) {
+ mInBatchInput = false;
+ final SuggestedWords suggestedWords = getSuggestedWordsGestureLocked(
+ batchPointers, latinIme);
latinIme.mHandler.showGesturePreviewAndSuggestionStrip(
- suggestedWords, dismissGestureFloatingPreviewText);
+ suggestedWords, true /* dismissGestureFloatingPreviewText */);
+ return suggestedWords;
}
// {@link LatinIME#getSuggestedWords(int)} method calls with same session id have to
// be synchronized.
- public synchronized SuggestedWords getSuggestedWordsGesture(
+ private static SuggestedWords getSuggestedWordsGestureLocked(
final InputPointers batchPointers, final LatinIME latinIme) {
latinIme.mWordComposer.setBatchInputPointers(batchPointers);
return latinIme.getSuggestedWords(Suggest.SESSION_GESTURE);
@@ -1485,8 +1535,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private void showGesturePreviewAndSuggestionStrip(final SuggestedWords suggestedWords,
final boolean dismissGestureFloatingPreviewText) {
- final String batchInputText = (suggestedWords.size() > 0)
- ? suggestedWords.getWord(0) : null;
+ final String batchInputText = suggestedWords.isEmpty()
+ ? null : suggestedWords.getWord(0);
final KeyboardView mainKeyboardView = mKeyboardSwitcher.getMainKeyboardView();
mainKeyboardView.showGestureFloatingPreviewText(batchInputText);
showSuggestionStrip(suggestedWords, null);
@@ -1497,25 +1547,22 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
@Override
public void onUpdateBatchInput(final InputPointers batchPointers) {
- BatchInputUpdater.getInstance().updateGesturePreviewAndSuggestionStrip(batchPointers, this);
+ BatchInputUpdater.getInstance().onUpdateBatchInput(batchPointers, this);
}
@Override
public void onEndBatchInput(final InputPointers batchPointers) {
- final BatchInputUpdater batchInputUpdater = BatchInputUpdater.getInstance();
- final SuggestedWords suggestedWords = batchInputUpdater.getSuggestedWordsGesture(
+ final SuggestedWords suggestedWords = BatchInputUpdater.getInstance().onEndBatchInput(
batchPointers, this);
- batchInputUpdater.showGesturePreviewAndSuggestionStrip(
- suggestedWords, true /* dismissGestureFloatingPreviewText */, this);
- final String batchInputText = (suggestedWords.size() > 0)
- ? suggestedWords.getWord(0) : null;
+ final String batchInputText = suggestedWords.isEmpty()
+ ? null : suggestedWords.getWord(0);
if (TextUtils.isEmpty(batchInputText)) {
return;
}
mWordComposer.setBatchInputWord(batchInputText);
mConnection.beginBatchEdit();
if (SPACE_STATE_PHANTOM == mSpaceState) {
- sendKeyCodePoint(Keyboard.CODE_SPACE);
+ sendKeyCodePoint(Constants.CODE_SPACE);
}
mConnection.setComposingText(batchInputText, 1);
mExpectingUpdateSelection = true;
@@ -1525,8 +1572,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mKeyboardSwitcher.updateShiftState();
}
- private CharSequence specificTldProcessingOnTextInput(final CharSequence text) {
- if (text.length() <= 1 || text.charAt(0) != Keyboard.CODE_PERIOD
+ private String specificTldProcessingOnTextInput(final String text) {
+ if (text.length() <= 1 || text.charAt(0) != Constants.CODE_PERIOD
|| !Character.isLetter(text.charAt(1))) {
// Not a tld: do nothing.
return text;
@@ -1534,10 +1581,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// We have a TLD (or something that looks like this): make sure we don't add
// a space even if currently in phantom mode.
mSpaceState = SPACE_STATE_NONE;
+ // TODO: use getCodePointBeforeCursor instead to improve performance and simplify the code
final CharSequence lastOne = mConnection.getTextBeforeCursor(1, 0);
if (lastOne != null && lastOne.length() == 1
- && lastOne.charAt(0) == Keyboard.CODE_PERIOD) {
- return text.subSequence(1, text.length());
+ && lastOne.charAt(0) == Constants.CODE_PERIOD) {
+ return text.substring(1);
} else {
return text;
}
@@ -1551,7 +1599,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
private void handleBackspace(final int spaceState) {
- // In many cases, we may have to put the keyboard in auto-shift state again.
+ // In many cases, we may have to put the keyboard in auto-shift state again. However
+ // we want to wait a few milliseconds before doing it to avoid the keyboard flashing
+ // during key repeat.
mHandler.postUpdateShiftState();
if (mWordComposer.isComposingWord()) {
@@ -1639,7 +1689,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private boolean maybeStripSpace(final int code,
final int spaceState, final boolean isFromSuggestionStrip) {
- if (Keyboard.CODE_ENTER == code && SPACE_STATE_SWAP_PUNCTUATION == spaceState) {
+ if (Constants.CODE_ENTER == code && SPACE_STATE_SWAP_PUNCTUATION == spaceState) {
mConnection.removeTrailingSpace();
return false;
} else if ((SPACE_STATE_WEAK == spaceState
@@ -1668,7 +1718,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// Sanity check
throw new RuntimeException("Should not be composing here");
}
- sendKeyCodePoint(Keyboard.CODE_SPACE);
+ sendKeyCodePoint(Constants.CODE_SPACE);
}
// NOTE: isCursorTouchingWord() is a blocking IPC call, so it often takes several
@@ -1682,7 +1732,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// the character is a single quote. The idea here is, single quote is not a
// separator and it should be treated as a normal character, except in the first
// position where it should not start composing a word.
- isComposingWord = (Keyboard.CODE_SINGLE_QUOTE != primaryCode);
+ isComposingWord = (Constants.CODE_SINGLE_QUOTE != primaryCode);
// Here we don't need to reset the last composed word. It will be reset
// when we commit this one, if we ever do; if on the other hand we backspace
// it entirely and resume suggestions on the previous word, we'd like to still
@@ -1691,15 +1741,14 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
if (isComposingWord) {
final int keyX, keyY;
- if (KeyboardActionListener.Adapter.isInvalidCoordinate(x)
- || KeyboardActionListener.Adapter.isInvalidCoordinate(y)) {
- keyX = x;
- keyY = y;
- } else {
+ if (Constants.isValidCoordinate(x) && Constants.isValidCoordinate(y)) {
final KeyDetector keyDetector =
mKeyboardSwitcher.getMainKeyboardView().getKeyDetector();
keyX = keyDetector.getTouchX(x);
keyY = keyDetector.getTouchY(y);
+ } else {
+ keyX = x;
+ keyY = y;
}
mWordComposer.add(primaryCode, keyX, keyY);
// If it's the first letter, make note of auto-caps state
@@ -1746,11 +1795,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (SPACE_STATE_PHANTOM == spaceState &&
mCurrentSettings.isPhantomSpacePromotingSymbol(primaryCode)) {
- sendKeyCodePoint(Keyboard.CODE_SPACE);
+ sendKeyCodePoint(Constants.CODE_SPACE);
}
sendKeyCodePoint(primaryCode);
- if (Keyboard.CODE_SPACE == primaryCode) {
+ if (Constants.CODE_SPACE == primaryCode) {
if (mCurrentSettings.isSuggestionsRequested(mDisplayOrientation)) {
if (maybeDoubleSpace()) {
mSpaceState = SPACE_STATE_DOUBLE;
@@ -1791,11 +1840,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
Utils.Stats.onSeparator((char)primaryCode, x, y);
}
- mHandler.postUpdateShiftState();
+ mKeyboardSwitcher.updateShiftState();
return didAutoCorrect;
}
- private CharSequence getTextWithUnderline(final CharSequence text) {
+ private CharSequence getTextWithUnderline(final String text) {
return mIsAutoCorrectionIndicatorOn
? SuggestionSpanUtils.getTextWithAutoCorrectionIndicatorUnderline(this, text)
: text;
@@ -1812,7 +1861,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// TODO: make this private
// Outside LatinIME, only used by the test suite.
- /* package for tests */
+ @UsedForTesting
boolean isShowingPunctuationList() {
if (mSuggestionStripView == null) return false;
return mCurrentSettings.mSuggestPuncList == mSuggestionStripView.getSuggestions();
@@ -1849,6 +1898,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mIsAutoCorrectionIndicatorOn = newAutoCorrectionIndicator;
final CharSequence textWithUnderline =
getTextWithUnderline(mWordComposer.getTypedWord());
+ // TODO: when called from an updateSuggestionStrip() call that results from a posted
+ // message, this is called outside any batch edit. Potentially, this may result in some
+ // janky flickering of the screen, although the display speed makes it unlikely in
+ // the practice.
mConnection.setComposingText(textWithUnderline, 1);
}
}
@@ -1877,21 +1930,25 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
private SuggestedWords getSuggestedWords(final int sessionId) {
+ final Keyboard keyboard = mKeyboardSwitcher.getKeyboard();
+ if (keyboard == null || mSuggest == null) {
+ return SuggestedWords.EMPTY;
+ }
final String typedWord = mWordComposer.getTypedWord();
// Get the word on which we should search the bigrams. If we are composing a word, it's
// whatever is *before* the half-committed word in the buffer, hence 2; if we aren't, we
// should just skip whitespace if any, so 1.
// TODO: this is slow (2-way IPC) - we should probably cache this instead.
- final CharSequence prevWord =
+ final String prevWord =
mConnection.getNthPreviousWord(mCurrentSettings.mWordSeparators,
mWordComposer.isComposingWord() ? 2 : 1);
final SuggestedWords suggestedWords = mSuggest.getSuggestedWords(mWordComposer,
- prevWord, mKeyboardSwitcher.getKeyboard().getProximityInfo(),
- mCurrentSettings.mCorrectionEnabled, sessionId);
+ prevWord, keyboard.getProximityInfo(), mCurrentSettings.mCorrectionEnabled,
+ sessionId);
return maybeRetrieveOlderSuggestions(typedWord, suggestedWords);
}
- private SuggestedWords maybeRetrieveOlderSuggestions(final CharSequence typedWord,
+ private SuggestedWords maybeRetrieveOlderSuggestions(final String typedWord,
final SuggestedWords suggestedWords) {
// TODO: consolidate this into getSuggestedWords
// We update the suggestion strip only when we have some suggestions to show, i.e. when
@@ -1921,21 +1978,16 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
}
- private void showSuggestionStrip(final SuggestedWords suggestedWords,
- final CharSequence typedWord) {
- if (null == suggestedWords || suggestedWords.size() <= 0) {
+ private void showSuggestionStrip(final SuggestedWords suggestedWords, final String typedWord) {
+ if (suggestedWords.isEmpty()) {
clearSuggestionStrip();
return;
}
- final CharSequence autoCorrection;
- if (suggestedWords.size() > 0) {
- if (suggestedWords.mWillAutoCorrect) {
- autoCorrection = suggestedWords.getWord(1);
- } else {
- autoCorrection = typedWord;
- }
+ final String autoCorrection;
+ if (suggestedWords.mWillAutoCorrect) {
+ autoCorrection = suggestedWords.getWord(1);
} else {
- autoCorrection = null;
+ autoCorrection = typedWord;
}
mWordComposer.setAutoCorrection(autoCorrection);
final boolean isAutoCorrection = suggestedWords.willAutoCorrect();
@@ -1949,9 +2001,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (mHandler.hasPendingUpdateSuggestions()) {
updateSuggestionStrip();
}
- final CharSequence typedAutoCorrection = mWordComposer.getAutoCorrectionOrNull();
+ final String typedAutoCorrection = mWordComposer.getAutoCorrectionOrNull();
final String typedWord = mWordComposer.getTypedWord();
- final CharSequence autoCorrection = (typedAutoCorrection != null)
+ final String autoCorrection = (typedAutoCorrection != null)
? typedAutoCorrection : typedWord;
if (autoCorrection != null) {
if (TextUtils.isEmpty(typedWord)) {
@@ -1982,7 +2034,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// Called from {@link SuggestionStripView} through the {@link SuggestionStripView#Listener}
// interface
@Override
- public void pickSuggestionManually(final int index, final CharSequence suggestion) {
+ public void pickSuggestionManually(final int index, final String suggestion) {
final SuggestedWords suggestedWords = mSuggestionStripView.getSuggestions();
// If this is a punctuation picked from the suggestion strip, pass it to onCodeInput
if (suggestion.length() == 1 && isShowingPunctuationList()) {
@@ -2007,7 +2059,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
int firstChar = Character.codePointAt(suggestion, 0);
if ((!mCurrentSettings.isWeakSpaceStripper(firstChar))
&& (!mCurrentSettings.isWeakSpaceSwapper(firstChar))) {
- sendKeyCodePoint(Keyboard.CODE_SPACE);
+ sendKeyCodePoint(Constants.CODE_SPACE);
}
}
@@ -2052,7 +2104,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
&& !AutoCorrection.isValidWord(mSuggest.getUnigramDictionaries(), suggestion, true);
if (ProductionFlag.IS_INTERNAL) {
- Stats.onSeparator((char)Keyboard.CODE_SPACE,
+ Stats.onSeparator((char)Constants.CODE_SPACE,
Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE);
}
if (showingAddToDictionaryHint && mIsUserDictionaryAvailable) {
@@ -2067,13 +2119,13 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
/**
* Commits the chosen word to the text field and saves it for later retrieval.
*/
- private void commitChosenWord(final CharSequence chosenWord, final int commitType,
+ private void commitChosenWord(final String chosenWord, final int commitType,
final String separatorString) {
final SuggestedWords suggestedWords = mSuggestionStripView.getSuggestions();
mConnection.commitText(SuggestionSpanUtils.getTextWithSuggestionSpan(
this, chosenWord, suggestedWords, mIsMainDictionaryAvailable), 1);
// Add the word to the user history dictionary
- final CharSequence prevWord = addToUserHistoryDictionary(chosenWord);
+ final String prevWord = addToUserHistoryDictionary(chosenWord);
// TODO: figure out here if this is an auto-correct or if the best word is actually
// what user typed. Note: currently this is done much later in
// LastComposedWord#didCommitTypedWord by string equality of the remembered
@@ -2092,7 +2144,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
setSuggestionStripShown(isSuggestionsStripVisible());
}
- private CharSequence addToUserHistoryDictionary(final CharSequence suggestion) {
+ private String addToUserHistoryDictionary(final String suggestion) {
if (TextUtils.isEmpty(suggestion)) return null;
if (mSuggest == null) return null;
@@ -2107,19 +2159,18 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
= mConnection.getNthPreviousWord(mCurrentSettings.mWordSeparators, 2);
final String secondWord;
if (mWordComposer.wasAutoCapitalized() && !mWordComposer.isMostlyCaps()) {
- secondWord = suggestion.toString().toLowerCase(
- mSubtypeSwitcher.getCurrentSubtypeLocale());
+ secondWord = suggestion.toLowerCase(mSubtypeSwitcher.getCurrentSubtypeLocale());
} else {
- secondWord = suggestion.toString();
+ secondWord = suggestion;
}
// We demote unrecognized words (frequency < 0, below) by specifying them as "invalid".
// We don't add words with 0-frequency (assuming they would be profanity etc.).
final int maxFreq = AutoCorrection.getMaxFrequency(
mSuggest.getUnigramDictionaries(), suggestion);
if (maxFreq == 0) return null;
- userHistoryDictionary.addToUserHistory(null == prevWord ? null : prevWord.toString(),
- secondWord, maxFreq > 0);
- return prevWord;
+ final String prevWordString = (null == prevWord) ? null : prevWord.toString();
+ userHistoryDictionary.addToUserHistory(prevWordString, secondWord, maxFreq > 0);
+ return prevWordString;
}
return null;
}
@@ -2144,9 +2195,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
private void revertCommit() {
- final CharSequence previousWord = mLastComposedWord.mPrevWord;
+ final String previousWord = mLastComposedWord.mPrevWord;
final String originallyTypedWord = mLastComposedWord.mTypedWord;
- final CharSequence committedWord = mLastComposedWord.mCommittedWord;
+ final String committedWord = mLastComposedWord.mCommittedWord;
final int cancelLength = committedWord.length();
final int separatorLength = LastComposedWord.getSeparatorLength(
mLastComposedWord.mSeparatorString);
@@ -2156,9 +2207,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (mWordComposer.isComposingWord()) {
throw new RuntimeException("revertCommit, but we are composing a word");
}
- final String wordBeforeCursor =
+ final CharSequence wordBeforeCursor =
mConnection.getTextBeforeCursor(deleteLength, 0)
- .subSequence(0, cancelLength).toString();
+ .subSequence(0, cancelLength);
if (!TextUtils.equals(committedWord, wordBeforeCursor)) {
throw new RuntimeException("revertCommit check failed: we thought we were "
+ "reverting \"" + committedWord
@@ -2192,7 +2243,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// TODO: Make this private
// Outside LatinIME, only used by the {@link InputTestsBase} test suite.
- /* package for test */
+ @UsedForTesting
void loadKeyboard() {
// When the device locale is changed in SetupWizard etc., this method may get called via
// onConfigurationChanged before SoftInputWindow is shown.
@@ -2208,13 +2259,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mHandler.postUpdateSuggestionStrip();
}
- // TODO: Remove this method from {@link LatinIME} and move {@link FeedbackManager} to
- // {@link KeyboardSwitcher}. Called from KeyboardSwitcher
- public void hapticAndAudioFeedback(final int primaryCode) {
- mFeedbackManager.hapticAndAudioFeedback(
- primaryCode, mKeyboardSwitcher.getMainKeyboardView());
- }
-
// Callback called by PointerTracker through the KeyboardActionListener. This is called when a
// key is depressed; release matching call is onReleaseKey below.
@Override
@@ -2231,19 +2275,20 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// If accessibility is on, ensure the user receives keyboard state updates.
if (AccessibilityUtils.getInstance().isTouchExplorationEnabled()) {
switch (primaryCode) {
- case Keyboard.CODE_SHIFT:
+ case Constants.CODE_SHIFT:
AccessibleKeyboardViewProxy.getInstance().notifyShiftState();
break;
- case Keyboard.CODE_SWITCH_ALPHA_SYMBOL:
+ case Constants.CODE_SWITCH_ALPHA_SYMBOL:
AccessibleKeyboardViewProxy.getInstance().notifySymbolsState();
break;
}
}
- if (Keyboard.CODE_DELETE == primaryCode) {
+ if (Constants.CODE_DELETE == primaryCode) {
// This is a stopgap solution to avoid leaving a high surrogate alone in a text view.
// In the future, we need to deprecate deteleSurroundingText() and have a surrogate
// pair-friendly way of deleting characters in InputConnection.
+ // TODO: use getCodePointBeforeCursor instead to improve performance
final CharSequence lastChar = mConnection.getTextBeforeCursor(1, 0);
if (!TextUtils.isEmpty(lastChar) && Character.isHighSurrogate(lastChar.charAt(0))) {
mConnection.deleteSurroundingText(1, 0);
@@ -2259,7 +2304,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
mSubtypeSwitcher.onNetworkStateChanged(intent);
} else if (action.equals(AudioManager.RINGER_MODE_CHANGED_ACTION)) {
- mFeedbackManager.onRingerModeChanged();
+ mKeyboardSwitcher.onRingerModeChanged();
}
}
};