diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index f7a77cae7c5efe88f96afaac55e157d2a62b33f0..4f26a21f9d2ba86d0978620beeadded40749c2d5 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -948,6 +948,10 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
         }
         mExpectingUpdateSelection = false;
         mHandler.postUpdateShiftKeyState();
+        // TODO: Decide to call restartSuggestionsOnWordBeforeCursorIfAtEndOfWord() or not
+        // here. It would probably be too expensive to call directly here but we may want to post a
+        // message to delay it. The point would be to unify behavior between backspace to the
+        // end of a word and manually put the pointer at the end of the word.
 
         // Make a note of the cursor position
         mLastSelectionStart = newSelStart;
@@ -1466,10 +1470,11 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
                 // inconsistent with backspacing after selecting other suggestions.
                 revertLastWord(ic);
             } else {
-                sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL);
+                ic.deleteSurroundingText(1, 0);
                 if (mDeleteCount > DELETE_ACCELERATE_AT) {
-                    sendDownUpKeyEvents(KeyEvent.KEYCODE_DEL);
+                    ic.deleteSurroundingText(1, 0);
                 }
+                restartSuggestionsOnWordBeforeCursorIfAtEndOfWord(ic);
             }
         }
         ic.endBatchEdit();
@@ -2117,6 +2122,53 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
         return TextUtils.equals(text, beforeText);
     }
 
+    // "ic" must not be null
+    /**
+     * Check if the cursor is actually at the end of a word. If so, restart suggestions on this
+     * word, else do nothing.
+     */
+    private void restartSuggestionsOnWordBeforeCursorIfAtEndOfWord(
+            final InputConnection ic) {
+        // Bail out if the cursor is not at the end of a word (cursor must be preceded by
+        // non-whitespace, non-separator, non-start-of-text)
+        // Example ("|" is the cursor here) : <SOL>"|a" " |a" " | " all get rejected here.
+        final CharSequence textBeforeCursor = ic.getTextBeforeCursor(1, 0);
+        if (TextUtils.isEmpty(textBeforeCursor)
+                || mSettingsValues.isWordSeparator(textBeforeCursor.charAt(0))) return;
+
+        // Bail out if the cursor is in the middle of a word (cursor must be followed by whitespace,
+        // separator or end of line/text)
+        // Example: "test|"<EOL> "te|st" get rejected here
+        final CharSequence textAfterCursor = ic.getTextAfterCursor(1, 0);
+        if (!TextUtils.isEmpty(textAfterCursor)
+                && !mSettingsValues.isWordSeparator(textAfterCursor.charAt(0))) return;
+
+        // Bail out if word before cursor is 0-length or a single non letter (like an apostrophe)
+        // Example: " '|" gets rejected here but "I'|" and "I|" are okay
+        final CharSequence word = EditingUtils.getWordAtCursor(ic, mSettingsValues.mWordSeparators);
+        if (TextUtils.isEmpty(word)) return;
+        if (word.length() == 1 && !Character.isLetter(word.charAt(0))) return;
+
+        // Okay, we are at the end of a word. Restart suggestions.
+        restartSuggestionsOnWordBeforeCursor(ic, word);
+    }
+
+    // "ic" must not be null
+    private void restartSuggestionsOnWordBeforeCursor(final InputConnection ic,
+            final CharSequence word) {
+        mWordComposer.setComposingWord(word, mKeyboardSwitcher.getLatinKeyboard());
+        mComposingStringBuilder.setLength(0);
+        mComposingStringBuilder.append(word);
+        // mBestWord will be set appropriately by updateSuggestions() called by the handler
+        mBestWord = null;
+        mHasUncommittedTypedChars = true;
+        mComposingStateManager.onStartComposingText();
+        TextEntryState.restartSuggestionsOnWordBeforeCursor();
+        ic.deleteSurroundingText(word.length(), 0);
+        ic.setComposingText(word, 1);
+        mHandler.postUpdateSuggestions();
+    }
+
     // "ic" must not be null
     private void revertLastWord(final InputConnection ic) {
         if (mHasUncommittedTypedChars || mComposingStringBuilder.length() <= 0) {
@@ -2143,6 +2195,10 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
             // Clear composing text
             mComposingStringBuilder.setLength(0);
         } else {
+            // Note: this relies on the last word still being held in the WordComposer
+            // Note: in the interest of code simplicity, we may want to just call
+            // restartSuggestionsOnWordBeforeCursorIfAtEndOfWord instead, but retrieving
+            // the old WordComposer allows to reuse the actual typed coordinates.
             mHasUncommittedTypedChars = true;
             ic.setComposingText(mComposingStringBuilder, 1);
             TextEntryState.backspace();
diff --git a/java/src/com/android/inputmethod/latin/TextEntryState.java b/java/src/com/android/inputmethod/latin/TextEntryState.java
index 82242f87e79e0ac7eda5d1da97cf3488283ad0cb..a6041b31070ba57093a9a8ff2439f7d369fcfe39 100644
--- a/java/src/com/android/inputmethod/latin/TextEntryState.java
+++ b/java/src/com/android/inputmethod/latin/TextEntryState.java
@@ -146,9 +146,24 @@ public class TextEntryState {
         } else if (sState == UNDO_COMMIT) {
             setState(IN_WORD);
         }
+        // TODO: tidy up this logic. At the moment, for example, writing a word goes to
+        // ACCEPTED_DEFAULT, backspace will go to UNDO_COMMIT, another backspace will go to IN_WORD,
+        // and subsequent backspaces will leave the status at IN_WORD, even if the user backspaces
+        // past the end of the word. We are not in a word any more but the state is still IN_WORD.
         if (DEBUG) displayState("backspace");
     }
 
+    public static void restartSuggestionsOnWordBeforeCursor() {
+        if (UNKNOWN == sState || ACCEPTED_DEFAULT == sState) {
+            // Here we can come from pretty much any state, except the ones that we can't
+            // come from after backspace, so supposedly anything except UNKNOWN and
+            // ACCEPTED_DEFAULT. Note : we could be in UNDO_COMMIT if
+            // LatinIME#revertLastWord() was calling LatinIME#restartSuggestions...()
+            Log.e(TAG, "Strange state change : coming from state " + sState);
+        }
+        setState(IN_WORD);
+    }
+
     public static void reset() {
         setState(START);
         if (DEBUG) displayState("reset");
diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java
index 612b1607193856227211038591f22ffc01f9ee0f..ef2e4d378b9ccd6d83c7aa8ff1ca385929cadca6 100644
--- a/java/src/com/android/inputmethod/latin/WordComposer.java
+++ b/java/src/com/android/inputmethod/latin/WordComposer.java
@@ -17,7 +17,9 @@
 package com.android.inputmethod.latin;
 
 import com.android.inputmethod.keyboard.Keyboard;
+import com.android.inputmethod.keyboard.Key;
 import com.android.inputmethod.keyboard.KeyDetector;
+import com.android.inputmethod.keyboard.LatinKeyboard;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -136,6 +138,50 @@ public class WordComposer {
         mIsLastCharASingleQuote = Keyboard.CODE_SINGLE_QUOTE == primaryCode;
     }
 
+    /**
+     * Internal method to retrieve reasonable proximity info for a character.
+     */
+    private void addKeyInfo(final int codePoint, final LatinKeyboard keyboard,
+            final KeyDetector keyDetector) {
+        for (final Key key : keyboard.mKeys) {
+            if (key.mCode == codePoint) {
+                final int x = key.mX + key.mWidth / 2;
+                final int y = key.mY + key.mHeight / 2;
+                final int[] codes = keyDetector.newCodeArray();
+                keyDetector.getKeyIndexAndNearbyCodes(x, y, codes);
+                add(codePoint, codes, x, y);
+                return;
+            }
+        }
+        add(codePoint, new int[] { codePoint },
+                WordComposer.NOT_A_COORDINATE, WordComposer.NOT_A_COORDINATE);
+    }
+
+    /**
+     * Set the currently composing word to the one passed as an argument.
+     * This will register NOT_A_COORDINATE for X and Ys, and use the passed keyboard for proximity.
+     */
+    public void setComposingWord(final CharSequence word, final LatinKeyboard keyboard,
+            final KeyDetector keyDetector) {
+        reset();
+        final int length = word.length();
+        for (int i = 0; i < length; ++i) {
+            int codePoint = word.charAt(i);
+            addKeyInfo(codePoint, keyboard, keyDetector);
+        }
+    }
+
+    /**
+     * Shortcut for the above method, this will create a new KeyDetector for the passed keyboard.
+     */
+    public void setComposingWord(final CharSequence word, final LatinKeyboard keyboard) {
+        final KeyDetector keyDetector = new KeyDetector(0);
+        keyDetector.setKeyboard(keyboard, 0, 0);
+        keyDetector.setProximityCorrectionEnabled(true);
+        keyDetector.setProximityThreshold(keyboard.mMostCommonKeyWidth);
+        setComposingWord(word, keyboard, keyDetector);
+    }
+
     /**
      * Swaps the first and second values in the codes array if the primary code is not the first
      * value in the array but the second. This happens when the preferred key is not the key that
diff --git a/tests/src/com/android/inputmethod/latin/SuggestHelper.java b/tests/src/com/android/inputmethod/latin/SuggestHelper.java
index 464930f4c7d6921133e3b41b195882278a750486..a1f16c9ca1bf8c5b3873b590245dfd243d9c29d2 100644
--- a/tests/src/com/android/inputmethod/latin/SuggestHelper.java
+++ b/tests/src/com/android/inputmethod/latin/SuggestHelper.java
@@ -65,26 +65,9 @@ public class SuggestHelper {
         return mSuggest.hasMainDictionary();
     }
 
-    private void addKeyInfo(WordComposer word, char c) {
-        for (final Key key : mKeyboard.mKeys) {
-            if (key.mCode == c) {
-                final int x = key.mX + key.mWidth / 2;
-                final int y = key.mY + key.mHeight / 2;
-                final int[] codes = mKeyDetector.newCodeArray();
-                mKeyDetector.getKeyIndexAndNearbyCodes(x, y, codes);
-                word.add(c, codes, x, y);
-                return;
-            }
-        }
-        word.add(c, new int[] { c }, WordComposer.NOT_A_COORDINATE, WordComposer.NOT_A_COORDINATE);
-    }
-
     protected WordComposer createWordComposer(CharSequence s) {
         WordComposer word = new WordComposer();
-        for (int i = 0; i < s.length(); i++) {
-            final char c = s.charAt(i);
-            addKeyInfo(word, c);
-        }
+        word.setComposingWord(s, mKeyboard, mKeyDetector);
         return word;
     }