Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 183fd507 authored by Keisuke Kuroyanagi's avatar Keisuke Kuroyanagi
Browse files

Make hasTransientState be true only if user created selection is active.

Previously, hasTransientState returned true even when TextView has a
selection that hasn't been created by the user. This unnecessarily
prevents the TextView from being recycled.
This issue was introduced by Ib454b0fbbc2c2f8d198, which fixes that
setHasTransientState(true) is not always coupled with
setHasTransientState(false).

With this CL:
hasTransientState will get true when selection action mode is started.
hasTransientState will get false when selection is removed.
Note that hasTransientState intentionally continues to be true when
selection action mode is terminated with preserving selection.

Bug: 27913323
Change-Id: I960ddfd7221caeb676c23926af06a8a415dec288
parent d9435ea0
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -3640,6 +3640,9 @@ public class Editor {
            }

            if (menu.hasVisibleItems() || mode.getCustomView() != null) {
                if (mHasSelection && !mTextView.hasTransientState()) {
                    mTextView.setHasTransientState(true);
                }
                return true;
            } else {
                return false;
+4 −6
Original line number Diff line number Diff line
@@ -8294,14 +8294,12 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                    newSelEnd = Selection.getSelectionEnd(buf);
                }

                if (newSelStart == newSelEnd && hasTransientState()) {
                    setHasTransientState(false);
                } else if (newSelStart != newSelEnd && !hasTransientState()) {
                    setHasTransientState(true);
                }

                if (mEditor != null) {
                    mEditor.refreshTextActionMode();
                    if (!hasSelection() && mEditor.mTextActionMode == null && hasTransientState()) {
                        // User generated selection has been removed.
                        setHasTransientState(false);
                    }
                }
                onSelectionChanged(newSelStart, newSelEnd);
            }
+22 −0
Original line number Diff line number Diff line
@@ -675,4 +675,26 @@ public class TextViewActivityTest extends ActivityInstrumentationTestCase2<TextV
        assertFloatingToolbarContainsItem(
                getActivity().getString(com.android.internal.R.string.copy));
    }

    @SmallTest
    public void testTransientState() throws Exception {
        final String text = "abc def";
        onView(withId(R.id.textview)).perform(click());
        onView(withId(R.id.textview)).perform(replaceText(text));

        final TextView textView = (TextView) getActivity().findViewById(R.id.textview);
        assertFalse(textView.hasTransientState());

        onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf('b')));
        // hasTransientState should return true when user generated selection is active.
        assertTrue(textView.hasTransientState());
        onView(withId(R.id.textview)).perform(clickOnTextAtIndex(text.indexOf('d')));
        // hasTransientState should return false as the selection has been cleared.
        assertFalse(textView.hasTransientState());
        textView.post(
                () -> Selection.setSelection((Spannable) textView.getText(), 0, text.length()));
        getInstrumentation().waitForIdleSync();
        // hasTransientState should return false when selection is created by API.
        assertFalse(textView.hasTransientState());
    }
}