[IL2] Move onCodeInput to InputLogic.
Bug: 8636060 Change-Id: I8c5c028d81183adb0167b2034ee01de8048edafbmain
parent
7bd2a75ca1
commit
cddf4f9d78
|
@ -154,6 +154,9 @@ public final class Constants {
|
|||
// Must be equal to MAX_WORD_LENGTH in native/jni/src/defines.h
|
||||
public static final int DICTIONARY_MAX_WORD_LENGTH = 48;
|
||||
|
||||
// Key events coming any faster than this are long-presses.
|
||||
public static final int LONG_PRESS_MILLISECONDS = 200;
|
||||
|
||||
public static boolean isValidCoordinate(final int coordinate) {
|
||||
// Detect {@link NOT_A_COORDINATE}, {@link SUGGESTION_STRIP_COORDINATE},
|
||||
// and {@link SPELL_CHECKER_COORDINATE}.
|
||||
|
@ -242,5 +245,4 @@ public final class Constants {
|
|||
private Constants() {
|
||||
// This utility class is not publicly instantiable.
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -77,6 +77,7 @@ import com.android.inputmethod.latin.Suggest.OnGetSuggestedWordsCallback;
|
|||
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
|
||||
import com.android.inputmethod.latin.define.ProductionFlag;
|
||||
import com.android.inputmethod.latin.inputlogic.InputLogic;
|
||||
import com.android.inputmethod.latin.inputlogic.SpaceState;
|
||||
import com.android.inputmethod.latin.personalization.DictionaryDecayBroadcastReciever;
|
||||
import com.android.inputmethod.latin.personalization.PersonalizationDictionarySessionRegister;
|
||||
import com.android.inputmethod.latin.personalization.UserHistoryDictionary;
|
||||
|
@ -122,8 +123,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
|
||||
// How many continuous deletes at which to start deleting at a higher speed.
|
||||
private static final int DELETE_ACCELERATE_AT = 20;
|
||||
// Key events coming any faster than this are long-presses.
|
||||
private static final int QUICK_PRESS = 200;
|
||||
|
||||
private static final int PENDING_IMS_CALLBACK_DURATION = 800;
|
||||
|
||||
|
@ -138,22 +137,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
*/
|
||||
private static final String SCHEME_PACKAGE = "package";
|
||||
|
||||
private static final int SPACE_STATE_NONE = 0;
|
||||
// Double space: the state where the user pressed space twice quickly, which LatinIME
|
||||
// resolved as period-space. Undoing this converts the period to a space.
|
||||
private static final int SPACE_STATE_DOUBLE = 1;
|
||||
// Swap punctuation: the state where a weak space and a punctuation from the suggestion strip
|
||||
// have just been swapped. Undoing this swaps them back; the space is still considered weak.
|
||||
private static final int SPACE_STATE_SWAP_PUNCTUATION = 2;
|
||||
// Weak space: a space that should be swapped only by suggestion strip punctuation. Weak
|
||||
// spaces happen when the user presses space, accepting the current suggestion (whether
|
||||
// it's an auto-correction or not).
|
||||
private static final int SPACE_STATE_WEAK = 3;
|
||||
// Phantom space: a not-yet-inserted space that should get inserted on the next input,
|
||||
// character provided it's not a separator. If it's a separator, the phantom space is dropped.
|
||||
// Phantom spaces happen when a user chooses a word from the suggestion strip.
|
||||
private static final int SPACE_STATE_PHANTOM = 4;
|
||||
|
||||
private final Settings mSettings;
|
||||
private final InputLogic mInputLogic = new InputLogic(this);
|
||||
|
||||
|
@ -803,7 +786,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
mInputLogic.mEnteredText = null;
|
||||
resetComposingState(true /* alsoResetLastComposedWord */);
|
||||
mInputLogic.mDeleteCount = 0;
|
||||
mInputLogic.mSpaceState = SPACE_STATE_NONE;
|
||||
mInputLogic.mSpaceState = SpaceState.NONE;
|
||||
mInputLogic.mRecapitalizeStatus.deactivate();
|
||||
mInputLogic.mCurrentlyPressedHardwareKeys.clear();
|
||||
|
||||
|
@ -1038,7 +1021,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
// the call to updateShiftState.
|
||||
// We set this to NONE because after a cursor move, we don't want the space
|
||||
// state-related special processing to kick in.
|
||||
mInputLogic.mSpaceState = SPACE_STATE_NONE;
|
||||
mInputLogic.mSpaceState = SpaceState.NONE;
|
||||
|
||||
// TODO: is it still necessary to test for composingSpan related stuff?
|
||||
final boolean selectionChangedOrSafeToReset = selectionChanged
|
||||
|
@ -1332,7 +1315,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
// Warning: this depends on mSpaceState, which may not be the most current value. If
|
||||
// mSpaceState gets updated later, whoever called this may need to be told about it.
|
||||
return mInputLogic.mConnection.getCursorCapsMode(inputType, currentSettingsValues,
|
||||
SPACE_STATE_PHANTOM == mInputLogic.mSpaceState);
|
||||
SpaceState.PHANTOM == mInputLogic.mSpaceState);
|
||||
}
|
||||
|
||||
public int getCurrentRecapitalizeState() {
|
||||
|
@ -1441,7 +1424,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
mUserDictionary.addWordToUserDictionary(wordToEdit);
|
||||
}
|
||||
|
||||
private void onSettingsKeyPressed() {
|
||||
// TODO[IL]: Rework the route through which this is called.
|
||||
public void onSettingsKeyPressed() {
|
||||
if (isShowingOptionDialog()) return;
|
||||
showSubtypeSelectorAndSettings();
|
||||
}
|
||||
|
@ -1464,12 +1448,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
return mOptionsDialog != null && mOptionsDialog.isShowing();
|
||||
}
|
||||
|
||||
private void performEditorAction(final int actionId) {
|
||||
mInputLogic.mConnection.performEditorAction(actionId);
|
||||
}
|
||||
|
||||
// TODO: Revise the language switch key behavior to make it much smarter and more reasonable.
|
||||
private void handleLanguageSwitchKey() {
|
||||
// TODO[IL]: Move a part of this to InputLogic and straighten out the interface for this.
|
||||
public void handleLanguageSwitchKey() {
|
||||
final IBinder token = getWindow().getWindow().getAttributes().token;
|
||||
if (mSettings.getCurrent().mIncludesOtherImesInLanguageSwitchList) {
|
||||
mRichImm.switchToNextInputMethod(token, false /* onlyCurrentIme */);
|
||||
|
@ -1513,121 +1494,13 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
// Implementation of {@link KeyboardActionListener}.
|
||||
@Override
|
||||
public void onCodeInput(final int primaryCode, final int x, final int y) {
|
||||
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
|
||||
ResearchLogger.latinIME_onCodeInput(primaryCode, x, y);
|
||||
}
|
||||
final long when = SystemClock.uptimeMillis();
|
||||
if (primaryCode != Constants.CODE_DELETE
|
||||
|| when > mInputLogic.mLastKeyTime + QUICK_PRESS) {
|
||||
mInputLogic.mDeleteCount = 0;
|
||||
}
|
||||
mInputLogic.mLastKeyTime = when;
|
||||
mInputLogic.mConnection.beginBatchEdit();
|
||||
final KeyboardSwitcher switcher = mKeyboardSwitcher;
|
||||
// The space state depends only on the last character pressed and its own previous
|
||||
// state. Here, we revert the space state to neutral if the key is actually modifying
|
||||
// the input contents (any non-shift key), which is what we should do for
|
||||
// all inputs that do not result in a special state. Each character handling is then
|
||||
// free to override the state as they see fit.
|
||||
final int spaceState = mInputLogic.mSpaceState;
|
||||
if (!mInputLogic.mWordComposer.isComposingWord()) {
|
||||
mInputLogic.mIsAutoCorrectionIndicatorOn = false;
|
||||
}
|
||||
|
||||
// TODO: Consolidate the double-space period timer, mLastKeyTime, and the space state.
|
||||
if (primaryCode != Constants.CODE_SPACE) {
|
||||
mHandler.cancelDoubleSpacePeriodTimer();
|
||||
}
|
||||
|
||||
boolean didAutoCorrect = false;
|
||||
switch (primaryCode) {
|
||||
case Constants.CODE_DELETE:
|
||||
mInputLogic.mSpaceState = SPACE_STATE_NONE;
|
||||
handleBackspace(spaceState);
|
||||
LatinImeLogger.logOnDelete(x, y);
|
||||
break;
|
||||
case Constants.CODE_SHIFT:
|
||||
// Note: Calling back to the keyboard on Shift key is handled in
|
||||
// {@link #onPressKey(int,int,boolean)} and {@link #onReleaseKey(int,boolean)}.
|
||||
final Keyboard currentKeyboard = switcher.getKeyboard();
|
||||
if (null != currentKeyboard && currentKeyboard.mId.isAlphabetKeyboard()) {
|
||||
// TODO: Instead of checking for alphabetic keyboard here, separate keycodes for
|
||||
// alphabetic shift and shift while in symbol layout.
|
||||
handleRecapitalize();
|
||||
}
|
||||
break;
|
||||
case Constants.CODE_CAPSLOCK:
|
||||
// Note: Changing keyboard to shift lock state is handled in
|
||||
// {@link KeyboardSwitcher#onCodeInput(int)}.
|
||||
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:
|
||||
mSubtypeSwitcher.switchToShortcutIME(this);
|
||||
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_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(Constants.CODE_ENTER, x, y, spaceState);
|
||||
}
|
||||
break;
|
||||
case Constants.CODE_SHIFT_ENTER:
|
||||
didAutoCorrect = handleNonSpecialCharacter(Constants.CODE_ENTER, x, y, spaceState);
|
||||
break;
|
||||
default:
|
||||
didAutoCorrect = handleNonSpecialCharacter(primaryCode, x, y, spaceState);
|
||||
break;
|
||||
}
|
||||
switcher.onCodeInput(primaryCode);
|
||||
// Reset after any single keystroke, except shift, capslock, and symbol-shift
|
||||
if (!didAutoCorrect && primaryCode != Constants.CODE_SHIFT
|
||||
&& primaryCode != Constants.CODE_CAPSLOCK
|
||||
&& primaryCode != Constants.CODE_SWITCH_ALPHA_SYMBOL)
|
||||
mInputLogic.mLastComposedWord.deactivate();
|
||||
if (Constants.CODE_DELETE != primaryCode) {
|
||||
mInputLogic.mEnteredText = null;
|
||||
}
|
||||
mInputLogic.mConnection.endBatchEdit();
|
||||
mInputLogic.onCodeInput(primaryCode, x, y, mHandler, mKeyboardSwitcher, mSubtypeSwitcher);
|
||||
}
|
||||
|
||||
private boolean handleNonSpecialCharacter(final int primaryCode, final int x, final int y,
|
||||
// TODO[IL]: Move this to InputLogic and make it private again.
|
||||
public boolean handleNonSpecialCharacter(final int primaryCode, final int x, final int y,
|
||||
final int spaceState) {
|
||||
mInputLogic.mSpaceState = SPACE_STATE_NONE;
|
||||
mInputLogic.mSpaceState = SpaceState.NONE;
|
||||
final boolean didAutoCorrect;
|
||||
final SettingsValues settingsValues = mSettings.getCurrent();
|
||||
if (settingsValues.isWordSeparator(primaryCode)
|
||||
|
@ -1635,7 +1508,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
didAutoCorrect = handleSeparator(primaryCode, x, y, spaceState);
|
||||
} else {
|
||||
didAutoCorrect = false;
|
||||
if (SPACE_STATE_PHANTOM == spaceState) {
|
||||
if (SpaceState.PHANTOM == spaceState) {
|
||||
if (settingsValues.mIsInternal) {
|
||||
if (mInputLogic.mWordComposer.isComposingWord()
|
||||
&& mInputLogic.mWordComposer.isBatchMode()) {
|
||||
|
@ -1683,7 +1556,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
return;
|
||||
}
|
||||
final String text = specificTldProcessingOnTextInput(rawText);
|
||||
if (SPACE_STATE_PHANTOM == mInputLogic.mSpaceState) {
|
||||
if (SpaceState.PHANTOM == mInputLogic.mSpaceState) {
|
||||
promotePhantomSpace();
|
||||
}
|
||||
mInputLogic.mConnection.commitText(text, 1);
|
||||
|
@ -1692,7 +1565,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
}
|
||||
mInputLogic.mConnection.endBatchEdit();
|
||||
// Space state must be updated before calling updateShiftState
|
||||
mInputLogic.mSpaceState = SPACE_STATE_NONE;
|
||||
mInputLogic.mSpaceState = SpaceState.NONE;
|
||||
mKeyboardSwitcher.updateShiftState();
|
||||
mKeyboardSwitcher.onCodeInput(Constants.CODE_OUTPUT_TEXT);
|
||||
mInputLogic.mEnteredText = text;
|
||||
|
@ -1737,7 +1610,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
|| currentSettingsValues.isUsuallyFollowedBySpace(codePointBeforeCursor)) {
|
||||
final boolean autoShiftHasBeenOverriden = mKeyboardSwitcher.getKeyboardShiftMode() !=
|
||||
getCurrentAutoCapsState();
|
||||
mInputLogic.mSpaceState = SPACE_STATE_PHANTOM;
|
||||
mInputLogic.mSpaceState = SpaceState.PHANTOM;
|
||||
if (!autoShiftHasBeenOverriden) {
|
||||
// When we change the space state, we need to update the shift state of the
|
||||
// keyboard unless it has been overridden manually. This is happening for example
|
||||
|
@ -1924,7 +1797,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
batchPointers.shift(candidate.mIndexOfTouchPointOfSecondWord);
|
||||
promotePhantomSpace();
|
||||
mInputLogic.mConnection.commitText(commitParts[0], 0);
|
||||
mInputLogic.mSpaceState = SPACE_STATE_PHANTOM;
|
||||
mInputLogic.mSpaceState = SpaceState.PHANTOM;
|
||||
mKeyboardSwitcher.updateShiftState();
|
||||
mInputLogic.mWordComposer.
|
||||
setCapitalizedModeAndPreviousWordAtStartComposingTime(
|
||||
|
@ -1943,7 +1816,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
return;
|
||||
}
|
||||
mInputLogic.mConnection.beginBatchEdit();
|
||||
if (SPACE_STATE_PHANTOM == mInputLogic.mSpaceState) {
|
||||
if (SpaceState.PHANTOM == mInputLogic.mSpaceState) {
|
||||
promotePhantomSpace();
|
||||
}
|
||||
if (mSettings.getCurrent().mPhraseGestureEnabled) {
|
||||
|
@ -1966,7 +1839,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
ResearchLogger.latinIME_onEndBatchInput(batchInputText, 0, suggestedWords);
|
||||
}
|
||||
// Space state must be updated before calling updateShiftState
|
||||
mInputLogic.mSpaceState = SPACE_STATE_PHANTOM;
|
||||
mInputLogic.mSpaceState = SpaceState.PHANTOM;
|
||||
mKeyboardSwitcher.updateShiftState();
|
||||
}
|
||||
|
||||
|
@ -1983,7 +1856,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
}
|
||||
// We have a TLD (or something that looks like this): make sure we don't add
|
||||
// a space even if currently in phantom mode.
|
||||
mInputLogic.mSpaceState = SPACE_STATE_NONE;
|
||||
mInputLogic.mSpaceState = SpaceState.NONE;
|
||||
// TODO: use getCodePointBeforeCursor instead to improve performance and simplify the code
|
||||
final CharSequence lastOne = mInputLogic.mConnection.getTextBeforeCursor(1, 0);
|
||||
if (lastOne != null && lastOne.length() == 1
|
||||
|
@ -2013,7 +1886,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
mInputUpdater.onCancelBatchInput();
|
||||
}
|
||||
|
||||
private void handleBackspace(final int spaceState) {
|
||||
// TODO[IL]: Move this to InputLogic and make private again.
|
||||
public void handleBackspace(final int spaceState) {
|
||||
mInputLogic.mDeleteCount++;
|
||||
|
||||
// In many cases, we may have to put the keyboard in auto-shift state again. However
|
||||
|
@ -2073,14 +1947,14 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
// reverting any autocorrect at this point. So we can safely return.
|
||||
return;
|
||||
}
|
||||
if (SPACE_STATE_DOUBLE == spaceState) {
|
||||
if (SpaceState.DOUBLE == spaceState) {
|
||||
mHandler.cancelDoubleSpacePeriodTimer();
|
||||
if (mInputLogic.mConnection.revertDoubleSpacePeriod()) {
|
||||
// No need to reset mSpaceState, it has already be done (that's why we
|
||||
// receive it as a parameter)
|
||||
return;
|
||||
}
|
||||
} else if (SPACE_STATE_SWAP_PUNCTUATION == spaceState) {
|
||||
} else if (SpaceState.SWAP_PUNCTUATION == spaceState) {
|
||||
if (mInputLogic.mConnection.revertSwapPunctuation()) {
|
||||
// Likewise
|
||||
return;
|
||||
|
@ -2167,11 +2041,11 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
*/
|
||||
private boolean maybeStripSpace(final int code, final int spaceState,
|
||||
final boolean isFromSuggestionStrip) {
|
||||
if (Constants.CODE_ENTER == code && SPACE_STATE_SWAP_PUNCTUATION == spaceState) {
|
||||
if (Constants.CODE_ENTER == code && SpaceState.SWAP_PUNCTUATION == spaceState) {
|
||||
mInputLogic.mConnection.removeTrailingSpace();
|
||||
return false;
|
||||
}
|
||||
if ((SPACE_STATE_WEAK == spaceState || SPACE_STATE_SWAP_PUNCTUATION == spaceState)
|
||||
if ((SpaceState.WEAK == spaceState || SpaceState.SWAP_PUNCTUATION == spaceState)
|
||||
&& isFromSuggestionStrip) {
|
||||
final SettingsValues currentSettings = mSettings.getCurrent();
|
||||
if (currentSettings.isUsuallyPrecededBySpace(code)) return false;
|
||||
|
@ -2191,7 +2065,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
// TODO: remove isWordConnector() and use isUsuallyFollowedBySpace() instead.
|
||||
// See onStartBatchInput() to see how to do it.
|
||||
final SettingsValues currentSettings = mSettings.getCurrent();
|
||||
if (SPACE_STATE_PHANTOM == spaceState && !currentSettings.isWordConnector(primaryCode)) {
|
||||
if (SpaceState.PHANTOM == spaceState && !currentSettings.isWordConnector(primaryCode)) {
|
||||
if (isComposingWord) {
|
||||
// Sanity check
|
||||
throw new RuntimeException("Should not be composing here");
|
||||
|
@ -2256,7 +2130,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
|
||||
if (swapWeakSpace) {
|
||||
swapSwapperAndSpace();
|
||||
mInputLogic.mSpaceState = SPACE_STATE_WEAK;
|
||||
mInputLogic.mSpaceState = SpaceState.WEAK;
|
||||
}
|
||||
// In case the "add to dictionary" hint was still displayed.
|
||||
if (null != mSuggestionStripView) mSuggestionStripView.dismissAddToDictionaryHint();
|
||||
|
@ -2267,7 +2141,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
}
|
||||
}
|
||||
|
||||
private void handleRecapitalize() {
|
||||
// TODO[IL]: Move this to InputLogic and rename to processRecapitalize.
|
||||
public void handleRecapitalize() {
|
||||
if (mInputLogic.mLastSelectionStart == mInputLogic.mLastSelectionEnd) {
|
||||
return; // No selection
|
||||
}
|
||||
|
@ -2342,7 +2217,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
final boolean swapWeakSpace = maybeStripSpace(primaryCode, spaceState,
|
||||
Constants.SUGGESTION_STRIP_COORDINATE == x);
|
||||
|
||||
if (SPACE_STATE_PHANTOM == spaceState &&
|
||||
if (SpaceState.PHANTOM == spaceState &&
|
||||
currentSettings.isUsuallyPrecededBySpace(primaryCode)) {
|
||||
promotePhantomSpace();
|
||||
}
|
||||
|
@ -2358,9 +2233,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
if (Constants.CODE_SPACE == primaryCode) {
|
||||
if (currentSettings.isSuggestionsRequested(mDisplayOrientation)) {
|
||||
if (maybeDoubleSpacePeriod()) {
|
||||
mInputLogic.mSpaceState = SPACE_STATE_DOUBLE;
|
||||
mInputLogic.mSpaceState = SpaceState.DOUBLE;
|
||||
} else if (!isShowingPunctuationList()) {
|
||||
mInputLogic.mSpaceState = SPACE_STATE_WEAK;
|
||||
mInputLogic.mSpaceState = SpaceState.WEAK;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2369,8 +2244,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
} else {
|
||||
if (swapWeakSpace) {
|
||||
swapSwapperAndSpace();
|
||||
mInputLogic.mSpaceState = SPACE_STATE_SWAP_PUNCTUATION;
|
||||
} else if (SPACE_STATE_PHANTOM == spaceState
|
||||
mInputLogic.mSpaceState = SpaceState.SWAP_PUNCTUATION;
|
||||
} else if (SpaceState.PHANTOM == spaceState
|
||||
&& currentSettings.isUsuallyFollowedBySpace(primaryCode)) {
|
||||
// If we are in phantom space state, and the user presses a separator, we want to
|
||||
// stay in phantom space state so that the next keypress has a chance to add the
|
||||
|
@ -2382,7 +2257,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
// separator does not normally need a space on the right (that's the difference
|
||||
// between swappers and strippers), so we should not stay in phantom space state if
|
||||
// the separator is a stripper. Hence the additional test above.
|
||||
mInputLogic.mSpaceState = SPACE_STATE_PHANTOM;
|
||||
mInputLogic.mSpaceState = SpaceState.PHANTOM;
|
||||
}
|
||||
|
||||
// Set punctuation right away. onUpdateSelection will fire but tests whether it is
|
||||
|
@ -2710,7 +2585,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
|
||||
mInputLogic.mConnection.beginBatchEdit();
|
||||
final SettingsValues currentSettings = mSettings.getCurrent();
|
||||
if (SPACE_STATE_PHANTOM == mInputLogic.mSpaceState && suggestion.length() > 0
|
||||
if (SpaceState.PHANTOM == mInputLogic.mSpaceState && suggestion.length() > 0
|
||||
// In the batch input mode, a manually picked suggested word should just replace
|
||||
// the current batch input text and there is no need for a phantom space.
|
||||
&& !mInputLogic.mWordComposer.isBatchMode()) {
|
||||
|
@ -2751,7 +2626,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
// Don't allow cancellation of manual pick
|
||||
mInputLogic.mLastComposedWord.deactivate();
|
||||
// Space state must be updated before calling updateShiftState
|
||||
mInputLogic.mSpaceState = SPACE_STATE_PHANTOM;
|
||||
mInputLogic.mSpaceState = SpaceState.PHANTOM;
|
||||
mKeyboardSwitcher.updateShiftState();
|
||||
|
||||
// We should show the "Touch again to save" hint if the user pressed the first entry
|
||||
|
|
|
@ -16,15 +16,26 @@
|
|||
|
||||
package com.android.inputmethod.latin.inputlogic;
|
||||
|
||||
import android.os.SystemClock;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
|
||||
import com.android.inputmethod.event.EventInterpreter;
|
||||
import com.android.inputmethod.keyboard.Keyboard;
|
||||
import com.android.inputmethod.keyboard.KeyboardSwitcher;
|
||||
import com.android.inputmethod.latin.Constants;
|
||||
import com.android.inputmethod.latin.LastComposedWord;
|
||||
import com.android.inputmethod.latin.LatinIME;
|
||||
import com.android.inputmethod.latin.LatinImeLogger;
|
||||
import com.android.inputmethod.latin.RichInputConnection;
|
||||
import com.android.inputmethod.latin.SubtypeSwitcher;
|
||||
import com.android.inputmethod.latin.Suggest;
|
||||
import com.android.inputmethod.latin.SuggestedWords;
|
||||
import com.android.inputmethod.latin.WordComposer;
|
||||
import com.android.inputmethod.latin.define.ProductionFlag;
|
||||
import com.android.inputmethod.latin.utils.CollectionUtils;
|
||||
import com.android.inputmethod.latin.utils.InputTypeUtils;
|
||||
import com.android.inputmethod.latin.utils.RecapitalizeStatus;
|
||||
import com.android.inputmethod.research.ResearchLogger;
|
||||
|
||||
import java.util.TreeSet;
|
||||
|
||||
|
@ -75,4 +86,182 @@ public final class InputLogic {
|
|||
public void startInput(final boolean restarting) {
|
||||
|
||||
}
|
||||
|
||||
public void onCodeInput(final int primaryCode, final int x, final int y,
|
||||
// TODO: remove these three arguments
|
||||
final LatinIME.UIHandler handler, final KeyboardSwitcher keyboardSwitcher,
|
||||
final SubtypeSwitcher subtypeSwitcher) {
|
||||
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
|
||||
ResearchLogger.latinIME_onCodeInput(primaryCode, x, y);
|
||||
}
|
||||
final long when = SystemClock.uptimeMillis();
|
||||
if (primaryCode != Constants.CODE_DELETE
|
||||
|| when > mLastKeyTime + Constants.LONG_PRESS_MILLISECONDS) {
|
||||
mDeleteCount = 0;
|
||||
}
|
||||
mLastKeyTime = when;
|
||||
mConnection.beginBatchEdit();
|
||||
final KeyboardSwitcher switcher = keyboardSwitcher;
|
||||
// The space state depends only on the last character pressed and its own previous
|
||||
// state. Here, we revert the space state to neutral if the key is actually modifying
|
||||
// the input contents (any non-shift key), which is what we should do for
|
||||
// all inputs that do not result in a special state. Each character handling is then
|
||||
// free to override the state as they see fit.
|
||||
final int spaceState = mSpaceState;
|
||||
if (!mWordComposer.isComposingWord()) {
|
||||
mIsAutoCorrectionIndicatorOn = false;
|
||||
}
|
||||
|
||||
// TODO: Consolidate the double-space period timer, mLastKeyTime, and the space state.
|
||||
if (primaryCode != Constants.CODE_SPACE) {
|
||||
handler.cancelDoubleSpacePeriodTimer();
|
||||
}
|
||||
|
||||
boolean didAutoCorrect = false;
|
||||
switch (primaryCode) {
|
||||
case Constants.CODE_DELETE:
|
||||
mSpaceState = SpaceState.NONE;
|
||||
handleBackspace(spaceState);
|
||||
LatinImeLogger.logOnDelete(x, y);
|
||||
break;
|
||||
case Constants.CODE_SHIFT:
|
||||
// Note: Calling back to the keyboard on Shift key is handled in
|
||||
// {@link #onPressKey(int,int,boolean)} and {@link #onReleaseKey(int,boolean)}.
|
||||
final Keyboard currentKeyboard = switcher.getKeyboard();
|
||||
if (null != currentKeyboard && currentKeyboard.mId.isAlphabetKeyboard()) {
|
||||
// TODO: Instead of checking for alphabetic keyboard here, separate keycodes for
|
||||
// alphabetic shift and shift while in symbol layout.
|
||||
handleRecapitalize();
|
||||
}
|
||||
break;
|
||||
case Constants.CODE_CAPSLOCK:
|
||||
// Note: Changing keyboard to shift lock state is handled in
|
||||
// {@link KeyboardSwitcher#onCodeInput(int)}.
|
||||
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:
|
||||
subtypeSwitcher.switchToShortcutIME(mLatinIME);
|
||||
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_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(Constants.CODE_ENTER, x, y, spaceState);
|
||||
}
|
||||
break;
|
||||
case Constants.CODE_SHIFT_ENTER:
|
||||
didAutoCorrect = handleNonSpecialCharacter(Constants.CODE_ENTER, x, y, spaceState);
|
||||
break;
|
||||
default:
|
||||
didAutoCorrect = handleNonSpecialCharacter(primaryCode, x, y, spaceState);
|
||||
break;
|
||||
}
|
||||
switcher.onCodeInput(primaryCode);
|
||||
// Reset after any single keystroke, except shift, capslock, and symbol-shift
|
||||
if (!didAutoCorrect && primaryCode != Constants.CODE_SHIFT
|
||||
&& primaryCode != Constants.CODE_CAPSLOCK
|
||||
&& primaryCode != Constants.CODE_SWITCH_ALPHA_SYMBOL)
|
||||
mLastComposedWord.deactivate();
|
||||
if (Constants.CODE_DELETE != primaryCode) {
|
||||
mEnteredText = null;
|
||||
}
|
||||
mConnection.endBatchEdit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle inputting a code point to the editor.
|
||||
*
|
||||
* 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 code the code point associated with the key.
|
||||
* @param x the x-coordinate of the key press, or Contants.NOT_A_COORDINATE if not applicable.
|
||||
* @param y the y-coordinate of the key press, or Contants.NOT_A_COORDINATE if not applicable.
|
||||
* @param spaceState the space state at start of the batch input.
|
||||
* @return whether this caused an auto-correction to happen.
|
||||
*/
|
||||
private boolean handleNonSpecialCharacter(final int code, final int x, final int y,
|
||||
final int spaceState) {
|
||||
return mLatinIME.handleNonSpecialCharacter(code, x, y, spaceState);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a press on the backspace key.
|
||||
* @param spaceState The space state at start of this batch edit.
|
||||
*/
|
||||
private void handleBackspace(final int spaceState) {
|
||||
mLatinIME.handleBackspace(spaceState);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a press on the language switch key (the "globe key")
|
||||
*/
|
||||
private void handleLanguageSwitchKey() {
|
||||
mLatinIME.handleLanguageSwitchKey();
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a recapitalize event.
|
||||
*/
|
||||
private void handleRecapitalize() {
|
||||
mLatinIME.handleRecapitalize();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the editor info for the current editor
|
||||
*/
|
||||
private EditorInfo getCurrentInputEditorInfo() {
|
||||
return mLatinIME.getCurrentInputEditorInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param actionId the action to perform
|
||||
*/
|
||||
private void performEditorAction(final int actionId) {
|
||||
mConnection.performEditorAction(actionId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a press on the settings key.
|
||||
*/
|
||||
private void onSettingsKeyPressed() {
|
||||
mLatinIME.onSettingsKeyPressed();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.inputmethod.latin.inputlogic;
|
||||
|
||||
/**
|
||||
* Class for managing space states.
|
||||
*
|
||||
* At any given time, the input logic is in one of five possible space states. Depending on the
|
||||
* current space state, some behavior will change; the prime example of this is the PHANTOM state,
|
||||
* in which any subsequent letter input will input a space before the letter. Read on the
|
||||
* description inside this class for each of the space states.
|
||||
*/
|
||||
public class SpaceState {
|
||||
// None: the state where all the keyboard behavior is the most "standard" and no automatic
|
||||
// input is added or removed. In this state, all self-inserting keys only insert themselves,
|
||||
// and backspace removes one character.
|
||||
public static final int NONE = 0;
|
||||
// Double space: the state where the user pressed space twice quickly, which LatinIME
|
||||
// resolved as period-space. In this state, pressing backspace will undo the
|
||||
// double-space-to-period insertion: it will replace ". " with " ".
|
||||
public static final int DOUBLE = 1;
|
||||
// Swap punctuation: the state where a weak space and a punctuation from the suggestion strip
|
||||
// have just been swapped. In this state, pressing backspace will undo the swap: the
|
||||
// characters will be swapped back back, and the space state will go to WEAK.
|
||||
public static final int SWAP_PUNCTUATION = 2;
|
||||
// Weak space: a space that should be swapped only by suggestion strip punctuation. Weak
|
||||
// spaces happen when the user presses space, accepting the current suggestion (whether
|
||||
// it's an auto-correction or not). In this state, pressing a punctuation from the suggestion
|
||||
// strip inserts it before the space (while it inserts it after the space in the NONE state).
|
||||
public static final int WEAK = 3;
|
||||
// Phantom space: a not-yet-inserted space that should get inserted on the next input,
|
||||
// character provided it's not a separator. If it's a separator, the phantom space is dropped.
|
||||
// Phantom spaces happen when a user chooses a word from the suggestion strip. In this state,
|
||||
// non-separators insert a space before they get inserted.
|
||||
public static final int PHANTOM = 4;
|
||||
|
||||
private SpaceState() {
|
||||
// This class is not publicly instantiable.
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue