Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 90a91272 authored by Jean Chalard's avatar Jean Chalard
Browse files

Take space state into account for caps (A11)

Bug: 6950087
Change-Id: I8a1bca24db64b4dd54db8ac74d90cf43cbdddab6
parent 764dd712
Loading
Loading
Loading
Loading
+10 −8
Original line number Diff line number Diff line
@@ -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();
@@ -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.
@@ -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;
    }

@@ -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) {
@@ -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
+19 −2
Original line number Diff line number Diff line
@@ -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;
@@ -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) {
+13 −6
Original line number Diff line number Diff line
@@ -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.
@@ -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
@@ -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
@@ -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--;
        }
+37 −30
Original line number Diff line number Diff line
@@ -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() {
@@ -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);
    }
}