aboutsummaryrefslogtreecommitdiffstats
path: root/java/src/com/android/inputmethod/latin/LatinIME.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/src/com/android/inputmethod/latin/LatinIME.java')
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java105
1 files changed, 80 insertions, 25 deletions
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 83658f77e..38549436b 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -27,6 +27,7 @@ import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
+import android.content.pm.ApplicationInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Rect;
@@ -44,6 +45,8 @@ import android.text.TextUtils;
import android.util.Log;
import android.util.PrintWriterPrinter;
import android.util.Printer;
+import android.view.KeyCharacterMap;
+import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
@@ -80,7 +83,7 @@ import java.util.Locale;
* Input method implementation for Qwerty'ish keyboard.
*/
public class LatinIME extends InputMethodService implements KeyboardActionListener,
- SuggestionsView.Listener {
+ SuggestionsView.Listener, TargetApplicationGetter.OnTargetApplicationKnownListener {
private static final String TAG = LatinIME.class.getSimpleName();
private static final boolean TRACE = false;
private static boolean DEBUG;
@@ -152,6 +155,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private SuggestionsView mSuggestionsView;
/* package for tests */ Suggest mSuggest;
private CompletionInfo[] mApplicationSpecifiedCompletions;
+ private ApplicationInfo mTargetApplicationInfo;
private InputMethodManagerCompatWrapper mImm;
private Resources mResources;
@@ -492,7 +496,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
resetContactsDictionary(oldContactsDictionary);
mUserHistoryDictionary = new UserHistoryDictionary(
- this, localeStr, Suggest.DIC_USER_HISTORY);
+ this, localeStr, Suggest.DIC_USER_HISTORY, mPrefs);
mSuggest.setUserHistoryDictionary(mUserHistoryDictionary);
}
@@ -665,6 +669,13 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
Log.w(TAG, "Use EditorInfo.IME_FLAG_FORCE_ASCII flag instead");
}
+ mTargetApplicationInfo =
+ TargetApplicationGetter.getCachedApplicationInfo(editorInfo.packageName);
+ if (null == mTargetApplicationInfo) {
+ new TargetApplicationGetter(this /* context */, this /* listener */)
+ .execute(editorInfo.packageName);
+ }
+
LatinImeLogger.onStartInputView(editorInfo);
// In landscape mode, this method gets called without the input view being created.
if (inputView == null) {
@@ -718,6 +729,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (TRACE) Debug.startMethodTracing("/data/trace/latinime");
}
+ public void onTargetApplicationKnown(final ApplicationInfo info) {
+ mTargetApplicationInfo = info;
+ }
+
@Override
public void onWindowHidden() {
super.onWindowHidden();
@@ -732,7 +747,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
KeyboardView inputView = mKeyboardSwitcher.getKeyboardView();
if (inputView != null) inputView.closing();
- if (mUserHistoryDictionary != null) mUserHistoryDictionary.flushPendingWrites();
}
private void onFinishInputViewInternal(boolean finishingInput) {
@@ -1027,16 +1041,16 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (!mWordComposer.isComposingWord()) return;
final CharSequence typedWord = mWordComposer.getTypedWord();
if (typedWord.length() > 0) {
- mLastComposedWord = mWordComposer.commitWord(
- LastComposedWord.COMMIT_TYPE_USER_TYPED_WORD, typedWord.toString(),
- separatorCode);
if (ic != null) {
ic.commitText(typedWord, 1);
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_commitText(typedWord);
}
}
- addToUserHistoryDictionary(typedWord);
+ final CharSequence prevWord = addToUserHistoryDictionary(typedWord);
+ mLastComposedWord = mWordComposer.commitWord(
+ LastComposedWord.COMMIT_TYPE_USER_TYPED_WORD, typedWord.toString(),
+ separatorCode, prevWord);
}
updateSuggestions();
}
@@ -1211,6 +1225,16 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
}
+ static private void sendUpDownEnterOrBackspace(final int code, final InputConnection ic) {
+ final long eventTime = SystemClock.uptimeMillis();
+ ic.sendKeyEvent(new KeyEvent(eventTime, eventTime,
+ KeyEvent.ACTION_DOWN, code, 0, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
+ KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE));
+ ic.sendKeyEvent(new KeyEvent(SystemClock.uptimeMillis(), eventTime,
+ KeyEvent.ACTION_UP, code, 0, 0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0,
+ KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE));
+ }
+
private void sendKeyCodePoint(int code) {
// TODO: Remove this special handling of digit letters.
// For backward compatibility. See {@link InputMethodService#sendKeyChar(char)}.
@@ -1221,8 +1245,19 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
final InputConnection ic = getCurrentInputConnection();
if (ic != null) {
- final String text = new String(new int[] { code }, 0, 1);
- ic.commitText(text, text.length());
+ // 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
+ && 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
+ // reasons (there are race conditions with commits) but some applications are
+ // relying on this behavior so we continue to support it for older apps.
+ sendUpDownEnterOrBackspace(KeyEvent.KEYCODE_ENTER, ic);
+ } else {
+ final String text = new String(new int[] { code }, 0, 1);
+ ic.commitText(text, text.length());
+ }
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_sendKeyCodePoint(code);
}
@@ -1451,7 +1486,18 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// This should never happen.
Log.e(TAG, "Backspace when we don't know the selection position");
}
- ic.deleteSurroundingText(1, 0);
+ // 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 (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
+ // reasons (there are race conditions with commits) but some applications are
+ // relying on this behavior so we continue to support it for older apps.
+ sendUpDownEnterOrBackspace(KeyEvent.KEYCODE_DEL, ic);
+ } else {
+ ic.deleteSurroundingText(1, 0);
+ }
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_deleteSurroundingText(1);
}
@@ -1836,8 +1882,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mExpectingUpdateSelection = true;
commitChosenWord(autoCorrection, LastComposedWord.COMMIT_TYPE_DECIDED_WORD,
separatorCodePoint);
- // Add the word to the user history dictionary
- addToUserHistoryDictionary(autoCorrection);
if (!typedWord.equals(autoCorrection) && null != ic) {
// This will make the correction flash for a short while as a visual clue
// to the user that auto-correction happened.
@@ -1915,8 +1959,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
LastComposedWord.NOT_A_SEPARATOR);
// Don't allow cancellation of manual pick
mLastComposedWord.deactivate();
- // Add the word to the user history dictionary
- addToUserHistoryDictionary(suggestion);
mSpaceState = SPACE_STATE_PHANTOM;
// TODO: is this necessary?
mKeyboardSwitcher.updateShiftState();
@@ -1959,31 +2001,33 @@ 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 bestWord, final int commitType,
+ private void commitChosenWord(final CharSequence chosenWord, final int commitType,
final int separatorCode) {
final InputConnection ic = getCurrentInputConnection();
if (ic != null) {
if (mSettingsValues.mEnableSuggestionSpanInsertion) {
final SuggestedWords suggestedWords = mSuggestionsView.getSuggestions();
ic.commitText(SuggestionSpanUtils.getTextWithSuggestionSpan(
- this, bestWord, suggestedWords, mIsMainDictionaryAvailable),
+ this, chosenWord, suggestedWords, mIsMainDictionaryAvailable),
1);
if (ProductionFlag.IS_EXPERIMENTAL) {
- ResearchLogger.latinIME_commitText(bestWord);
+ ResearchLogger.latinIME_commitText(chosenWord);
}
} else {
- ic.commitText(bestWord, 1);
+ ic.commitText(chosenWord, 1);
if (ProductionFlag.IS_EXPERIMENTAL) {
- ResearchLogger.latinIME_commitText(bestWord);
+ ResearchLogger.latinIME_commitText(chosenWord);
}
}
}
+ // Add the word to the user history dictionary
+ final CharSequence 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
// strings.
- mLastComposedWord = mWordComposer.commitWord(commitType, bestWord.toString(),
- separatorCode);
+ mLastComposedWord = mWordComposer.commitWord(commitType, chosenWord.toString(),
+ separatorCode, prevWord);
}
public void updateBigramPredictions() {
@@ -2023,15 +2067,15 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
setSuggestionStripShown(isSuggestionsStripVisible());
}
- private void addToUserHistoryDictionary(final CharSequence suggestion) {
- if (TextUtils.isEmpty(suggestion)) return;
+ private CharSequence addToUserHistoryDictionary(final CharSequence suggestion) {
+ if (TextUtils.isEmpty(suggestion)) return null;
// Only auto-add to dictionary if auto-correct is ON. Otherwise we'll be
// adding words in situations where the user or application really didn't
// want corrections enabled or learned.
if (!(mCorrectionMode == Suggest.CORRECTION_FULL
|| mCorrectionMode == Suggest.CORRECTION_FULL_BIGRAM)) {
- return;
+ return null;
}
if (mUserHistoryDictionary != null) {
@@ -2049,9 +2093,15 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
} else {
secondWord = suggestion.toString();
}
+ // We demote unrecognized word and words with 0-frequency (assuming they would be
+ // profanity etc.) by specifying them as "invalid".
+ final int maxFreq = AutoCorrection.getMaxFrequency(
+ mSuggest.getUnigramDictionaries(), suggestion);
mUserHistoryDictionary.addToUserHistory(null == prevWord ? null : prevWord.toString(),
- secondWord);
+ secondWord, maxFreq > 0);
+ return prevWord;
}
+ return null;
}
public boolean isCursorTouchingWord() {
@@ -2136,6 +2186,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// "ic" must not be null
private void revertCommit(final InputConnection ic) {
+ final CharSequence previousWord = mLastComposedWord.mPrevWord;
final String originallyTypedWord = mLastComposedWord.mTypedWord;
final CharSequence committedWord = mLastComposedWord.mCommittedWord;
final int cancelLength = committedWord.length();
@@ -2160,6 +2211,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_deleteSurroundingText(deleteLength);
}
+ if (!TextUtils.isEmpty(previousWord) && !TextUtils.isEmpty(committedWord)) {
+ mUserHistoryDictionary.cancelAddingUserHistory(
+ previousWord.toString(), committedWord.toString());
+ }
if (0 == separatorLength || mLastComposedWord.didCommitTypedWord()) {
// This is the case when we cancel a manual pick.
// We should restart suggestion on the word right away.