Bug 751513 - End composition in onTextChanged() only if we are currently committing. r=blassey
authorChris Peterson <cpeterson@mozilla.com>
Wed, 16 May 2012 22:29:23 -0700
changeset 94204 43aa1f392da4d6b2f7087e9a015d1738d7d523ea
parent 94203 05a3396204397a4ac11d0964eef04b69b1221184
child 94205 3eb58d060ac83dd7d55e1b7f67f258b9538ae6f6
push id22702
push userryanvm@gmail.com
push dateThu, 17 May 2012 18:02:05 +0000
treeherdermozilla-central@895e12563245 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersblassey
bugs751513
milestone15.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 751513 - End composition in onTextChanged() only if we are currently committing. r=blassey
mobile/android/base/GeckoInputConnection.java
--- a/mobile/android/base/GeckoInputConnection.java
+++ b/mobile/android/base/GeckoInputConnection.java
@@ -138,29 +138,33 @@ public class GeckoInputConnection
 
     @Override
     public boolean commitCompletion(CompletionInfo text) {
         return commitText(text.getText(), 1);
     }
 
     @Override
     public boolean commitText(CharSequence text, int newCursorPosition) {
+        if (mCommittingText)
+            Log.e(LOGTAG, "Please report this bug:", new IllegalStateException("commitText, but already committing text?!"));
+
         mCommittingText = true;
         replaceText(text, newCursorPosition, false);
         mCommittingText = false;
 
         if (hasCompositionString()) {
             if (DEBUG) Log.d(LOGTAG, ". . . commitText: endComposition");
             endComposition();
         }
         return true;
     }
 
     @Override
     public boolean finishComposingText() {
+        // finishComposingText() is sometimes called even when we are not composing text.
         if (hasCompositionString()) {
             if (DEBUG) Log.d(LOGTAG, ". . . finishComposingText: endComposition");
             endComposition();
         }
 
         final Editable content = getEditable();
         if (content != null) {
             beginBatchEdit();
@@ -284,16 +288,17 @@ public class GeckoInputConnection
     @Override
     public CharSequence getTextAfterCursor(int length, int flags) {
         clampSelection();
         return super.getTextAfterCursor(length, flags);
     }
 
     @Override
     public boolean setComposingText(CharSequence text, int newCursorPosition) {
+        // setComposingText will likely be called multiple times while we are composing text.
         clampSelection();
         return super.setComposingText(text, newCursorPosition);
     }
 
     // Android's BaseInputConnection.java is vulnerable to IndexOutOfBoundsExceptions because it
     // does not adequately protect against stale indexes for selections exceeding the content length
     // when the Editable content changes. We must clamp the indexes to be safe.
     private void clampSelection() {
@@ -587,18 +592,18 @@ public class GeckoInputConnection
             // we can send Gecko keydown/keyup events instead of composition events.
             if (mCommittingText && !hasCompositionString() && synthesizeKeyEvents(changedChar)) {
                 // Block this thread until all pending events are processed
                 GeckoAppShell.geckoEventSync();
                 return;
             }
         }
 
-        boolean needCompositionString = !hasCompositionString();
-        if (needCompositionString) {
+        boolean startCompositionString = !hasCompositionString();
+        if (startCompositionString) {
             if (DEBUG) Log.d(LOGTAG, ". . . onTextChanged: IME_COMPOSITION_BEGIN");
             GeckoAppShell.sendEventToGecko(
                 GeckoEvent.createIMEEvent(GeckoEvent.IME_COMPOSITION_BEGIN, 0, 0));
             mCompositionStart = start;
 
             if (DEBUG) {
                 Log.d(LOGTAG, ". . . onTextChanged: IME_SET_SELECTION, start=" + start + ", len="
                               + before);
@@ -615,17 +620,17 @@ public class GeckoInputConnection
                           + ", 0");
         }
 
         GeckoAppShell.sendEventToGecko(
             GeckoEvent.createIMEEvent(GeckoEvent.IME_SET_SELECTION, start + count, 0));
 
         // End composition if all characters in the word have been deleted.
         // This fixes autocomplete results not appearing.
-        if (count == 0 || needCompositionString)
+        if (count == 0 || (startCompositionString && mCommittingText))
             endComposition();
 
         // Block this thread until all pending events are processed
         GeckoAppShell.geckoEventSync();
     }
 
     private boolean synthesizeKeyEvents(char inputChar) {
         if (mKeyCharacterMap == null) {
@@ -658,18 +663,23 @@ public class GeckoInputConnection
             }
         }
 
         return sentKeyEvents;
     }
 
     private void endComposition() {
         if (DEBUG) Log.d(LOGTAG, "IME: endComposition: IME_COMPOSITION_END");
+
+        if (!hasCompositionString())
+           Log.e(LOGTAG, "Please report this bug:", new IllegalStateException("endComposition, but not composing text?!"));
+
         GeckoAppShell.sendEventToGecko(
             GeckoEvent.createIMEEvent(GeckoEvent.IME_COMPOSITION_END, 0, 0));
+
         mCompositionStart = NO_COMPOSITION_STRING;
     }
 
     private void sendTextToGecko(CharSequence text, int caretPos) {
         if (DEBUG) Log.d(LOGTAG, "IME: sendTextToGecko(\"" + text + "\")");
 
         // Handle composition text styles
         if (text != null && text instanceof Spanned) {