am a0fd2b40
: am 37872892
: Merge "Make onUpdateSelection much more resilient to race conditions." into jb-mr1-dev
* commit 'a0fd2b4053b338576e8e706067b921f8f9c1ee76': Make onUpdateSelection much more resilient to race conditions.
This commit is contained in:
commit
d666c125bc
2 changed files with 32 additions and 1 deletions
|
@ -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
|
||||
|
|
|
@ -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…
Reference in a new issue