1616
1717package android .widget ;
1818
19+ import com .android .internal .util .ArrayUtils ;
20+ import com .android .internal .widget .EditableInputConnection ;
21+
1922import android .R ;
2023import android .content .ClipData ;
2124import android .content .ClipData .Item ;
7073import android .view .MenuItem ;
7174import android .view .MotionEvent ;
7275import android .view .View ;
73- import android .view .ViewConfiguration ;
74- import android .view .ViewGroup ;
7576import android .view .View .DragShadowBuilder ;
7677import android .view .View .OnClickListener ;
78+ import android .view .ViewConfiguration ;
79+ import android .view .ViewGroup ;
7780import android .view .ViewGroup .LayoutParams ;
7881import android .view .ViewParent ;
7982import android .view .ViewTreeObserver ;
8588import android .view .inputmethod .InputConnection ;
8689import android .view .inputmethod .InputMethodManager ;
8790import android .widget .AdapterView .OnItemClickListener ;
91+ import android .widget .Editor .InputContentType ;
92+ import android .widget .Editor .InputMethodState ;
93+ import android .widget .Editor .SelectionModifierCursorController ;
8894import android .widget .TextView .Drawables ;
8995import android .widget .TextView .OnEditorActionListener ;
9096
91- import com .android .internal .util .ArrayUtils ;
92- import com .android .internal .widget .EditableInputConnection ;
93-
9497import java .text .BreakIterator ;
9598import java .util .Arrays ;
9699import java .util .Comparator ;
102105 * @hide
103106 */
104107public class Editor {
108+ private static final String TAG = "Editor" ;
109+
105110 static final int BLINK = 500 ;
106111 private static final float [] TEMP_POSITION = new float [2 ];
107112 private static int DRAG_SHADOW_MAX_TEXT_LENGTH = 20 ;
@@ -151,6 +156,8 @@ public class Editor {
151156
152157 boolean mInBatchEditControllers ;
153158 boolean mShowSoftInputOnFocus = true ;
159+ boolean mPreserveDetachedSelection ;
160+ boolean mTemporaryDetach ;
154161
155162 SuggestionsPopupWindow mSuggestionsPopupWindow ;
156163 SuggestionRangeSpan mSuggestionRangeSpan ;
@@ -190,6 +197,7 @@ void onAttachedToWindow() {
190197 showError ();
191198 mShowErrorAfterAttach = false ;
192199 }
200+ mTemporaryDetach = false ;
193201
194202 final ViewTreeObserver observer = mTextView .getViewTreeObserver ();
195203 // No need to create the controller.
@@ -198,10 +206,22 @@ void onAttachedToWindow() {
198206 observer .addOnTouchModeChangeListener (mInsertionPointCursorController );
199207 }
200208 if (mSelectionModifierCursorController != null ) {
209+ mSelectionModifierCursorController .resetTouchOffsets ();
201210 observer .addOnTouchModeChangeListener (mSelectionModifierCursorController );
202211 }
203212 updateSpellCheckSpans (0 , mTextView .getText ().length (),
204213 true /* create the spell checker if needed */ );
214+
215+ if (mTextView .hasTransientState () &&
216+ mTextView .getSelectionStart () != mTextView .getSelectionEnd ()) {
217+ // Since transient state is reference counted make sure it stays matched
218+ // with our own calls to it for managing selection.
219+ // The action mode callback will set this back again when/if the action mode starts.
220+ mTextView .setHasTransientState (false );
221+
222+ // We had an active selection from before, start the selection mode.
223+ startSelectionActionMode ();
224+ }
205225 }
206226
207227 void onDetachedFromWindow () {
@@ -234,7 +254,10 @@ void onDetachedFromWindow() {
234254 mSpellChecker = null ;
235255 }
236256
257+ mPreserveDetachedSelection = true ;
237258 hideControllers ();
259+ mPreserveDetachedSelection = false ;
260+ mTemporaryDetach = false ;
238261 }
239262
240263 private void showError () {
@@ -877,7 +900,9 @@ void onFocusChanged(boolean focused, int direction) {
877900 hideControllers ();
878901 Selection .setSelection ((Spannable ) mTextView .getText (), selStart , selEnd );
879902 } else {
903+ if (mTemporaryDetach ) mPreserveDetachedSelection = true ;
880904 hideControllers ();
905+ if (mTemporaryDetach ) mPreserveDetachedSelection = false ;
881906 downgradeEasyCorrectionSpans ();
882907 }
883908
@@ -2679,6 +2704,7 @@ public boolean onCreateActionMode(ActionMode mode, Menu menu) {
26792704
26802705 if (menu .hasVisibleItems () || mode .getCustomView () != null ) {
26812706 getSelectionController ().show ();
2707+ mTextView .setHasTransientState (true );
26822708 return true ;
26832709 } else {
26842710 return false ;
@@ -2707,7 +2733,17 @@ public void onDestroyActionMode(ActionMode mode) {
27072733 if (mCustomSelectionActionModeCallback != null ) {
27082734 mCustomSelectionActionModeCallback .onDestroyActionMode (mode );
27092735 }
2710- Selection .setSelection ((Spannable ) mTextView .getText (), mTextView .getSelectionEnd ());
2736+
2737+ /*
2738+ * If we're ending this mode because we're detaching from a window,
2739+ * we still have selection state to preserve. Don't clear it, we'll
2740+ * bring back the selection mode when (if) we get reattached.
2741+ */
2742+ if (!mPreserveDetachedSelection ) {
2743+ Selection .setSelection ((Spannable ) mTextView .getText (),
2744+ mTextView .getSelectionEnd ());
2745+ mTextView .setHasTransientState (false );
2746+ }
27112747
27122748 if (mSelectionModifierCursorController != null ) {
27132749 mSelectionModifierCursorController .hide ();
0 commit comments