aboutsummaryrefslogtreecommitdiffstats
path: root/java/src
diff options
context:
space:
mode:
Diffstat (limited to 'java/src')
-rw-r--r--java/src/com/android/inputmethod/event/InputTransaction.java16
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java34
-rw-r--r--java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java287
3 files changed, 201 insertions, 136 deletions
diff --git a/java/src/com/android/inputmethod/event/InputTransaction.java b/java/src/com/android/inputmethod/event/InputTransaction.java
index cdff265c6..5bc9111de 100644
--- a/java/src/com/android/inputmethod/event/InputTransaction.java
+++ b/java/src/com/android/inputmethod/event/InputTransaction.java
@@ -42,6 +42,7 @@ public class InputTransaction {
private int mRequiredShiftUpdate = SHIFT_NO_UPDATE;
private boolean mRequiresUpdateSuggestions = false;
private boolean mDidAffectContents = false;
+ private boolean mDidAutoCorrect = false;
public InputTransaction(final SettingsValues settingsValues, final Event event,
final long timestamp, final int spaceState, final int shiftState) {
@@ -97,4 +98,19 @@ public class InputTransaction {
public boolean didAffectContents() {
return mDidAffectContents;
}
+
+ /**
+ * Indicate that this transaction performed an auto-correction.
+ */
+ public void setDidAutoCorrect() {
+ mDidAutoCorrect = true;
+ }
+
+ /**
+ * Find out whether this transaction performed an auto-correction.
+ * @return Whether this transaction performed an auto-correction.
+ */
+ public boolean didAutoCorrect() {
+ return mDidAutoCorrect;
+ }
}
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 719aeac77..4adc28d7a 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -248,7 +248,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
break;
case MSG_RESET_CACHES:
final SettingsValues settingsValues = latinIme.mSettings.getCurrent();
- if (latinIme.mInputLogic.retryResetCachesAndReturnSuccess(settingsValues,
+ if (latinIme.mInputLogic.retryResetCachesAndReturnSuccess(
msg.arg1 == 1 /* tryResumeSuggestions */,
msg.arg2 /* remainingTries */, this /* handler */)) {
// If we were able to reset the caches, then we can reload the keyboard.
@@ -752,8 +752,30 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
loadKeyboard();
}
+ /**
+ * A class that holds information to pass from onStartInputInternal to onStartInputViewInternal
+ *
+ * OnStartInput needs to reload the settings and that will prevent onStartInputViewInternal
+ * from comparing the old settings with the new ones, so we use this memory to pass the
+ * necessary information along.
+ */
+ private static class EditorChangeInfo {
+ public final boolean mIsSameInputType;
+ public final boolean mHasSameOrientation;
+ public EditorChangeInfo(final boolean isSameInputType, final boolean hasSameOrientation) {
+ mIsSameInputType = isSameInputType;
+ mHasSameOrientation = hasSameOrientation;
+ }
+ }
+
+ private EditorChangeInfo mLastEditorChangeInfo;
+
private void onStartInputInternal(final EditorInfo editorInfo, final boolean restarting) {
super.onStartInput(editorInfo, restarting);
+ SettingsValues currentSettingsValues = mSettings.getCurrent();
+ mLastEditorChangeInfo = new EditorChangeInfo(
+ currentSettingsValues.isSameInputType(editorInfo),
+ currentSettingsValues.hasSameOrientation(getResources().getConfiguration()));
}
@SuppressWarnings("deprecation")
@@ -763,9 +785,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
final KeyboardSwitcher switcher = mKeyboardSwitcher;
switcher.updateKeyboardTheme();
final MainKeyboardView mainKeyboardView = switcher.getMainKeyboardView();
- // If we are starting input in a different text field from before, we'll have to reload
- // settings, so currentSettingsValues can't be final.
- SettingsValues currentSettingsValues = mSettings.getCurrent();
if (editorInfo == null) {
Log.e(TAG, "Null EditorInfo in onStartInputView()");
@@ -808,7 +827,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
accessUtils.onStartInputViewInternal(mainKeyboardView, editorInfo, restarting);
}
- final boolean inputTypeChanged = !currentSettingsValues.isSameInputType(editorInfo);
+ final boolean inputTypeChanged = !mLastEditorChangeInfo.mIsSameInputType;
final boolean isDifferentTextField = !restarting || inputTypeChanged;
if (isDifferentTextField) {
mSubtypeSwitcher.updateParametersOnStartInputView();
@@ -853,13 +872,12 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
canReachInputConnection = true;
}
- if (isDifferentTextField ||
- !currentSettingsValues.hasSameOrientation(getResources().getConfiguration())) {
+ if (isDifferentTextField || !mLastEditorChangeInfo.mHasSameOrientation) {
loadSettings();
}
+ final SettingsValues currentSettingsValues = mSettings.getCurrent();
if (isDifferentTextField) {
mainKeyboardView.closing();
- currentSettingsValues = mSettings.getCurrent();
if (currentSettingsValues.mAutoCorrectionEnabledPerUserSettings) {
suggest.setAutoCorrectionThreshold(
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
index dee7cd466..9e20abc17 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
@@ -426,121 +426,14 @@ public final class InputLogic {
cancelDoubleSpacePeriodCountdown();
}
- boolean didAutoCorrect = false;
if (processedEvent.isConsumed()) {
- // A consumed event may have text to commit and an update to the composing state, so
- // we evaluate both. With some combiners, it's possible than an event contains both
- // and we enter both of the following if clauses.
- final CharSequence textToCommit = processedEvent.getTextToCommit();
- if (!TextUtils.isEmpty(textToCommit)) {
- mConnection.commitText(textToCommit, 1);
- inputTransaction.setDidAffectContents();
- }
- if (mWordComposer.isComposingWord()) {
- mConnection.setComposingText(mWordComposer.getTypedWord(), 1);
- inputTransaction.setDidAffectContents();
- inputTransaction.setRequiresUpdateSuggestions();
- }
+ handleConsumedEvent(inputTransaction);
} else if (processedEvent.isFunctionalKeyEvent()) {
- // A special key, like delete, shift, emoji, or the settings key.
- switch (processedEvent.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);
- inputTransaction.requireShiftUpdate(InputTransaction.SHIFT_UPDATE_NOW);
- if (mSuggestedWords.mIsPrediction) {
- inputTransaction.setRequiresUpdateSuggestions();
- }
- break;
- case Constants.CODE_CAPSLOCK:
- // Note: Changing keyboard to shift lock state is handled in
- // {@link KeyboardSwitcher#onCodeInput(int)}.
- break;
- case Constants.CODE_SYMBOL_SHIFT:
- // Note: Calling back to the keyboard on the symbol Shift key is handled in
- // {@link #onPressKey(int,int,boolean)} and {@link #onReleaseKey(int,boolean)}.
- break;
- case Constants.CODE_SWITCH_ALPHA_SYMBOL:
- // Note: Calling back to the keyboard on symbol key is handled in
- // {@link #onPressKey(int,int,boolean)} and {@link #onReleaseKey(int,boolean)}.
- break;
- case Constants.CODE_SETTINGS:
- onSettingsKeyPressed();
- break;
- case Constants.CODE_SHORTCUT:
- // We need to switch to the shortcut IME. This is handled by LatinIME since the
- // input logic has no business with IME switching.
- break;
- case Constants.CODE_ACTION_NEXT:
- performEditorAction(EditorInfo.IME_ACTION_NEXT);
- break;
- case Constants.CODE_ACTION_PREVIOUS:
- performEditorAction(EditorInfo.IME_ACTION_PREVIOUS);
- break;
- case Constants.CODE_LANGUAGE_SWITCH:
- handleLanguageSwitchKey();
- break;
- case Constants.CODE_EMOJI:
- // Note: Switching emoji keyboard is being handled in
- // {@link KeyboardState#onCodeInput(int,int)}.
- break;
- case Constants.CODE_ALPHA_FROM_EMOJI:
- // Note: Switching back from Emoji keyboard to the main keyboard is being
- // handled in {@link KeyboardState#onCodeInput(int,int)}.
- break;
- case Constants.CODE_SHIFT_ENTER:
- // TODO: remove this object
- final Event tmpEvent = Event.createSoftwareKeypressEvent(Constants.CODE_ENTER,
- processedEvent.mKeyCode, processedEvent.mX, processedEvent.mY,
- processedEvent.isKeyRepeat());
- final InputTransaction tmpTransaction = new InputTransaction(
- inputTransaction.mSettingsValues, tmpEvent,
- 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 : " + processedEvent.mKeyCode);
- }
+ handleFunctionalEvent(inputTransaction, currentKeyboardScriptId, handler);
} else {
- inputTransaction.setDidAffectContents();
- switch (processedEvent.mCodePoint) {
- case Constants.CODE_ENTER:
- final EditorInfo editorInfo = getCurrentInputEditorInfo();
- final int imeOptionsActionId =
- InputTypeUtils.getImeOptionsActionIdFromEditorInfo(editorInfo);
- if (InputTypeUtils.IME_ACTION_CUSTOM_LABEL == imeOptionsActionId) {
- // Either we have an actionLabel and we should performEditorAction with
- // actionId regardless of its value.
- performEditorAction(editorInfo.actionId);
- } else if (EditorInfo.IME_ACTION_NONE != imeOptionsActionId) {
- // We didn't have an actionLabel, but we had another action to execute.
- // EditorInfo.IME_ACTION_NONE explicitly means no action. In contrast,
- // EditorInfo.IME_ACTION_UNSPECIFIED is the default value for an action, so it
- // means there should be an action and the app didn't bother to set a specific
- // code for it - presumably it only handles one. It does not have to be treated
- // in any specific way: anything that is not IME_ACTION_NONE should be sent to
- // performEditorAction.
- performEditorAction(imeOptionsActionId);
- } else {
- // No action label, and the action from imeOptions is NONE: this is a regular
- // enter key that should input a carriage return.
- didAutoCorrect = handleNonSpecialCharacter(inputTransaction, handler);
- }
- break;
- default:
- didAutoCorrect = handleNonSpecialCharacter(inputTransaction, handler);
- break;
- }
+ handleNonFunctionalEvent(inputTransaction, handler);
}
- if (!didAutoCorrect && processedEvent.mKeyCode != Constants.CODE_SHIFT
+ if (!inputTransaction.didAutoCorrect() && processedEvent.mKeyCode != Constants.CODE_SHIFT
&& processedEvent.mKeyCode != Constants.CODE_CAPSLOCK
&& processedEvent.mKeyCode != Constants.CODE_SWITCH_ALPHA_SYMBOL)
mLastComposedWord.deactivate();
@@ -686,6 +579,155 @@ public final class InputLogic {
}
/**
+ * Handle a consumed event.
+ *
+ * Consumed events represent events that have already been consumed, typically by the
+ * combining chain.
+ *
+ * @param inputTransaction The transaction in progress.
+ */
+ private void handleConsumedEvent(final InputTransaction inputTransaction) {
+ // A consumed event may have text to commit and an update to the composing state, so
+ // we evaluate both. With some combiners, it's possible than an event contains both
+ // and we enter both of the following if clauses.
+ final CharSequence textToCommit = inputTransaction.mEvent.getTextToCommit();
+ if (!TextUtils.isEmpty(textToCommit)) {
+ mConnection.commitText(textToCommit, 1);
+ inputTransaction.setDidAffectContents();
+ }
+ if (mWordComposer.isComposingWord()) {
+ mConnection.setComposingText(mWordComposer.getTypedWord(), 1);
+ inputTransaction.setDidAffectContents();
+ inputTransaction.setRequiresUpdateSuggestions();
+ }
+ }
+
+ /**
+ * Handle a functional key event.
+ *
+ * A functional event is a special key, like delete, shift, emoji, or the settings key.
+ * Non-special keys are those that generate a single code point.
+ * This includes all letters, digits, punctuation, separators, emoji. It excludes keys that
+ * manage keyboard-related stuff like shift, language switch, settings, layout switch, or
+ * any key that results in multiple code points like the ".com" key.
+ *
+ * @param inputTransaction The transaction in progress.
+ */
+ private void handleFunctionalEvent(final InputTransaction inputTransaction,
+ // TODO: remove these arguments
+ final int currentKeyboardScriptId, final LatinIME.UIHandler handler) {
+ final Event event = inputTransaction.mEvent;
+ 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);
+ inputTransaction.requireShiftUpdate(InputTransaction.SHIFT_UPDATE_NOW);
+ if (mSuggestedWords.mIsPrediction) {
+ inputTransaction.setRequiresUpdateSuggestions();
+ }
+ break;
+ case Constants.CODE_CAPSLOCK:
+ // Note: Changing keyboard to shift lock state is handled in
+ // {@link KeyboardSwitcher#onCodeInput(int)}.
+ break;
+ case Constants.CODE_SYMBOL_SHIFT:
+ // Note: Calling back to the keyboard on the symbol Shift key is handled in
+ // {@link #onPressKey(int,int,boolean)} and {@link #onReleaseKey(int,boolean)}.
+ break;
+ case Constants.CODE_SWITCH_ALPHA_SYMBOL:
+ // Note: Calling back to the keyboard on symbol key is handled in
+ // {@link #onPressKey(int,int,boolean)} and {@link #onReleaseKey(int,boolean)}.
+ break;
+ case Constants.CODE_SETTINGS:
+ onSettingsKeyPressed();
+ break;
+ case Constants.CODE_SHORTCUT:
+ // We need to switch to the shortcut IME. This is handled by LatinIME since the
+ // input logic has no business with IME switching.
+ break;
+ case Constants.CODE_ACTION_NEXT:
+ performEditorAction(EditorInfo.IME_ACTION_NEXT);
+ break;
+ case Constants.CODE_ACTION_PREVIOUS:
+ performEditorAction(EditorInfo.IME_ACTION_PREVIOUS);
+ break;
+ case Constants.CODE_LANGUAGE_SWITCH:
+ handleLanguageSwitchKey();
+ break;
+ case Constants.CODE_EMOJI:
+ // Note: Switching emoji keyboard is being handled in
+ // {@link KeyboardState#onCodeInput(int,int)}.
+ break;
+ case Constants.CODE_ALPHA_FROM_EMOJI:
+ // Note: Switching back from Emoji keyboard to the main keyboard is being
+ // handled in {@link KeyboardState#onCodeInput(int,int)}.
+ break;
+ case Constants.CODE_SHIFT_ENTER:
+ // TODO: remove this object
+ final Event tmpEvent = Event.createSoftwareKeypressEvent(Constants.CODE_ENTER,
+ event.mKeyCode, event.mX, event.mY, event.isKeyRepeat());
+ final InputTransaction tmpTransaction = new InputTransaction(
+ inputTransaction.mSettingsValues, tmpEvent,
+ inputTransaction.mTimestamp, inputTransaction.mSpaceState,
+ inputTransaction.mShiftState);
+ 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);
+ }
+ }
+
+ /**
+ * Handle an event that is not a functional event.
+ *
+ * These events are generally events that cause input, but in some cases they may do other
+ * things like trigger an editor action.
+ *
+ * @param inputTransaction The transaction in progress.
+ */
+ private void handleNonFunctionalEvent(final InputTransaction inputTransaction,
+ // TODO: remove this argument
+ final LatinIME.UIHandler handler) {
+ final Event event = inputTransaction.mEvent;
+ inputTransaction.setDidAffectContents();
+ switch (event.mCodePoint) {
+ case Constants.CODE_ENTER:
+ final EditorInfo editorInfo = getCurrentInputEditorInfo();
+ final int imeOptionsActionId =
+ InputTypeUtils.getImeOptionsActionIdFromEditorInfo(editorInfo);
+ if (InputTypeUtils.IME_ACTION_CUSTOM_LABEL == imeOptionsActionId) {
+ // Either we have an actionLabel and we should performEditorAction with
+ // actionId regardless of its value.
+ performEditorAction(editorInfo.actionId);
+ } else if (EditorInfo.IME_ACTION_NONE != imeOptionsActionId) {
+ // We didn't have an actionLabel, but we had another action to execute.
+ // EditorInfo.IME_ACTION_NONE explicitly means no action. In contrast,
+ // EditorInfo.IME_ACTION_UNSPECIFIED is the default value for an action, so it
+ // means there should be an action and the app didn't bother to set a specific
+ // code for it - presumably it only handles one. It does not have to be treated
+ // in any specific way: anything that is not IME_ACTION_NONE should be sent to
+ // performEditorAction.
+ performEditorAction(imeOptionsActionId);
+ } else {
+ // No action label, and the action from imeOptions is NONE: this is a regular
+ // enter key that should input a carriage return.
+ handleNonSpecialCharacter(inputTransaction, handler);
+ }
+ break;
+ default:
+ handleNonSpecialCharacter(inputTransaction, handler);
+ break;
+ }
+ }
+
+ /**
* Handle inputting a code point to the editor.
*
* Non-special keys are those that generate a single code point.
@@ -694,20 +736,16 @@ public final class InputLogic {
* any key that results in multiple code points like the ".com" key.
*
* @param inputTransaction The transaction in progress.
- * @return whether this caused an auto-correction to happen.
*/
- private boolean handleNonSpecialCharacter(final InputTransaction inputTransaction,
+ private void handleNonSpecialCharacter(final InputTransaction inputTransaction,
// TODO: remove this argument
final LatinIME.UIHandler handler) {
final int codePoint = inputTransaction.mEvent.mCodePoint;
mSpaceState = SpaceState.NONE;
- final boolean didAutoCorrect;
if (inputTransaction.mSettingsValues.isWordSeparator(codePoint)
|| Character.getType(codePoint) == Character.OTHER_SYMBOL) {
- didAutoCorrect = handleSeparator(inputTransaction,
- inputTransaction.mEvent.isSuggestionStripPress(), handler);
+ handleSeparator(inputTransaction, handler);
} else {
- didAutoCorrect = false;
if (SpaceState.PHANTOM == inputTransaction.mSpaceState) {
if (mWordComposer.isCursorFrontOrMiddleOfComposingWord()) {
// If we are in the middle of a recorrection, we need to commit the recorrection
@@ -720,7 +758,6 @@ public final class InputLogic {
}
handleNonSeparator(inputTransaction.mSettingsValues, inputTransaction);
}
- return didAutoCorrect;
}
/**
@@ -805,16 +842,12 @@ public final class InputLogic {
/**
* Handle input of a separator code point.
* @param inputTransaction The transaction in progress.
- * @param isFromSuggestionStrip whether this code point comes from the suggestion strip.
- * @return whether this caused an auto-correction to happen.
*/
- private boolean handleSeparator(final InputTransaction inputTransaction,
- final boolean isFromSuggestionStrip,
+ private void handleSeparator(final InputTransaction inputTransaction,
// TODO: remove this argument
final LatinIME.UIHandler handler) {
final int codePoint = inputTransaction.mEvent.mCodePoint;
final SettingsValues settingsValues = inputTransaction.mSettingsValues;
- boolean didAutoCorrect = false;
final boolean wasComposingWord = mWordComposer.isComposingWord();
// We avoid sending spaces in languages without spaces if we were composing.
final boolean shouldAvoidSendingCode = Constants.CODE_SPACE == codePoint
@@ -832,7 +865,7 @@ public final class InputLogic {
final String separator = shouldAvoidSendingCode ? LastComposedWord.NOT_A_SEPARATOR
: StringUtils.newSingleCodePointString(codePoint);
commitCurrentAutoCorrection(settingsValues, separator, handler);
- didAutoCorrect = true;
+ inputTransaction.setDidAutoCorrect();
} else {
commitTyped(settingsValues,
StringUtils.newSingleCodePointString(codePoint));
@@ -910,7 +943,6 @@ public final class InputLogic {
}
inputTransaction.requireShiftUpdate(InputTransaction.SHIFT_UPDATE_NOW);
- return didAutoCorrect;
}
/**
@@ -1974,14 +2006,13 @@ public final class InputLogic {
* This method handles the retry, and re-schedules a new retry if we still can't access.
* We only retry up to 5 times before giving up.
*
- * @param settingsValues the current values of the settings.
* @param tryResumeSuggestions Whether we should resume suggestions or not.
* @param remainingTries How many times we may try again before giving up.
* @return whether true if the caches were successfully reset, false otherwise.
*/
// TODO: make this private
- public boolean retryResetCachesAndReturnSuccess(final SettingsValues settingsValues,
- final boolean tryResumeSuggestions, final int remainingTries,
+ public boolean retryResetCachesAndReturnSuccess(final boolean tryResumeSuggestions,
+ final int remainingTries,
// TODO: remove these arguments
final LatinIME.UIHandler handler) {
final boolean shouldFinishComposition = mConnection.hasSelection()