Loading java/src/com/android/inputmethod/latin/LatinIME.java +10 −8 Original line number Diff line number Diff line Loading @@ -741,6 +741,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // switcher.loadKeyboard; in apps like Talk, we come here when the text is sent and the // field gets emptied and we need to re-evaluate the shift state, but not the whole layout // which would be disruptive. // Space state must be updated before calling updateShiftState mKeyboardSwitcher.updateShiftState(); mHandler.cancelUpdateSuggestionStrip(); Loading Loading @@ -1114,11 +1115,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // unless needed. if (mWordComposer.isComposingWord()) return Constants.TextUtils.CAP_MODE_OFF; // TODO: This blocking IPC call is heavy. Consider doing this without using IPC calls. // Note: getCursorCapsMode() returns the current capitalization mode that is any // combination of CAP_MODE_CHARACTERS, CAP_MODE_WORDS, and CAP_MODE_SENTENCES. 0 means none // of them. return mConnection.getCursorCapsMode(inputType, mSubtypeSwitcher.getCurrentSubtypeLocale()); // 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 mConnection.getCursorCapsMode(inputType, mSubtypeSwitcher.getCurrentSubtypeLocale(), SPACE_STATE_PHANTOM == mSpaceState); } // Factor in auto-caps and manual caps and compute the current caps mode. Loading Loading @@ -1391,9 +1391,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } mConnection.commitText(text, 1); mConnection.endBatchEdit(); // Space state must be updated before calling updateShiftState mSpaceState = SPACE_STATE_NONE; mKeyboardSwitcher.updateShiftState(); mKeyboardSwitcher.onCodeInput(Keyboard.CODE_OUTPUT_TEXT); mSpaceState = SPACE_STATE_NONE; mEnteredText = text; } Loading Loading @@ -1509,8 +1510,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mConnection.setComposingText(batchInputText, 1); mExpectingUpdateSelection = true; mConnection.endBatchEdit(); mKeyboardSwitcher.updateShiftState(); // Space state must be updated before calling updateShiftState mSpaceState = SPACE_STATE_PHANTOM; mKeyboardSwitcher.updateShiftState(); } private CharSequence specificTldProcessingOnTextInput(final CharSequence text) { Loading Loading @@ -2019,8 +2021,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mConnection.endBatchEdit(); // Don't allow cancellation of manual pick mLastComposedWord.deactivate(); // Space state must be updated before calling updateShiftState mSpaceState = SPACE_STATE_PHANTOM; // TODO: is this necessary? mKeyboardSwitcher.updateShiftState(); // We should show the "Touch again to save" hint if the user pressed the first entry Loading java/src/com/android/inputmethod/latin/RichInputConnection.java +19 −2 Original line number Diff line number Diff line Loading @@ -190,7 +190,23 @@ public class RichInputConnection { } } public int getCursorCapsMode(final int inputType, final Locale locale) { /** * Gets the caps modes we should be in after this specific string. * * This returns a bit set of TextUtils#CAP_MODE_*, masked by the inputType argument. * This method also supports faking an additional space after the string passed in argument, * to support cases where a space will be added automatically, like in phantom space * state for example. * Note that for English, we are using American typography rules (which are not specific to * American English, it's just the most common set of rules for English). * * @param inputType a mask of the caps modes to test for. * @param locale what language should be considered. * @param hasSpaceBefore if we should consider there should be a space after the string. * @return the caps modes that should be on as a set of bits */ public int getCursorCapsMode(final int inputType, final Locale locale, final boolean hasSpaceBefore) { mIC = mParent.getCurrentInputConnection(); if (null == mIC) return Constants.TextUtils.CAP_MODE_OFF; if (!TextUtils.isEmpty(mComposingText)) return Constants.TextUtils.CAP_MODE_OFF; Loading @@ -205,7 +221,8 @@ public class RichInputConnection { } // This never calls InputConnection#getCapsMode - in fact, it's a static method that // never blocks or initiates IPC. return StringUtils.getCapsMode(mCommittedTextBeforeComposingText, inputType, locale); return StringUtils.getCapsMode(mCommittedTextBeforeComposingText, inputType, locale, hasSpaceBefore); } public CharSequence getTextBeforeCursor(final int i, final int j) { Loading java/src/com/android/inputmethod/latin/StringUtils.java +13 −6 Original line number Diff line number Diff line Loading @@ -197,13 +197,15 @@ public final class StringUtils { * {@link TextUtils#CAP_MODE_CHARACTERS}, {@link TextUtils#CAP_MODE_WORDS}, and * {@link TextUtils#CAP_MODE_SENTENCES}. * @param locale The locale to consider for capitalization rules * @param hasSpaceBefore Whether we should consider there is a space inserted at the end of cs * * @return Returns the actual capitalization modes that can be in effect * at the current position, which is any combination of * {@link TextUtils#CAP_MODE_CHARACTERS}, {@link TextUtils#CAP_MODE_WORDS}, and * {@link TextUtils#CAP_MODE_SENTENCES}. */ public static int getCapsMode(final CharSequence cs, final int reqModes, final Locale locale) { public static int getCapsMode(final CharSequence cs, final int reqModes, final Locale locale, final boolean hasSpaceBefore) { // Quick description of what we want to do: // CAP_MODE_CHARACTERS is always on. // CAP_MODE_WORDS is on if there is some whitespace before the cursor. Loading @@ -230,6 +232,9 @@ public final class StringUtils { // single quote since they aren't start punctuation in the unicode sense, but should still // be skipped for English. TODO: does this depend on the language? int i; if (hasSpaceBefore) { i = cs.length() + 1; } else { for (i = cs.length(); i > 0; i--) { final char c = cs.charAt(i - 1); if (c != Keyboard.CODE_DOUBLE_QUOTE && c != Keyboard.CODE_SINGLE_QUOTE Loading @@ -237,6 +242,7 @@ public final class StringUtils { break; } } } // We are now on the character that precedes any starting punctuation, so in the most // frequent case this will be whitespace or a letter, although it may occasionally be a Loading @@ -247,6 +253,7 @@ public final class StringUtils { // if the first char that's not a space or tab is a start of line (as in, either \n or // start of text). int j = i; if (hasSpaceBefore) --j; while (j > 0 && Character.isWhitespace(cs.charAt(j - 1))) { j--; } Loading tests/src/com/android/inputmethod/latin/StringUtilsTests.java +37 −30 Original line number Diff line number Diff line Loading @@ -93,22 +93,24 @@ public class StringUtilsTests extends AndroidTestCase { } private void onePathForCaps(final CharSequence cs, final int expectedResult, final int mask, final Locale l) { final Locale l, final boolean hasSpaceBefore) { int oneTimeResult = expectedResult & mask; assertEquals("After >" + cs + "<", oneTimeResult, StringUtils.getCapsMode(cs, mask, l)); assertEquals("After >" + cs + "<", oneTimeResult, StringUtils.getCapsMode(cs, mask, l, hasSpaceBefore)); } private void allPathsForCaps(final CharSequence cs, final int expectedResult, final Locale l) { private void allPathsForCaps(final CharSequence cs, final int expectedResult, final Locale l, final boolean hasSpaceBefore) { final int c = TextUtils.CAP_MODE_CHARACTERS; final int w = TextUtils.CAP_MODE_WORDS; final int s = TextUtils.CAP_MODE_SENTENCES; onePathForCaps(cs, expectedResult, c | w | s, l); onePathForCaps(cs, expectedResult, w | s, l); onePathForCaps(cs, expectedResult, c | s, l); onePathForCaps(cs, expectedResult, c | w, l); onePathForCaps(cs, expectedResult, c, l); onePathForCaps(cs, expectedResult, w, l); onePathForCaps(cs, expectedResult, s, l); onePathForCaps(cs, expectedResult, c | w | s, l, hasSpaceBefore); onePathForCaps(cs, expectedResult, w | s, l, hasSpaceBefore); onePathForCaps(cs, expectedResult, c | s, l, hasSpaceBefore); onePathForCaps(cs, expectedResult, c | w, l, hasSpaceBefore); onePathForCaps(cs, expectedResult, c, l, hasSpaceBefore); onePathForCaps(cs, expectedResult, w, l, hasSpaceBefore); onePathForCaps(cs, expectedResult, s, l, hasSpaceBefore); } public void testGetCapsMode() { Loading @@ -116,26 +118,31 @@ public class StringUtilsTests extends AndroidTestCase { final int w = TextUtils.CAP_MODE_WORDS; final int s = TextUtils.CAP_MODE_SENTENCES; Locale l = Locale.ENGLISH; allPathsForCaps("", c | w | s, l); allPathsForCaps("Word", c, l); allPathsForCaps("Word.", c, l); allPathsForCaps("Word ", c | w, l); allPathsForCaps("Word. ", c | w | s, l); allPathsForCaps("Word..", c, l); allPathsForCaps("Word.. ", c | w | s, l); allPathsForCaps("Word... ", c | w | s, l); allPathsForCaps("Word ... ", c | w | s, l); allPathsForCaps("Word . ", c | w, l); allPathsForCaps("In the U.S ", c | w, l); allPathsForCaps("In the U.S. ", c | w, l); allPathsForCaps("Some stuff (e.g. ", c | w, l); allPathsForCaps("In the U.S.. ", c | w | s, l); allPathsForCaps("\"Word.\" ", c | w | s, l); allPathsForCaps("\"Word\". ", c | w | s, l); allPathsForCaps("\"Word\" ", c | w, l); allPathsForCaps("", c | w | s, l, false); allPathsForCaps("Word", c, l, false); allPathsForCaps("Word.", c, l, false); allPathsForCaps("Word ", c | w, l, false); allPathsForCaps("Word. ", c | w | s, l, false); allPathsForCaps("Word..", c, l, false); allPathsForCaps("Word.. ", c | w | s, l, false); allPathsForCaps("Word... ", c | w | s, l, false); allPathsForCaps("Word ... ", c | w | s, l, false); allPathsForCaps("Word . ", c | w, l, false); allPathsForCaps("In the U.S ", c | w, l, false); allPathsForCaps("In the U.S. ", c | w, l, false); allPathsForCaps("Some stuff (e.g. ", c | w, l, false); allPathsForCaps("In the U.S.. ", c | w | s, l, false); allPathsForCaps("\"Word.\" ", c | w | s, l, false); allPathsForCaps("\"Word\". ", c | w | s, l, false); allPathsForCaps("\"Word\" ", c | w, l, false); // Test for phantom space allPathsForCaps("Word", c | w, l, true); allPathsForCaps("Word.", c | w | s, l, true); l = Locale.FRENCH; allPathsForCaps("\"Word.\" ", c | w, l); allPathsForCaps("\"Word\". ", c | w | s, l); allPathsForCaps("\"Word\" ", c | w, l); allPathsForCaps("\"Word.\" ", c | w, l, false); allPathsForCaps("\"Word\". ", c | w | s, l, false); allPathsForCaps("\"Word\" ", c | w, l, false); } } Loading
java/src/com/android/inputmethod/latin/LatinIME.java +10 −8 Original line number Diff line number Diff line Loading @@ -741,6 +741,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // switcher.loadKeyboard; in apps like Talk, we come here when the text is sent and the // field gets emptied and we need to re-evaluate the shift state, but not the whole layout // which would be disruptive. // Space state must be updated before calling updateShiftState mKeyboardSwitcher.updateShiftState(); mHandler.cancelUpdateSuggestionStrip(); Loading Loading @@ -1114,11 +1115,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // unless needed. if (mWordComposer.isComposingWord()) return Constants.TextUtils.CAP_MODE_OFF; // TODO: This blocking IPC call is heavy. Consider doing this without using IPC calls. // Note: getCursorCapsMode() returns the current capitalization mode that is any // combination of CAP_MODE_CHARACTERS, CAP_MODE_WORDS, and CAP_MODE_SENTENCES. 0 means none // of them. return mConnection.getCursorCapsMode(inputType, mSubtypeSwitcher.getCurrentSubtypeLocale()); // 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 mConnection.getCursorCapsMode(inputType, mSubtypeSwitcher.getCurrentSubtypeLocale(), SPACE_STATE_PHANTOM == mSpaceState); } // Factor in auto-caps and manual caps and compute the current caps mode. Loading Loading @@ -1391,9 +1391,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen } mConnection.commitText(text, 1); mConnection.endBatchEdit(); // Space state must be updated before calling updateShiftState mSpaceState = SPACE_STATE_NONE; mKeyboardSwitcher.updateShiftState(); mKeyboardSwitcher.onCodeInput(Keyboard.CODE_OUTPUT_TEXT); mSpaceState = SPACE_STATE_NONE; mEnteredText = text; } Loading Loading @@ -1509,8 +1510,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mConnection.setComposingText(batchInputText, 1); mExpectingUpdateSelection = true; mConnection.endBatchEdit(); mKeyboardSwitcher.updateShiftState(); // Space state must be updated before calling updateShiftState mSpaceState = SPACE_STATE_PHANTOM; mKeyboardSwitcher.updateShiftState(); } private CharSequence specificTldProcessingOnTextInput(final CharSequence text) { Loading Loading @@ -2019,8 +2021,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mConnection.endBatchEdit(); // Don't allow cancellation of manual pick mLastComposedWord.deactivate(); // Space state must be updated before calling updateShiftState mSpaceState = SPACE_STATE_PHANTOM; // TODO: is this necessary? mKeyboardSwitcher.updateShiftState(); // We should show the "Touch again to save" hint if the user pressed the first entry Loading
java/src/com/android/inputmethod/latin/RichInputConnection.java +19 −2 Original line number Diff line number Diff line Loading @@ -190,7 +190,23 @@ public class RichInputConnection { } } public int getCursorCapsMode(final int inputType, final Locale locale) { /** * Gets the caps modes we should be in after this specific string. * * This returns a bit set of TextUtils#CAP_MODE_*, masked by the inputType argument. * This method also supports faking an additional space after the string passed in argument, * to support cases where a space will be added automatically, like in phantom space * state for example. * Note that for English, we are using American typography rules (which are not specific to * American English, it's just the most common set of rules for English). * * @param inputType a mask of the caps modes to test for. * @param locale what language should be considered. * @param hasSpaceBefore if we should consider there should be a space after the string. * @return the caps modes that should be on as a set of bits */ public int getCursorCapsMode(final int inputType, final Locale locale, final boolean hasSpaceBefore) { mIC = mParent.getCurrentInputConnection(); if (null == mIC) return Constants.TextUtils.CAP_MODE_OFF; if (!TextUtils.isEmpty(mComposingText)) return Constants.TextUtils.CAP_MODE_OFF; Loading @@ -205,7 +221,8 @@ public class RichInputConnection { } // This never calls InputConnection#getCapsMode - in fact, it's a static method that // never blocks or initiates IPC. return StringUtils.getCapsMode(mCommittedTextBeforeComposingText, inputType, locale); return StringUtils.getCapsMode(mCommittedTextBeforeComposingText, inputType, locale, hasSpaceBefore); } public CharSequence getTextBeforeCursor(final int i, final int j) { Loading
java/src/com/android/inputmethod/latin/StringUtils.java +13 −6 Original line number Diff line number Diff line Loading @@ -197,13 +197,15 @@ public final class StringUtils { * {@link TextUtils#CAP_MODE_CHARACTERS}, {@link TextUtils#CAP_MODE_WORDS}, and * {@link TextUtils#CAP_MODE_SENTENCES}. * @param locale The locale to consider for capitalization rules * @param hasSpaceBefore Whether we should consider there is a space inserted at the end of cs * * @return Returns the actual capitalization modes that can be in effect * at the current position, which is any combination of * {@link TextUtils#CAP_MODE_CHARACTERS}, {@link TextUtils#CAP_MODE_WORDS}, and * {@link TextUtils#CAP_MODE_SENTENCES}. */ public static int getCapsMode(final CharSequence cs, final int reqModes, final Locale locale) { public static int getCapsMode(final CharSequence cs, final int reqModes, final Locale locale, final boolean hasSpaceBefore) { // Quick description of what we want to do: // CAP_MODE_CHARACTERS is always on. // CAP_MODE_WORDS is on if there is some whitespace before the cursor. Loading @@ -230,6 +232,9 @@ public final class StringUtils { // single quote since they aren't start punctuation in the unicode sense, but should still // be skipped for English. TODO: does this depend on the language? int i; if (hasSpaceBefore) { i = cs.length() + 1; } else { for (i = cs.length(); i > 0; i--) { final char c = cs.charAt(i - 1); if (c != Keyboard.CODE_DOUBLE_QUOTE && c != Keyboard.CODE_SINGLE_QUOTE Loading @@ -237,6 +242,7 @@ public final class StringUtils { break; } } } // We are now on the character that precedes any starting punctuation, so in the most // frequent case this will be whitespace or a letter, although it may occasionally be a Loading @@ -247,6 +253,7 @@ public final class StringUtils { // if the first char that's not a space or tab is a start of line (as in, either \n or // start of text). int j = i; if (hasSpaceBefore) --j; while (j > 0 && Character.isWhitespace(cs.charAt(j - 1))) { j--; } Loading
tests/src/com/android/inputmethod/latin/StringUtilsTests.java +37 −30 Original line number Diff line number Diff line Loading @@ -93,22 +93,24 @@ public class StringUtilsTests extends AndroidTestCase { } private void onePathForCaps(final CharSequence cs, final int expectedResult, final int mask, final Locale l) { final Locale l, final boolean hasSpaceBefore) { int oneTimeResult = expectedResult & mask; assertEquals("After >" + cs + "<", oneTimeResult, StringUtils.getCapsMode(cs, mask, l)); assertEquals("After >" + cs + "<", oneTimeResult, StringUtils.getCapsMode(cs, mask, l, hasSpaceBefore)); } private void allPathsForCaps(final CharSequence cs, final int expectedResult, final Locale l) { private void allPathsForCaps(final CharSequence cs, final int expectedResult, final Locale l, final boolean hasSpaceBefore) { final int c = TextUtils.CAP_MODE_CHARACTERS; final int w = TextUtils.CAP_MODE_WORDS; final int s = TextUtils.CAP_MODE_SENTENCES; onePathForCaps(cs, expectedResult, c | w | s, l); onePathForCaps(cs, expectedResult, w | s, l); onePathForCaps(cs, expectedResult, c | s, l); onePathForCaps(cs, expectedResult, c | w, l); onePathForCaps(cs, expectedResult, c, l); onePathForCaps(cs, expectedResult, w, l); onePathForCaps(cs, expectedResult, s, l); onePathForCaps(cs, expectedResult, c | w | s, l, hasSpaceBefore); onePathForCaps(cs, expectedResult, w | s, l, hasSpaceBefore); onePathForCaps(cs, expectedResult, c | s, l, hasSpaceBefore); onePathForCaps(cs, expectedResult, c | w, l, hasSpaceBefore); onePathForCaps(cs, expectedResult, c, l, hasSpaceBefore); onePathForCaps(cs, expectedResult, w, l, hasSpaceBefore); onePathForCaps(cs, expectedResult, s, l, hasSpaceBefore); } public void testGetCapsMode() { Loading @@ -116,26 +118,31 @@ public class StringUtilsTests extends AndroidTestCase { final int w = TextUtils.CAP_MODE_WORDS; final int s = TextUtils.CAP_MODE_SENTENCES; Locale l = Locale.ENGLISH; allPathsForCaps("", c | w | s, l); allPathsForCaps("Word", c, l); allPathsForCaps("Word.", c, l); allPathsForCaps("Word ", c | w, l); allPathsForCaps("Word. ", c | w | s, l); allPathsForCaps("Word..", c, l); allPathsForCaps("Word.. ", c | w | s, l); allPathsForCaps("Word... ", c | w | s, l); allPathsForCaps("Word ... ", c | w | s, l); allPathsForCaps("Word . ", c | w, l); allPathsForCaps("In the U.S ", c | w, l); allPathsForCaps("In the U.S. ", c | w, l); allPathsForCaps("Some stuff (e.g. ", c | w, l); allPathsForCaps("In the U.S.. ", c | w | s, l); allPathsForCaps("\"Word.\" ", c | w | s, l); allPathsForCaps("\"Word\". ", c | w | s, l); allPathsForCaps("\"Word\" ", c | w, l); allPathsForCaps("", c | w | s, l, false); allPathsForCaps("Word", c, l, false); allPathsForCaps("Word.", c, l, false); allPathsForCaps("Word ", c | w, l, false); allPathsForCaps("Word. ", c | w | s, l, false); allPathsForCaps("Word..", c, l, false); allPathsForCaps("Word.. ", c | w | s, l, false); allPathsForCaps("Word... ", c | w | s, l, false); allPathsForCaps("Word ... ", c | w | s, l, false); allPathsForCaps("Word . ", c | w, l, false); allPathsForCaps("In the U.S ", c | w, l, false); allPathsForCaps("In the U.S. ", c | w, l, false); allPathsForCaps("Some stuff (e.g. ", c | w, l, false); allPathsForCaps("In the U.S.. ", c | w | s, l, false); allPathsForCaps("\"Word.\" ", c | w | s, l, false); allPathsForCaps("\"Word\". ", c | w | s, l, false); allPathsForCaps("\"Word\" ", c | w, l, false); // Test for phantom space allPathsForCaps("Word", c | w, l, true); allPathsForCaps("Word.", c | w | s, l, true); l = Locale.FRENCH; allPathsForCaps("\"Word.\" ", c | w, l); allPathsForCaps("\"Word\". ", c | w | s, l); allPathsForCaps("\"Word\" ", c | w, l); allPathsForCaps("\"Word.\" ", c | w, l, false); allPathsForCaps("\"Word\". ", c | w | s, l, false); allPathsForCaps("\"Word\" ", c | w, l, false); } }