Merge remote-tracking branch 'goog/master' into mergescript

Conflicts:
	native/jni/Android.mk

Change-Id: I5e4657b0949274ce29315a2c9047db428d5455af
This commit is contained in:
Satoshi Kataoka 2012-07-06 16:35:27 +09:00
commit 46eea3c13f
15 changed files with 172 additions and 184 deletions

View file

@ -133,6 +133,17 @@
latin:keyIconPreview="!icon/tab_key_preview" latin:keyIconPreview="!icon/tab_key_preview"
latin:backgroundType="functional" /> latin:backgroundType="functional" />
</case> </case>
<case
latin:keyboardLayoutSetElement="alphabet|alphabetAutomaticShifted|alphabetShiftLocked"
latin:navigateNext="true"
>
<key-style
latin:styleName="tabKeyStyle"
latin:code="!code/key_action_next"
latin:keyIcon="!icon/tab_key"
latin:keyIconPreview="!icon/tab_key_preview"
latin:backgroundType="functional" />
</case>
<default> <default>
<key-style <key-style
latin:styleName="tabKeyStyle" latin:styleName="tabKeyStyle"

View file

@ -117,6 +117,17 @@
latin:keyLabelFlags="fontNormal|preserveCase" latin:keyLabelFlags="fontNormal|preserveCase"
latin:backgroundType="functional" /> latin:backgroundType="functional" />
</case> </case>
<case
latin:keyboardLayoutSetElement="alphabet|alphabetAutomaticShifted|alphabetShiftLocked"
latin:navigateNext="true"
>
<key-style
latin:styleName="tabKeyStyle"
latin:code="!code/key_action_next"
latin:keyLabel="!text/label_tab_key"
latin:keyLabelFlags="fontNormal|preserveCase"
latin:backgroundType="functional" />
</case>
<default> <default>
<key-style <key-style
latin:styleName="tabKeyStyle" latin:styleName="tabKeyStyle"

View file

@ -137,11 +137,13 @@ public class KeyboardId {
} }
public boolean navigateNext() { public boolean navigateNext() {
return (mEditorInfo.imeOptions & EditorInfo.IME_FLAG_NAVIGATE_NEXT) != 0; return (mEditorInfo.imeOptions & EditorInfo.IME_FLAG_NAVIGATE_NEXT) != 0
|| imeAction() == EditorInfo.IME_ACTION_NEXT;
} }
public boolean navigatePrevious() { public boolean navigatePrevious() {
return (mEditorInfo.imeOptions & EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS) != 0; return (mEditorInfo.imeOptions & EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS) != 0
|| imeAction() == EditorInfo.IME_ACTION_PREVIOUS;
} }
public boolean passwordInput() { public boolean passwordInput() {

View file

@ -29,7 +29,6 @@ public class InputAttributes {
final public boolean mInputTypeNoAutoCorrect; final public boolean mInputTypeNoAutoCorrect;
final public boolean mIsSettingsSuggestionStripOn; final public boolean mIsSettingsSuggestionStripOn;
final public boolean mApplicationSpecifiedCompletionOn; final public boolean mApplicationSpecifiedCompletionOn;
final public int mEditorAction;
public InputAttributes(final EditorInfo editorInfo, final boolean isFullscreenMode) { public InputAttributes(final EditorInfo editorInfo, final boolean isFullscreenMode) {
final int inputType = null != editorInfo ? editorInfo.inputType : 0; final int inputType = null != editorInfo ? editorInfo.inputType : 0;
@ -92,8 +91,6 @@ public class InputAttributes {
mApplicationSpecifiedCompletionOn = flagAutoComplete && isFullscreenMode; mApplicationSpecifiedCompletionOn = flagAutoComplete && isFullscreenMode;
} }
mEditorAction = (editorInfo == null) ? EditorInfo.IME_ACTION_UNSPECIFIED
: editorInfo.imeOptions & EditorInfo.IME_MASK_ACTION;
} }
@SuppressWarnings("unused") @SuppressWarnings("unused")

View file

@ -73,10 +73,10 @@ public class LastComposedWord {
} }
public boolean canRevertCommit() { public boolean canRevertCommit() {
return mActive && !TextUtils.isEmpty(mCommittedWord); return mActive && !TextUtils.isEmpty(mCommittedWord) && !didCommitTypedWord();
} }
public boolean didCommitTypedWord() { private boolean didCommitTypedWord() {
return TextUtils.equals(mTypedWord, mCommittedWord); return TextUtils.equals(mTypedWord, mCommittedWord);
} }

View file

@ -48,9 +48,7 @@ import android.util.Printer;
import android.view.KeyCharacterMap; import android.view.KeyCharacterMap;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.View; import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams; import android.view.ViewGroup.LayoutParams;
import android.view.ViewParent;
import android.view.Window; import android.view.Window;
import android.view.WindowManager; import android.view.WindowManager;
import android.view.inputmethod.CompletionInfo; import android.view.inputmethod.CompletionInfo;
@ -146,7 +144,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private LastComposedWord mLastComposedWord = LastComposedWord.NOT_A_COMPOSED_WORD; private LastComposedWord mLastComposedWord = LastComposedWord.NOT_A_COMPOSED_WORD;
private WordComposer mWordComposer = new WordComposer(); private WordComposer mWordComposer = new WordComposer();
private RichInputConnection mConnection = new RichInputConnection(); private RichInputConnection mConnection = new RichInputConnection(this);
// Keep track of the last selection range to decide if we need to show word alternatives // Keep track of the last selection range to decide if we need to show word alternatives
private static final int NOT_A_CURSOR_POSITION = -1; private static final int NOT_A_CURSOR_POSITION = -1;
@ -220,12 +218,13 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
} }
public void postUpdateSuggestions() { public void postUpdateSuggestions() {
removeMessages(MSG_UPDATE_SUGGESTIONS); cancelUpdateSuggestionStrip();
sendMessageDelayed(obtainMessage(MSG_UPDATE_SUGGESTIONS), mDelayUpdateSuggestions); sendMessageDelayed(obtainMessage(MSG_UPDATE_SUGGESTIONS), mDelayUpdateSuggestions);
} }
public void cancelUpdateSuggestions() { public void cancelUpdateSuggestionStrip() {
removeMessages(MSG_UPDATE_SUGGESTIONS); removeMessages(MSG_UPDATE_SUGGESTIONS);
removeMessages(MSG_SET_BIGRAM_PREDICTIONS);
} }
public boolean hasPendingUpdateSuggestions() { public boolean hasPendingUpdateSuggestions() {
@ -242,14 +241,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
} }
public void postUpdateBigramPredictions() { public void postUpdateBigramPredictions() {
removeMessages(MSG_SET_BIGRAM_PREDICTIONS); cancelUpdateSuggestionStrip();
sendMessageDelayed(obtainMessage(MSG_SET_BIGRAM_PREDICTIONS), mDelayUpdateSuggestions); sendMessageDelayed(obtainMessage(MSG_SET_BIGRAM_PREDICTIONS), mDelayUpdateSuggestions);
} }
public void cancelUpdateBigramPredictions() {
removeMessages(MSG_SET_BIGRAM_PREDICTIONS);
}
public void startDoubleSpacesTimer() { public void startDoubleSpacesTimer() {
mDoubleSpaceTimerStart = SystemClock.uptimeMillis(); mDoubleSpaceTimerStart = SystemClock.uptimeMillis();
} }
@ -542,7 +537,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (mDisplayOrientation != conf.orientation) { if (mDisplayOrientation != conf.orientation) {
mDisplayOrientation = conf.orientation; mDisplayOrientation = conf.orientation;
mHandler.startOrientationChanging(); mHandler.startOrientationChanging();
mConnection.beginBatchEdit(getCurrentInputConnection()); mConnection.beginBatchEdit();
commitTyped(LastComposedWord.NOT_A_SEPARATOR); commitTyped(LastComposedWord.NOT_A_SEPARATOR);
mConnection.finishComposingText(); mConnection.finishComposingText();
mConnection.endBatchEdit(); mConnection.endBatchEdit();
@ -739,7 +734,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
KeyboardView inputView = mKeyboardSwitcher.getKeyboardView(); KeyboardView inputView = mKeyboardSwitcher.getKeyboardView();
if (inputView != null) inputView.cancelAllMessages(); if (inputView != null) inputView.cancelAllMessages();
// Remove pending messages related to update suggestions // Remove pending messages related to update suggestions
mHandler.cancelUpdateSuggestions(); mHandler.cancelUpdateSuggestionStrip();
} }
@Override @Override
@ -1003,7 +998,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// the composing word, reset the last composed word, tell the inputconnection about it. // the composing word, reset the last composed word, tell the inputconnection about it.
private void resetEntireInputState() { private void resetEntireInputState() {
resetComposingState(true /* alsoResetLastComposedWord */); resetComposingState(true /* alsoResetLastComposedWord */);
updateSuggestionsOrPredictions(false /* isPredictions */); clearSuggestions();
mConnection.finishComposingText(); mConnection.finishComposingText();
} }
@ -1105,11 +1100,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
} }
@Override @Override
public boolean addWordToDictionary(String word) { public boolean addWordToUserDictionary(String word) {
mUserDictionary.addWordToUserDictionary(word, 128); mUserDictionary.addWordToUserDictionary(word, 128);
// Suggestion strip should be updated after the operation of adding word to the
// user dictionary
mHandler.postUpdateSuggestions();
return true; return true;
} }
@ -1218,7 +1210,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mDeleteCount = 0; mDeleteCount = 0;
} }
mLastKeyTime = when; mLastKeyTime = when;
mConnection.beginBatchEdit(getCurrentInputConnection()); mConnection.beginBatchEdit();
if (ProductionFlag.IS_EXPERIMENTAL) { if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_onCodeInput(primaryCode, x, y); ResearchLogger.latinIME_onCodeInput(primaryCode, x, y);
@ -1276,10 +1268,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
} }
break; break;
default: default:
if (primaryCode == Keyboard.CODE_TAB && mCurrentSettings.isEditorActionNext()) {
performEditorAction(EditorInfo.IME_ACTION_NEXT);
break;
}
mSpaceState = SPACE_STATE_NONE; mSpaceState = SPACE_STATE_NONE;
if (mCurrentSettings.isWordSeparator(primaryCode)) { if (mCurrentSettings.isWordSeparator(primaryCode)) {
didAutoCorrect = handleSeparator(primaryCode, x, y, spaceState); didAutoCorrect = handleSeparator(primaryCode, x, y, spaceState);
@ -1307,7 +1295,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
@Override @Override
public void onTextInput(CharSequence text) { public void onTextInput(CharSequence text) {
mConnection.beginBatchEdit(getCurrentInputConnection()); mConnection.beginBatchEdit();
commitTyped(LastComposedWord.NOT_A_SEPARATOR); commitTyped(LastComposedWord.NOT_A_SEPARATOR);
text = specificTldProcessingOnTextInput(text); text = specificTldProcessingOnTextInput(text);
if (SPACE_STATE_PHANTOM == mSpaceState) { if (SPACE_STATE_PHANTOM == mSpaceState) {
@ -1553,7 +1541,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
final int spaceState) { final int spaceState) {
// Should dismiss the "Touch again to save" message when handling separator // Should dismiss the "Touch again to save" message when handling separator
if (mSuggestionsView != null && mSuggestionsView.dismissAddToDictionaryHint()) { if (mSuggestionsView != null && mSuggestionsView.dismissAddToDictionaryHint()) {
mHandler.cancelUpdateBigramPredictions();
mHandler.postUpdateSuggestions(); mHandler.postUpdateSuggestions();
} }
@ -1592,7 +1579,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mHandler.startDoubleSpacesTimer(); mHandler.startDoubleSpacesTimer();
if (!mConnection.isCursorTouchingWord(mCurrentSettings)) { if (!mConnection.isCursorTouchingWord(mCurrentSettings)) {
mHandler.cancelUpdateSuggestions();
mHandler.postUpdateBigramPredictions(); mHandler.postUpdateBigramPredictions();
} }
} else { } else {
@ -1650,27 +1636,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
return mCurrentSettings.isSuggestionsRequested(mDisplayOrientation); return mCurrentSettings.isSuggestionsRequested(mDisplayOrientation);
} }
public void switchToKeyboardView() {
if (DEBUG) {
Log.d(TAG, "Switch to keyboard view.");
}
if (ProductionFlag.IS_EXPERIMENTAL) {
ResearchLogger.latinIME_switchToKeyboardView();
}
View v = mKeyboardSwitcher.getKeyboardView();
if (v != null) {
// Confirms that the keyboard view doesn't have parent view.
ViewParent p = v.getParent();
if (p != null && p instanceof ViewGroup) {
((ViewGroup) p).removeView(v);
}
setInputView(v);
}
setSuggestionStripShown(isSuggestionsStripVisible());
updateInputViewShown();
mHandler.postUpdateSuggestions();
}
public void clearSuggestions() { public void clearSuggestions() {
setSuggestions(SuggestedWords.EMPTY, false); setSuggestions(SuggestedWords.EMPTY, false);
setAutoCorrectionIndicator(false); setAutoCorrectionIndicator(false);
@ -1695,38 +1660,42 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
} }
public void updateSuggestionsOrPredictions(final boolean isPredictions) { public void updateSuggestionsOrPredictions(final boolean isPredictions) {
if (isPredictions) { mHandler.cancelUpdateSuggestionStrip();
updateBigramPredictions();
} else {
updateSuggestions();
}
}
private void updateSuggestions() {
mHandler.cancelUpdateSuggestions();
mHandler.cancelUpdateBigramPredictions();
// Check if we have a suggestion engine attached. // Check if we have a suggestion engine attached.
if ((mSuggest == null || !mCurrentSettings.isSuggestionsRequested(mDisplayOrientation))) { if (mSuggest == null || !mCurrentSettings.isSuggestionsRequested(mDisplayOrientation)) {
if (mWordComposer.isComposingWord()) { if (mWordComposer.isComposingWord()) {
Log.w(TAG, "Called updateSuggestions but suggestions were not requested!"); Log.w(TAG, "Called updateSuggestionsOrPredictions but suggestions were not "
+ "requested!");
mWordComposer.setAutoCorrection(mWordComposer.getTypedWord()); mWordComposer.setAutoCorrection(mWordComposer.getTypedWord());
} }
return; return;
} }
if (!mWordComposer.isComposingWord()) { final CharSequence typedWord;
// We are never called with an empty word composer, but if because of a bug final SuggestedWords suggestions;
// we are, what we should do here is just call updateBigramsPredictions. This will if (isPredictions || !mWordComposer.isComposingWord()) {
// update the predictions if the "predict next word" option is on, or display if (!mCurrentSettings.mBigramPredictionEnabled) {
// punctuation signs if it's off. setPunctuationSuggestions();
updateBigramPredictions();
return; return;
} }
typedWord = "";
suggestions = updateBigramPredictions(typedWord);
} else {
typedWord = mWordComposer.getTypedWord();
suggestions = updateSuggestions(typedWord);
}
if (null != suggestions && suggestions.size() > 0) {
showSuggestions(suggestions, typedWord);
} else {
clearSuggestions();
}
}
private SuggestedWords updateSuggestions(final CharSequence typedWord) {
// TODO: May need a better way of retrieving previous word // TODO: May need a better way of retrieving previous word
final CharSequence prevWord = mConnection.getPreviousWord(mCurrentSettings.mWordSeparators); final CharSequence prevWord = mConnection.getPreviousWord(mCurrentSettings.mWordSeparators);
final CharSequence typedWord = mWordComposer.getTypedWord();
// getSuggestedWords handles gracefully a null value of prevWord // getSuggestedWords handles gracefully a null value of prevWord
final SuggestedWords suggestedWords = mSuggest.getSuggestedWords(mWordComposer, final SuggestedWords suggestedWords = mSuggest.getSuggestedWords(mWordComposer,
prevWord, mKeyboardSwitcher.getKeyboard().getProximityInfo(), prevWord, mKeyboardSwitcher.getKeyboard().getProximityInfo(),
@ -1741,7 +1710,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (suggestedWords.size() > 1 || typedWord.length() == 1 if (suggestedWords.size() > 1 || typedWord.length() == 1
|| !suggestedWords.mTypedWordValid || !suggestedWords.mTypedWordValid
|| mSuggestionsView.isShowingAddToDictionaryHint()) { || mSuggestionsView.isShowingAddToDictionaryHint()) {
showSuggestions(suggestedWords, typedWord); return suggestedWords;
} else { } else {
SuggestedWords previousSuggestions = mSuggestionsView.getSuggestions(); SuggestedWords previousSuggestions = mSuggestionsView.getSuggestions();
if (previousSuggestions == mCurrentSettings.mSuggestPuncList) { if (previousSuggestions == mCurrentSettings.mSuggestPuncList) {
@ -1750,18 +1719,18 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
final ArrayList<SuggestedWords.SuggestedWordInfo> typedWordAndPreviousSuggestions = final ArrayList<SuggestedWords.SuggestedWordInfo> typedWordAndPreviousSuggestions =
SuggestedWords.getTypedWordAndPreviousSuggestions( SuggestedWords.getTypedWordAndPreviousSuggestions(
typedWord, previousSuggestions); typedWord, previousSuggestions);
final SuggestedWords obsoleteSuggestedWords = return new SuggestedWords(typedWordAndPreviousSuggestions,
new SuggestedWords(typedWordAndPreviousSuggestions,
false /* typedWordValid */, false /* typedWordValid */,
false /* hasAutoCorrectionCandidate */, false /* hasAutoCorrectionCandidate */,
false /* isPunctuationSuggestions */, false /* isPunctuationSuggestions */,
true /* isObsoleteSuggestions */, true /* isObsoleteSuggestions */,
false /* isPrediction */); false /* isPrediction */);
showSuggestions(obsoleteSuggestedWords, typedWord);
} }
} }
public void showSuggestions(final SuggestedWords suggestedWords, final CharSequence typedWord) { private void showSuggestions(final SuggestedWords suggestedWords,
final CharSequence typedWord) {
// This method is only ever called by updateSuggestions or updateBigramPredictions.
final CharSequence autoCorrection; final CharSequence autoCorrection;
if (suggestedWords.size() > 0) { if (suggestedWords.size() > 0) {
if (suggestedWords.mWillAutoCorrect) { if (suggestedWords.mWillAutoCorrect) {
@ -1782,7 +1751,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private void commitCurrentAutoCorrection(final int separatorCodePoint) { private void commitCurrentAutoCorrection(final int separatorCodePoint) {
// Complete any pending suggestions query first // Complete any pending suggestions query first
if (mHandler.hasPendingUpdateSuggestions()) { if (mHandler.hasPendingUpdateSuggestions()) {
mHandler.cancelUpdateSuggestions(); mHandler.cancelUpdateSuggestionStrip();
updateSuggestionsOrPredictions(false /* isPredictions */); updateSuggestionsOrPredictions(false /* isPredictions */);
} }
final CharSequence autoCorrection = mWordComposer.getAutoCorrectionOrNull(); final CharSequence autoCorrection = mWordComposer.getAutoCorrectionOrNull();
@ -1847,7 +1816,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mKeyboardSwitcher.updateShiftState(); mKeyboardSwitcher.updateShiftState();
resetComposingState(true /* alsoResetLastComposedWord */); resetComposingState(true /* alsoResetLastComposedWord */);
final CompletionInfo completionInfo = mApplicationSpecifiedCompletions[index]; final CompletionInfo completionInfo = mApplicationSpecifiedCompletions[index];
mConnection.beginBatchEdit(getCurrentInputConnection()); mConnection.beginBatchEdit();
mConnection.commitCompletion(completionInfo); mConnection.commitCompletion(completionInfo);
mConnection.endBatchEdit(); mConnection.endBatchEdit();
if (ProductionFlag.IS_EXPERIMENTAL) { if (ProductionFlag.IS_EXPERIMENTAL) {
@ -1890,20 +1859,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
Utils.Stats.onSeparator((char)Keyboard.CODE_SPACE, WordComposer.NOT_A_COORDINATE, Utils.Stats.onSeparator((char)Keyboard.CODE_SPACE, WordComposer.NOT_A_COORDINATE,
WordComposer.NOT_A_COORDINATE); WordComposer.NOT_A_COORDINATE);
if (!showingAddToDictionaryHint) { if (showingAddToDictionaryHint && mIsUserDictionaryAvailable) {
// If we're not showing the "Touch again to save", then show corrections again. mSuggestionsView.showAddToDictionaryHint(suggestion, mCurrentSettings.mHintToSaveText);
// In case the cursor position doesn't change, make sure we show the suggestions again.
updateSuggestionsOrPredictions(true /* isPredictions */);
// Updating the predictions right away may be slow and feel unresponsive on slower
// terminals. On the other hand if we just postUpdateBigramPredictions() it will
// take a noticeable delay to update them which may feel uneasy.
} else { } else {
if (mIsUserDictionaryAvailable) { // If we're not showing the "Touch again to save", then show predictions.
mSuggestionsView.showAddToDictionaryHint( mHandler.postUpdateBigramPredictions();
suggestion, mCurrentSettings.mHintToSaveText);
} else {
mHandler.postUpdateSuggestions();
}
} }
} }
@ -1928,44 +1888,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
separatorCode, prevWord); separatorCode, prevWord);
} }
public void updateBigramPredictions() { private SuggestedWords updateBigramPredictions(final CharSequence typedWord) {
mHandler.cancelUpdateSuggestions();
mHandler.cancelUpdateBigramPredictions();
if (mSuggest == null || !mCurrentSettings.isSuggestionsRequested(mDisplayOrientation)) {
if (mWordComposer.isComposingWord()) {
Log.w(TAG, "Called updateBigramPredictions but suggestions were not requested!");
mWordComposer.setAutoCorrection(mWordComposer.getTypedWord());
}
return;
}
if (!mCurrentSettings.mBigramPredictionEnabled) {
setPunctuationSuggestions();
return;
}
final SuggestedWords suggestedWords;
if (mCurrentSettings.mCorrectionEnabled) {
final CharSequence prevWord = mConnection.getThisWord(mCurrentSettings.mWordSeparators); final CharSequence prevWord = mConnection.getThisWord(mCurrentSettings.mWordSeparators);
if (!TextUtils.isEmpty(prevWord)) { return mSuggest.getSuggestedWords(mWordComposer,
suggestedWords = mSuggest.getSuggestedWords(mWordComposer,
prevWord, mKeyboardSwitcher.getKeyboard().getProximityInfo(), prevWord, mKeyboardSwitcher.getKeyboard().getProximityInfo(),
mCurrentSettings.mCorrectionEnabled, true); mCurrentSettings.mCorrectionEnabled, true);
} else {
suggestedWords = null;
}
} else {
suggestedWords = null;
}
if (null != suggestedWords && suggestedWords.size() > 0) {
// Explicitly supply an empty typed word (the no-second-arg version of
// showSuggestions will retrieve the word near the cursor, we don't want that here)
showSuggestions(suggestedWords, "");
} else {
clearSuggestions();
}
} }
public void setPunctuationSuggestions() { public void setPunctuationSuggestions() {
@ -2061,12 +1988,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mUserHistoryDictionary.cancelAddingUserHistory( mUserHistoryDictionary.cancelAddingUserHistory(
previousWord.toString(), committedWord.toString()); 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.
mWordComposer.resumeSuggestionOnLastComposedWord(mLastComposedWord);
mConnection.setComposingText(originallyTypedWord, 1);
} else {
mConnection.commitText(originallyTypedWord, 1); mConnection.commitText(originallyTypedWord, 1);
// Re-insert the separator // Re-insert the separator
sendKeyCodePoint(mLastComposedWord.mSeparatorCode); sendKeyCodePoint(mLastComposedWord.mSeparatorCode);
@ -2077,10 +1998,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
} }
// Don't restart suggestion yet. We'll restart if the user deletes the // Don't restart suggestion yet. We'll restart if the user deletes the
// separator. // separator.
}
mLastComposedWord = LastComposedWord.NOT_A_COMPOSED_WORD; mLastComposedWord = LastComposedWord.NOT_A_COMPOSED_WORD;
mHandler.cancelUpdateBigramPredictions(); // We have a separator between the word and the cursor: we should show predictions.
mHandler.postUpdateSuggestions(); mHandler.postUpdateBigramPredictions();
} }
public boolean isWordSeparator(int code) { public boolean isWordSeparator(int code) {

View file

@ -933,13 +933,6 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
EVENTKEYS_NULLVALUES); EVENTKEYS_NULLVALUES);
} }
private static final String[] EVENTKEYS_LATINIME_SWITCHTOKEYBOARDVIEW = {
"LatinIMESwitchToKeyboardView"
};
public static void latinIME_switchToKeyboardView() {
getInstance().enqueueEvent(EVENTKEYS_LATINIME_SWITCHTOKEYBOARDVIEW, EVENTKEYS_NULLVALUES);
}
private static final String[] EVENTKEYS_LATINKEYBOARDVIEW_ONLONGPRESS = { private static final String[] EVENTKEYS_LATINKEYBOARDVIEW_ONLONGPRESS = {
"LatinKeyboardViewOnLongPress" "LatinKeyboardViewOnLongPress"
}; };

View file

@ -16,6 +16,7 @@
package com.android.inputmethod.latin; package com.android.inputmethod.latin;
import android.inputmethodservice.InputMethodService;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import android.view.KeyEvent; import android.view.KeyEvent;
@ -41,16 +42,18 @@ public class RichInputConnection {
private static final Pattern spaceRegex = Pattern.compile("\\s+"); private static final Pattern spaceRegex = Pattern.compile("\\s+");
private static final int INVALID_CURSOR_POSITION = -1; private static final int INVALID_CURSOR_POSITION = -1;
private final InputMethodService mParent;
InputConnection mIC; InputConnection mIC;
int mNestLevel; int mNestLevel;
public RichInputConnection() { public RichInputConnection(final InputMethodService parent) {
mParent = parent;
mIC = null; mIC = null;
mNestLevel = 0; mNestLevel = 0;
} }
public void beginBatchEdit(final InputConnection newInputConnection) { public void beginBatchEdit() {
if (++mNestLevel == 1) { if (++mNestLevel == 1) {
mIC = newInputConnection; mIC = mParent.getCurrentInputConnection();
if (null != mIC) mIC.beginBatchEdit(); if (null != mIC) mIC.beginBatchEdit();
} else { } else {
if (DBG) { if (DBG) {
@ -84,16 +87,19 @@ public class RichInputConnection {
} }
public int getCursorCapsMode(final int inputType) { public int getCursorCapsMode(final int inputType) {
mIC = mParent.getCurrentInputConnection();
if (null == mIC) return Constants.TextUtils.CAP_MODE_OFF; if (null == mIC) return Constants.TextUtils.CAP_MODE_OFF;
return mIC.getCursorCapsMode(inputType); return mIC.getCursorCapsMode(inputType);
} }
public CharSequence getTextBeforeCursor(final int i, final int j) { public CharSequence getTextBeforeCursor(final int i, final int j) {
mIC = mParent.getCurrentInputConnection();
if (null != mIC) return mIC.getTextBeforeCursor(i, j); if (null != mIC) return mIC.getTextBeforeCursor(i, j);
return null; return null;
} }
public CharSequence getTextAfterCursor(final int i, final int j) { public CharSequence getTextAfterCursor(final int i, final int j) {
mIC = mParent.getCurrentInputConnection();
if (null != mIC) return mIC.getTextAfterCursor(i, j); if (null != mIC) return mIC.getTextAfterCursor(i, j);
return null; return null;
} }
@ -104,6 +110,7 @@ public class RichInputConnection {
} }
public void performEditorAction(final int actionId) { public void performEditorAction(final int actionId) {
mIC = mParent.getCurrentInputConnection();
if (null != mIC) mIC.performEditorAction(actionId); if (null != mIC) mIC.performEditorAction(actionId);
} }
@ -133,6 +140,7 @@ public class RichInputConnection {
} }
public CharSequence getPreviousWord(final String sentenceSeperators) { public CharSequence getPreviousWord(final String sentenceSeperators) {
mIC = mParent.getCurrentInputConnection();
//TODO: Should fix this. This could be slow! //TODO: Should fix this. This could be slow!
if (null == mIC) return null; if (null == mIC) return null;
CharSequence prev = mIC.getTextBeforeCursor(LOOKBACK_CHARACTER_NUM, 0); CharSequence prev = mIC.getTextBeforeCursor(LOOKBACK_CHARACTER_NUM, 0);
@ -194,6 +202,7 @@ public class RichInputConnection {
} }
public CharSequence getThisWord(String sentenceSeperators) { public CharSequence getThisWord(String sentenceSeperators) {
mIC = mParent.getCurrentInputConnection();
if (null == mIC) return null; if (null == mIC) return null;
final CharSequence prev = mIC.getTextBeforeCursor(LOOKBACK_CHARACTER_NUM, 0); final CharSequence prev = mIC.getTextBeforeCursor(LOOKBACK_CHARACTER_NUM, 0);
return getThisWord(prev, sentenceSeperators); return getThisWord(prev, sentenceSeperators);
@ -233,6 +242,7 @@ public class RichInputConnection {
} }
private int getCursorPosition() { private int getCursorPosition() {
mIC = mParent.getCurrentInputConnection();
if (null == mIC) return INVALID_CURSOR_POSITION; if (null == mIC) return INVALID_CURSOR_POSITION;
final ExtractedText extracted = mIC.getExtractedText(new ExtractedTextRequest(), 0); final ExtractedText extracted = mIC.getExtractedText(new ExtractedTextRequest(), 0);
if (extracted == null) { if (extracted == null) {
@ -250,6 +260,7 @@ public class RichInputConnection {
* @return a range containing the text surrounding the cursor * @return a range containing the text surrounding the cursor
*/ */
public Range getWordRangeAtCursor(String sep, int additionalPrecedingWordsCount) { public Range getWordRangeAtCursor(String sep, int additionalPrecedingWordsCount) {
mIC = mParent.getCurrentInputConnection();
if (mIC == null || sep == null) { if (mIC == null || sep == null) {
return null; return null;
} }

View file

@ -111,6 +111,10 @@ public class Settings extends InputMethodSettingsFragment
final Resources res = getResources(); final Resources res = getResources();
final Context context = getActivity(); final Context context = getActivity();
// When we are called from the Settings application but we are not already running, the
// {@link SubtypeLocale} class may not have been initialized. It is safe to call
// {@link SubtypeLocale#init(Context)} multiple times.
SubtypeLocale.init(context);
mVoicePreference = (ListPreference) findPreference(PREF_VOICE_MODE); mVoicePreference = (ListPreference) findPreference(PREF_VOICE_MODE);
mShowCorrectionSuggestionsPreference = mShowCorrectionSuggestionsPreference =
(ListPreference) findPreference(PREF_SHOW_SUGGESTIONS_SETTING); (ListPreference) findPreference(PREF_SHOW_SUGGESTIONS_SETTING);

View file

@ -224,10 +224,6 @@ public class SettingsValues {
return mInputAttributes.mApplicationSpecifiedCompletionOn; return mInputAttributes.mApplicationSpecifiedCompletionOn;
} }
public boolean isEditorActionNext() {
return mInputAttributes.mEditorAction == EditorInfo.IME_ACTION_NEXT;
}
public boolean isSuggestionsRequested(final int displayOrientation) { public boolean isSuggestionsRequested(final int displayOrientation) {
return mInputAttributes.mIsSettingsSuggestionStripOn return mInputAttributes.mIsSettingsSuggestionStripOn
&& (mCorrectionEnabled && (mCorrectionEnabled

View file

@ -41,6 +41,7 @@ public class SubtypeLocale {
public static final String QWERTY = "qwerty"; public static final String QWERTY = "qwerty";
public static final int UNKNOWN_KEYBOARD_LAYOUT = R.string.subtype_generic; public static final int UNKNOWN_KEYBOARD_LAYOUT = R.string.subtype_generic;
private static boolean sInitialized = false;
private static String[] sPredefinedKeyboardLayoutSet; private static String[] sPredefinedKeyboardLayoutSet;
// Keyboard layout to its display name map. // Keyboard layout to its display name map.
private static final HashMap<String, String> sKeyboardLayoutToDisplayNameMap = private static final HashMap<String, String> sKeyboardLayoutToDisplayNameMap =
@ -69,7 +70,10 @@ public class SubtypeLocale {
// Intentional empty constructor for utility class. // Intentional empty constructor for utility class.
} }
public static void init(Context context) { // Note that this initialization method can be called multiple times.
public static synchronized void init(Context context) {
if (sInitialized) return;
final Resources res = context.getResources(); final Resources res = context.getResources();
final String[] predefinedLayoutSet = res.getStringArray(R.array.predefined_layouts); final String[] predefinedLayoutSet = res.getStringArray(R.array.predefined_layouts);
@ -109,6 +113,8 @@ public class SubtypeLocale {
final String keyboardLayoutSet = keyboardLayoutSetMap[i + 1]; final String keyboardLayoutSet = keyboardLayoutSetMap[i + 1];
sLocaleAndExtraValueToKeyboardLayoutSetMap.put(key, keyboardLayoutSet); sLocaleAndExtraValueToKeyboardLayoutSetMap.put(key, keyboardLayoutSet);
} }
sInitialized = true;
} }
public static String[] getPredefinedKeyboardLayoutSet() { public static String[] getPredefinedKeyboardLayoutSet() {

View file

@ -71,7 +71,7 @@ import java.util.ArrayList;
public class SuggestionsView extends RelativeLayout implements OnClickListener, public class SuggestionsView extends RelativeLayout implements OnClickListener,
OnLongClickListener { OnLongClickListener {
public interface Listener { public interface Listener {
public boolean addWordToDictionary(String word); public boolean addWordToUserDictionary(String word);
public void pickSuggestionManually(int index, CharSequence word, int x, int y); public void pickSuggestionManually(int index, CharSequence word, int x, int y);
} }
@ -718,10 +718,6 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
mPreviewPopup.dismiss(); mPreviewPopup.dismiss();
} }
private void addToDictionary(CharSequence word) {
mListener.addWordToDictionary(word.toString());
}
private final KeyboardActionListener mMoreSuggestionsListener = private final KeyboardActionListener mMoreSuggestionsListener =
new KeyboardActionListener.Adapter() { new KeyboardActionListener.Adapter() {
@Override @Override
@ -863,7 +859,7 @@ public class SuggestionsView extends RelativeLayout implements OnClickListener,
@Override @Override
public void onClick(View view) { public void onClick(View view) {
if (mParams.isAddToDictionaryShowing(view)) { if (mParams.isAddToDictionaryShowing(view)) {
addToDictionary(mParams.getAddToDictionaryWord()); mListener.addWordToUserDictionary(mParams.getAddToDictionaryWord().toString());
clear(); clear();
return; return;
} }

View file

@ -68,9 +68,13 @@ endif # FLAG_DO_PROFILE
LOCAL_MODULE := libjni_latinime_common_static LOCAL_MODULE := libjni_latinime_common_static
LOCAL_MODULE_TAGS := optional LOCAL_MODULE_TAGS := optional
ifdef ANDROID_BUILD_TOP # In the platform build system
include external/stlport/libstlport.mk
else # In the unbundled build system
LOCAL_NDK_VERSION := 7 LOCAL_NDK_VERSION := 7
LOCAL_SDK_VERSION := 14 LOCAL_SDK_VERSION := 14
LOCAL_NDK_STL_VARIANT := stlport_static LOCAL_NDK_STL_VARIANT := stlport_static
endif
include $(BUILD_STATIC_LIBRARY) include $(BUILD_STATIC_LIBRARY)
###################################### ######################################
@ -92,9 +96,13 @@ endif # FLAG_DO_PROFILE
LOCAL_MODULE := libjni_latinime LOCAL_MODULE := libjni_latinime
LOCAL_MODULE_TAGS := optional LOCAL_MODULE_TAGS := optional
ifdef ANDROID_BUILD_TOP # In the platform build system
LOCAL_STATIC_LIBRARIES += libstlport_static
else # In the unbundled build system
LOCAL_NDK_VERSION := 7 LOCAL_NDK_VERSION := 7
LOCAL_SDK_VERSION := 14 LOCAL_SDK_VERSION := 14
LOCAL_NDK_STL_VARIANT := stlport_static LOCAL_NDK_STL_VARIANT := stlport_static
endif
include $(BUILD_SHARED_LIBRARY) include $(BUILD_SHARED_LIBRARY)

View file

@ -126,6 +126,26 @@ public class InputLogicTests extends InputTestsBase {
mTextView.getText().toString()); mTextView.getText().toString());
} }
public void testAutoCorrectWithSpaceThenRevert() {
final String STRING_TO_TYPE = "tgis ";
final String EXPECTED_RESULT = "tgis ";
type(STRING_TO_TYPE);
mLatinIME.onUpdateSelection(0, 0, STRING_TO_TYPE.length(), STRING_TO_TYPE.length(), -1, -1);
type(Keyboard.CODE_DELETE);
assertEquals("auto-correct with space then revert", EXPECTED_RESULT,
mTextView.getText().toString());
}
public void testAutoCorrectToSelfDoesNotRevert() {
final String STRING_TO_TYPE = "this ";
final String EXPECTED_RESULT = "this";
type(STRING_TO_TYPE);
mLatinIME.onUpdateSelection(0, 0, STRING_TO_TYPE.length(), STRING_TO_TYPE.length(), -1, -1);
type(Keyboard.CODE_DELETE);
assertEquals("auto-correct with space does not revert", EXPECTED_RESULT,
mTextView.getText().toString());
}
public void testDoubleSpace() { public void testDoubleSpace() {
final String STRING_TO_TYPE = "this "; final String STRING_TO_TYPE = "this ";
final String EXPECTED_RESULT = "this. "; final String EXPECTED_RESULT = "this. ";

View file

@ -16,6 +16,7 @@
package com.android.inputmethod.latin; package com.android.inputmethod.latin;
import android.inputmethodservice.InputMethodService;
import android.test.AndroidTestCase; import android.test.AndroidTestCase;
import android.view.inputmethod.ExtractedText; import android.view.inputmethod.ExtractedText;
import android.view.inputmethod.ExtractedTextRequest; import android.view.inputmethod.ExtractedTextRequest;
@ -83,6 +84,17 @@ public class RichInputConnectionTests extends AndroidTestCase {
} }
} }
private class MockInputMethodService extends InputMethodService {
InputConnection mInputConnection;
public void setInputConnection(final InputConnection inputConnection) {
mInputConnection = inputConnection;
}
@Override
public InputConnection getCurrentInputConnection() {
return mInputConnection;
}
}
/************************** Tests ************************/ /************************** Tests ************************/
/** /**
@ -122,14 +134,14 @@ public class RichInputConnectionTests extends AndroidTestCase {
*/ */
public void testGetWordRangeAtCursor() { public void testGetWordRangeAtCursor() {
ExtractedText et = new ExtractedText(); ExtractedText et = new ExtractedText();
final RichInputConnection ic = new RichInputConnection(); final MockInputMethodService mockInputMethodService = new MockInputMethodService();
InputConnection mockConnection; final RichInputConnection ic = new RichInputConnection(mockInputMethodService);
mockConnection = new MockConnection("word wo", "rd", et); mockInputMethodService.setInputConnection(new MockConnection("word wo", "rd", et));
et.startOffset = 0; et.startOffset = 0;
et.selectionStart = 7; et.selectionStart = 7;
Range r; Range r;
ic.beginBatchEdit(mockConnection); ic.beginBatchEdit();
// basic case // basic case
r = ic.getWordRangeAtCursor(" ", 0); r = ic.getWordRangeAtCursor(" ", 0);
assertEquals("word", r.mWord); assertEquals("word", r.mWord);
@ -140,37 +152,38 @@ public class RichInputConnectionTests extends AndroidTestCase {
ic.endBatchEdit(); ic.endBatchEdit();
// tab character instead of space // tab character instead of space
mockConnection = new MockConnection("one\tword\two", "rd", et); mockInputMethodService.setInputConnection(new MockConnection("one\tword\two", "rd", et));
ic.beginBatchEdit(mockConnection); ic.beginBatchEdit();
r = ic.getWordRangeAtCursor("\t", 1); r = ic.getWordRangeAtCursor("\t", 1);
ic.endBatchEdit(); ic.endBatchEdit();
assertEquals("word\tword", r.mWord); assertEquals("word\tword", r.mWord);
// only one word doesn't go too far // only one word doesn't go too far
mockConnection = new MockConnection("one\tword\two", "rd", et); mockInputMethodService.setInputConnection(new MockConnection("one\tword\two", "rd", et));
ic.beginBatchEdit(mockConnection); ic.beginBatchEdit();
r = ic.getWordRangeAtCursor("\t", 1); r = ic.getWordRangeAtCursor("\t", 1);
ic.endBatchEdit(); ic.endBatchEdit();
assertEquals("word\tword", r.mWord); assertEquals("word\tword", r.mWord);
// tab or space // tab or space
mockConnection = new MockConnection("one word\two", "rd", et); mockInputMethodService.setInputConnection(new MockConnection("one word\two", "rd", et));
ic.beginBatchEdit(mockConnection); ic.beginBatchEdit();
r = ic.getWordRangeAtCursor(" \t", 1); r = ic.getWordRangeAtCursor(" \t", 1);
ic.endBatchEdit(); ic.endBatchEdit();
assertEquals("word\tword", r.mWord); assertEquals("word\tword", r.mWord);
// tab or space multiword // tab or space multiword
mockConnection = new MockConnection("one word\two", "rd", et); mockInputMethodService.setInputConnection(new MockConnection("one word\two", "rd", et));
ic.beginBatchEdit(mockConnection); ic.beginBatchEdit();
r = ic.getWordRangeAtCursor(" \t", 2); r = ic.getWordRangeAtCursor(" \t", 2);
ic.endBatchEdit(); ic.endBatchEdit();
assertEquals("one word\tword", r.mWord); assertEquals("one word\tword", r.mWord);
// splitting on supplementary character // splitting on supplementary character
final String supplementaryChar = "\uD840\uDC8A"; final String supplementaryChar = "\uD840\uDC8A";
mockConnection = new MockConnection("one word" + supplementaryChar + "wo", "rd", et); mockInputMethodService.setInputConnection(
ic.beginBatchEdit(mockConnection); new MockConnection("one word" + supplementaryChar + "wo", "rd", et));
ic.beginBatchEdit();
r = ic.getWordRangeAtCursor(supplementaryChar, 0); r = ic.getWordRangeAtCursor(supplementaryChar, 0);
ic.endBatchEdit(); ic.endBatchEdit();
assertEquals("word", r.mWord); assertEquals("word", r.mWord);