Bug 1051556 - Make GeckoEditable.onTextChange more efficient; r=esawin

This patch simplifies the onTextChange method, makes it more efficient
by avoiding unnecessary text copying, and fixes some small bugs.
This commit is contained in:
Jim Chen 2015-12-09 17:46:45 -05:00
Родитель 51fa9a0774
Коммит 5f701f27e0
1 изменённых файлов: 39 добавлений и 55 удалений

Просмотреть файл

@ -968,10 +968,14 @@ final class GeckoEditable extends JNIObject
} }
private void geckoReplaceText(int start, int oldEnd, CharSequence newText) { private void geckoReplaceText(int start, int oldEnd, CharSequence newText) {
if (AppConstants.Versions.preHC) {
// Don't use replace() because Gingerbread has a bug where if the replaced text // Don't use replace() because Gingerbread has a bug where if the replaced text
// has the same spans as the original text, the spans will end up being deleted // has the same spans as the original text, the spans will end up being deleted
mText.delete(start, oldEnd); mText.delete(start, oldEnd);
mText.insert(start, newText); mText.insert(start, newText);
} else {
mText.replace(start, oldEnd, newText);
}
} }
private boolean isSameText(int start, int oldEnd, CharSequence newText) { private boolean isSameText(int start, int oldEnd, CharSequence newText) {
@ -1013,44 +1017,24 @@ final class GeckoEditable extends JNIObject
// Simply replace the text for newly-focused editors. // Simply replace the text for newly-focused editors.
mText.replace(0, mText.length(), text); mText.replace(0, mText.length(), text);
} else { } else if (action != null &&
mChangedText.clearSpans();
mChangedText.replace(0, mChangedText.length(), text);
// Preserve as many spans as possible
TextUtils.copySpansFrom(mText, start, Math.min(oldEnd, newEnd),
Object.class, mChangedText, 0);
if (action != null &&
action.mType == Action.TYPE_REPLACE_TEXT && action.mType == Action.TYPE_REPLACE_TEXT &&
start <= action.mStart && start <= action.mStart &&
action.mStart + action.mSequence.length() <= newEnd) { oldEnd >= action.mEnd &&
newEnd >= action.mStart + action.mSequence.length()) {
// actionNewEnd is the new end of the original replacement action // actionNewEnd is the new end of the original replacement action
final int actionNewEnd = action.mStart + action.mSequence.length(); final int actionNewEnd = action.mStart + action.mSequence.length();
int selStart = Selection.getSelectionStart(mText);
int selEnd = Selection.getSelectionEnd(mText);
// Replace old spans with new spans // Replace old spans with new spans
mChangedText.replace(action.mStart - start, actionNewEnd - start, if (start == action.mStart && oldEnd == action.mEnd && newEnd == actionNewEnd) {
action.mSequence); // The new text exactly matches our sequence, so do a direct replace.
geckoReplaceText(start, oldEnd, action.mSequence);
} else {
mChangedText.clearSpans();
mChangedText.replace(0, mChangedText.length(), mText, start, oldEnd);
mChangedText.replace(action.mStart - start, action.mEnd - start, action.mSequence);
geckoReplaceText(start, oldEnd, mChangedText); geckoReplaceText(start, oldEnd, mChangedText);
// delete/insert above might have moved our selection to somewhere else
// this happens when the Gecko text change covers a larger range than
// the original replacement action. Fix selection here
if (selStart >= start && selStart <= oldEnd) {
selStart = selStart < action.mStart ? selStart :
selStart < action.mEnd ? actionNewEnd :
selStart + actionNewEnd - action.mEnd;
mText.setSpan(Selection.SELECTION_START, selStart, selStart,
Spanned.SPAN_POINT_POINT);
}
if (selEnd >= start && selEnd <= oldEnd) {
selEnd = selEnd < action.mStart ? selEnd :
selEnd < action.mEnd ? actionNewEnd :
selEnd + actionNewEnd - action.mEnd;
mText.setSpan(Selection.SELECTION_END, selEnd, selEnd,
Spanned.SPAN_POINT_POINT);
} }
// Ignore the next selection change because the selection change is a // Ignore the next selection change because the selection change is a
@ -1059,7 +1043,7 @@ final class GeckoEditable extends JNIObject
} else { } else {
// Gecko side initiated the text change. // Gecko side initiated the text change.
if (isSameText(start, oldEnd, mChangedText)) { if (isSameText(start, oldEnd, text)) {
// Nothing to do because the text is the same. This could happen when // Nothing to do because the text is the same. This could happen when
// the composition is updated for example. Ignore the next selection // the composition is updated for example. Ignore the next selection
// change because the selection change is a side-effect of the // change because the selection change is a side-effect of the
@ -1067,8 +1051,8 @@ final class GeckoEditable extends JNIObject
mIgnoreSelectionChange = true; mIgnoreSelectionChange = true;
return; return;
} }
geckoReplaceText(start, oldEnd, mChangedText);
} geckoReplaceText(start, oldEnd, text);
} }
geckoPostToIc(new Runnable() { geckoPostToIc(new Runnable() {