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

Commit 41de3748 authored by Lan Wei's avatar Lan Wei
Browse files

Update the cursor visibility correctly after dismissing popup window

The cursor visibilty should be resumed to previous without regard to
whether IME is temporarily cousming input.

Test: atest FrameworksCoreTests:SuggestionsPopupWindowTest

Bug: 179088361
Bug: 175362887

Change-Id: Ibcae7ef47d942b47c00734bd55c6712e0edc3990
parent 878589db
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -3790,7 +3790,7 @@ public class Editor {
        }

        public SuggestionsPopupWindow() {
            mCursorWasVisibleBeforeSuggestions = mCursorVisible;
            mCursorWasVisibleBeforeSuggestions = mTextView.isCursorVisibleFromAttr();
        }

        @Override
@@ -3957,7 +3957,7 @@ public class Editor {
            }

            if (updateSuggestions()) {
                mCursorWasVisibleBeforeSuggestions = mCursorVisible;
                mCursorWasVisibleBeforeSuggestions = mTextView.isCursorVisibleFromAttr();
                mTextView.setCursorVisible(false);
                mIsShowingUp = true;
                super.show();
+12 −1
Original line number Diff line number Diff line
@@ -500,7 +500,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
    private boolean mImeIsConsumingInput;
    // Whether cursor is visible without regard to {@link mImeConsumesInput}.
    // {code true} is the default value.
    // {@code true} is the default value.
    private boolean mCursorVisibleFromAttr = true;
    static class Drawables {
@@ -10564,6 +10564,17 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
        return mEditor == null ? true : mEditor.mCursorVisible;
    }
    /**
     * @return whether cursor is visible without regard to {@code mImeIsConsumingInput}.
     * {@code true} is the default value.
     *
     * @see #setCursorVisible(boolean)
     * @hide
     */
    public boolean isCursorVisibleFromAttr() {
        return mCursorVisibleFromAttr;
    }
    private boolean canMarquee() {
        int width = mRight - mLeft - getCompoundPaddingLeft() - getCompoundPaddingRight();
        return width > 0 && (mLayout.getLineWidth(0) > width
+69 −0
Original line number Diff line number Diff line
@@ -41,7 +41,9 @@ import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentat

import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import android.content.res.TypedArray;
import android.text.Selection;
@@ -356,4 +358,71 @@ public class SuggestionsPopupWindowTest {
                    .perform(clearText());
        }
    }

    @Test
    public void testCursorVisibility() {
        final TextView textView = getActivity().findViewById(R.id.textview);
        final String text = "abc";

        assertTrue(textView.isCursorVisible());

        onView(withId(R.id.textview)).perform(click());
        onView(withId(R.id.textview)).perform(replaceText(text));
        final SuggestionSpan suggestionSpan = new SuggestionSpan(getActivity(),
                new String[]{"ABC"}, SuggestionSpan.FLAG_AUTO_CORRECTION);
        setSuggestionSpan(suggestionSpan, text.indexOf('a'), text.indexOf('c') + 1);
        showSuggestionsPopup();

        assertSuggestionsPopupIsDisplayed();
        assertSuggestionsPopupContainsItem("ABC");
        assertFalse(textView.isCursorVisible());

        // Delete an item.
        clickSuggestionsPopupItem(
                getActivity().getString(com.android.internal.R.string.delete));
        assertSuggestionsPopupIsNotDisplayed();
        assertTrue(textView.isCursorVisible());
    }

    @Test
    public void testCursorVisibilityWhenImeConsumesInput() {
        final TextView textView = getActivity().findViewById(R.id.textview);
        final String text = "abc";

        assertTrue(textView.isCursorVisible());

        onView(withId(R.id.textview)).perform(click());
        onView(withId(R.id.textview)).perform(replaceText(text));
        setImeConsumesInputWithExpect(textView, true /* imeConsumesInput */,
                false /* expectedCursorVisibility */);
        final SuggestionSpan suggestionSpan = new SuggestionSpan(getActivity(),
                new String[]{"ABC"}, SuggestionSpan.FLAG_AUTO_CORRECTION);
        setSuggestionSpan(suggestionSpan, text.indexOf('a'), text.indexOf('c') + 1);
        showSuggestionsPopup();

        assertSuggestionsPopupIsDisplayed();
        assertSuggestionsPopupContainsItem("ABC");
        assertFalse(textView.isCursorVisible());

        // Delete an item.
        clickSuggestionsPopupItem(
                getActivity().getString(com.android.internal.R.string.delete));
        assertSuggestionsPopupIsNotDisplayed();
        assertFalse(textView.isCursorVisible());

        // Set IME not consumes input, cursor should be back to visible.
        setImeConsumesInputWithExpect(textView, false /* imeConsumesInput */,
                true /* expectedCursorVisibility */);
    }

    private void setImeConsumesInputWithExpect(
            final TextView textView, boolean imeConsumesInput, boolean expectedCursorVisibility) {
        textView.post(() -> textView.setImeConsumesInput(imeConsumesInput));
        getInstrumentation().waitForIdleSync();
        if (expectedCursorVisibility) {
            assertTrue(textView.isCursorVisible());
        } else {
            assertFalse(textView.isCursorVisible());
        }
    }
}