aboutsummaryrefslogtreecommitdiffstats
path: root/java/src/com/android/inputmethod/latin/RichInputConnection.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/src/com/android/inputmethod/latin/RichInputConnection.java')
-rw-r--r--java/src/com/android/inputmethod/latin/RichInputConnection.java87
1 files changed, 70 insertions, 17 deletions
diff --git a/java/src/com/android/inputmethod/latin/RichInputConnection.java b/java/src/com/android/inputmethod/latin/RichInputConnection.java
index 7cf64a3bc..79d66744b 100644
--- a/java/src/com/android/inputmethod/latin/RichInputConnection.java
+++ b/java/src/com/android/inputmethod/latin/RichInputConnection.java
@@ -28,6 +28,7 @@ import android.view.inputmethod.InputConnection;
import com.android.inputmethod.latin.define.ProductionFlag;
import com.android.inputmethod.latin.settings.SettingsValues;
+import com.android.inputmethod.latin.settings.SpacingAndPunctuations;
import com.android.inputmethod.latin.utils.CapsModeUtils;
import com.android.inputmethod.latin.utils.DebugLogUtils;
import com.android.inputmethod.latin.utils.SpannableStringUtils;
@@ -35,7 +36,6 @@ import com.android.inputmethod.latin.utils.StringUtils;
import com.android.inputmethod.latin.utils.TextRange;
import com.android.inputmethod.research.ResearchLogger;
-import java.util.Locale;
import java.util.regex.Pattern;
/**
@@ -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;
}
@@ -302,7 +304,7 @@ public final class RichInputConnection {
// This never calls InputConnection#getCapsMode - in fact, it's a static method that
// never blocks or initiates IPC.
return CapsModeUtils.getCapsMode(mCommittedTextBeforeComposingText, inputType,
- settingsValues, hasSpaceBefore);
+ settingsValues.mSpacingAndPunctuations, hasSpaceBefore);
}
public int getCodePointBeforeCursor() {
@@ -538,7 +540,8 @@ public final class RichInputConnection {
}
@SuppressWarnings("unused")
- public String getNthPreviousWord(final SettingsValues currentSettingsValues, final int n) {
+ public String getNthPreviousWord(final SpacingAndPunctuations spacingAndPunctuations,
+ final int n) {
mIC = mParent.getCurrentInputConnection();
if (null == mIC) return null;
final CharSequence prev = getTextBeforeCursor(LOOKBACK_CHARACTER_NUM, 0);
@@ -557,7 +560,7 @@ public final class RichInputConnection {
}
}
}
- return getNthPreviousWord(prev, currentSettingsValues, n);
+ return getNthPreviousWord(prev, spacingAndPunctuations, n);
}
private static boolean isSeparator(int code, String sep) {
@@ -581,7 +584,7 @@ public final class RichInputConnection {
// (n = 2) "abc |" -> null
// (n = 2) "abc. def|" -> null
public static String getNthPreviousWord(final CharSequence prev,
- final SettingsValues currentSettingsValues, final int n) {
+ final SpacingAndPunctuations spacingAndPunctuations, final int n) {
if (prev == null) return null;
final String[] w = spaceRegex.split(prev);
@@ -593,8 +596,8 @@ public final class RichInputConnection {
// If ends in a separator, return null
final char lastChar = nthPrevWord.charAt(length - 1);
- if (currentSettingsValues.isWordSeparator(lastChar)
- || currentSettingsValues.isWordConnector(lastChar)) return null;
+ if (spacingAndPunctuations.isWordSeparator(lastChar)
+ || spacingAndPunctuations.isWordConnector(lastChar)) return null;
return nthPrevWord;
}
@@ -782,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)
@@ -810,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;
+ }
}