Loading java/src/com/android/inputmethod/event/InputTransaction.java +14 −1 Original line number Original line Diff line number Diff line Loading @@ -30,12 +30,25 @@ public class InputTransaction { public static final int SHIFT_UPDATE_LATER = 2; public static final int SHIFT_UPDATE_LATER = 2; // Initial conditions // Initial conditions // If the key inserts a code point, mKeyCode is always equal to the code points. Otherwise, // it's always a code that may not be a code point, typically a negative number. public final int mKeyCode; public final int mX; // Pressed x-coordinate, or one of Constants.*_COORDINATE public final int mY; // Pressed y-coordinate, or one of Constants.*_COORDINATE public final long mTimestamp; public final int mSpaceState; public final int mShiftState; public final int mShiftState; // Outputs // Outputs private int mRequiredShiftUpdate = SHIFT_NO_UPDATE; private int mRequiredShiftUpdate = SHIFT_NO_UPDATE; public InputTransaction(final int shiftState) { public InputTransaction(final int keyCode, final int x, final int y, final long timestamp, final int spaceState, final int shiftState) { mKeyCode = keyCode; mX = x; mY = y; mTimestamp = timestamp; mSpaceState = spaceState; mShiftState = shiftState; mShiftState = shiftState; } } Loading java/src/com/android/inputmethod/keyboard/PointerTracker.java +2 −2 Original line number Original line Diff line number Diff line Loading @@ -323,7 +323,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element, } } // Note that we need primaryCode argument because the keyboard may in shifted state and the // Note that we need primaryCode argument because the keyboard may in shifted state and the // primaryCode is different from {@link Key#mCode}. // primaryCode is different from {@link Key#mKeyCode}. private void callListenerOnCodeInput(final Key key, final int primaryCode, final int x, private void callListenerOnCodeInput(final Key key, final int primaryCode, final int x, final int y, final long eventTime) { final int y, final long eventTime) { final boolean ignoreModifierKey = mIsInDraggingFinger && key.isModifier(); final boolean ignoreModifierKey = mIsInDraggingFinger && key.isModifier(); Loading Loading @@ -360,7 +360,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element, } } // Note that we need primaryCode argument because the keyboard may be in shifted state and the // Note that we need primaryCode argument because the keyboard may be in shifted state and the // primaryCode is different from {@link Key#mCode}. // primaryCode is different from {@link Key#mKeyCode}. private void callListenerOnRelease(final Key key, final int primaryCode, private void callListenerOnRelease(final Key key, final int primaryCode, final boolean withSliding) { final boolean withSliding) { // See the comment at {@link #callListenerOnPressAndCheckKeyboardLayoutChange(Key}}. // See the comment at {@link #callListenerOnPressAndCheckKeyboardLayoutChange(Key}}. Loading java/src/com/android/inputmethod/latin/Constants.java +1 −0 Original line number Original line Diff line number Diff line Loading @@ -144,6 +144,7 @@ public final class Constants { public static final int NOT_A_CODE = -1; public static final int NOT_A_CODE = -1; public static final int NOT_A_CURSOR_POSITION = -1; public static final int NOT_A_CURSOR_POSITION = -1; // TODO: replace the following constants with state in InputTransaction? public static final int NOT_A_COORDINATE = -1; public static final int NOT_A_COORDINATE = -1; public static final int SUGGESTION_STRIP_COORDINATE = -2; public static final int SUGGESTION_STRIP_COORDINATE = -2; public static final int SPELL_CHECKER_COORDINATE = -3; public static final int SPELL_CHECKER_COORDINATE = -3; Loading java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java +77 −83 Original line number Original line Diff line number Diff line Loading @@ -361,38 +361,33 @@ public final class InputLogic { final SettingsValues settingsValues, final SettingsValues settingsValues, // TODO: remove these two arguments // TODO: remove these two arguments final LatinIME.UIHandler handler, final KeyboardSwitcher keyboardSwitcher) { final LatinIME.UIHandler handler, final KeyboardSwitcher keyboardSwitcher) { final InputTransaction inputTransaction = new InputTransaction(code, x, y, SystemClock.uptimeMillis(), mSpaceState, getActualCapsMode(settingsValues, keyboardSwitcher.getKeyboardShiftMode())); if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { ResearchLogger.latinIME_onCodeInput(code, x, y); ResearchLogger.latinIME_onCodeInput(inputTransaction.mKeyCode, inputTransaction.mX, inputTransaction.mY); } } final long when = SystemClock.uptimeMillis(); if (inputTransaction.mKeyCode != Constants.CODE_DELETE final InputTransaction inputTransaction = new InputTransaction( || inputTransaction.mTimestamp > mLastKeyTime + Constants.LONG_PRESS_MILLISECONDS) { getActualCapsMode(settingsValues, keyboardSwitcher.getKeyboardShiftMode())); if (code != Constants.CODE_DELETE || when > mLastKeyTime + Constants.LONG_PRESS_MILLISECONDS) { mDeleteCount = 0; mDeleteCount = 0; } } mLastKeyTime = when; mLastKeyTime = inputTransaction.mTimestamp; mConnection.beginBatchEdit(); mConnection.beginBatchEdit(); // 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()) { if (!mWordComposer.isComposingWord()) { mIsAutoCorrectionIndicatorOn = false; mIsAutoCorrectionIndicatorOn = false; } } // TODO: Consolidate the double-space period timer, mLastKeyTime, and the space state. // TODO: Consolidate the double-space period timer, mLastKeyTime, and the space state. if (code != Constants.CODE_SPACE) { if (inputTransaction.mKeyCode != Constants.CODE_SPACE) { handler.cancelDoubleSpacePeriodTimer(); handler.cancelDoubleSpacePeriodTimer(); } } boolean didAutoCorrect = false; boolean didAutoCorrect = false; switch (code) { switch (inputTransaction.mKeyCode) { case Constants.CODE_DELETE: case Constants.CODE_DELETE: handleBackspace(settingsValues, spaceState, inputTransaction, handler); handleBackspace(settingsValues, inputTransaction, handler); LatinImeLogger.logOnDelete(x, y); LatinImeLogger.logOnDelete(inputTransaction.mX, inputTransaction.mY); break; break; case Constants.CODE_SHIFT: case Constants.CODE_SHIFT: performRecapitalization(settingsValues); performRecapitalization(settingsValues); Loading Loading @@ -450,29 +445,31 @@ public final class InputLogic { } else { } else { // No action label, and the action from imeOptions is NONE: this is a regular // No action label, and the action from imeOptions is NONE: this is a regular // enter key that should input a carriage return. // enter key that should input a carriage return. didAutoCorrect = handleNonSpecialCharacter(settingsValues, Constants.CODE_ENTER, didAutoCorrect = handleNonSpecialCharacter(settingsValues, inputTransaction, x, y, spaceState, inputTransaction, handler); handler); } } break; break; case Constants.CODE_SHIFT_ENTER: case Constants.CODE_SHIFT_ENTER: didAutoCorrect = handleNonSpecialCharacter(settingsValues, Constants.CODE_ENTER, // TODO: remove this object x, y, spaceState, inputTransaction, handler); final InputTransaction tmpTransaction = new InputTransaction(inputTransaction.mKeyCode, inputTransaction.mX, inputTransaction.mY, inputTransaction.mTimestamp, inputTransaction.mSpaceState, inputTransaction.mShiftState); didAutoCorrect = handleNonSpecialCharacter(settingsValues, tmpTransaction, handler); break; break; case Constants.CODE_ALPHA_FROM_EMOJI: case Constants.CODE_ALPHA_FROM_EMOJI: // Note: Switching back from Emoji keyboard to the main keyboard is being handled in // Note: Switching back from Emoji keyboard to the main keyboard is being handled in // {@link KeyboardState#onCodeInput(int,int)}. // {@link KeyboardState#onCodeInput(int,int)}. break; break; default: default: didAutoCorrect = handleNonSpecialCharacter(settingsValues, didAutoCorrect = handleNonSpecialCharacter(settingsValues, inputTransaction, handler); code, x, y, spaceState, inputTransaction, handler); break; break; } } // Reset after any single keystroke, except shift, capslock, and symbol-shift // Reset after any single keystroke, except shift, capslock, and symbol-shift if (!didAutoCorrect && code != Constants.CODE_SHIFT if (!didAutoCorrect && inputTransaction.mKeyCode != Constants.CODE_SHIFT && code != Constants.CODE_CAPSLOCK && inputTransaction.mKeyCode != Constants.CODE_CAPSLOCK && code != Constants.CODE_SWITCH_ALPHA_SYMBOL) && inputTransaction.mKeyCode != Constants.CODE_SWITCH_ALPHA_SYMBOL) mLastComposedWord.deactivate(); mLastComposedWord.deactivate(); if (Constants.CODE_DELETE != code) { if (Constants.CODE_DELETE != inputTransaction.mKeyCode) { mEnteredText = null; mEnteredText = null; } } mConnection.endBatchEdit(); mConnection.endBatchEdit(); Loading Loading @@ -629,31 +626,27 @@ public final class InputLogic { * any key that results in multiple code points like the ".com" key. * any key that results in multiple code points like the ".com" key. * * * @param settingsValues The current settings values. * @param settingsValues The current settings values. * @param codePoint 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. * @param inputTransaction The transaction in progress. * @param inputTransaction The transaction in progress. * @return whether this caused an auto-correction to happen. * @return whether this caused an auto-correction to happen. */ */ private boolean handleNonSpecialCharacter(final SettingsValues settingsValues, private boolean handleNonSpecialCharacter(final SettingsValues settingsValues, final int codePoint, final int x, final int y, final int spaceState, final InputTransaction inputTransaction, final InputTransaction inputTransaction, // TODO: remove this argument // TODO: remove this argument final LatinIME.UIHandler handler) { final LatinIME.UIHandler handler) { mSpaceState = SpaceState.NONE; mSpaceState = SpaceState.NONE; final boolean didAutoCorrect; final boolean didAutoCorrect; if (settingsValues.isWordSeparator(codePoint) if (settingsValues.isWordSeparator(inputTransaction.mKeyCode) || Character.getType(codePoint) == Character.OTHER_SYMBOL) { || Character.getType(inputTransaction.mKeyCode) == Character.OTHER_SYMBOL) { didAutoCorrect = handleSeparator(settingsValues, codePoint, didAutoCorrect = handleSeparator(settingsValues, Constants.SUGGESTION_STRIP_COORDINATE == x, spaceState, inputTransaction, Constants.SUGGESTION_STRIP_COORDINATE == inputTransaction.mX, inputTransaction, handler); handler); if (settingsValues.mIsInternal) { if (settingsValues.mIsInternal) { LatinImeLoggerUtils.onSeparator((char)codePoint, x, y); LatinImeLoggerUtils.onSeparator((char)inputTransaction.mKeyCode, inputTransaction.mX, inputTransaction.mY); } } } else { } else { didAutoCorrect = false; didAutoCorrect = false; if (SpaceState.PHANTOM == spaceState) { if (SpaceState.PHANTOM == inputTransaction.mSpaceState) { if (settingsValues.mIsInternal) { if (settingsValues.mIsInternal) { if (mWordComposer.isComposingWord() && mWordComposer.isBatchMode()) { if (mWordComposer.isComposingWord() && mWordComposer.isBatchMode()) { LatinImeLoggerUtils.onAutoCorrection("", mWordComposer.getTypedWord(), " ", LatinImeLoggerUtils.onAutoCorrection("", mWordComposer.getTypedWord(), " ", Loading @@ -669,8 +662,7 @@ public final class InputLogic { commitTyped(settingsValues, LastComposedWord.NOT_A_SEPARATOR); commitTyped(settingsValues, LastComposedWord.NOT_A_SEPARATOR); } } } } handleNonSeparator(settingsValues, codePoint, x, y, spaceState, handleNonSeparator(settingsValues, inputTransaction, handler); inputTransaction, handler); } } return didAutoCorrect; return didAutoCorrect; } } Loading @@ -678,14 +670,9 @@ public final class InputLogic { /** /** * Handle a non-separator. * Handle a non-separator. * @param settingsValues The current settings values. * @param settingsValues The current settings values. * @param codePoint 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. * @param inputTransaction The transaction in progress. * @param inputTransaction The transaction in progress. */ */ private void handleNonSeparator(final SettingsValues settingsValues, private void handleNonSeparator(final SettingsValues settingsValues, final int codePoint, final int x, final int y, final int spaceState, final InputTransaction inputTransaction, final InputTransaction inputTransaction, // TODO: Remove this argument // TODO: Remove this argument final LatinIME.UIHandler handler) { final LatinIME.UIHandler handler) { Loading @@ -696,7 +683,8 @@ public final class InputLogic { // TODO: remove isWordConnector() and use isUsuallyFollowedBySpace() instead. // TODO: remove isWordConnector() and use isUsuallyFollowedBySpace() instead. // See onStartBatchInput() to see how to do it. // See onStartBatchInput() to see how to do it. if (SpaceState.PHANTOM == spaceState && !settingsValues.isWordConnector(codePoint)) { if (SpaceState.PHANTOM == inputTransaction.mSpaceState && !settingsValues.isWordConnector(inputTransaction.mKeyCode)) { if (isComposingWord) { if (isComposingWord) { // Sanity check // Sanity check throw new RuntimeException("Should not be composing here"); throw new RuntimeException("Should not be composing here"); Loading @@ -718,7 +706,7 @@ public final class InputLogic { if (!isComposingWord if (!isComposingWord // We only start composing if this is a word code point. Essentially that means it's a // We only start composing if this is a word code point. Essentially that means it's a // a letter or a word connector. // a letter or a word connector. && settingsValues.isWordCodePoint(codePoint) && settingsValues.isWordCodePoint(inputTransaction.mKeyCode) // We never go into composing state if suggestions are not requested. // We never go into composing state if suggestions are not requested. && settingsValues.isSuggestionsRequested() && && settingsValues.isSuggestionsRequested() && // In languages with spaces, we only start composing a word when we are not already // In languages with spaces, we only start composing a word when we are not already Loading @@ -729,8 +717,8 @@ public final class InputLogic { // the character is a single quote or a dash. The idea here is, single quote and dash // the character is a single quote or a dash. The idea here is, single quote and dash // are not separators and they should be treated as normal characters, except in the // are not separators and they should be treated as normal characters, except in the // first position where they should not start composing a word. // first position where they should not start composing a word. isComposingWord = (Constants.CODE_SINGLE_QUOTE != codePoint isComposingWord = (Constants.CODE_SINGLE_QUOTE != inputTransaction.mKeyCode && Constants.CODE_DASH != codePoint); && Constants.CODE_DASH != inputTransaction.mKeyCode); // Here we don't need to reset the last composed word. It will be reset // Here we don't need to reset the last composed word. It will be reset // when we commit this one, if we ever do; if on the other hand we backspace // when we commit this one, if we ever do; if on the other hand we backspace // it entirely and resume suggestions on the previous word, we'd like to still // it entirely and resume suggestions on the previous word, we'd like to still Loading @@ -738,7 +726,7 @@ public final class InputLogic { resetComposingState(false /* alsoResetLastComposedWord */); resetComposingState(false /* alsoResetLastComposedWord */); } } if (isComposingWord) { if (isComposingWord) { mWordComposer.add(codePoint, x, y); mWordComposer.add(inputTransaction.mKeyCode, inputTransaction.mX, inputTransaction.mY); // If it's the first letter, make note of auto-caps state // If it's the first letter, make note of auto-caps state if (mWordComposer.size() == 1) { if (mWordComposer.size() == 1) { // We pass 1 to getPreviousWordForSuggestion because we were not composing a word // We pass 1 to getPreviousWordForSuggestion because we were not composing a word Loading @@ -750,10 +738,10 @@ public final class InputLogic { mConnection.setComposingText(getTextWithUnderline( mConnection.setComposingText(getTextWithUnderline( mWordComposer.getTypedWord()), 1); mWordComposer.getTypedWord()), 1); } else { } else { final boolean swapWeakSpace = maybeStripSpace(settingsValues, final boolean swapWeakSpace = maybeStripSpace(settingsValues, inputTransaction, codePoint, spaceState, Constants.SUGGESTION_STRIP_COORDINATE == x); Constants.SUGGESTION_STRIP_COORDINATE == inputTransaction.mX); sendKeyCodePoint(settingsValues, codePoint); sendKeyCodePoint(settingsValues, inputTransaction.mKeyCode); if (swapWeakSpace) { if (swapWeakSpace) { swapSwapperAndSpace(inputTransaction); swapSwapperAndSpace(inputTransaction); Loading @@ -764,27 +752,25 @@ public final class InputLogic { } } handler.postUpdateSuggestionStrip(); handler.postUpdateSuggestionStrip(); if (settingsValues.mIsInternal) { if (settingsValues.mIsInternal) { LatinImeLoggerUtils.onNonSeparator((char)codePoint, x, y); LatinImeLoggerUtils.onNonSeparator((char)inputTransaction.mKeyCode, inputTransaction.mX, inputTransaction.mY); } } } } /** /** * Handle input of a separator code point. * Handle input of a separator code point. * @param settingsValues The current settings values. * @param settingsValues The current settings values. * @param codePoint the code point associated with the key. * @param isFromSuggestionStrip whether this code point comes from the suggestion strip. * @param isFromSuggestionStrip whether this code point comes from the suggestion strip. * @param spaceState the space state at start of the batch input. * @param inputTransaction The transaction in progress. * @param inputTransaction The transaction in progress. * @return whether this caused an auto-correction to happen. * @return whether this caused an auto-correction to happen. */ */ private boolean handleSeparator(final SettingsValues settingsValues, private boolean handleSeparator(final SettingsValues settingsValues, final int codePoint, final boolean isFromSuggestionStrip, final int spaceState, final boolean isFromSuggestionStrip, final InputTransaction inputTransaction, final InputTransaction inputTransaction, // TODO: remove this argument // TODO: remove this argument final LatinIME.UIHandler handler) { final LatinIME.UIHandler handler) { boolean didAutoCorrect = false; boolean didAutoCorrect = false; // We avoid sending spaces in languages without spaces if we were composing. // We avoid sending spaces in languages without spaces if we were composing. final boolean shouldAvoidSendingCode = Constants.CODE_SPACE == codePoint final boolean shouldAvoidSendingCode = Constants.CODE_SPACE == inputTransaction.mKeyCode && !settingsValues.mSpacingAndPunctuations.mCurrentLanguageHasSpaces && !settingsValues.mSpacingAndPunctuations.mCurrentLanguageHasSpaces && mWordComposer.isComposingWord(); && mWordComposer.isComposingWord(); if (mWordComposer.isCursorFrontOrMiddleOfComposingWord()) { if (mWordComposer.isCursorFrontOrMiddleOfComposingWord()) { Loading @@ -797,43 +783,47 @@ public final class InputLogic { if (mWordComposer.isComposingWord()) { if (mWordComposer.isComposingWord()) { if (settingsValues.mCorrectionEnabled) { if (settingsValues.mCorrectionEnabled) { final String separator = shouldAvoidSendingCode ? LastComposedWord.NOT_A_SEPARATOR final String separator = shouldAvoidSendingCode ? LastComposedWord.NOT_A_SEPARATOR : StringUtils.newSingleCodePointString(codePoint); : StringUtils.newSingleCodePointString(inputTransaction.mKeyCode); commitCurrentAutoCorrection(settingsValues, separator, handler); commitCurrentAutoCorrection(settingsValues, separator, handler); didAutoCorrect = true; didAutoCorrect = true; } else { } else { commitTyped(settingsValues, StringUtils.newSingleCodePointString(codePoint)); commitTyped(settingsValues, StringUtils.newSingleCodePointString(inputTransaction.mKeyCode)); } } } } final boolean swapWeakSpace = maybeStripSpace(settingsValues, codePoint, spaceState, final boolean swapWeakSpace = maybeStripSpace(settingsValues, inputTransaction, isFromSuggestionStrip); isFromSuggestionStrip); final boolean isInsideDoubleQuoteOrAfterDigit = Constants.CODE_DOUBLE_QUOTE == codePoint final boolean isInsideDoubleQuoteOrAfterDigit = Constants.CODE_DOUBLE_QUOTE == inputTransaction.mKeyCode && mConnection.isInsideDoubleQuoteOrAfterDigit(); && mConnection.isInsideDoubleQuoteOrAfterDigit(); final boolean needsPrecedingSpace; final boolean needsPrecedingSpace; if (SpaceState.PHANTOM != spaceState) { if (SpaceState.PHANTOM != inputTransaction.mSpaceState) { needsPrecedingSpace = false; needsPrecedingSpace = false; } else if (Constants.CODE_DOUBLE_QUOTE == codePoint) { } else if (Constants.CODE_DOUBLE_QUOTE == inputTransaction.mKeyCode) { // Double quotes behave like they are usually preceded by space iff we are // Double quotes behave like they are usually preceded by space iff we are // not inside a double quote or after a digit. // not inside a double quote or after a digit. needsPrecedingSpace = !isInsideDoubleQuoteOrAfterDigit; needsPrecedingSpace = !isInsideDoubleQuoteOrAfterDigit; } else { } else { needsPrecedingSpace = settingsValues.isUsuallyPrecededBySpace(codePoint); needsPrecedingSpace = settingsValues.isUsuallyPrecededBySpace(inputTransaction.mKeyCode); } } if (needsPrecedingSpace) { if (needsPrecedingSpace) { promotePhantomSpace(settingsValues); promotePhantomSpace(settingsValues); } } if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { ResearchLogger.latinIME_handleSeparator(codePoint, mWordComposer.isComposingWord()); ResearchLogger.latinIME_handleSeparator(inputTransaction.mKeyCode, mWordComposer.isComposingWord()); } } if (!shouldAvoidSendingCode) { if (!shouldAvoidSendingCode) { sendKeyCodePoint(settingsValues, codePoint); sendKeyCodePoint(settingsValues, inputTransaction.mKeyCode); } } if (Constants.CODE_SPACE == codePoint) { if (Constants.CODE_SPACE == inputTransaction.mKeyCode) { if (settingsValues.isSuggestionsRequested()) { if (settingsValues.isSuggestionsRequested()) { if (maybeDoubleSpacePeriod(settingsValues, handler)) { if (maybeDoubleSpacePeriod(settingsValues, handler)) { inputTransaction.requireShiftUpdate(InputTransaction.SHIFT_UPDATE_NOW); inputTransaction.requireShiftUpdate(InputTransaction.SHIFT_UPDATE_NOW); Loading @@ -849,9 +839,9 @@ public final class InputLogic { if (swapWeakSpace) { if (swapWeakSpace) { swapSwapperAndSpace(inputTransaction); swapSwapperAndSpace(inputTransaction); mSpaceState = SpaceState.SWAP_PUNCTUATION; mSpaceState = SpaceState.SWAP_PUNCTUATION; } else if ((SpaceState.PHANTOM == spaceState } else if ((SpaceState.PHANTOM == inputTransaction.mSpaceState && settingsValues.isUsuallyFollowedBySpace(codePoint)) && settingsValues.isUsuallyFollowedBySpace(inputTransaction.mKeyCode)) || (Constants.CODE_DOUBLE_QUOTE == codePoint || (Constants.CODE_DOUBLE_QUOTE == inputTransaction.mKeyCode && isInsideDoubleQuoteOrAfterDigit)) { && isInsideDoubleQuoteOrAfterDigit)) { // If we are in phantom space state, and the user presses a separator, we want to // 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 // stay in phantom space state so that the next keypress has a chance to add the Loading Loading @@ -879,10 +869,9 @@ public final class InputLogic { /** /** * Handle a press on the backspace key. * Handle a press on the backspace key. * @param settingsValues The current settings values. * @param settingsValues The current settings values. * @param spaceState The space state at start of this batch edit. * @param inputTransaction The transaction in progress. * @param inputTransaction The transaction in progress. */ */ private void handleBackspace(final SettingsValues settingsValues, final int spaceState, private void handleBackspace(final SettingsValues settingsValues, final InputTransaction inputTransaction, final InputTransaction inputTransaction, // TODO: remove this argument // TODO: remove this argument final LatinIME.UIHandler handler) { final LatinIME.UIHandler handler) { Loading Loading @@ -942,14 +931,14 @@ public final class InputLogic { // reverting any autocorrect at this point. So we can safely return. // reverting any autocorrect at this point. So we can safely return. return; return; } } if (SpaceState.DOUBLE == spaceState) { if (SpaceState.DOUBLE == inputTransaction.mSpaceState) { handler.cancelDoubleSpacePeriodTimer(); handler.cancelDoubleSpacePeriodTimer(); if (mConnection.revertDoubleSpacePeriod()) { if (mConnection.revertDoubleSpacePeriod()) { // No need to reset mSpaceState, it has already be done (that's why we // No need to reset mSpaceState, it has already be done (that's why we // receive it as a parameter) // receive it as a parameter) return; return; } } } else if (SpaceState.SWAP_PUNCTUATION == spaceState) { } else if (SpaceState.SWAP_PUNCTUATION == inputTransaction.mSpaceState) { if (mConnection.revertSwapPunctuation()) { if (mConnection.revertSwapPunctuation()) { // Likewise // Likewise return; return; Loading Loading @@ -1065,21 +1054,26 @@ public final class InputLogic { /* /* * Strip a trailing space if necessary and returns whether it's a swap weak space situation. * Strip a trailing space if necessary and returns whether it's a swap weak space situation. * @param settingsValues The current settings values. * @param settingsValues The current settings values. * @param codePoint The code point that is about to be inserted. * @param inputTransaction The transaction in progress. * @param spaceState The space state at start of this batch edit. * @param isFromSuggestionStrip Whether this code point is coming from the suggestion strip. * @param isFromSuggestionStrip Whether this code point is coming from the suggestion strip. * @return whether we should swap the space instead of removing it. * @return whether we should swap the space instead of removing it. */ */ private boolean maybeStripSpace(final SettingsValues settingsValues, private boolean maybeStripSpace(final SettingsValues settingsValues, final int code, final int spaceState, final boolean isFromSuggestionStrip) { final InputTransaction inputTransaction, final boolean isFromSuggestionStrip) { if (Constants.CODE_ENTER == code && SpaceState.SWAP_PUNCTUATION == spaceState) { if (Constants.CODE_ENTER == inputTransaction.mKeyCode && SpaceState.SWAP_PUNCTUATION == inputTransaction.mSpaceState) { mConnection.removeTrailingSpace(); mConnection.removeTrailingSpace(); return false; return false; } } if ((SpaceState.WEAK == spaceState || SpaceState.SWAP_PUNCTUATION == spaceState) if ((SpaceState.WEAK == inputTransaction.mSpaceState || SpaceState.SWAP_PUNCTUATION == inputTransaction.mSpaceState) && isFromSuggestionStrip) { && isFromSuggestionStrip) { if (settingsValues.isUsuallyPrecededBySpace(code)) return false; if (settingsValues.isUsuallyPrecededBySpace(inputTransaction.mKeyCode)) { if (settingsValues.isUsuallyFollowedBySpace(code)) return true; return false; } if (settingsValues.isUsuallyFollowedBySpace(inputTransaction.mKeyCode)) { return true; } mConnection.removeTrailingSpace(); mConnection.removeTrailingSpace(); } } return false; return false; Loading Loading
java/src/com/android/inputmethod/event/InputTransaction.java +14 −1 Original line number Original line Diff line number Diff line Loading @@ -30,12 +30,25 @@ public class InputTransaction { public static final int SHIFT_UPDATE_LATER = 2; public static final int SHIFT_UPDATE_LATER = 2; // Initial conditions // Initial conditions // If the key inserts a code point, mKeyCode is always equal to the code points. Otherwise, // it's always a code that may not be a code point, typically a negative number. public final int mKeyCode; public final int mX; // Pressed x-coordinate, or one of Constants.*_COORDINATE public final int mY; // Pressed y-coordinate, or one of Constants.*_COORDINATE public final long mTimestamp; public final int mSpaceState; public final int mShiftState; public final int mShiftState; // Outputs // Outputs private int mRequiredShiftUpdate = SHIFT_NO_UPDATE; private int mRequiredShiftUpdate = SHIFT_NO_UPDATE; public InputTransaction(final int shiftState) { public InputTransaction(final int keyCode, final int x, final int y, final long timestamp, final int spaceState, final int shiftState) { mKeyCode = keyCode; mX = x; mY = y; mTimestamp = timestamp; mSpaceState = spaceState; mShiftState = shiftState; mShiftState = shiftState; } } Loading
java/src/com/android/inputmethod/keyboard/PointerTracker.java +2 −2 Original line number Original line Diff line number Diff line Loading @@ -323,7 +323,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element, } } // Note that we need primaryCode argument because the keyboard may in shifted state and the // Note that we need primaryCode argument because the keyboard may in shifted state and the // primaryCode is different from {@link Key#mCode}. // primaryCode is different from {@link Key#mKeyCode}. private void callListenerOnCodeInput(final Key key, final int primaryCode, final int x, private void callListenerOnCodeInput(final Key key, final int primaryCode, final int x, final int y, final long eventTime) { final int y, final long eventTime) { final boolean ignoreModifierKey = mIsInDraggingFinger && key.isModifier(); final boolean ignoreModifierKey = mIsInDraggingFinger && key.isModifier(); Loading Loading @@ -360,7 +360,7 @@ public final class PointerTracker implements PointerTrackerQueue.Element, } } // Note that we need primaryCode argument because the keyboard may be in shifted state and the // Note that we need primaryCode argument because the keyboard may be in shifted state and the // primaryCode is different from {@link Key#mCode}. // primaryCode is different from {@link Key#mKeyCode}. private void callListenerOnRelease(final Key key, final int primaryCode, private void callListenerOnRelease(final Key key, final int primaryCode, final boolean withSliding) { final boolean withSliding) { // See the comment at {@link #callListenerOnPressAndCheckKeyboardLayoutChange(Key}}. // See the comment at {@link #callListenerOnPressAndCheckKeyboardLayoutChange(Key}}. Loading
java/src/com/android/inputmethod/latin/Constants.java +1 −0 Original line number Original line Diff line number Diff line Loading @@ -144,6 +144,7 @@ public final class Constants { public static final int NOT_A_CODE = -1; public static final int NOT_A_CODE = -1; public static final int NOT_A_CURSOR_POSITION = -1; public static final int NOT_A_CURSOR_POSITION = -1; // TODO: replace the following constants with state in InputTransaction? public static final int NOT_A_COORDINATE = -1; public static final int NOT_A_COORDINATE = -1; public static final int SUGGESTION_STRIP_COORDINATE = -2; public static final int SUGGESTION_STRIP_COORDINATE = -2; public static final int SPELL_CHECKER_COORDINATE = -3; public static final int SPELL_CHECKER_COORDINATE = -3; Loading
java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java +77 −83 Original line number Original line Diff line number Diff line Loading @@ -361,38 +361,33 @@ public final class InputLogic { final SettingsValues settingsValues, final SettingsValues settingsValues, // TODO: remove these two arguments // TODO: remove these two arguments final LatinIME.UIHandler handler, final KeyboardSwitcher keyboardSwitcher) { final LatinIME.UIHandler handler, final KeyboardSwitcher keyboardSwitcher) { final InputTransaction inputTransaction = new InputTransaction(code, x, y, SystemClock.uptimeMillis(), mSpaceState, getActualCapsMode(settingsValues, keyboardSwitcher.getKeyboardShiftMode())); if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { ResearchLogger.latinIME_onCodeInput(code, x, y); ResearchLogger.latinIME_onCodeInput(inputTransaction.mKeyCode, inputTransaction.mX, inputTransaction.mY); } } final long when = SystemClock.uptimeMillis(); if (inputTransaction.mKeyCode != Constants.CODE_DELETE final InputTransaction inputTransaction = new InputTransaction( || inputTransaction.mTimestamp > mLastKeyTime + Constants.LONG_PRESS_MILLISECONDS) { getActualCapsMode(settingsValues, keyboardSwitcher.getKeyboardShiftMode())); if (code != Constants.CODE_DELETE || when > mLastKeyTime + Constants.LONG_PRESS_MILLISECONDS) { mDeleteCount = 0; mDeleteCount = 0; } } mLastKeyTime = when; mLastKeyTime = inputTransaction.mTimestamp; mConnection.beginBatchEdit(); mConnection.beginBatchEdit(); // 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()) { if (!mWordComposer.isComposingWord()) { mIsAutoCorrectionIndicatorOn = false; mIsAutoCorrectionIndicatorOn = false; } } // TODO: Consolidate the double-space period timer, mLastKeyTime, and the space state. // TODO: Consolidate the double-space period timer, mLastKeyTime, and the space state. if (code != Constants.CODE_SPACE) { if (inputTransaction.mKeyCode != Constants.CODE_SPACE) { handler.cancelDoubleSpacePeriodTimer(); handler.cancelDoubleSpacePeriodTimer(); } } boolean didAutoCorrect = false; boolean didAutoCorrect = false; switch (code) { switch (inputTransaction.mKeyCode) { case Constants.CODE_DELETE: case Constants.CODE_DELETE: handleBackspace(settingsValues, spaceState, inputTransaction, handler); handleBackspace(settingsValues, inputTransaction, handler); LatinImeLogger.logOnDelete(x, y); LatinImeLogger.logOnDelete(inputTransaction.mX, inputTransaction.mY); break; break; case Constants.CODE_SHIFT: case Constants.CODE_SHIFT: performRecapitalization(settingsValues); performRecapitalization(settingsValues); Loading Loading @@ -450,29 +445,31 @@ public final class InputLogic { } else { } else { // No action label, and the action from imeOptions is NONE: this is a regular // No action label, and the action from imeOptions is NONE: this is a regular // enter key that should input a carriage return. // enter key that should input a carriage return. didAutoCorrect = handleNonSpecialCharacter(settingsValues, Constants.CODE_ENTER, didAutoCorrect = handleNonSpecialCharacter(settingsValues, inputTransaction, x, y, spaceState, inputTransaction, handler); handler); } } break; break; case Constants.CODE_SHIFT_ENTER: case Constants.CODE_SHIFT_ENTER: didAutoCorrect = handleNonSpecialCharacter(settingsValues, Constants.CODE_ENTER, // TODO: remove this object x, y, spaceState, inputTransaction, handler); final InputTransaction tmpTransaction = new InputTransaction(inputTransaction.mKeyCode, inputTransaction.mX, inputTransaction.mY, inputTransaction.mTimestamp, inputTransaction.mSpaceState, inputTransaction.mShiftState); didAutoCorrect = handleNonSpecialCharacter(settingsValues, tmpTransaction, handler); break; break; case Constants.CODE_ALPHA_FROM_EMOJI: case Constants.CODE_ALPHA_FROM_EMOJI: // Note: Switching back from Emoji keyboard to the main keyboard is being handled in // Note: Switching back from Emoji keyboard to the main keyboard is being handled in // {@link KeyboardState#onCodeInput(int,int)}. // {@link KeyboardState#onCodeInput(int,int)}. break; break; default: default: didAutoCorrect = handleNonSpecialCharacter(settingsValues, didAutoCorrect = handleNonSpecialCharacter(settingsValues, inputTransaction, handler); code, x, y, spaceState, inputTransaction, handler); break; break; } } // Reset after any single keystroke, except shift, capslock, and symbol-shift // Reset after any single keystroke, except shift, capslock, and symbol-shift if (!didAutoCorrect && code != Constants.CODE_SHIFT if (!didAutoCorrect && inputTransaction.mKeyCode != Constants.CODE_SHIFT && code != Constants.CODE_CAPSLOCK && inputTransaction.mKeyCode != Constants.CODE_CAPSLOCK && code != Constants.CODE_SWITCH_ALPHA_SYMBOL) && inputTransaction.mKeyCode != Constants.CODE_SWITCH_ALPHA_SYMBOL) mLastComposedWord.deactivate(); mLastComposedWord.deactivate(); if (Constants.CODE_DELETE != code) { if (Constants.CODE_DELETE != inputTransaction.mKeyCode) { mEnteredText = null; mEnteredText = null; } } mConnection.endBatchEdit(); mConnection.endBatchEdit(); Loading Loading @@ -629,31 +626,27 @@ public final class InputLogic { * any key that results in multiple code points like the ".com" key. * any key that results in multiple code points like the ".com" key. * * * @param settingsValues The current settings values. * @param settingsValues The current settings values. * @param codePoint 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. * @param inputTransaction The transaction in progress. * @param inputTransaction The transaction in progress. * @return whether this caused an auto-correction to happen. * @return whether this caused an auto-correction to happen. */ */ private boolean handleNonSpecialCharacter(final SettingsValues settingsValues, private boolean handleNonSpecialCharacter(final SettingsValues settingsValues, final int codePoint, final int x, final int y, final int spaceState, final InputTransaction inputTransaction, final InputTransaction inputTransaction, // TODO: remove this argument // TODO: remove this argument final LatinIME.UIHandler handler) { final LatinIME.UIHandler handler) { mSpaceState = SpaceState.NONE; mSpaceState = SpaceState.NONE; final boolean didAutoCorrect; final boolean didAutoCorrect; if (settingsValues.isWordSeparator(codePoint) if (settingsValues.isWordSeparator(inputTransaction.mKeyCode) || Character.getType(codePoint) == Character.OTHER_SYMBOL) { || Character.getType(inputTransaction.mKeyCode) == Character.OTHER_SYMBOL) { didAutoCorrect = handleSeparator(settingsValues, codePoint, didAutoCorrect = handleSeparator(settingsValues, Constants.SUGGESTION_STRIP_COORDINATE == x, spaceState, inputTransaction, Constants.SUGGESTION_STRIP_COORDINATE == inputTransaction.mX, inputTransaction, handler); handler); if (settingsValues.mIsInternal) { if (settingsValues.mIsInternal) { LatinImeLoggerUtils.onSeparator((char)codePoint, x, y); LatinImeLoggerUtils.onSeparator((char)inputTransaction.mKeyCode, inputTransaction.mX, inputTransaction.mY); } } } else { } else { didAutoCorrect = false; didAutoCorrect = false; if (SpaceState.PHANTOM == spaceState) { if (SpaceState.PHANTOM == inputTransaction.mSpaceState) { if (settingsValues.mIsInternal) { if (settingsValues.mIsInternal) { if (mWordComposer.isComposingWord() && mWordComposer.isBatchMode()) { if (mWordComposer.isComposingWord() && mWordComposer.isBatchMode()) { LatinImeLoggerUtils.onAutoCorrection("", mWordComposer.getTypedWord(), " ", LatinImeLoggerUtils.onAutoCorrection("", mWordComposer.getTypedWord(), " ", Loading @@ -669,8 +662,7 @@ public final class InputLogic { commitTyped(settingsValues, LastComposedWord.NOT_A_SEPARATOR); commitTyped(settingsValues, LastComposedWord.NOT_A_SEPARATOR); } } } } handleNonSeparator(settingsValues, codePoint, x, y, spaceState, handleNonSeparator(settingsValues, inputTransaction, handler); inputTransaction, handler); } } return didAutoCorrect; return didAutoCorrect; } } Loading @@ -678,14 +670,9 @@ public final class InputLogic { /** /** * Handle a non-separator. * Handle a non-separator. * @param settingsValues The current settings values. * @param settingsValues The current settings values. * @param codePoint 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. * @param inputTransaction The transaction in progress. * @param inputTransaction The transaction in progress. */ */ private void handleNonSeparator(final SettingsValues settingsValues, private void handleNonSeparator(final SettingsValues settingsValues, final int codePoint, final int x, final int y, final int spaceState, final InputTransaction inputTransaction, final InputTransaction inputTransaction, // TODO: Remove this argument // TODO: Remove this argument final LatinIME.UIHandler handler) { final LatinIME.UIHandler handler) { Loading @@ -696,7 +683,8 @@ public final class InputLogic { // TODO: remove isWordConnector() and use isUsuallyFollowedBySpace() instead. // TODO: remove isWordConnector() and use isUsuallyFollowedBySpace() instead. // See onStartBatchInput() to see how to do it. // See onStartBatchInput() to see how to do it. if (SpaceState.PHANTOM == spaceState && !settingsValues.isWordConnector(codePoint)) { if (SpaceState.PHANTOM == inputTransaction.mSpaceState && !settingsValues.isWordConnector(inputTransaction.mKeyCode)) { if (isComposingWord) { if (isComposingWord) { // Sanity check // Sanity check throw new RuntimeException("Should not be composing here"); throw new RuntimeException("Should not be composing here"); Loading @@ -718,7 +706,7 @@ public final class InputLogic { if (!isComposingWord if (!isComposingWord // We only start composing if this is a word code point. Essentially that means it's a // We only start composing if this is a word code point. Essentially that means it's a // a letter or a word connector. // a letter or a word connector. && settingsValues.isWordCodePoint(codePoint) && settingsValues.isWordCodePoint(inputTransaction.mKeyCode) // We never go into composing state if suggestions are not requested. // We never go into composing state if suggestions are not requested. && settingsValues.isSuggestionsRequested() && && settingsValues.isSuggestionsRequested() && // In languages with spaces, we only start composing a word when we are not already // In languages with spaces, we only start composing a word when we are not already Loading @@ -729,8 +717,8 @@ public final class InputLogic { // the character is a single quote or a dash. The idea here is, single quote and dash // the character is a single quote or a dash. The idea here is, single quote and dash // are not separators and they should be treated as normal characters, except in the // are not separators and they should be treated as normal characters, except in the // first position where they should not start composing a word. // first position where they should not start composing a word. isComposingWord = (Constants.CODE_SINGLE_QUOTE != codePoint isComposingWord = (Constants.CODE_SINGLE_QUOTE != inputTransaction.mKeyCode && Constants.CODE_DASH != codePoint); && Constants.CODE_DASH != inputTransaction.mKeyCode); // Here we don't need to reset the last composed word. It will be reset // Here we don't need to reset the last composed word. It will be reset // when we commit this one, if we ever do; if on the other hand we backspace // when we commit this one, if we ever do; if on the other hand we backspace // it entirely and resume suggestions on the previous word, we'd like to still // it entirely and resume suggestions on the previous word, we'd like to still Loading @@ -738,7 +726,7 @@ public final class InputLogic { resetComposingState(false /* alsoResetLastComposedWord */); resetComposingState(false /* alsoResetLastComposedWord */); } } if (isComposingWord) { if (isComposingWord) { mWordComposer.add(codePoint, x, y); mWordComposer.add(inputTransaction.mKeyCode, inputTransaction.mX, inputTransaction.mY); // If it's the first letter, make note of auto-caps state // If it's the first letter, make note of auto-caps state if (mWordComposer.size() == 1) { if (mWordComposer.size() == 1) { // We pass 1 to getPreviousWordForSuggestion because we were not composing a word // We pass 1 to getPreviousWordForSuggestion because we were not composing a word Loading @@ -750,10 +738,10 @@ public final class InputLogic { mConnection.setComposingText(getTextWithUnderline( mConnection.setComposingText(getTextWithUnderline( mWordComposer.getTypedWord()), 1); mWordComposer.getTypedWord()), 1); } else { } else { final boolean swapWeakSpace = maybeStripSpace(settingsValues, final boolean swapWeakSpace = maybeStripSpace(settingsValues, inputTransaction, codePoint, spaceState, Constants.SUGGESTION_STRIP_COORDINATE == x); Constants.SUGGESTION_STRIP_COORDINATE == inputTransaction.mX); sendKeyCodePoint(settingsValues, codePoint); sendKeyCodePoint(settingsValues, inputTransaction.mKeyCode); if (swapWeakSpace) { if (swapWeakSpace) { swapSwapperAndSpace(inputTransaction); swapSwapperAndSpace(inputTransaction); Loading @@ -764,27 +752,25 @@ public final class InputLogic { } } handler.postUpdateSuggestionStrip(); handler.postUpdateSuggestionStrip(); if (settingsValues.mIsInternal) { if (settingsValues.mIsInternal) { LatinImeLoggerUtils.onNonSeparator((char)codePoint, x, y); LatinImeLoggerUtils.onNonSeparator((char)inputTransaction.mKeyCode, inputTransaction.mX, inputTransaction.mY); } } } } /** /** * Handle input of a separator code point. * Handle input of a separator code point. * @param settingsValues The current settings values. * @param settingsValues The current settings values. * @param codePoint the code point associated with the key. * @param isFromSuggestionStrip whether this code point comes from the suggestion strip. * @param isFromSuggestionStrip whether this code point comes from the suggestion strip. * @param spaceState the space state at start of the batch input. * @param inputTransaction The transaction in progress. * @param inputTransaction The transaction in progress. * @return whether this caused an auto-correction to happen. * @return whether this caused an auto-correction to happen. */ */ private boolean handleSeparator(final SettingsValues settingsValues, private boolean handleSeparator(final SettingsValues settingsValues, final int codePoint, final boolean isFromSuggestionStrip, final int spaceState, final boolean isFromSuggestionStrip, final InputTransaction inputTransaction, final InputTransaction inputTransaction, // TODO: remove this argument // TODO: remove this argument final LatinIME.UIHandler handler) { final LatinIME.UIHandler handler) { boolean didAutoCorrect = false; boolean didAutoCorrect = false; // We avoid sending spaces in languages without spaces if we were composing. // We avoid sending spaces in languages without spaces if we were composing. final boolean shouldAvoidSendingCode = Constants.CODE_SPACE == codePoint final boolean shouldAvoidSendingCode = Constants.CODE_SPACE == inputTransaction.mKeyCode && !settingsValues.mSpacingAndPunctuations.mCurrentLanguageHasSpaces && !settingsValues.mSpacingAndPunctuations.mCurrentLanguageHasSpaces && mWordComposer.isComposingWord(); && mWordComposer.isComposingWord(); if (mWordComposer.isCursorFrontOrMiddleOfComposingWord()) { if (mWordComposer.isCursorFrontOrMiddleOfComposingWord()) { Loading @@ -797,43 +783,47 @@ public final class InputLogic { if (mWordComposer.isComposingWord()) { if (mWordComposer.isComposingWord()) { if (settingsValues.mCorrectionEnabled) { if (settingsValues.mCorrectionEnabled) { final String separator = shouldAvoidSendingCode ? LastComposedWord.NOT_A_SEPARATOR final String separator = shouldAvoidSendingCode ? LastComposedWord.NOT_A_SEPARATOR : StringUtils.newSingleCodePointString(codePoint); : StringUtils.newSingleCodePointString(inputTransaction.mKeyCode); commitCurrentAutoCorrection(settingsValues, separator, handler); commitCurrentAutoCorrection(settingsValues, separator, handler); didAutoCorrect = true; didAutoCorrect = true; } else { } else { commitTyped(settingsValues, StringUtils.newSingleCodePointString(codePoint)); commitTyped(settingsValues, StringUtils.newSingleCodePointString(inputTransaction.mKeyCode)); } } } } final boolean swapWeakSpace = maybeStripSpace(settingsValues, codePoint, spaceState, final boolean swapWeakSpace = maybeStripSpace(settingsValues, inputTransaction, isFromSuggestionStrip); isFromSuggestionStrip); final boolean isInsideDoubleQuoteOrAfterDigit = Constants.CODE_DOUBLE_QUOTE == codePoint final boolean isInsideDoubleQuoteOrAfterDigit = Constants.CODE_DOUBLE_QUOTE == inputTransaction.mKeyCode && mConnection.isInsideDoubleQuoteOrAfterDigit(); && mConnection.isInsideDoubleQuoteOrAfterDigit(); final boolean needsPrecedingSpace; final boolean needsPrecedingSpace; if (SpaceState.PHANTOM != spaceState) { if (SpaceState.PHANTOM != inputTransaction.mSpaceState) { needsPrecedingSpace = false; needsPrecedingSpace = false; } else if (Constants.CODE_DOUBLE_QUOTE == codePoint) { } else if (Constants.CODE_DOUBLE_QUOTE == inputTransaction.mKeyCode) { // Double quotes behave like they are usually preceded by space iff we are // Double quotes behave like they are usually preceded by space iff we are // not inside a double quote or after a digit. // not inside a double quote or after a digit. needsPrecedingSpace = !isInsideDoubleQuoteOrAfterDigit; needsPrecedingSpace = !isInsideDoubleQuoteOrAfterDigit; } else { } else { needsPrecedingSpace = settingsValues.isUsuallyPrecededBySpace(codePoint); needsPrecedingSpace = settingsValues.isUsuallyPrecededBySpace(inputTransaction.mKeyCode); } } if (needsPrecedingSpace) { if (needsPrecedingSpace) { promotePhantomSpace(settingsValues); promotePhantomSpace(settingsValues); } } if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { ResearchLogger.latinIME_handleSeparator(codePoint, mWordComposer.isComposingWord()); ResearchLogger.latinIME_handleSeparator(inputTransaction.mKeyCode, mWordComposer.isComposingWord()); } } if (!shouldAvoidSendingCode) { if (!shouldAvoidSendingCode) { sendKeyCodePoint(settingsValues, codePoint); sendKeyCodePoint(settingsValues, inputTransaction.mKeyCode); } } if (Constants.CODE_SPACE == codePoint) { if (Constants.CODE_SPACE == inputTransaction.mKeyCode) { if (settingsValues.isSuggestionsRequested()) { if (settingsValues.isSuggestionsRequested()) { if (maybeDoubleSpacePeriod(settingsValues, handler)) { if (maybeDoubleSpacePeriod(settingsValues, handler)) { inputTransaction.requireShiftUpdate(InputTransaction.SHIFT_UPDATE_NOW); inputTransaction.requireShiftUpdate(InputTransaction.SHIFT_UPDATE_NOW); Loading @@ -849,9 +839,9 @@ public final class InputLogic { if (swapWeakSpace) { if (swapWeakSpace) { swapSwapperAndSpace(inputTransaction); swapSwapperAndSpace(inputTransaction); mSpaceState = SpaceState.SWAP_PUNCTUATION; mSpaceState = SpaceState.SWAP_PUNCTUATION; } else if ((SpaceState.PHANTOM == spaceState } else if ((SpaceState.PHANTOM == inputTransaction.mSpaceState && settingsValues.isUsuallyFollowedBySpace(codePoint)) && settingsValues.isUsuallyFollowedBySpace(inputTransaction.mKeyCode)) || (Constants.CODE_DOUBLE_QUOTE == codePoint || (Constants.CODE_DOUBLE_QUOTE == inputTransaction.mKeyCode && isInsideDoubleQuoteOrAfterDigit)) { && isInsideDoubleQuoteOrAfterDigit)) { // If we are in phantom space state, and the user presses a separator, we want to // 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 // stay in phantom space state so that the next keypress has a chance to add the Loading Loading @@ -879,10 +869,9 @@ public final class InputLogic { /** /** * Handle a press on the backspace key. * Handle a press on the backspace key. * @param settingsValues The current settings values. * @param settingsValues The current settings values. * @param spaceState The space state at start of this batch edit. * @param inputTransaction The transaction in progress. * @param inputTransaction The transaction in progress. */ */ private void handleBackspace(final SettingsValues settingsValues, final int spaceState, private void handleBackspace(final SettingsValues settingsValues, final InputTransaction inputTransaction, final InputTransaction inputTransaction, // TODO: remove this argument // TODO: remove this argument final LatinIME.UIHandler handler) { final LatinIME.UIHandler handler) { Loading Loading @@ -942,14 +931,14 @@ public final class InputLogic { // reverting any autocorrect at this point. So we can safely return. // reverting any autocorrect at this point. So we can safely return. return; return; } } if (SpaceState.DOUBLE == spaceState) { if (SpaceState.DOUBLE == inputTransaction.mSpaceState) { handler.cancelDoubleSpacePeriodTimer(); handler.cancelDoubleSpacePeriodTimer(); if (mConnection.revertDoubleSpacePeriod()) { if (mConnection.revertDoubleSpacePeriod()) { // No need to reset mSpaceState, it has already be done (that's why we // No need to reset mSpaceState, it has already be done (that's why we // receive it as a parameter) // receive it as a parameter) return; return; } } } else if (SpaceState.SWAP_PUNCTUATION == spaceState) { } else if (SpaceState.SWAP_PUNCTUATION == inputTransaction.mSpaceState) { if (mConnection.revertSwapPunctuation()) { if (mConnection.revertSwapPunctuation()) { // Likewise // Likewise return; return; Loading Loading @@ -1065,21 +1054,26 @@ public final class InputLogic { /* /* * Strip a trailing space if necessary and returns whether it's a swap weak space situation. * Strip a trailing space if necessary and returns whether it's a swap weak space situation. * @param settingsValues The current settings values. * @param settingsValues The current settings values. * @param codePoint The code point that is about to be inserted. * @param inputTransaction The transaction in progress. * @param spaceState The space state at start of this batch edit. * @param isFromSuggestionStrip Whether this code point is coming from the suggestion strip. * @param isFromSuggestionStrip Whether this code point is coming from the suggestion strip. * @return whether we should swap the space instead of removing it. * @return whether we should swap the space instead of removing it. */ */ private boolean maybeStripSpace(final SettingsValues settingsValues, private boolean maybeStripSpace(final SettingsValues settingsValues, final int code, final int spaceState, final boolean isFromSuggestionStrip) { final InputTransaction inputTransaction, final boolean isFromSuggestionStrip) { if (Constants.CODE_ENTER == code && SpaceState.SWAP_PUNCTUATION == spaceState) { if (Constants.CODE_ENTER == inputTransaction.mKeyCode && SpaceState.SWAP_PUNCTUATION == inputTransaction.mSpaceState) { mConnection.removeTrailingSpace(); mConnection.removeTrailingSpace(); return false; return false; } } if ((SpaceState.WEAK == spaceState || SpaceState.SWAP_PUNCTUATION == spaceState) if ((SpaceState.WEAK == inputTransaction.mSpaceState || SpaceState.SWAP_PUNCTUATION == inputTransaction.mSpaceState) && isFromSuggestionStrip) { && isFromSuggestionStrip) { if (settingsValues.isUsuallyPrecededBySpace(code)) return false; if (settingsValues.isUsuallyPrecededBySpace(inputTransaction.mKeyCode)) { if (settingsValues.isUsuallyFollowedBySpace(code)) return true; return false; } if (settingsValues.isUsuallyFollowedBySpace(inputTransaction.mKeyCode)) { return true; } mConnection.removeTrailingSpace(); mConnection.removeTrailingSpace(); } } return false; return false; Loading