Bug 1351170 - 3. Do more to synchronize spans to shadow text; r=esawin draft
authorJim Chen <nchen@mozilla.com>
Wed, 19 Jul 2017 14:30:00 -0400
changeset 611464 743828adfe9dfda93480a5372697989a77492d52
parent 611463 da0cc3073e4b8ad23c6f6eab42da5aa8b269cae9
child 638161 6ca0994011b158e3aebe9a1371177f4a8bbbf3cb
push id69220
push userbmo:nchen@mozilla.com
push dateWed, 19 Jul 2017 18:31:25 +0000
reviewersesawin
bugs1351170
milestone56.0a1
Bug 1351170 - 3. Do more to synchronize spans to shadow text; r=esawin There are some situations where spans are not properly synced from current text to shadow text. This patch takes more steps to make sure spans are synchronized. MozReview-Commit-ID: 1xhsJllE7Ro
mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoEditable.java
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoEditable.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoEditable.java
@@ -288,21 +288,31 @@ final class GeckoEditable extends IGecko
             }
 
             // Copy the portion of the current text that has changed over to the shadow
             // text, with consideration for any concurrent changes in the shadow text.
             final int start = Math.min(mShadowStart, mCurrentStart);
             final int shadowEnd = mShadowNewEnd + Math.max(0, mCurrentOldEnd - mShadowOldEnd);
             final int currentEnd = mCurrentNewEnd + Math.max(0, mShadowOldEnd - mCurrentOldEnd);
 
-            // Perform replacement in two steps (delete and insert) so that old spans are
-            // properly deleted before identical new spans are inserted. Otherwise the new
-            // spans won't be inserted due to the text already having the old spans.
-            mShadowText.delete(start, shadowEnd);
-            mShadowText.insert(start, mCurrentText, start, currentEnd);
+            // Remove identical spans that are in the new text from the old text.
+            // Otherwise the new spans won't be inserted due to the text already having
+            // the old spans.
+            Object[] spans = mCurrentText.getSpans(start, currentEnd, Object.class);
+            for (final Object span : spans) {
+                mShadowText.removeSpan(span);
+            }
+
+            // Also remove existing spans that are no longer in the new text.
+            spans = mShadowText.getSpans(start, shadowEnd, Object.class);
+            for (final Object span : spans) {
+                mShadowText.removeSpan(span);
+            }
+
+            mShadowText.replace(start, shadowEnd, mCurrentText, start, currentEnd);
 
             // SpannableStringBuilder has some internal logic to fix up selections, but we
             // don't want that, so we always fix up the selection a second time.
             final int selStart = Selection.getSelectionStart(mCurrentText);
             final int selEnd = Selection.getSelectionEnd(mCurrentText);
             Selection.setSelection(mShadowText, selStart, selEnd);
 
             if (DEBUG && !checkEqualText(mShadowText, mCurrentText)) {