aboutsummaryrefslogtreecommitdiffstats
path: root/java/src
diff options
context:
space:
mode:
Diffstat (limited to 'java/src')
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java103
-rw-r--r--java/src/com/android/inputmethod/latin/SettingsValues.java36
-rw-r--r--java/src/com/android/inputmethod/latin/UserDictionary.java5
3 files changed, 77 insertions, 67 deletions
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index aef248e19..a208a8748 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -165,8 +165,8 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
// Double space: the state where the user pressed space twice quickly, which LatinIME
// resolved as period-space. Undoing this converts the period to a space.
private static final int SPACE_STATE_DOUBLE = 1;
- // Swap punctuation: the state where a (weak or magic) space and a punctuation from the
- // suggestion strip have just been swapped. Undoing this swaps them back.
+ // Swap punctuation: the state where a weak space and a punctuation from the suggestion strip
+ // have just been swapped. Undoing this swaps them back; the space is still considered weak.
private static final int SPACE_STATE_SWAP_PUNCTUATION = 2;
// Weak space: a space that should be swapped only by suggestion strip punctuation. Weak
// spaces happen when the user presses space, accepting the current suggestion (whether
@@ -761,14 +761,15 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
// Most such things we decide below in initializeInputAttributesAndGetMode, but we need to
// know now whether this is a password text field, because we need to know now whether we
// want to enable the voice button.
- final VoiceProxy voiceIme = mVoiceProxy;
final int inputType = (editorInfo != null) ? editorInfo.inputType : 0;
- voiceIme.resetVoiceStates(InputTypeCompatUtils.isPasswordInputType(inputType)
+ mVoiceProxy.resetVoiceStates(InputTypeCompatUtils.isPasswordInputType(inputType)
|| InputTypeCompatUtils.isVisiblePasswordInputType(inputType));
// The EditorInfo might have a flag that affects fullscreen mode.
// Note: This call should be done by InputMethodService?
updateFullscreenMode();
+ mLastSelectionStart = editorInfo.initialSelStart;
+ mLastSelectionEnd = editorInfo.initialSelEnd;
mInputAttributes = new InputAttributes(editorInfo, isFullscreenMode());
mApplicationSpecifiedCompletions = null;
@@ -805,7 +806,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
mSettingsValues.mKeyPreviewPopupDismissDelay);
inputView.setProximityCorrectionEnabled(true);
- voiceIme.onStartInputView(inputView.getWindowToken());
+ mVoiceProxy.onStartInputView(inputView.getWindowToken());
if (TRACE) Debug.startMethodTracing("/data/trace/latinime");
}
@@ -848,9 +849,9 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
@Override
public void onUpdateSelection(int oldSelStart, int oldSelEnd,
int newSelStart, int newSelEnd,
- int candidatesStart, int candidatesEnd) {
+ int composingSpanStart, int composingSpanEnd) {
super.onUpdateSelection(oldSelStart, oldSelEnd, newSelStart, newSelEnd,
- candidatesStart, candidatesEnd);
+ composingSpanStart, composingSpanEnd);
if (DEBUG) {
Log.i(TAG, "onUpdateSelection: oss=" + oldSelStart
@@ -859,44 +860,43 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
+ ", lse=" + mLastSelectionEnd
+ ", nss=" + newSelStart
+ ", nse=" + newSelEnd
- + ", cs=" + candidatesStart
- + ", ce=" + candidatesEnd);
+ + ", cs=" + composingSpanStart
+ + ", ce=" + composingSpanEnd);
}
mVoiceProxy.setCursorAndSelection(newSelEnd, newSelStart);
- // If the current selection in the text view changes, we should
- // clear whatever candidate text we have.
- final boolean selectionChanged = (newSelStart != candidatesEnd
- || newSelEnd != candidatesEnd) && mLastSelectionStart != newSelStart;
- final boolean candidatesCleared = candidatesStart == -1 && candidatesEnd == -1;
+ // TODO: refactor the following code to be less contrived.
+ // "newSelStart != composingSpanEnd" || "newSelEnd != composingSpanEnd" means
+ // that the cursor is not at the end of the composing span, or there is a selection.
+ // "mLastSelectionStart != newSelStart" means that the cursor is not in the same place
+ // as last time we were called (if there is a selection, it means the start hasn't
+ // changed, so it's the end that did).
+ final boolean selectionChanged = (newSelStart != composingSpanEnd
+ || newSelEnd != composingSpanEnd) && mLastSelectionStart != newSelStart;
+ // if composingSpanStart and composingSpanEnd are -1, it means there is no composing
+ // span in the view - we can use that to narrow down whether the cursor was moved
+ // by us or not. If we are composing a word but there is no composing span, then
+ // we know for sure the cursor moved while we were composing and we should reset
+ // the state.
+ final boolean noComposingSpan = composingSpanStart == -1 && composingSpanEnd == -1;
if (!mExpectingUpdateSelection) {
// TAKE CARE: there is a race condition when we enter this test even when the user
// did not explicitly move the cursor. This happens when typing fast, where two keys
// turn this flag on in succession and both onUpdateSelection() calls arrive after
// the second one - the first call successfully avoids this test, but the second one
- // enters. For the moment we rely on candidatesCleared to further reduce the impact.
+ // enters. For the moment we rely on noComposingSpan to further reduce the impact.
+ // 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.
// 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())
- || mVoiceProxy.isVoiceInputHighlighted())
- && (selectionChanged || candidatesCleared)) {
- resetComposingState(true /* alsoResetLastComposedWord */);
- updateSuggestions();
- final InputConnection ic = getCurrentInputConnection();
- if (ic != null) {
- ic.finishComposingText();
- }
- mComposingStateManager.onFinishComposingText();
- mVoiceProxy.setVoiceInputHighlighted(false);
- } else if (!mWordComposer.isComposingWord()) {
- // TODO: is the following reset still needed, given that we are not composing
- // a word?
- resetComposingState(true /* alsoResetLastComposedWord */);
- updateSuggestions();
+ if ((!mWordComposer.isComposingWord()) || selectionChanged || noComposingSpan) {
+ resetEntireInputState();
}
mHandler.postUpdateShiftState();
@@ -1106,6 +1106,20 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
return super.onKeyUp(keyCode, event);
}
+ // This will reset the whole input state to the starting state. It will clear
+ // the composing word, reset the last composed word, tell the inputconnection
+ // and the composingStateManager about it.
+ private void resetEntireInputState() {
+ resetComposingState(true /* alsoResetLastComposedWord */);
+ updateSuggestions();
+ final InputConnection ic = getCurrentInputConnection();
+ if (ic != null) {
+ ic.finishComposingText();
+ }
+ mComposingStateManager.onFinishComposingText();
+ mVoiceProxy.setVoiceInputHighlighted(false);
+ }
+
private void resetComposingState(final boolean alsoResetLastComposedWord) {
mWordComposer.reset();
if (alsoResetLastComposedWord)
@@ -1457,18 +1471,10 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
ic.deleteSurroundingText(lengthToDelete, 0);
} else {
if (NOT_A_CURSOR_POSITION == mLastSelectionEnd) {
- // We don't know whether there is a selection or not. We just send a false
- // hardware key event and let TextView sort it out for us. The problem
- // here is, this is asynchronous with respect to the input connection
- // batch edit, so it may flicker. But this only ever happens if backspace
- // is pressed just after the IME is invoked, and then again only once.
- // TODO: add an API call that gets the selection indices. This is available
- // to the IME in the general case via onUpdateSelection anyway, and would
- // allow us to remove this race condition.
- sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL);
- } else {
- ic.deleteSurroundingText(1, 0);
+ // This should never happen.
+ Log.e(TAG, "Backspace when we don't know the selection position");
}
+ ic.deleteSurroundingText(1, 0);
if (mDeleteCount > DELETE_ACCELERATE_AT) {
ic.deleteSurroundingText(1, 0);
}
@@ -1489,10 +1495,10 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
} else if ((SPACE_STATE_WEAK == spaceState
|| SPACE_STATE_SWAP_PUNCTUATION == spaceState)
&& isFromSuggestionStrip) {
- if (mSettingsValues.isMagicSpaceSwapper(code)) {
+ if (mSettingsValues.isWeakSpaceSwapper(code)) {
return true;
} else {
- if (mSettingsValues.isMagicSpaceStripper(code)) {
+ if (mSettingsValues.isWeakSpaceStripper(code)) {
removeTrailingSpaceWhileInBatchEdit(ic);
}
return false;
@@ -1565,6 +1571,15 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
swapSwapperAndSpaceWhileInBatchEdit(ic);
mSpaceState = SPACE_STATE_WEAK;
}
+ // Some characters are not word separators, yet they don't start a new
+ // composing span. For these, we haven't changed the suggestion strip, and
+ // if the "add to dictionary" hint is shown, we should do so now. Examples of
+ // such characters include single quote, dollar, and others; the exact list is
+ // the list of characters for which we enter handleCharacterWhileInBatchEdit
+ // that don't match the test if ((isAlphabet...)) at the top of this method.
+ if (null != mSuggestionsView && mSuggestionsView.dismissAddToDictionaryHint()) {
+ mHandler.postUpdateBigramPredictions();
+ }
}
Utils.Stats.onNonSeparator((char)primaryCode, x, y);
}
diff --git a/java/src/com/android/inputmethod/latin/SettingsValues.java b/java/src/com/android/inputmethod/latin/SettingsValues.java
index 7a43cb827..d123b608f 100644
--- a/java/src/com/android/inputmethod/latin/SettingsValues.java
+++ b/java/src/com/android/inputmethod/latin/SettingsValues.java
@@ -35,8 +35,8 @@ public class SettingsValues {
// From resources:
public final int mDelayUpdateOldSuggestions;
- public final String mMagicSpaceStrippers;
- public final String mMagicSpaceSwappers;
+ public final String mWeakSpaceStrippers;
+ public final String mWeakSpaceSwappers;
private final String mSuggestPuncs;
public final SuggestedWords mSuggestPuncList;
public final SuggestedWords mSuggestPuncOutputTextList;
@@ -89,14 +89,14 @@ public class SettingsValues {
// Get the resources
mDelayUpdateOldSuggestions = res.getInteger(R.integer.config_delay_update_old_suggestions);
- mMagicSpaceStrippers = res.getString(R.string.magic_space_stripping_symbols);
- mMagicSpaceSwappers = res.getString(R.string.magic_space_swapping_symbols);
+ mWeakSpaceStrippers = res.getString(R.string.weak_space_stripping_symbols);
+ mWeakSpaceSwappers = res.getString(R.string.weak_space_swapping_symbols);
if (LatinImeLogger.sDBG) {
- final int length = mMagicSpaceStrippers.length();
- for (int i = 0; i < length; i = mMagicSpaceStrippers.offsetByCodePoints(i, 1)) {
- if (isMagicSpaceSwapper(mMagicSpaceStrippers.codePointAt(i))) {
- throw new RuntimeException("Char code " + mMagicSpaceStrippers.codePointAt(i)
- + " is both a magic space swapper and stripper.");
+ final int length = mWeakSpaceStrippers.length();
+ for (int i = 0; i < length; i = mWeakSpaceStrippers.offsetByCodePoints(i, 1)) {
+ if (isWeakSpaceSwapper(mWeakSpaceStrippers.codePointAt(i))) {
+ throw new RuntimeException("Char code " + mWeakSpaceStrippers.codePointAt(i)
+ + " is both a weak space swapper and stripper.");
}
}
}
@@ -107,7 +107,7 @@ public class SettingsValues {
mSuggestPuncOutputTextList = createSuggestPuncOutputTextList(suggestPuncsSpec);
mSymbolsExcludedFromWordSeparators =
res.getString(R.string.symbols_excluded_from_word_separators);
- mWordSeparators = createWordSeparators(mMagicSpaceStrippers, mMagicSpaceSwappers,
+ mWordSeparators = createWordSeparators(mWeakSpaceStrippers, mWeakSpaceSwappers,
mSymbolsExcludedFromWordSeparators, res);
mHintToSaveText = context.getText(R.string.hint_add_to_dictionary);
@@ -188,11 +188,11 @@ public class SettingsValues {
return builder.setIsPunctuationSuggestions().build();
}
- private static String createWordSeparators(final String magicSpaceStrippers,
- final String magicSpaceSwappers, final String symbolsExcludedFromWordSeparators,
+ private static String createWordSeparators(final String weakSpaceStrippers,
+ final String weakSpaceSwappers, final String symbolsExcludedFromWordSeparators,
final Resources res) {
- String wordSeparators = magicSpaceStrippers + magicSpaceSwappers
- + res.getString(R.string.magic_space_promoting_symbols);
+ String wordSeparators = weakSpaceStrippers + weakSpaceSwappers
+ + res.getString(R.string.weak_space_promoting_symbols);
for (int i = symbolsExcludedFromWordSeparators.length() - 1; i >= 0; --i) {
wordSeparators = wordSeparators.replace(
symbolsExcludedFromWordSeparators.substring(i, i + 1), "");
@@ -215,14 +215,14 @@ public class SettingsValues {
return mSymbolsExcludedFromWordSeparators.contains(String.valueOf((char)code));
}
- public boolean isMagicSpaceStripper(int code) {
+ public boolean isWeakSpaceStripper(int code) {
// TODO: this does not work if the code does not fit in a char
- return mMagicSpaceStrippers.contains(String.valueOf((char)code));
+ return mWeakSpaceStrippers.contains(String.valueOf((char)code));
}
- public boolean isMagicSpaceSwapper(int code) {
+ public boolean isWeakSpaceSwapper(int code) {
// TODO: this does not work if the code does not fit in a char
- return mMagicSpaceSwappers.contains(String.valueOf((char)code));
+ return mWeakSpaceSwappers.contains(String.valueOf((char)code));
}
private static boolean isAutoCorrectEnabled(final Resources resources,
diff --git a/java/src/com/android/inputmethod/latin/UserDictionary.java b/java/src/com/android/inputmethod/latin/UserDictionary.java
index 6d6296e10..51b993343 100644
--- a/java/src/com/android/inputmethod/latin/UserDictionary.java
+++ b/java/src/com/android/inputmethod/latin/UserDictionary.java
@@ -165,17 +165,12 @@ public class UserDictionary extends ExpandableDictionary {
// Safeguard against adding long words. Can cause stack overflow.
if (word.length() >= getMaxWordLength()) return;
- super.addWord(word, frequency);
-
// TODO: Add an argument to the intent to specify the frequency.
Intent intent = new Intent(ACTION_USER_DICTIONARY_INSERT);
intent.putExtra(Words.WORD, word);
intent.putExtra(Words.LOCALE, mLocale);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getContext().startActivity(intent);
-
- // In case the above does a synchronous callback of the change observer
- setRequiresReload(false);
}
@Override