Merge "Allow mmapping dictionary file in writable mode in openNative."
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 0efe0eb..3b4bb19 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -926,19 +926,15 @@
             }
         }
 
-        // TODO: refactor the following code to be less contrived.
-        // "newSelStart != composingSpanEnd" || "newSelEnd != composingSpanEnd" means
-        // that the cursor is not at the end of the composing span, or there is a selection.
-        // "mLastSelectionStart != newSelStart" means that the cursor is not in the same place
-        // as last time we were called (if there is a selection, it means the start hasn't
-        // changed, so it's the end that did).
-        final boolean selectionChanged = (newSelStart != composingSpanEnd
-                || newSelEnd != composingSpanEnd) && mLastSelectionStart != newSelStart;
+        final boolean selectionChanged = mLastSelectionStart != newSelStart
+                || mLastSelectionEnd != newSelEnd;
         // if composingSpanStart and composingSpanEnd are -1, it means there is no composing
         // span in the view - we can use that to narrow down whether the cursor was moved
         // by us or not. If we are composing a word but there is no composing span, then
         // we know for sure the cursor moved while we were composing and we should reset
-        // the state.
+        // the state. TODO: rescind this policy: the framework never removes the composing
+        // span on its own accord while editing. This test is useless.
+
         final boolean noComposingSpan = composingSpanStart == -1 && composingSpanEnd == -1;
         // If the keyboard is not visible, we don't need to do all the housekeeping work, as it
         // will be reset when the keyboard shows up anyway.
@@ -979,6 +975,7 @@
             if (isSuggestionsStripVisible()) {
                 mHandler.postResumeSuggestions();
             }
+            mConnection.userMovedCursor(newSelEnd);
             // Reset the last recapitalization.
             mRecapitalizeStatus.deactivate();
             mKeyboardSwitcher.updateShiftState();
diff --git a/java/src/com/android/inputmethod/latin/RichInputConnection.java b/java/src/com/android/inputmethod/latin/RichInputConnection.java
index d431ad6..dc3aaaa 100644
--- a/java/src/com/android/inputmethod/latin/RichInputConnection.java
+++ b/java/src/com/android/inputmethod/latin/RichInputConnection.java
@@ -340,7 +340,6 @@
     public void setComposingRegion(final int start, final int end) {
         if (DEBUG_BATCH_NESTING) checkBatchEdit();
         if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug();
-        mCurrentCursorPosition = end;
         final CharSequence textBeforeCursor =
                 getTextBeforeCursor(DEFAULT_TEXT_CACHE_SIZE + (end - start), 0);
         mCommittedTextBeforeComposingText.setLength(0);
@@ -731,6 +730,14 @@
     }
 
     /**
+     * The user moved the cursor by hand. Take a note of it.
+     * @param newCursorPosition The new cursor position.
+     */
+    public void userMovedCursor(final int newCursorPosition) {
+        mCurrentCursorPosition = newCursorPosition;
+    }
+
+    /**
      * Looks at the text just before the cursor to find out if it looks like a URL.
      *
      * The weakest point here is, if we don't have enough text bufferized, we may fail to realize