aboutsummaryrefslogtreecommitdiffstats
path: root/java/src/com/android/inputmethod/latin/inputlogic
diff options
context:
space:
mode:
Diffstat (limited to 'java/src/com/android/inputmethod/latin/inputlogic')
-rw-r--r--java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java147
-rw-r--r--java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java27
2 files changed, 82 insertions, 92 deletions
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
index 968129a96..7222b73b3 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
@@ -46,6 +46,7 @@ import com.android.inputmethod.latin.WordComposer;
import com.android.inputmethod.latin.define.ProductionFlag;
import com.android.inputmethod.latin.settings.Settings;
import com.android.inputmethod.latin.settings.SettingsValues;
+import com.android.inputmethod.latin.settings.SpacingAndPunctuations;
import com.android.inputmethod.latin.suggestions.SuggestionStripView;
import com.android.inputmethod.latin.utils.AsyncResultHolder;
import com.android.inputmethod.latin.utils.CollectionUtils;
@@ -68,7 +69,8 @@ public final class InputLogic {
// TODO : Remove this member when we can.
private final LatinIME mLatinIME;
- private InputLogicHandler mInputLogicHandler;
+ // Never null.
+ private InputLogicHandler mInputLogicHandler = InputLogicHandler.NULL_HANDLER;
// TODO : make all these fields private as soon as possible.
// Current space state of the input method. This can be any of the above constants.
@@ -84,10 +86,6 @@ public final class InputLogic {
public final RichInputConnection mConnection;
public final RecapitalizeStatus mRecapitalizeStatus = new RecapitalizeStatus();
- // Keep track of the last selection range to decide if we need to show word alternatives
- public int mLastSelectionStart = Constants.NOT_A_CURSOR_POSITION;
- public int mLastSelectionEnd = Constants.NOT_A_CURSOR_POSITION;
-
private int mDeleteCount;
private long mLastKeyTime;
public final TreeSet<Long> mCurrentlyPressedHardwareKeys = CollectionUtils.newTreeSet();
@@ -104,7 +102,7 @@ public final class InputLogic {
mWordComposer = new WordComposer();
mEventInterpreter = new EventInterpreter(latinIME);
mConnection = new RichInputConnection(latinIME);
- mInputLogicHandler = null;
+ mInputLogicHandler = InputLogicHandler.NULL_HANDLER;
}
/**
@@ -127,11 +125,9 @@ public final class InputLogic {
mRecapitalizeStatus.deactivate();
mCurrentlyPressedHardwareKeys.clear();
mSuggestedWords = SuggestedWords.EMPTY;
- mLastSelectionStart = editorInfo.initialSelStart;
- mLastSelectionEnd = editorInfo.initialSelEnd;
// In some cases (namely, after rotation of the device) editorInfo.initialSelStart is lying
// so we try using some heuristics to find out about these and fix them.
- tryFixLyingCursorPosition();
+ mConnection.tryFixLyingCursorPosition();
mInputLogicHandler = new InputLogicHandler(mLatinIME, this);
}
@@ -144,7 +140,7 @@ public final class InputLogic {
}
resetComposingState(true /* alsoResetLastComposedWord */);
mInputLogicHandler.destroy();
- mInputLogicHandler = null;
+ mInputLogicHandler = InputLogicHandler.NULL_HANDLER;
}
/**
@@ -335,7 +331,8 @@ public final class InputLogic {
if (mWordComposer.isCursorFrontOrMiddleOfComposingWord()) {
// If we are in the middle of a recorrection, we need to commit the recorrection
// first so that we can insert the batch input at the current cursor position.
- resetEntireInputState(settingsValues, mLastSelectionStart, mLastSelectionEnd);
+ resetEntireInputState(settingsValues, mConnection.getExpectedSelectionStart(),
+ mConnection.getExpectedSelectionEnd());
} else if (wordComposerSize <= 1) {
// We auto-correct the previous (typed, not gestured) string iff it's one character
// long. The reason for this is, even in the middle of gesture typing, you'll still
@@ -369,7 +366,8 @@ public final class InputLogic {
mWordComposer.setCapitalizedModeAndPreviousWordAtStartComposingTime(
getActualCapsMode(settingsValues, keyboardSwitcher.getKeyboardShiftMode()),
// Prev word is 1st word before cursor
- getNthPreviousWordForSuggestion(settingsValues, 1 /* nthPreviousWord */));
+ getNthPreviousWordForSuggestion(
+ settingsValues.mSpacingAndPunctuations, 1 /* nthPreviousWord */));
}
/* The sequence number member is only used in onUpdateBatchInput. It is increased each time
@@ -463,7 +461,8 @@ public final class InputLogic {
if (mWordComposer.isCursorFrontOrMiddleOfComposingWord()) {
// If we are in the middle of a recorrection, we need to commit the recorrection
// first so that we can insert the character at the current cursor position.
- resetEntireInputState(settingsValues, mLastSelectionStart, mLastSelectionEnd);
+ resetEntireInputState(settingsValues, mConnection.getExpectedSelectionStart(),
+ mConnection.getExpectedSelectionEnd());
} else {
commitTyped(settingsValues, LastComposedWord.NOT_A_SEPARATOR);
}
@@ -513,7 +512,8 @@ public final class InputLogic {
if (mWordComposer.isCursorFrontOrMiddleOfComposingWord()) {
// If we are in the middle of a recorrection, we need to commit the recorrection
// first so that we can insert the character at the current cursor position.
- resetEntireInputState(settingsValues, mLastSelectionStart, mLastSelectionEnd);
+ resetEntireInputState(settingsValues, mConnection.getExpectedSelectionStart(),
+ mConnection.getExpectedSelectionEnd());
isComposingWord = false;
}
// We want to find out whether to start composing a new word with this character. If so,
@@ -555,7 +555,8 @@ public final class InputLogic {
// yet, so the word we want is the 1st word before the cursor.
mWordComposer.setCapitalizedModeAndPreviousWordAtStartComposingTime(
getActualCapsMode(settingsValues, keyboardSwitcher.getKeyboardShiftMode()),
- getNthPreviousWordForSuggestion(settingsValues, 1 /* nthPreviousWord */));
+ getNthPreviousWordForSuggestion(
+ settingsValues.mSpacingAndPunctuations, 1 /* nthPreviousWord */));
}
mConnection.setComposingText(getTextWithUnderline(
mWordComposer.getTypedWord()), 1);
@@ -599,7 +600,8 @@ public final class InputLogic {
if (mWordComposer.isCursorFrontOrMiddleOfComposingWord()) {
// If we are in the middle of a recorrection, we need to commit the recorrection
// first so that we can insert the separator at the current cursor position.
- resetEntireInputState(settingsValues, mLastSelectionStart, mLastSelectionEnd);
+ resetEntireInputState(settingsValues, mConnection.getExpectedSelectionStart(),
+ mConnection.getExpectedSelectionEnd());
}
// isComposingWord() may have changed since we stored wasComposing
if (mWordComposer.isComposingWord()) {
@@ -691,7 +693,8 @@ public final class InputLogic {
if (mWordComposer.isCursorFrontOrMiddleOfComposingWord()) {
// If we are in the middle of a recorrection, we need to commit the recorrection
// first so that we can remove the character at the current cursor position.
- resetEntireInputState(settingsValues, mLastSelectionStart, mLastSelectionEnd);
+ resetEntireInputState(settingsValues, mConnection.getExpectedSelectionStart(),
+ mConnection.getExpectedSelectionEnd());
// When we exit this if-clause, mWordComposer.isComposingWord() will return false.
}
if (mWordComposer.isComposingWord()) {
@@ -751,15 +754,12 @@ public final class InputLogic {
// No cancelling of commit/double space/swap: we have a regular backspace.
// We should backspace one char and restart suggestion if at the end of a word.
- if (mLastSelectionStart != mLastSelectionEnd) {
+ if (mConnection.hasSelection()) {
// If there is a selection, remove it.
- final int numCharsDeleted = mLastSelectionEnd - mLastSelectionStart;
- mConnection.setSelection(mLastSelectionEnd, mLastSelectionEnd);
- // Reset mLastSelectionEnd to mLastSelectionStart. This is what is supposed to
- // happen, and if it's wrong, the next call to onUpdateSelection will correct it,
- // but we want to set it right away to avoid it being used with the wrong values
- // later (typically, in a subsequent press on backspace).
- mLastSelectionEnd = mLastSelectionStart;
+ final int numCharsDeleted = mConnection.getExpectedSelectionEnd()
+ - mConnection.getExpectedSelectionStart();
+ mConnection.setSelection(mConnection.getExpectedSelectionEnd(),
+ mConnection.getExpectedSelectionEnd());
mConnection.deleteSurroundingText(numCharsDeleted, 0);
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
ResearchLogger.latinIME_handleBackspace(numCharsDeleted,
@@ -767,7 +767,7 @@ public final class InputLogic {
}
} else {
// There is no selection, just delete one character.
- if (Constants.NOT_A_CURSOR_POSITION == mLastSelectionEnd) {
+ if (Constants.NOT_A_CURSOR_POSITION == mConnection.getExpectedSelectionEnd()) {
// This should never happen.
Log.e(TAG, "Backspace when we don't know the selection position");
}
@@ -956,38 +956,32 @@ public final class InputLogic {
* @param settingsValues The current settings values.
*/
private void performRecapitalization(final SettingsValues settingsValues) {
- if (mLastSelectionStart == mLastSelectionEnd) {
+ if (!mConnection.hasSelection()) {
return; // No selection
}
// If we have a recapitalize in progress, use it; otherwise, create a new one.
if (!mRecapitalizeStatus.isActive()
- || !mRecapitalizeStatus.isSetAt(mLastSelectionStart, mLastSelectionEnd)) {
+ || !mRecapitalizeStatus.isSetAt(mConnection.getExpectedSelectionStart(),
+ mConnection.getExpectedSelectionEnd())) {
final CharSequence selectedText =
mConnection.getSelectedText(0 /* flags, 0 for no styles */);
if (TextUtils.isEmpty(selectedText)) return; // Race condition with the input connection
- mRecapitalizeStatus.initialize(mLastSelectionStart, mLastSelectionEnd,
- selectedText.toString(),
+ mRecapitalizeStatus.initialize(mConnection.getExpectedSelectionStart(),
+ mConnection.getExpectedSelectionEnd(), selectedText.toString(),
settingsValues.mLocale, settingsValues.mSpacingAndPunctuations.mWordSeparators);
// We trim leading and trailing whitespace.
mRecapitalizeStatus.trim();
- // Trimming the object may have changed the length of the string, and we need to
- // reposition the selection handles accordingly. As this result in an IPC call,
- // only do it if it's actually necessary, in other words if the recapitalize status
- // is not set at the same place as before.
- if (!mRecapitalizeStatus.isSetAt(mLastSelectionStart, mLastSelectionEnd)) {
- mLastSelectionStart = mRecapitalizeStatus.getNewCursorStart();
- mLastSelectionEnd = mRecapitalizeStatus.getNewCursorEnd();
- }
}
mConnection.finishComposingText();
mRecapitalizeStatus.rotate();
- final int numCharsDeleted = mLastSelectionEnd - mLastSelectionStart;
- mConnection.setSelection(mLastSelectionEnd, mLastSelectionEnd);
+ final int numCharsDeleted = mConnection.getExpectedSelectionEnd()
+ - mConnection.getExpectedSelectionStart();
+ mConnection.setSelection(mConnection.getExpectedSelectionEnd(),
+ mConnection.getExpectedSelectionEnd());
mConnection.deleteSurroundingText(numCharsDeleted, 0);
mConnection.commitText(mRecapitalizeStatus.getRecapitalizedString(), 0);
- mLastSelectionStart = mRecapitalizeStatus.getNewCursorStart();
- mLastSelectionEnd = mRecapitalizeStatus.getNewCursorEnd();
- mConnection.setSelection(mLastSelectionStart, mLastSelectionEnd);
+ mConnection.setSelection(mRecapitalizeStatus.getNewCursorStart(),
+ mRecapitalizeStatus.getNewCursorEnd());
}
private void performAdditionToUserHistoryDictionary(final SettingsValues settingsValues,
@@ -1068,10 +1062,10 @@ public final class InputLogic {
// how to segment them yet.
if (!settingsValues.mSpacingAndPunctuations.mCurrentLanguageHasSpaces) return;
// If the cursor is not touching a word, or if there is a selection, return right away.
- if (mLastSelectionStart != mLastSelectionEnd) return;
+ if (mConnection.hasSelection()) return;
// If we don't know the cursor location, return.
- if (mLastSelectionStart < 0) return;
- final int expectedCursorPosition = mLastSelectionStart + offset; // We know Start == End
+ if (mConnection.getExpectedSelectionStart() < 0) return;
+ final int expectedCursorPosition = mConnection.getExpectedSelectionStart();
if (!mConnection.isCursorTouchingWord(settingsValues)) return;
final TextRange range = mConnection.getWordRangeAtCursor(
settingsValues.mSpacingAndPunctuations.mWordSeparators,
@@ -1107,7 +1101,7 @@ public final class InputLogic {
}
}
mWordComposer.setComposingWord(typedWord,
- getNthPreviousWordForSuggestion(settingsValues,
+ getNthPreviousWordForSuggestion(settingsValues.mSpacingAndPunctuations,
// We want the previous word for suggestion. If we have chars in the word
// before the cursor, then we want the word before that, hence 2; otherwise,
// we want the word immediately before the cursor, hence 1.
@@ -1285,7 +1279,8 @@ public final class InputLogic {
public int getCurrentRecapitalizeState() {
if (!mRecapitalizeStatus.isActive()
- || !mRecapitalizeStatus.isSetAt(mLastSelectionStart, mLastSelectionEnd)) {
+ || !mRecapitalizeStatus.isSetAt(mConnection.getExpectedSelectionStart(),
+ mConnection.getExpectedSelectionEnd())) {
// Not recapitalizing at the moment
return RecapitalizeStatus.NOT_A_RECAPITALIZE_MODE;
}
@@ -1301,17 +1296,17 @@ public final class InputLogic {
/**
* Get the nth previous word before the cursor as context for the suggestion process.
- * @param currentSettings the current settings values.
+ * @param spacingAndPunctuations the current spacing and punctuations settings.
* @param nthPreviousWord reverse index of the word to get (1-indexed)
* @return the nth previous word before the cursor.
*/
// TODO: Make this private
- public String getNthPreviousWordForSuggestion(final SettingsValues currentSettings,
- final int nthPreviousWord) {
- if (currentSettings.mSpacingAndPunctuations.mCurrentLanguageHasSpaces) {
+ public String getNthPreviousWordForSuggestion(
+ final SpacingAndPunctuations spacingAndPunctuations, final int nthPreviousWord) {
+ if (spacingAndPunctuations.mCurrentLanguageHasSpaces) {
// If we are typing in a language with spaces we can just look up the previous
// word from textview.
- return mConnection.getNthPreviousWord(currentSettings, nthPreviousWord);
+ return mConnection.getNthPreviousWord(spacingAndPunctuations, nthPreviousWord);
} else {
return LastComposedWord.NOT_A_COMPOSED_WORD == mLastComposedWord ? null
: mLastComposedWord.mCommittedWord;
@@ -1638,7 +1633,8 @@ public final class InputLogic {
// of the auto-correction flash. At this moment, the "typedWord" argument is
// ignored by TextView.
mConnection.commitCorrection(
- new CorrectionInfo(mLastSelectionEnd - typedWord.length(),
+ new CorrectionInfo(
+ mConnection.getExpectedSelectionEnd() - typedWord.length(),
typedWord, autoCorrection));
}
}
@@ -1659,7 +1655,8 @@ public final class InputLogic {
mConnection.commitText(SuggestionSpanUtils.getTextWithSuggestionSpan(mLatinIME, chosenWord,
suggestedWords), 1);
// TODO: we pass 2 here, but would it be better to move this above and pass 1 instead?
- final String prevWord = mConnection.getNthPreviousWord(settingsValues, 2);
+ final String prevWord = mConnection.getNthPreviousWord(
+ settingsValues.mSpacingAndPunctuations, 2);
// Add the word to the user history dictionary
performAdditionToUserHistoryDictionary(settingsValues, chosenWord, prevWord);
// TODO: figure out here if this is an auto-correct or if the best word is actually
@@ -1686,41 +1683,6 @@ public final class InputLogic {
}
/**
- * Try to get the text from the editor to expose lies the framework may have been
- * telling us. Concretely, when the device rotates, the frameworks tells us about where the
- * cursor used to be initially in the editor at the time it first received the focus; this
- * may be completely different from the place it is upon rotation. Since we don't have any
- * means to get the real value, try at least to ask the text view for some characters and
- * detect the most damaging cases: when the cursor position is declared to be much smaller
- * than it really is.
- */
- private void tryFixLyingCursorPosition() {
- final CharSequence textBeforeCursor = mConnection.getTextBeforeCursor(
- Constants.EDITOR_CONTENTS_CACHE_SIZE, 0);
- if (null == textBeforeCursor) {
- mLastSelectionStart = mLastSelectionEnd = Constants.NOT_A_CURSOR_POSITION;
- } else {
- final int textLength = textBeforeCursor.length();
- if (textLength > mLastSelectionStart
- || (textLength < Constants.EDITOR_CONTENTS_CACHE_SIZE
- && mLastSelectionStart < Constants.EDITOR_CONTENTS_CACHE_SIZE)) {
- // It should not be possible to have only one of those variables be
- // NOT_A_CURSOR_POSITION, so if they are equal, either the selection is zero-sized
- // (simple cursor, no selection) or there is no cursor/we don't know its pos
- final boolean wasEqual = mLastSelectionStart == mLastSelectionEnd;
- mLastSelectionStart = textLength;
- // We can't figure out the value of mLastSelectionEnd :(
- // But at least if it's smaller than mLastSelectionStart something is wrong,
- // and if they used to be equal we also don't want to make it look like there is a
- // selection.
- if (wasEqual || mLastSelectionStart > mLastSelectionEnd) {
- mLastSelectionEnd = mLastSelectionStart;
- }
- }
- }
- }
-
- /**
* Retry resetting caches in the rich input connection.
*
* When the editor can't be accessed we can't reset the caches, so we schedule a retry.
@@ -1737,7 +1699,8 @@ public final class InputLogic {
// TODO: remove these arguments
final KeyboardSwitcher keyboardSwitcher, final LatinIME.UIHandler handler) {
if (!mConnection.resetCachesUponCursorMoveAndReturnSuccess(
- mLastSelectionStart, mLastSelectionEnd, false)) {
+ mConnection.getExpectedSelectionStart(), mConnection.getExpectedSelectionEnd(),
+ false)) {
if (0 < remainingTries) {
handler.postResetCaches(tryResumeSuggestions, remainingTries - 1);
return;
@@ -1745,7 +1708,7 @@ public final class InputLogic {
// If remainingTries is 0, we should stop waiting for new tries, but it's still
// better to load the keyboard (less things will be broken).
}
- tryFixLyingCursorPosition();
+ mConnection.tryFixLyingCursorPosition();
keyboardSwitcher.loadKeyboard(getCurrentInputEditorInfo(), settingsValues);
if (tryResumeSuggestions) {
handler.postResumeSuggestions();
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java
index 3258dcdfb..ea010b6f5 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java
@@ -40,6 +40,33 @@ public class InputLogicHandler implements Handler.Callback {
private static final int MSG_GET_SUGGESTED_WORDS = 1;
+ // A handler that never does anything. This is used for cases where events come before anything
+ // is initialized, though probably only the monkey can actually do this.
+ public static final InputLogicHandler NULL_HANDLER = new InputLogicHandler() {
+ @Override
+ public void destroy() {}
+ @Override
+ public boolean handleMessage(final Message msg) { return true; }
+ @Override
+ public void onStartBatchInput() {}
+ @Override
+ public void onUpdateBatchInput(final InputPointers batchPointers,
+ final int sequenceNumber) {}
+ @Override
+ public void onCancelBatchInput() {}
+ @Override
+ public void onEndBatchInput(final InputPointers batchPointers, final int sequenceNumber) {}
+ @Override
+ public void getSuggestedWords(final int sessionId, final int sequenceNumber,
+ final OnGetSuggestedWordsCallback callback) {}
+ };
+
+ private InputLogicHandler() {
+ mNonUIThreadHandler = null;
+ mLatinIME = null;
+ mInputLogic = null;
+ }
+
public InputLogicHandler(final LatinIME latinIME, final InputLogic inputLogic) {
final HandlerThread handlerThread = new HandlerThread(
InputLogicHandler.class.getSimpleName());