Bug 1351170 - 3. Do more to synchronize spans to shadow text; r=esawin
authorJim Chen <nchen@mozilla.com>
Wed, 19 Jul 2017 14:30:00 -0400
changeset 418395 9fc3f64f258358a93d2b6ea11e931725a8e3e677
parent 418394 b7909eddfe2659a1d02afe4f416b28a2a21c0b28
child 418396 43d31b5d432513ccdb1482e82d6dff321377137e
push id7566
push usermtabara@mozilla.com
push dateWed, 02 Aug 2017 08:25:16 +0000
treeherdermozilla-beta@86913f512c3c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersesawin
bugs1351170
milestone56.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 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)) {