diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 78c65e0c780ae13cba93335289472d2c2ea2be79..d8b1c292b5a3822be15ee254d9f8aae5e6a8365f 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -700,6 +700,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
             }
         }
 
+        mConnection.resetCachesUponCursorMove(mLastSelectionStart);
+
         if (isDifferentTextField) {
             mainKeyboardView.closing();
             loadSettings();
@@ -733,8 +735,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
         mainKeyboardView.setGesturePreviewMode(mCurrentSettings.mGesturePreviewTrailEnabled,
                 mCurrentSettings.mGestureFloatingPreviewTextEnabled);
 
-        mConnection.resetCachesUponCursorMove(mLastSelectionStart);
-
         if (TRACE) Debug.startMethodTracing("/data/trace/latinime");
     }
 
diff --git a/java/src/com/android/inputmethod/latin/RichInputConnection.java b/java/src/com/android/inputmethod/latin/RichInputConnection.java
index 37e1dbb6903ce136e9a9e6c3d3e4d93e6fefc9b1..efda623e566f0012b330ef4cd31f2d02193c0289 100644
--- a/java/src/com/android/inputmethod/latin/RichInputConnection.java
+++ b/java/src/com/android/inputmethod/latin/RichInputConnection.java
@@ -192,7 +192,20 @@ public class RichInputConnection {
     public int getCursorCapsMode(final int inputType) {
         mIC = mParent.getCurrentInputConnection();
         if (null == mIC) return Constants.TextUtils.CAP_MODE_OFF;
-        return mIC.getCursorCapsMode(inputType);
+        if (!TextUtils.isEmpty(mComposingText)) return Constants.TextUtils.CAP_MODE_OFF;
+        // TODO: this will generally work, but there may be cases where the buffer contains SOME
+        // information but not enough to determine the caps mode accurately. This may happen after
+        // heavy pressing of delete, for example DEFAULT_TEXT_CACHE_SIZE - 5 times or so.
+        // getCapsMode should be updated to be able to return a "not enough info" result so that
+        // we can get more context only when needed.
+        if (TextUtils.isEmpty(mCommittedTextBeforeComposingText) && 0 != mCurrentCursorPosition) {
+            mCommittedTextBeforeComposingText.append(
+                    getTextBeforeCursor(DEFAULT_TEXT_CACHE_SIZE, 0));
+        }
+        // This never calls InputConnection#getCapsMode - in fact, it's a static method that
+        // never blocks or initiates IPC.
+        return StringUtils.getCapsMode(mCommittedTextBeforeComposingText,
+                mCommittedTextBeforeComposingText.length(), inputType);
     }
 
     public CharSequence getTextBeforeCursor(final int i, final int j) {
diff --git a/java/src/com/android/inputmethod/latin/StringUtils.java b/java/src/com/android/inputmethod/latin/StringUtils.java
index 9c47a38c23ce30f4890b17f8030af48b5c057c3f..d6509d6a61957566552d4895c5dae02360aa0c7a 100644
--- a/java/src/com/android/inputmethod/latin/StringUtils.java
+++ b/java/src/com/android/inputmethod/latin/StringUtils.java
@@ -197,4 +197,98 @@ public final class StringUtils {
         codePoints[dsti] = codePoint;
         return codePoints;
     }
+
+    /**
+     * Determine what caps mode should be in effect at the current offset in
+     * the text. Only the mode bits set in <var>reqModes</var> will be
+     * checked. Note that the caps mode flags here are explicitly defined
+     * to match those in {@link InputType}.
+     *
+     * This code is a straight copy of TextUtils.getCapsMode (modulo namespace and formatting
+     * issues). This will change in the future as we simplify the code for our use and fix bugs.
+     *
+     * @param cs The text that should be checked for caps modes.
+     * @param off Location in the text at which to check.
+     * @param reqModes The modes to be checked: may be any combination of
+     * {@link #CAP_MODE_CHARACTERS}, {@link #CAP_MODE_WORDS}, and
+     * {@link #CAP_MODE_SENTENCES}.
+     *
+     * @return Returns the actual capitalization modes that can be in effect
+     * at the current position, which is any combination of
+     * {@link #CAP_MODE_CHARACTERS}, {@link #CAP_MODE_WORDS}, and
+     * {@link #CAP_MODE_SENTENCES}.
+     */
+    public static int getCapsMode(CharSequence cs, int off, int reqModes) {
+        if (off < 0) {
+            return 0;
+        }
+
+        int i;
+        char c;
+        int mode = 0;
+
+        if ((reqModes & TextUtils.CAP_MODE_CHARACTERS) != 0) {
+            mode |= TextUtils.CAP_MODE_CHARACTERS;
+        }
+        if ((reqModes & (TextUtils.CAP_MODE_WORDS | TextUtils.CAP_MODE_SENTENCES)) == 0) {
+            return mode;
+        }
+
+        // Back over allowed opening punctuation.
+        for (i = off; i > 0; i--) {
+            c = cs.charAt(i - 1);
+            if (c != '"' && c != '\'' && Character.getType(c) != Character.START_PUNCTUATION) {
+                break;
+            }
+        }
+
+        // Start of paragraph, with optional whitespace.
+        int j = i;
+        while (j > 0 && ((c = cs.charAt(j - 1)) == ' ' || c == '\t')) {
+            j--;
+        }
+        if (j == 0 || cs.charAt(j - 1) == '\n') {
+            return mode | TextUtils.CAP_MODE_WORDS;
+        }
+
+        // Or start of word if we are that style.
+        if ((reqModes & TextUtils.CAP_MODE_SENTENCES) == 0) {
+            if (i != j) mode |= TextUtils.CAP_MODE_WORDS;
+            return mode;
+        }
+
+        // There must be a space if not the start of paragraph.
+        if (i == j) {
+            return mode;
+        }
+
+        // Back over allowed closing punctuation.
+        for (; j > 0; j--) {
+            c = cs.charAt(j - 1);
+            if (c != '"' && c != '\'' && Character.getType(c) != Character.END_PUNCTUATION) {
+                break;
+            }
+        }
+
+        if (j > 0) {
+            c = cs.charAt(j - 1);
+            if (c == '.' || c == '?' || c == '!') {
+                // Do not capitalize if the word ends with a period but
+                // also contains a period, in which case it is an abbreviation.
+                if (c == '.') {
+                    for (int k = j - 2; k >= 0; k--) {
+                        c = cs.charAt(k);
+                        if (c == '.') {
+                            return mode;
+                        }
+                        if (!Character.isLetter(c)) {
+                            break;
+                        }
+                    }
+                }
+                return mode | TextUtils.CAP_MODE_SENTENCES;
+            }
+        }
+        return mode;
+    }
 }