Make a better effort to detect a framework lie.
Bug: 17130496 Change-Id: I1a3631670c152d9b7667c9c4e08e14c48569eef5main
parent
7b673c7265
commit
38144047ea
|
@ -926,8 +926,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
// mLastSelection{Start,End} are reset later in this method, no need to do it here
|
// mLastSelection{Start,End} are reset later in this method, no need to do it here
|
||||||
needToCallLoadKeyboardLater = true;
|
needToCallLoadKeyboardLater = true;
|
||||||
} else {
|
} else {
|
||||||
// When rotating, initialSelStart and initialSelEnd sometimes are lying. Make a best
|
// When rotating, and when input is starting again in a field from where the focus
|
||||||
// effort to work around this bug.
|
// didn't move (the keyboard having been closed with the back key),
|
||||||
|
// initialSelStart and initialSelEnd sometimes are lying. Make a best effort to
|
||||||
|
// work around this bug.
|
||||||
mInputLogic.mConnection.tryFixLyingCursorPosition();
|
mInputLogic.mConnection.tryFixLyingCursorPosition();
|
||||||
mHandler.postResumeSuggestions(true /* shouldIncludeResumedWordInSuggestions */,
|
mHandler.postResumeSuggestions(true /* shouldIncludeResumedWordInSuggestions */,
|
||||||
true /* shouldDelay */);
|
true /* shouldDelay */);
|
||||||
|
|
|
@ -849,8 +849,9 @@ public final class RichInputConnection {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Try to get the text from the editor to expose lies the framework may have been
|
* 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
|
* telling us. Concretely, when the device rotates and when the keyboard reopens in the same
|
||||||
* cursor used to be initially in the editor at the time it first received the focus; this
|
* text field after having been closed with the back key, 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
|
* 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
|
* 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
|
* detect the most damaging cases: when the cursor position is declared to be much smaller
|
||||||
|
@ -859,7 +860,20 @@ public final class RichInputConnection {
|
||||||
public void tryFixLyingCursorPosition() {
|
public void tryFixLyingCursorPosition() {
|
||||||
final CharSequence textBeforeCursor = getTextBeforeCursor(
|
final CharSequence textBeforeCursor = getTextBeforeCursor(
|
||||||
Constants.EDITOR_CONTENTS_CACHE_SIZE, 0);
|
Constants.EDITOR_CONTENTS_CACHE_SIZE, 0);
|
||||||
if (null == textBeforeCursor) {
|
final CharSequence selectedText = mIC.getSelectedText(0 /* flags */);
|
||||||
|
if (null == textBeforeCursor ||
|
||||||
|
(!TextUtils.isEmpty(selectedText) && mExpectedSelEnd == mExpectedSelStart)) {
|
||||||
|
// If textBeforeCursor is null, we have no idea what kind of text field we have or if
|
||||||
|
// thinking about the "cursor position" actually makes any sense. In this case we
|
||||||
|
// remember a meaningless cursor position. Contrast this with an empty string, which is
|
||||||
|
// valid and should mean the cursor is at the start of the text.
|
||||||
|
// Also, if we expect we don't have a selection but we DO have non-empty selected text,
|
||||||
|
// then the framework lied to us about the cursor position. In this case, we should just
|
||||||
|
// revert to the most basic behavior possible for the next action (backspace in
|
||||||
|
// particular comes to mind), so we remember a meaningless cursor position which should
|
||||||
|
// result in degraded behavior from the next input.
|
||||||
|
// Interestingly, in either case, chances are any action the user takes next will result
|
||||||
|
// in a call to onUpdateSelection, which should set things right.
|
||||||
mExpectedSelStart = mExpectedSelEnd = Constants.NOT_A_CURSOR_POSITION;
|
mExpectedSelStart = mExpectedSelEnd = Constants.NOT_A_CURSOR_POSITION;
|
||||||
} else {
|
} else {
|
||||||
final int textLength = textBeforeCursor.length();
|
final int textLength = textBeforeCursor.length();
|
||||||
|
|
|
@ -1127,19 +1127,21 @@ public final class InputLogic {
|
||||||
StatsUtils.onBackspaceSelectedText(numCharsDeleted);
|
StatsUtils.onBackspaceSelectedText(numCharsDeleted);
|
||||||
} else {
|
} else {
|
||||||
// There is no selection, just delete one character.
|
// There is no selection, just delete one character.
|
||||||
if (Constants.NOT_A_CURSOR_POSITION == mConnection.getExpectedSelectionEnd()) {
|
if (inputTransaction.mSettingsValues.isBeforeJellyBean()
|
||||||
// This should never happen.
|
|| inputTransaction.mSettingsValues.mInputAttributes.isTypeNull()
|
||||||
Log.e(TAG, "Backspace when we don't know the selection position");
|
|| Constants.NOT_A_CURSOR_POSITION
|
||||||
}
|
== mConnection.getExpectedSelectionEnd()) {
|
||||||
if (inputTransaction.mSettingsValues.isBeforeJellyBean() ||
|
// There are three possible reasons to send a key event: either the field has
|
||||||
inputTransaction.mSettingsValues.mInputAttributes.isTypeNull()) {
|
|
||||||
// There are two possible reasons to send a key event: either the field has
|
|
||||||
// type TYPE_NULL, in which case the keyboard should send events, or we are
|
// type TYPE_NULL, in which case the keyboard should send events, or we are
|
||||||
// running in backward compatibility mode. Before Jelly bean, the keyboard
|
// running in backward compatibility mode, or we don't know the cursor position.
|
||||||
// would simulate a hardware keyboard event on pressing enter or delete. This
|
// Before Jelly bean, the keyboard would simulate a hardware keyboard event on
|
||||||
// is bad for many reasons (there are race conditions with commits) but some
|
// pressing enter or delete. This is bad for many reasons (there are race
|
||||||
// applications are relying on this behavior so we continue to support it for
|
// conditions with commits) but some applications are relying on this behavior
|
||||||
// older apps, so we retain this behavior if the app has target SDK < JellyBean.
|
// so we continue to support it for older apps, so we retain this behavior if
|
||||||
|
// the app has target SDK < JellyBean.
|
||||||
|
// As for the case where we don't know the cursor position, it can happen
|
||||||
|
// because of bugs in the framework. But the framework should know, so the next
|
||||||
|
// best thing is to leave it to whatever it thinks is best.
|
||||||
sendDownUpKeyEvent(KeyEvent.KEYCODE_DEL);
|
sendDownUpKeyEvent(KeyEvent.KEYCODE_DEL);
|
||||||
int totalDeletedLength = 1;
|
int totalDeletedLength = 1;
|
||||||
if (mDeleteCount > Constants.DELETE_ACCELERATE_AT) {
|
if (mDeleteCount > Constants.DELETE_ACCELERATE_AT) {
|
||||||
|
|
Loading…
Reference in New Issue