aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJean Chalard <jchalard@google.com>2012-09-13 02:30:23 -0700
committerAndroid Git Automerger <android-git-automerger@android.com>2012-09-13 02:30:23 -0700
commita0fd2b4053b338576e8e706067b921f8f9c1ee76 (patch)
tree17226c0313fef5ef0fd897787dbc80582481962e
parentf5297a2b615d98ebf178fb74c42c7349ac8f3e9f (diff)
parent378728920bec5e43138573acb8473093e674fde9 (diff)
downloadlatinime-a0fd2b4053b338576e8e706067b921f8f9c1ee76.tar.gz
latinime-a0fd2b4053b338576e8e706067b921f8f9c1ee76.tar.xz
latinime-a0fd2b4053b338576e8e706067b921f8f9c1ee76.zip
am 37872892: Merge "Make onUpdateSelection much more resilient to race conditions." into jb-mr1-dev
* commit '378728920bec5e43138573acb8473093e674fde9': Make onUpdateSelection much more resilient to race conditions.
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java3
-rw-r--r--java/src/com/android/inputmethod/latin/RichInputConnection.java30
2 files changed, 32 insertions, 1 deletions
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 78c65e0c7..b3f7e674d 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -825,7 +825,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// 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) {
+ if (!mExpectingUpdateSelection
+ && !mConnection.isBelatedExpectedUpdate(oldSelStart, newSelStart)) {
// 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
diff --git a/java/src/com/android/inputmethod/latin/RichInputConnection.java b/java/src/com/android/inputmethod/latin/RichInputConnection.java
index 37e1dbb69..ce7049f4f 100644
--- a/java/src/com/android/inputmethod/latin/RichInputConnection.java
+++ b/java/src/com/android/inputmethod/latin/RichInputConnection.java
@@ -629,4 +629,34 @@ public class RichInputConnection {
commitText(" " + textBeforeCursor.subSequence(0, 1), 1);
return true;
}
+
+ /**
+ * Heuristic to determine if this is an expected update of the cursor.
+ *
+ * Sometimes updates to the cursor position are late because of their asynchronous nature.
+ * This method tries to determine if this update is one, based on the values of the cursor
+ * position in the update, and the currently expected position of the cursor according to
+ * LatinIME's internal accounting. If this is not a belated expected update, then it should
+ * mean that the user moved the cursor explicitly.
+ * This is quite robust, but of course it's not perfect. In particular, it will fail in the
+ * case we get an update A, the user types in N characters so as to move the cursor to A+N but
+ * we don't get those, and then the user places the cursor between A and A+N, and we get only
+ * this update and not the ones in-between. This is almost impossible to achieve even trying
+ * very very hard.
+ *
+ * @param oldSelStart The value of the old cursor position in the update.
+ * @param newSelStart The value of the new cursor position in the update.
+ * @return whether this is a belated expected update or not.
+ */
+ public boolean isBelatedExpectedUpdate(final int oldSelStart, final int newSelStart) {
+ // If this is an update that arrives at our expected position, it's a belated update.
+ if (newSelStart == mCurrentCursorPosition) return true;
+ // If this is an update that moves the cursor from our expected position, it must be
+ // an explicit move.
+ if (oldSelStart == mCurrentCursorPosition) return false;
+ // The following returns true if newSelStart is between oldSelStart and
+ // mCurrentCursorPosition. We assume that if the updated position is between the old
+ // position and the expected position, then it must be a belated update.
+ return (newSelStart - oldSelStart) * (mCurrentCursorPosition - newSelStart) >= 0;
+ }
}