Loading java/src/com/android/inputmethod/keyboard/TextDecorator.java +27 −8 Original line number Diff line number Diff line Loading @@ -158,7 +158,7 @@ public class TextDecorator { if (!currentFullScreenMode && fullScreenMode) { // Currently full screen mode is not supported. // TODO: Support full screen mode. hideIndicator(); mUiOperator.hideUi(); } mIsFullScreenMode = fullScreenMode; } Loading Loading @@ -193,17 +193,36 @@ public class TextDecorator { layoutImmediately(); } private void hideIndicator() { /** * 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) { hideIndicator(); mUiOperator.hideUi(); Log.d(TAG, message); } private void cancelLayoutInternalExpectedly(final String message) { hideIndicator(); mUiOperator.hideUi(); if (DEBUG) { Log.d(TAG, message); } Loading Loading @@ -261,7 +280,7 @@ public class TextDecorator { lastCharRectFlag & CursorAnchorInfoCompatWrapper.CHARACTER_RECT_TYPE_MASK; if (lastCharRect == null || matrix == null || lastCharRectType != CursorAnchorInfoCompatWrapper.CHARACTER_RECT_TYPE_FULLY_VISIBLE) { hideIndicator(); mUiOperator.hideUi(); return; } final RectF segmentStartCharRect = new RectF(lastCharRect); Loading Loading @@ -312,13 +331,13 @@ public class TextDecorator { if (!TextUtils.isEmpty(composingText)) { // This is an unexpected case. // TODO: Document this. hideIndicator(); mUiOperator.hideUi(); return; } // 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. if (info.isInsertionMarkerClipped()) { hideIndicator(); mUiOperator.hideUi(); return; } final float insertionMarkerHolizontal = info.getInsertionMarkerHorizontal(); Loading java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java +25 −8 Original line number Diff line number Diff line Loading @@ -649,7 +649,7 @@ public final class InputLogic { // 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 // the practice. mConnection.setComposingText(textWithUnderline, 1); setComposingTextInternal(textWithUnderline, 1); } } Loading @@ -672,7 +672,7 @@ public final class InputLogic { inputTransaction.setDidAffectContents(); } if (mWordComposer.isComposingWord()) { mConnection.setComposingText(mWordComposer.getTypedWord(), 1); setComposingTextInternal(mWordComposer.getTypedWord(), 1); inputTransaction.setDidAffectContents(); inputTransaction.setRequiresUpdateSuggestions(); } Loading Loading @@ -908,8 +908,7 @@ public final class InputLogic { if (mWordComposer.isSingleLetter()) { mWordComposer.setCapitalizedModeAtStartComposingTime(inputTransaction.mShiftState); } mConnection.setComposingText(getTextWithUnderline( mWordComposer.getTypedWord()), 1); setComposingTextInternal(getTextWithUnderline(mWordComposer.getTypedWord()), 1); } else { final boolean swapWeakSpace = tryStripSpaceAndReturnWhetherShouldSwapInstead(event, inputTransaction); Loading Loading @@ -1072,7 +1071,7 @@ public final class InputLogic { mWordComposer.applyProcessedEvent(event); } if (mWordComposer.isComposingWord()) { mConnection.setComposingText(getTextWithUnderline(mWordComposer.getTypedWord()), 1); setComposingTextInternal(getTextWithUnderline(mWordComposer.getTypedWord()), 1); } else { mConnection.commitText("", 1); } Loading Loading @@ -1640,7 +1639,7 @@ public final class InputLogic { final int[] codePoints = StringUtils.toCodePointArray(stringToCommit); mWordComposer.setComposingWord(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. mLastComposedWord = LastComposedWord.NOT_A_COMPOSED_WORD; Loading Loading @@ -1973,10 +1972,10 @@ public final class InputLogic { } final String lastWord = batchInputText.substring(indexOfLastSpace); mWordComposer.setBatchInputWord(lastWord); mConnection.setComposingText(lastWord, 1); setComposingTextInternal(lastWord, 1); } else { mWordComposer.setBatchInputWord(batchInputText); mConnection.setComposingText(batchInputText, 1); setComposingTextInternal(batchInputText, 1); } mConnection.endBatchEdit(); // Space state must be updated before calling updateShiftState Loading Loading @@ -2175,6 +2174,24 @@ public final class InputLogic { 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 // TextDecorator. Loading Loading
java/src/com/android/inputmethod/keyboard/TextDecorator.java +27 −8 Original line number Diff line number Diff line Loading @@ -158,7 +158,7 @@ public class TextDecorator { if (!currentFullScreenMode && fullScreenMode) { // Currently full screen mode is not supported. // TODO: Support full screen mode. hideIndicator(); mUiOperator.hideUi(); } mIsFullScreenMode = fullScreenMode; } Loading Loading @@ -193,17 +193,36 @@ public class TextDecorator { layoutImmediately(); } private void hideIndicator() { /** * 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) { hideIndicator(); mUiOperator.hideUi(); Log.d(TAG, message); } private void cancelLayoutInternalExpectedly(final String message) { hideIndicator(); mUiOperator.hideUi(); if (DEBUG) { Log.d(TAG, message); } Loading Loading @@ -261,7 +280,7 @@ public class TextDecorator { lastCharRectFlag & CursorAnchorInfoCompatWrapper.CHARACTER_RECT_TYPE_MASK; if (lastCharRect == null || matrix == null || lastCharRectType != CursorAnchorInfoCompatWrapper.CHARACTER_RECT_TYPE_FULLY_VISIBLE) { hideIndicator(); mUiOperator.hideUi(); return; } final RectF segmentStartCharRect = new RectF(lastCharRect); Loading Loading @@ -312,13 +331,13 @@ public class TextDecorator { if (!TextUtils.isEmpty(composingText)) { // This is an unexpected case. // TODO: Document this. hideIndicator(); mUiOperator.hideUi(); return; } // 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. if (info.isInsertionMarkerClipped()) { hideIndicator(); mUiOperator.hideUi(); return; } final float insertionMarkerHolizontal = info.getInsertionMarkerHorizontal(); Loading
java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java +25 −8 Original line number Diff line number Diff line Loading @@ -649,7 +649,7 @@ public final class InputLogic { // 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 // the practice. mConnection.setComposingText(textWithUnderline, 1); setComposingTextInternal(textWithUnderline, 1); } } Loading @@ -672,7 +672,7 @@ public final class InputLogic { inputTransaction.setDidAffectContents(); } if (mWordComposer.isComposingWord()) { mConnection.setComposingText(mWordComposer.getTypedWord(), 1); setComposingTextInternal(mWordComposer.getTypedWord(), 1); inputTransaction.setDidAffectContents(); inputTransaction.setRequiresUpdateSuggestions(); } Loading Loading @@ -908,8 +908,7 @@ public final class InputLogic { if (mWordComposer.isSingleLetter()) { mWordComposer.setCapitalizedModeAtStartComposingTime(inputTransaction.mShiftState); } mConnection.setComposingText(getTextWithUnderline( mWordComposer.getTypedWord()), 1); setComposingTextInternal(getTextWithUnderline(mWordComposer.getTypedWord()), 1); } else { final boolean swapWeakSpace = tryStripSpaceAndReturnWhetherShouldSwapInstead(event, inputTransaction); Loading Loading @@ -1072,7 +1071,7 @@ public final class InputLogic { mWordComposer.applyProcessedEvent(event); } if (mWordComposer.isComposingWord()) { mConnection.setComposingText(getTextWithUnderline(mWordComposer.getTypedWord()), 1); setComposingTextInternal(getTextWithUnderline(mWordComposer.getTypedWord()), 1); } else { mConnection.commitText("", 1); } Loading Loading @@ -1640,7 +1639,7 @@ public final class InputLogic { final int[] codePoints = StringUtils.toCodePointArray(stringToCommit); mWordComposer.setComposingWord(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. mLastComposedWord = LastComposedWord.NOT_A_COMPOSED_WORD; Loading Loading @@ -1973,10 +1972,10 @@ public final class InputLogic { } final String lastWord = batchInputText.substring(indexOfLastSpace); mWordComposer.setBatchInputWord(lastWord); mConnection.setComposingText(lastWord, 1); setComposingTextInternal(lastWord, 1); } else { mWordComposer.setBatchInputWord(batchInputText); mConnection.setComposingText(batchInputText, 1); setComposingTextInternal(batchInputText, 1); } mConnection.endBatchEdit(); // Space state must be updated before calling updateShiftState Loading Loading @@ -2175,6 +2174,24 @@ public final class InputLogic { 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 // TextDecorator. Loading