am 00d140ca: am a475c854: Introduce a mechanism to hide the indicator speculatively

* commit '00d140caeb02e2e68f5b2cf7b71d349e1ad4cb5c':
  Introduce a mechanism to hide the indicator speculatively
main
Yohei Yukawa 2014-08-27 09:48:34 +00:00 committed by Android Git Automerger
commit 8a413a2a62
2 changed files with 52 additions and 16 deletions

View File

@ -158,7 +158,7 @@ public class TextDecorator {
if (!currentFullScreenMode && fullScreenMode) { if (!currentFullScreenMode && fullScreenMode) {
// Currently full screen mode is not supported. // Currently full screen mode is not supported.
// TODO: Support full screen mode. // TODO: Support full screen mode.
hideIndicator(); mUiOperator.hideUi();
} }
mIsFullScreenMode = fullScreenMode; mIsFullScreenMode = fullScreenMode;
} }
@ -193,17 +193,36 @@ public class TextDecorator {
layoutImmediately(); layoutImmediately();
} }
private void hideIndicator() { /**
mUiOperator.hideUi(); * Hides indicator if the new composing text doesn't match the expected one.
*
* <p>Calling this method is optional but recommended whenever the new composition is passed to
* the application. The motivation of this method is to reduce the UI latency. With this method,
* we can hide the indicator without waiting the arrival of the
* {@link InputMethodService#onUpdateCursorAnchorInfo(CursorAnchorInfo)} callback, assuming that
* the application accepts the new composing text without any modification. Even if this
* assumption is false, the indicator will be shown again when
* {@link InputMethodService#onUpdateCursorAnchorInfo(CursorAnchorInfo)} is actually received.
* </p>
*
* @param newComposingText the new composing text that is being passed to the application.
*/
public void hideIndicatorIfNecessary(final CharSequence newComposingText) {
if (mMode != MODE_COMMIT && mMode != MODE_ADD_TO_DICTIONARY) {
return;
}
if (!TextUtils.equals(newComposingText, mWaitingWord.mWord)) {
mUiOperator.hideUi();
}
} }
private void cancelLayoutInternalUnexpectedly(final String message) { private void cancelLayoutInternalUnexpectedly(final String message) {
hideIndicator(); mUiOperator.hideUi();
Log.d(TAG, message); Log.d(TAG, message);
} }
private void cancelLayoutInternalExpectedly(final String message) { private void cancelLayoutInternalExpectedly(final String message) {
hideIndicator(); mUiOperator.hideUi();
if (DEBUG) { if (DEBUG) {
Log.d(TAG, message); Log.d(TAG, message);
} }
@ -261,7 +280,7 @@ public class TextDecorator {
lastCharRectFlag & CursorAnchorInfoCompatWrapper.CHARACTER_RECT_TYPE_MASK; lastCharRectFlag & CursorAnchorInfoCompatWrapper.CHARACTER_RECT_TYPE_MASK;
if (lastCharRect == null || matrix == null || lastCharRectType != if (lastCharRect == null || matrix == null || lastCharRectType !=
CursorAnchorInfoCompatWrapper.CHARACTER_RECT_TYPE_FULLY_VISIBLE) { CursorAnchorInfoCompatWrapper.CHARACTER_RECT_TYPE_FULLY_VISIBLE) {
hideIndicator(); mUiOperator.hideUi();
return; return;
} }
final RectF segmentStartCharRect = new RectF(lastCharRect); final RectF segmentStartCharRect = new RectF(lastCharRect);
@ -312,13 +331,13 @@ public class TextDecorator {
if (!TextUtils.isEmpty(composingText)) { if (!TextUtils.isEmpty(composingText)) {
// This is an unexpected case. // This is an unexpected case.
// TODO: Document this. // TODO: Document this.
hideIndicator(); mUiOperator.hideUi();
return; return;
} }
// In MODE_ADD_TO_DICTIONARY, we cannot retrieve the character position at all because // In MODE_ADD_TO_DICTIONARY, we cannot retrieve the character position at all because
// of the lack of composing text. We will use the insertion marker position instead. // of the lack of composing text. We will use the insertion marker position instead.
if (info.isInsertionMarkerClipped()) { if (info.isInsertionMarkerClipped()) {
hideIndicator(); mUiOperator.hideUi();
return; return;
} }
final float insertionMarkerHolizontal = info.getInsertionMarkerHorizontal(); final float insertionMarkerHolizontal = info.getInsertionMarkerHorizontal();

View File

@ -649,7 +649,7 @@ public final class InputLogic {
// message, this is called outside any batch edit. Potentially, this may result in some // message, this is called outside any batch edit. Potentially, this may result in some
// janky flickering of the screen, although the display speed makes it unlikely in // janky flickering of the screen, although the display speed makes it unlikely in
// the practice. // the practice.
mConnection.setComposingText(textWithUnderline, 1); setComposingTextInternal(textWithUnderline, 1);
} }
} }
@ -672,7 +672,7 @@ public final class InputLogic {
inputTransaction.setDidAffectContents(); inputTransaction.setDidAffectContents();
} }
if (mWordComposer.isComposingWord()) { if (mWordComposer.isComposingWord()) {
mConnection.setComposingText(mWordComposer.getTypedWord(), 1); setComposingTextInternal(mWordComposer.getTypedWord(), 1);
inputTransaction.setDidAffectContents(); inputTransaction.setDidAffectContents();
inputTransaction.setRequiresUpdateSuggestions(); inputTransaction.setRequiresUpdateSuggestions();
} }
@ -908,8 +908,7 @@ public final class InputLogic {
if (mWordComposer.isSingleLetter()) { if (mWordComposer.isSingleLetter()) {
mWordComposer.setCapitalizedModeAtStartComposingTime(inputTransaction.mShiftState); mWordComposer.setCapitalizedModeAtStartComposingTime(inputTransaction.mShiftState);
} }
mConnection.setComposingText(getTextWithUnderline( setComposingTextInternal(getTextWithUnderline(mWordComposer.getTypedWord()), 1);
mWordComposer.getTypedWord()), 1);
} else { } else {
final boolean swapWeakSpace = tryStripSpaceAndReturnWhetherShouldSwapInstead(event, final boolean swapWeakSpace = tryStripSpaceAndReturnWhetherShouldSwapInstead(event,
inputTransaction); inputTransaction);
@ -1072,7 +1071,7 @@ public final class InputLogic {
mWordComposer.applyProcessedEvent(event); mWordComposer.applyProcessedEvent(event);
} }
if (mWordComposer.isComposingWord()) { if (mWordComposer.isComposingWord()) {
mConnection.setComposingText(getTextWithUnderline(mWordComposer.getTypedWord()), 1); setComposingTextInternal(getTextWithUnderline(mWordComposer.getTypedWord()), 1);
} else { } else {
mConnection.commitText("", 1); mConnection.commitText("", 1);
} }
@ -1640,7 +1639,7 @@ public final class InputLogic {
final int[] codePoints = StringUtils.toCodePointArray(stringToCommit); final int[] codePoints = StringUtils.toCodePointArray(stringToCommit);
mWordComposer.setComposingWord(codePoints, mWordComposer.setComposingWord(codePoints,
mLatinIME.getCoordinatesForCurrentKeyboard(codePoints)); mLatinIME.getCoordinatesForCurrentKeyboard(codePoints));
mConnection.setComposingText(textToCommit, 1); setComposingTextInternal(textToCommit, 1);
} }
// Don't restart suggestion yet. We'll restart if the user deletes the separator. // Don't restart suggestion yet. We'll restart if the user deletes the separator.
mLastComposedWord = LastComposedWord.NOT_A_COMPOSED_WORD; mLastComposedWord = LastComposedWord.NOT_A_COMPOSED_WORD;
@ -1973,10 +1972,10 @@ public final class InputLogic {
} }
final String lastWord = batchInputText.substring(indexOfLastSpace); final String lastWord = batchInputText.substring(indexOfLastSpace);
mWordComposer.setBatchInputWord(lastWord); mWordComposer.setBatchInputWord(lastWord);
mConnection.setComposingText(lastWord, 1); setComposingTextInternal(lastWord, 1);
} else { } else {
mWordComposer.setBatchInputWord(batchInputText); mWordComposer.setBatchInputWord(batchInputText);
mConnection.setComposingText(batchInputText, 1); setComposingTextInternal(batchInputText, 1);
} }
mConnection.endBatchEdit(); mConnection.endBatchEdit();
// Space state must be updated before calling updateShiftState // Space state must be updated before calling updateShiftState
@ -2175,6 +2174,24 @@ public final class InputLogic {
inputStyle, sequenceNumber, callback); inputStyle, sequenceNumber, callback);
} }
/**
* Used as an injection point for each call of
* {@link RichInputConnection#setComposingText(CharSequence, int)}.
*
* <p>Currently using this method is optional and you can still directly call
* {@link RichInputConnection#setComposingText(CharSequence, int)}, but it is recommended to
* use this method whenever possible to optimize the behavior of {@link TextDecorator}.<p>
* <p>TODO: Should we move this mechanism to {@link RichInputConnection}?</p>
*
* @param newComposingText the composing text to be set
* @param newCursorPosition the new cursor position
*/
private void setComposingTextInternal(final CharSequence newComposingText,
final int newCursorPosition) {
mConnection.setComposingText(newComposingText, newCursorPosition);
mTextDecorator.hideIndicatorIfNecessary(newComposingText);
}
////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////////
// Following methods are tentatively placed in this class for the integration with // Following methods are tentatively placed in this class for the integration with
// TextDecorator. // TextDecorator.