diff --git a/java/src/com/android/inputmethod/event/InputTransaction.java b/java/src/com/android/inputmethod/event/InputTransaction.java index 4fe9b403e..cdff265c6 100644 --- a/java/src/com/android/inputmethod/event/InputTransaction.java +++ b/java/src/com/android/inputmethod/event/InputTransaction.java @@ -41,6 +41,7 @@ public class InputTransaction { // Outputs private int mRequiredShiftUpdate = SHIFT_NO_UPDATE; private boolean mRequiresUpdateSuggestions = false; + private boolean mDidAffectContents = false; public InputTransaction(final SettingsValues settingsValues, final Event event, final long timestamp, final int spaceState, final int shiftState) { @@ -81,4 +82,19 @@ public class InputTransaction { public boolean requiresUpdateSuggestions() { return mRequiresUpdateSuggestions; } + + /** + * Indicate that this transaction affected the contents of the editor. + */ + public void setDidAffectContents() { + mDidAffectContents = true; + } + + /** + * Find out whether this transaction affected contents of the editor. + * @return Whether this transaction affected contents of the editor. + */ + public boolean didAffectContents() { + return mDidAffectContents; + } } diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index c9a4bf5a1..865ff07d6 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -232,10 +232,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen break; case MSG_REOPEN_DICTIONARIES: latinIme.resetSuggest(); - // In theory we could call latinIme.updateSuggestionStrip() right away, but - // in the practice, the dictionary is not finished opening yet so we wouldn't - // get any suggestions. Wait one frame. - postUpdateSuggestionStrip(); + // We need to re-evaluate the currently composing word in case the script has + // changed. + postResumeSuggestions(true /* shouldIncludeResumedWordInSuggestions */); break; case MSG_UPDATE_TAIL_BATCH_INPUT_COMPLETED: latinIme.mInputLogic.onUpdateTailBatchInputCompleted( @@ -447,22 +446,22 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen static final class SubtypeState { private InputMethodSubtype mLastActiveSubtype; - private boolean mCurrentSubtypeUsed; + private boolean mCurrentSubtypeHasBeenUsed; - public void currentSubtypeUsed() { - mCurrentSubtypeUsed = true; + public void setCurrentSubtypeHasBeenUsed() { + mCurrentSubtypeHasBeenUsed = true; } public void switchSubtype(final IBinder token, final RichInputMethodManager richImm) { final InputMethodSubtype currentSubtype = richImm.getInputMethodManager() .getCurrentInputMethodSubtype(); final InputMethodSubtype lastActiveSubtype = mLastActiveSubtype; - final boolean currentSubtypeUsed = mCurrentSubtypeUsed; - if (currentSubtypeUsed) { + final boolean currentSubtypeHasBeenUsed = mCurrentSubtypeHasBeenUsed; + if (currentSubtypeHasBeenUsed) { mLastActiveSubtype = currentSubtype; - mCurrentSubtypeUsed = false; + mCurrentSubtypeHasBeenUsed = false; } - if (currentSubtypeUsed + if (currentSubtypeHasBeenUsed && richImm.checkIfSubtypeBelongsToThisImeAndEnabled(lastActiveSubtype) && !currentSubtype.equals(lastActiveSubtype)) { richImm.setInputMethodAndSubtype(token, lastActiveSubtype); @@ -796,8 +795,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // span, so we should reset our state unconditionally, even if restarting is true. // We also tell the input logic about the combining rules for the current subtype, so // it can adjust its combiners if needed. - mInputLogic.startInput(restarting, editorInfo, - mSubtypeSwitcher.getCombiningRulesExtraValueOfCurrentSubtype()); + mInputLogic.startInput(mSubtypeSwitcher.getCombiningRulesExtraValueOfCurrentSubtype()); // Note: the following does a round-trip IPC on the main thread: be careful final Locale currentLocale = mSubtypeSwitcher.getCurrentSubtypeLocale(); @@ -930,12 +928,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mKeyboardSwitcher.requestUpdatingShiftState(getCurrentAutoCapsState(), getCurrentRecapitalizeState()); } - - mSubtypeState.currentSubtypeUsed(); } @Override - public void onUpdateCursor(Rect rect) { + public void onUpdateCursor(final Rect rect) { if (DEBUG) { Log.i(TAG, "onUpdateCursor:" + rect.toShortString()); } @@ -1268,9 +1264,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen public void onTextInput(final String rawText) { // TODO: have the keyboard pass the correct key code when we need it. final Event event = Event.createSoftwareTextEvent(rawText, Event.NOT_A_KEY_CODE); - mInputLogic.onTextInput(mSettings.getCurrent(), event, mHandler); - mKeyboardSwitcher.requestUpdatingShiftState(getCurrentAutoCapsState(), - getCurrentRecapitalizeState()); + final InputTransaction completeInputTransaction = + mInputLogic.onTextInput(mSettings.getCurrent(), event, + mKeyboardSwitcher.getKeyboardShiftMode(), mHandler); + updateStateAfterInputTransaction(completeInputTransaction); mKeyboardSwitcher.onCodeInput(Constants.CODE_OUTPUT_TEXT, getCurrentAutoCapsState(), getCurrentRecapitalizeState()); } @@ -1490,6 +1487,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen if (inputTransaction.requiresUpdateSuggestions()) { mHandler.postUpdateSuggestionStrip(); } + if (inputTransaction.didAffectContents()) { + mSubtypeState.setCurrentSubtypeHasBeenUsed(); + } } private void hapticAndAudioFeedback(final int code, final int repeatCount) { diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java index 158663d96..8831d36f7 100644 --- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java +++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java @@ -119,17 +119,10 @@ public final class InputLogic { * Initializes the input logic for input in an editor. * * Call this when input starts or restarts in some editor (typically, in onStartInputView). - * If the input is starting in the same field as before, set `restarting' to true. This allows - * the input logic to reset only necessary stuff and save performance. Also, when restarting - * some things must not be done (for example, the keyboard should not be reset to the - * alphabetic layout), so do not send false to this just in case. * - * @param restarting whether input is starting in the same field as before. Unused for now. - * @param editorInfo the editorInfo associated with the editor. * @param combiningSpec the combining spec string for this subtype */ - public void startInput(final boolean restarting, final EditorInfo editorInfo, - final String combiningSpec) { + public void startInput(final String combiningSpec) { mEnteredText = null; mWordComposer.restartCombining(combiningSpec); resetComposingState(true /* alsoResetLastComposedWord */); @@ -154,7 +147,8 @@ public final class InputLogic { * @param combiningSpec the spec string for the combining rules */ public void onSubtypeChanged(final String combiningSpec) { - mWordComposer.restartCombining(combiningSpec); + finishInput(); + startInput(combiningSpec); } /** @@ -187,11 +181,16 @@ public final class InputLogic { * * @param settingsValues the current values of the settings. * @param event the input event containing the data. + * @return the complete transaction object */ - public void onTextInput(final SettingsValues settingsValues, final Event event, + public InputTransaction onTextInput(final SettingsValues settingsValues, final Event event, + final int keyboardShiftMode, // TODO: remove this argument final LatinIME.UIHandler handler) { final String rawText = event.mText.toString(); + final InputTransaction inputTransaction = new InputTransaction(settingsValues, event, + SystemClock.uptimeMillis(), mSpaceState, + getActualCapsMode(settingsValues, keyboardShiftMode)); mConnection.beginBatchEdit(); if (mWordComposer.isComposingWord()) { commitCurrentAutoCorrection(settingsValues, rawText, handler); @@ -208,6 +207,9 @@ public final class InputLogic { // Space state must be updated before calling updateShiftState mSpaceState = SpaceState.NONE; mEnteredText = text; + inputTransaction.setDidAffectContents(); + inputTransaction.requireShiftUpdate(InputTransaction.SHIFT_UPDATE_NOW); + return inputTransaction; } /** @@ -238,6 +240,9 @@ public final class InputLogic { final Event event = Event.createSuggestionPickedEvent(suggestionInfo); final InputTransaction inputTransaction = new InputTransaction(settingsValues, event, SystemClock.uptimeMillis(), mSpaceState, keyboardShiftState); + // Manual pick affects the contents of the editor, so we take note of this. It's important + // for the sequence of language switching. + inputTransaction.setDidAffectContents(); mConnection.beginBatchEdit(); if (SpaceState.PHANTOM == mSpaceState && suggestion.length() > 0 // In the batch input mode, a manually picked suggested word should just replace @@ -404,6 +409,8 @@ public final class InputLogic { switch (event.mKeyCode) { case Constants.CODE_DELETE: handleBackspace(inputTransaction, currentKeyboardScriptId); + // Backspace is a functional key, but it affects the contents of the editor. + inputTransaction.setDidAffectContents(); break; case Constants.CODE_SHIFT: performRecapitalization(inputTransaction.mSettingsValues); @@ -457,11 +464,15 @@ public final class InputLogic { inputTransaction.mTimestamp, inputTransaction.mSpaceState, inputTransaction.mShiftState); didAutoCorrect = handleNonSpecialCharacter(tmpTransaction, handler); + // Shift + Enter is treated as a functional key but it results in adding a new + // line, so that does affect the contents of the editor. + inputTransaction.setDidAffectContents(); break; default: throw new RuntimeException("Unknown key code : " + event.mKeyCode); } } else { + inputTransaction.setDidAffectContents(); switch (event.mCodePoint) { case Constants.CODE_ENTER: final EditorInfo editorInfo = getCurrentInputEditorInfo();