Loading java/src/com/android/inputmethod/latin/LatinIME.java +2 −1 Original line number Diff line number Diff line Loading @@ -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 Loading java/src/com/android/inputmethod/latin/RichInputConnection.java +30 −0 Original line number Diff line number Diff line Loading @@ -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; } } Loading
java/src/com/android/inputmethod/latin/LatinIME.java +2 −1 Original line number Diff line number Diff line Loading @@ -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 Loading
java/src/com/android/inputmethod/latin/RichInputConnection.java +30 −0 Original line number Diff line number Diff line Loading @@ -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; } }