aboutsummaryrefslogtreecommitdiffstats
path: root/java/src/com
diff options
context:
space:
mode:
Diffstat (limited to 'java/src/com')
-rw-r--r--java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java1
-rw-r--r--java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java4
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java18
-rw-r--r--java/src/com/android/inputmethod/latin/RichInputConnection.java72
-rw-r--r--java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java135
-rw-r--r--java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryUpdateSession.java2
-rw-r--r--java/src/com/android/inputmethod/latin/settings/Settings.java23
-rw-r--r--java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java28
-rw-r--r--java/src/com/android/inputmethod/latin/utils/StringUtils.java26
9 files changed, 164 insertions, 145 deletions
diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java
index aa8bb2ccb..f733a9a6b 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java
@@ -410,6 +410,7 @@ public class DictionaryFacilitatorForSuggest {
final int sessionId, final Set<SuggestedWordInfo> suggestionSet) {
for (final String key : mDictionaries.keySet()) {
final Dictionary dictionary = mDictionaries.get(key);
+ if (null == dictionary) continue;
suggestionSet.addAll(dictionary.getSuggestionsWithSessionId(composer, prevWord,
proximityInfo, blockOffensiveWords, additionalFeaturesOptions, sessionId));
}
diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
index f785835b8..7757d2910 100644
--- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
@@ -282,7 +282,9 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
@Override
public void run() {
if (mDictionaryWriter == null) {
- mBinaryDictionary.close();
+ if (mBinaryDictionary != null) {
+ mBinaryDictionary.close();
+ }
final File file = getDictFile();
if (file.exists() && !FileUtils.deleteRecursively(file)) {
Log.e(TAG, "Can't remove a file: " + file.getName());
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 3984c197a..40391694c 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -202,7 +202,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
break;
case MSG_RESUME_SUGGESTIONS:
latinIme.mInputLogic.restartSuggestionsOnWordTouchedByCursor(
- latinIme.mSettings.getCurrent(), 0 /* offset */,
+ latinIme.mSettings.getCurrent(),
false /* includeResumedWordInSuggestions */, latinIme.mKeyboardSwitcher);
break;
case MSG_REOPEN_DICTIONARIES:
@@ -880,8 +880,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// Notify ResearchLogger
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
ResearchLogger.latinIME_onFinishInputViewInternal(finishingInput,
- mInputLogic.mLastSelectionStart,
- mInputLogic.mLastSelectionEnd, getCurrentInputConnection());
+ // TODO[IL]: mInputLogic.mConnection should be private
+ mInputLogic.mConnection.getExpectedSelectionStart(),
+ mInputLogic.mConnection.getExpectedSelectionEnd(), getCurrentInputConnection());
}
}
@@ -894,22 +895,18 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
if (DEBUG) {
Log.i(TAG, "onUpdateSelection: oss=" + oldSelStart
+ ", ose=" + oldSelEnd
- + ", lss=" + mInputLogic.mLastSelectionStart
- + ", lse=" + mInputLogic.mLastSelectionEnd
+ ", nss=" + newSelStart
+ ", nse=" + newSelEnd
+ ", cs=" + composingSpanStart
+ ", ce=" + composingSpanEnd);
}
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
- ResearchLogger.latinIME_onUpdateSelection(mInputLogic.mLastSelectionStart,
- mInputLogic.mLastSelectionEnd,
+ ResearchLogger.latinIME_onUpdateSelection(oldSelStart, oldSelEnd,
oldSelStart, oldSelEnd, newSelStart, newSelEnd, composingSpanStart,
composingSpanEnd, mInputLogic.mConnection);
}
- final boolean selectionChanged = mInputLogic.mLastSelectionStart != newSelStart
- || mInputLogic.mLastSelectionEnd != newSelEnd;
+ final boolean selectionChanged = oldSelStart != newSelStart || oldSelEnd != newSelEnd;
// 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
@@ -972,9 +969,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
mKeyboardSwitcher.updateShiftState();
}
- // Make a note of the cursor position
- mInputLogic.mLastSelectionStart = newSelStart;
- mInputLogic.mLastSelectionEnd = newSelEnd;
mSubtypeState.currentSubtypeUsed();
}
diff --git a/java/src/com/android/inputmethod/latin/RichInputConnection.java b/java/src/com/android/inputmethod/latin/RichInputConnection.java
index 67ea2991c..79d66744b 100644
--- a/java/src/com/android/inputmethod/latin/RichInputConnection.java
+++ b/java/src/com/android/inputmethod/latin/RichInputConnection.java
@@ -174,13 +174,15 @@ public final class RichInputConnection {
}
final int lengthOfTextBeforeCursor = mCommittedTextBeforeComposingText.length();
if (lengthOfTextBeforeCursor > newSelStart
- || (lengthOfTextBeforeCursor < Constants.EDITOR_CONTENTS_CACHE_SIZE
+ || (newSelStart != lengthOfTextBeforeCursor
+ && lengthOfTextBeforeCursor < Constants.EDITOR_CONTENTS_CACHE_SIZE
&& newSelStart < Constants.EDITOR_CONTENTS_CACHE_SIZE)) {
// newSelStart and newSelEnd may be lying -- when rotating the device (probably a
- // framework bug). If we have less chars than we asked for, then we know how many chars
- // we have, and if we got more than newSelStart says, then we know it was lying. In both
- // cases the length is more reliable. Note that we only have to check newSelStart (not
- // newSelEnd) since if newSelEnd is wrong, the newSelStart will be wrong as well.
+ // framework bug). If the values don't agree and we have less chars than we asked
+ // for, then we know how many chars we have. If we got more than newSelStart says, then
+ // we also know it was lying. In both cases the length is more reliable. Note that we
+ // only have to check newSelStart (not newSelEnd) since if newSelEnd is wrong, then
+ // newSelStart will be wrong as well.
mExpectedSelStart = lengthOfTextBeforeCursor;
mExpectedSelEnd = lengthOfTextBeforeCursor;
}
@@ -783,17 +785,17 @@ public final class RichInputConnection {
*/
public boolean isBelatedExpectedUpdate(final int oldSelStart, final int newSelStart,
final int oldSelEnd, final int newSelEnd) {
- // This update is "belated" if we are expecting it. That is, mExpectedSelStart and
+ // This update is "belated" if we are expecting it. That is, mExpectedSelStart and
// mExpectedSelEnd match the new values that the TextView is updating TO.
if (mExpectedSelStart == newSelStart && mExpectedSelEnd == newSelEnd) return true;
- // This update is not belated if mExpectedSelStart and mExpeectedSelend match the old
- // values, and one of newSelStart or newSelEnd is updated to a different value. In this
- // case, there is likely something other than the IME that has moved the selection endpoint
+ // This update is not belated if mExpectedSelStart and mExpectedSelEnd match the old
+ // values, and one of newSelStart or newSelEnd is updated to a different value. In this
+ // case, there is likely something other than the IME has moved the selection endpoint
// to the new value.
if (mExpectedSelStart == oldSelStart && mExpectedSelEnd == oldSelEnd
&& (oldSelStart != newSelStart || oldSelEnd != newSelEnd)) return false;
// If nether of the above two cases holds, then the system may be having trouble keeping up
- // with updates. If 1) the selection is a cursor, 2) newSelStart is between oldSelStart
+ // with updates. If 1) the selection is a cursor, 2) newSelStart is between oldSelStart
// and mExpectedSelStart, and 3) newSelEnd is between oldSelEnd and mExpectedSelEnd, then
// assume a belated update.
return (newSelStart == newSelEnd)
@@ -811,4 +813,54 @@ public final class RichInputConnection {
public boolean textBeforeCursorLooksLikeURL() {
return StringUtils.lastPartLooksLikeURL(mCommittedTextBeforeComposingText);
}
+
+ /**
+ * 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.
+ */
+ public void tryFixLyingCursorPosition() {
+ final CharSequence textBeforeCursor = getTextBeforeCursor(
+ Constants.EDITOR_CONTENTS_CACHE_SIZE, 0);
+ if (null == textBeforeCursor) {
+ mExpectedSelStart = mExpectedSelEnd = Constants.NOT_A_CURSOR_POSITION;
+ } else {
+ final int textLength = textBeforeCursor.length();
+ if (textLength > mExpectedSelStart
+ || (textLength < Constants.EDITOR_CONTENTS_CACHE_SIZE
+ && mExpectedSelStart < 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 = mExpectedSelStart == mExpectedSelEnd;
+ mExpectedSelStart = 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 || mExpectedSelStart > mExpectedSelEnd) {
+ mExpectedSelEnd = mExpectedSelStart;
+ }
+ }
+ }
+ }
+
+ public int getExpectedSelectionStart() {
+ return mExpectedSelStart;
+ }
+
+ public int getExpectedSelectionEnd() {
+ return mExpectedSelEnd;
+ }
+
+ /**
+ * @return whether there is a selection currently active.
+ */
+ public boolean hasSelection() {
+ return mExpectedSelEnd != mExpectedSelStart;
+ }
}
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
index 92b6a8544..55e92cc09 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
@@ -86,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();
@@ -129,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);
}
@@ -337,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
@@ -466,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);
}
@@ -516,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,
@@ -603,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()) {
@@ -695,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()) {
@@ -755,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,
@@ -771,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");
}
@@ -820,7 +816,6 @@ public final class InputLogic {
&& settingsValues.mSpacingAndPunctuations.mCurrentLanguageHasSpaces
&& !mConnection.isCursorFollowedByWordCharacter(settingsValues)) {
restartSuggestionsOnWordTouchedByCursor(settingsValues,
- deleteCountAtStart - mDeleteCount /* offset */,
true /* includeResumedWordInSuggestions */, keyboardSwitcher);
}
// We just removed at least one character. We need to update the auto-caps state.
@@ -960,38 +955,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,
@@ -1053,13 +1042,12 @@ public final class InputLogic {
* do nothing.
*
* @param settingsValues the current values of the settings.
- * @param offset how much the cursor is expected to have moved since the last updateSelection.
* @param includeResumedWordInSuggestions whether to include the word on which we resume
* suggestions in the suggestion list.
*/
// TODO: make this private.
public void restartSuggestionsOnWordTouchedByCursor(final SettingsValues settingsValues,
- final int offset, final boolean includeResumedWordInSuggestions,
+ final boolean includeResumedWordInSuggestions,
// TODO: Remove this argument.
final KeyboardSwitcher keyboardSwitcher) {
// HACK: We may want to special-case some apps that exhibit bad behavior in case of
@@ -1072,10 +1060,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,
@@ -1119,19 +1107,8 @@ public final class InputLogic {
keyboardSwitcher.getKeyboard());
mWordComposer.setCursorPositionWithinWord(
typedWord.codePointCount(0, numberOfCharsInWordBeforeCursor));
- // TODO: Change these lines to setComposingRegion(cursorPosition,
- // cursorPosition + range.getNumberOfCharsInWordAfterCursor());
- if (0 != offset) {
- // Backspace was pressed. We are at the end of a word, and we don't know the cursor
- // position for sure, so use relative methods.
- mConnection.deleteSurroundingText(numberOfCharsInWordBeforeCursor, 0);
- mConnection.setComposingText(typedWord, 1);
- } else {
- // This is recorrection. The cursor position is reasonably reliable, and the cursor
- // may be in the middle of a word so use setComposingRegion.
- mConnection.setComposingRegion(expectedCursorPosition - numberOfCharsInWordBeforeCursor,
+ mConnection.setComposingRegion(expectedCursorPosition - numberOfCharsInWordBeforeCursor,
expectedCursorPosition + range.getNumberOfCharsInWordAfterCursor());
- }
if (suggestions.isEmpty()) {
// We come here if there weren't any suggestion spans on this word. We will try to
// compute suggestions for it instead.
@@ -1289,7 +1266,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;
}
@@ -1642,7 +1620,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));
}
}
@@ -1691,41 +1670,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.
@@ -1742,7 +1686,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;
@@ -1750,7 +1695,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/personalization/PersonalizationDictionaryUpdateSession.java b/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryUpdateSession.java
index 61354762b..3eb8f35a9 100644
--- a/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryUpdateSession.java
+++ b/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryUpdateSession.java
@@ -57,7 +57,7 @@ public abstract class PersonalizationDictionaryUpdateSession {
dictionary.unRegisterUpdateSession(this);
}
- public void clearAndFlushDictionary(final Context context) {
+ public void clearAndFlushDictionary() {
final PersonalizationDictionary dictionary = getDictionary();
if (dictionary == null) {
return;
diff --git a/java/src/com/android/inputmethod/latin/settings/Settings.java b/java/src/com/android/inputmethod/latin/settings/Settings.java
index add983b3b..7db10714a 100644
--- a/java/src/com/android/inputmethod/latin/settings/Settings.java
+++ b/java/src/com/android/inputmethod/latin/settings/Settings.java
@@ -31,7 +31,9 @@ import com.android.inputmethod.latin.utils.ResourceUtils;
import com.android.inputmethod.latin.utils.RunInLocale;
import com.android.inputmethod.latin.utils.StringUtils;
+import java.util.Collections;
import java.util.Locale;
+import java.util.Set;
import java.util.concurrent.locks.ReentrantLock;
public final class Settings implements SharedPreferences.OnSharedPreferenceChangeListener {
@@ -93,6 +95,10 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
private static final String PREF_LAST_USED_PERSONALIZATION_TOKEN =
"pref_last_used_personalization_token";
+ private static final String PREF_LAST_PERSONALIZATION_DICT_WIPED_TIME =
+ "pref_last_used_personalization_dict_wiped_time";
+ private static final String PREF_CORPUS_HANDLES_FOR_PERSONALIZATION =
+ "pref_corpus_handles_for_personalization";
public static final String PREF_SEND_FEEDBACK = "send_feedback";
public static final String PREF_ABOUT_KEYBOARD = "about_keyboard";
@@ -372,6 +378,23 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
return StringUtils.hexStringToByteArray(tokenStr);
}
+ public void writeLastPersonalizationDictWipedTime(final long timestamp) {
+ mPrefs.edit().putLong(PREF_LAST_PERSONALIZATION_DICT_WIPED_TIME, timestamp).apply();
+ }
+
+ public long readLastPersonalizationDictGeneratedTime() {
+ return mPrefs.getLong(PREF_LAST_PERSONALIZATION_DICT_WIPED_TIME, 0);
+ }
+
+ public void writeCorpusHandlesForPersonalization(final Set<String> corpusHandles) {
+ mPrefs.edit().putStringSet(PREF_CORPUS_HANDLES_FOR_PERSONALIZATION, corpusHandles).apply();
+ }
+
+ public Set<String> readCorpusHandlesForPersonalization() {
+ final Set<String> emptySet = Collections.emptySet();
+ return mPrefs.getStringSet(PREF_CORPUS_HANDLES_FOR_PERSONALIZATION, emptySet);
+ }
+
public static void writeEmojiRecentKeys(final SharedPreferences prefs, String str) {
prefs.edit().putString(PREF_EMOJI_RECENT_KEYS, str).apply();
}
diff --git a/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java b/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java
index 3daa63ff4..b3c787e44 100644
--- a/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java
@@ -20,13 +20,16 @@ import android.content.ContentValues;
import android.content.Context;
import android.content.res.AssetManager;
import android.content.res.Resources;
+import android.text.TextUtils;
import android.util.Log;
+import com.android.inputmethod.annotations.UsedForTesting;
import com.android.inputmethod.latin.AssetFileAddress;
import com.android.inputmethod.latin.BinaryDictionaryGetter;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.makedict.BinaryDictIOUtils;
import com.android.inputmethod.latin.makedict.FormatSpec.FileHeader;
+import com.android.inputmethod.latin.settings.SpacingAndPunctuations;
import java.io.File;
import java.util.ArrayList;
@@ -364,4 +367,29 @@ public class DictionaryInfoUtils {
return dictList;
}
+
+ @UsedForTesting
+ public static boolean looksValidForDictionaryInsertion(final CharSequence text,
+ final SpacingAndPunctuations spacingAndPunctuations) {
+ if (TextUtils.isEmpty(text)) return false;
+ final int length = text.length();
+ int i = 0;
+ int digitCount = 0;
+ while (i < length) {
+ final int codePoint = Character.codePointAt(text, i);
+ final int charCount = Character.charCount(codePoint);
+ i += charCount;
+ if (Character.isDigit(codePoint)) {
+ // Count digits: see below
+ digitCount += charCount;
+ continue;
+ }
+ if (!spacingAndPunctuations.isWordCodePoint(codePoint)) return false;
+ }
+ // We reject strings entirely comprised of digits to avoid using PIN codes or credit
+ // card numbers. It would come in handy for word prediction though; a good example is
+ // when writing one's address where the street number is usually quite discriminative,
+ // as well as the postal code.
+ return digitCount < length;
+ }
}
diff --git a/java/src/com/android/inputmethod/latin/utils/StringUtils.java b/java/src/com/android/inputmethod/latin/utils/StringUtils.java
index 0042d8b42..c5ed39310 100644
--- a/java/src/com/android/inputmethod/latin/utils/StringUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/StringUtils.java
@@ -20,7 +20,6 @@ import android.text.TextUtils;
import com.android.inputmethod.annotations.UsedForTesting;
import com.android.inputmethod.latin.Constants;
-import com.android.inputmethod.latin.settings.SpacingAndPunctuations;
import java.util.ArrayList;
import java.util.Locale;
@@ -265,31 +264,6 @@ public final class StringUtils {
return true;
}
- @UsedForTesting
- public static boolean looksValidForDictionaryInsertion(final CharSequence text,
- final SpacingAndPunctuations spacingAndPunctuations) {
- if (TextUtils.isEmpty(text)) return false;
- final int length = text.length();
- int i = 0;
- int digitCount = 0;
- while (i < length) {
- final int codePoint = Character.codePointAt(text, i);
- final int charCount = Character.charCount(codePoint);
- i += charCount;
- if (Character.isDigit(codePoint)) {
- // Count digits: see below
- digitCount += charCount;
- continue;
- }
- if (!spacingAndPunctuations.isWordCodePoint(codePoint)) return false;
- }
- // We reject strings entirely comprised of digits to avoid using PIN codes or credit
- // card numbers. It would come in handy for word prediction though; a good example is
- // when writing one's address where the street number is usually quite discriminative,
- // as well as the postal code.
- return digitCount < length;
- }
-
public static boolean isIdenticalAfterCapitalizeEachWord(final String text,
final String separators) {
boolean needCapsNext = true;