Call View#setHasTransientState in TextView#spanChange.
setHasTransientState(true) and setHasTransientState(false) have to
be coupled, but they were not always coupled in TextView. e.g. when
we fire PROCESS_TEXT intent.
With this CL, TextView calls setHasTransientState() always when
selection is created or cleared to make sure 2 setHasTransientState
calls are always coupled.
Bug: 27409041
Change-Id: Ib454b0fbbc2c2f8d19818f154f415c4a5d7e2d7e
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index f693ce7..afac3bc 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -215,7 +215,7 @@
boolean mInBatchEditControllers;
boolean mShowSoftInputOnFocus = true;
- private boolean mPreserveDetachedSelection;
+ private boolean mPreserveSelection;
boolean mTemporaryDetach;
boolean mIsBeingLongClicked;
@@ -376,13 +376,7 @@
updateSpellCheckSpans(0, mTextView.getText().length(),
true /* create the spell checker if needed */);
- if (mTextView.hasTransientState() &&
- mTextView.getSelectionStart() != mTextView.getSelectionEnd()) {
- // Since transient state is reference counted make sure it stays matched
- // with our own calls to it for managing selection.
- // The action mode callback will set this back again when/if the action mode starts.
- mTextView.setHasTransientState(false);
-
+ if (mTextView.getSelectionStart() != mTextView.getSelectionEnd()) {
// We had an active selection from before, start the selection mode.
startSelectionActionMode();
}
@@ -2112,9 +2106,9 @@
}
private void stopTextActionModeWithPreservingSelection() {
- mPreserveDetachedSelection = true;
+ mPreserveSelection = true;
stopTextActionMode();
- mPreserveDetachedSelection = false;
+ mPreserveSelection = false;
}
/**
@@ -2512,7 +2506,7 @@
.setEnabled(mTextView.canSelectAllText())
.setOnMenuItemClickListener(mOnContextMenuItemClickListener);
- mPreserveDetachedSelection = true;
+ mPreserveSelection = true;
}
private void replaceWithSuggestion(final SuggestionInfo suggestionInfo) {
@@ -3585,7 +3579,6 @@
}
if (menu.hasVisibleItems() || mode.getCustomView() != null) {
- mTextView.setHasTransientState(true);
return true;
} else {
return false;
@@ -3685,15 +3678,14 @@
customCallback.onDestroyActionMode(mode);
}
- /*
- * If we're ending this mode because we're detaching from a window,
- * we still have selection state to preserve. Don't clear it, we'll
- * bring back the selection mode when (if) we get reattached.
- */
- if (!mPreserveDetachedSelection) {
+ if (!mPreserveSelection) {
+ /*
+ * Leave current selection when we tentatively destroy action mode for the
+ * selection. If we're detaching from a window, we'll bring back the selection
+ * mode when (if) we get reattached.
+ */
Selection.setSelection((Spannable) mTextView.getText(),
mTextView.getSelectionEnd());
- mTextView.setHasTransientState(false);
}
if (mSelectionModifierCursorController != null) {
@@ -6030,7 +6022,7 @@
private boolean fireIntent(Intent intent) {
if (intent != null && Intent.ACTION_PROCESS_TEXT.equals(intent.getAction())) {
intent.putExtra(Intent.EXTRA_PROCESS_TEXT, mTextView.getSelectedText());
- mEditor.mPreserveDetachedSelection = true;
+ mEditor.mPreserveSelection = true;
mTextView.startActivityForResult(intent, TextView.PROCESS_TEXT_REQUEST_CODE);
return true;
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 6feefb4..dd55cd8 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -8285,6 +8285,13 @@
if (newSelEnd < 0) {
newSelEnd = Selection.getSelectionEnd(buf);
}
+
+ if (newSelStart == newSelEnd && hasTransientState()) {
+ setHasTransientState(false);
+ } else if (newSelStart != newSelEnd && !hasTransientState()) {
+ setHasTransientState(true);
+ }
+
if (mEditor != null) {
mEditor.refreshTextActionMode();
}