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

Commit ac919b0e authored by Nikita Dubrovsky's avatar Nikita Dubrovsky
Browse files

Use DeviceConfig flags for cursor drag and insertion handle gestures

Bug: 149751656
Test: Manually and ran automated tests
  atest FrameworksCoreTests:TextViewActivityTest
  atest FrameworksCoreTests:EditorCursorDragTest
Change-Id: I431dd7c13b573d7acd9ce20e16a6476370202b5f
parent 8ac64bc0
Loading
Loading
Loading
Loading
+28 −18
Original line number Diff line number Diff line
@@ -151,9 +151,6 @@ public class Editor {
    private static final String TAG = "Editor";
    private static final boolean DEBUG_UNDO = false;

    // Specifies whether to allow starting a cursor drag by dragging anywhere over the text.
    @VisibleForTesting
    public static boolean FLAG_ENABLE_CURSOR_DRAG = true;
    // Specifies whether to use the magnifier when pressing the insertion or selection handles.
    private static final boolean FLAG_USE_MAGNIFIER = true;

@@ -387,9 +384,8 @@ public class Editor {

    private final SuggestionHelper mSuggestionHelper = new SuggestionHelper();

    // Specifies whether the cursor control feature set is enabled.
    // This can only be true if the text view is editable.
    private boolean mCursorControlEnabled;
    private boolean mFlagCursorDragFromAnywhereEnabled;
    private boolean mFlagInsertionHandleGesturesEnabled;

    // Specifies whether the new magnifier (with fish-eye effect) is enabled.
    private final boolean mNewMagnifierEnabled;
@@ -402,26 +398,40 @@ public class Editor {
        mHapticTextHandleEnabled = mTextView.getContext().getResources().getBoolean(
                com.android.internal.R.bool.config_enableHapticTextHandle);

        mCursorControlEnabled = AppGlobals.getIntCoreSetting(
                WidgetFlags.KEY_ENABLE_CURSOR_CONTROL , 0) != 0;
        mFlagCursorDragFromAnywhereEnabled = AppGlobals.getIntCoreSetting(
                WidgetFlags.KEY_ENABLE_CURSOR_DRAG_FROM_ANYWHERE , 1) != 0;
        mFlagInsertionHandleGesturesEnabled = AppGlobals.getIntCoreSetting(
                WidgetFlags.KEY_ENABLE_INSERTION_HANDLE_GESTURES , 0) != 0;
        mNewMagnifierEnabled = AppGlobals.getIntCoreSetting(
                WidgetFlags.KEY_ENABLE_NEW_MAGNIFIER, 0) != 0;
        if (TextView.DEBUG_CURSOR) {
            logCursor("Editor", "Cursor control is %s.",
                    mCursorControlEnabled ? "enabled" : "disabled");
            logCursor("Editor", "Cursor drag from anywhere is %s.",
                    mFlagCursorDragFromAnywhereEnabled ? "enabled" : "disabled");
            logCursor("Editor", "Insertion handle gestures is %s.",
                    mFlagInsertionHandleGesturesEnabled ? "enabled" : "disabled");
            logCursor("Editor", "New magnifier is %s.",
                    mNewMagnifierEnabled ? "enabled" : "disabled");
        }
    }

    @VisibleForTesting
    public void setCursorControlEnabled(boolean enabled) {
        mCursorControlEnabled = enabled;
    public boolean getFlagCursorDragFromAnywhereEnabled() {
        return mFlagCursorDragFromAnywhereEnabled;
    }

    @VisibleForTesting
    public void setFlagCursorDragFromAnywhereEnabled(boolean enabled) {
        mFlagCursorDragFromAnywhereEnabled = enabled;
    }

    @VisibleForTesting
    public boolean getFlagInsertionHandleGesturesEnabled() {
        return mFlagInsertionHandleGesturesEnabled;
    }

    @VisibleForTesting
    public boolean getCursorControlEnabled() {
        return mCursorControlEnabled;
    public void setFlagInsertionHandleGesturesEnabled(boolean enabled) {
        mFlagInsertionHandleGesturesEnabled = enabled;
    }

    // Lazy creates the magnifier animator.
@@ -5259,7 +5269,7 @@ public class Editor {

            int deltaHeight = 0;
            int opacity = 255;
            if (mCursorControlEnabled) {
            if (mFlagInsertionHandleGesturesEnabled) {
                deltaHeight = AppGlobals.getIntCoreSetting(
                        WidgetFlags.KEY_INSERTION_HANDLE_DELTA_HEIGHT, 25);
                opacity = AppGlobals.getIntCoreSetting(
@@ -5329,7 +5339,7 @@ public class Editor {

        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            if (mCursorControlEnabled) {
            if (mFlagInsertionHandleGesturesEnabled) {
                final int height = Math.max(
                        getPreferredHeight() + mDeltaHeight, mDrawable.getIntrinsicHeight());
                setMeasuredDimension(getPreferredWidth(), height);
@@ -5340,7 +5350,7 @@ public class Editor {

        @Override
        public boolean onTouchEvent(MotionEvent ev) {
            if (mCursorControlEnabled && FLAG_ENABLE_CURSOR_DRAG) {
            if (mFlagInsertionHandleGesturesEnabled && mFlagCursorDragFromAnywhereEnabled) {
                // Should only enable touch through when cursor drag is enabled.
                // Otherwise the insertion handle view cannot be moved.
                return touchThrough(ev);
@@ -6025,7 +6035,7 @@ public class Editor {
                    }
                    if (mIsDraggingCursor) {
                        performCursorDrag(event);
                    } else if (FLAG_ENABLE_CURSOR_DRAG
                    } else if (mFlagCursorDragFromAnywhereEnabled
                                && mTextView.getLayout() != null
                                && mTextView.isFocused()
                                && mTouchState.isMovedEnoughForDrag()
+20 −7
Original line number Diff line number Diff line
@@ -17,23 +17,36 @@
package android.widget;

/**
 * Keeps the flags related to the Widget namespace in {@link DeviceConfig}.
 * Flags in the {@link android.provider.DeviceConfig#NAMESPACE_WIDGET "widget" namespace}.
 *
 * @hide
 */
public final class WidgetFlags {

    /**
     * Whether the cursor control feature set is enabled.
     * TODO: Makes this flag key visible to webview/chrome.
     * Whether starting a cursor drag from anywhere in the text should be enabled.
     */
    public static final String ENABLE_CURSOR_CONTROL =
            "CursorControlFeature__enable_cursor_control";
    public static final String ENABLE_CURSOR_DRAG_FROM_ANYWHERE =
            "CursorControlFeature__enable_cursor_drag_from_anywhere";

    /**
     * The key name used in app core settings for enable cursor control.
     * The key used in app core settings for the flag {@link #ENABLE_CURSOR_DRAG_FROM_ANYWHERE}.
     */
    public static final String KEY_ENABLE_CURSOR_CONTROL = "widget__enable_cursor_control";
    public static final String KEY_ENABLE_CURSOR_DRAG_FROM_ANYWHERE =
            "widget__enable_cursor_drag_from_anywhere";

    /**
     * Whether additional gestures should be enabled for the insertion cursor handle (e.g.
     * long-press or double-tap on the handle to trigger selection).
     */
    public static final String ENABLE_INSERTION_HANDLE_GESTURES =
            "CursorControlFeature__enable_insertion_handle_gestures";

    /**
     * The key used in app core settings for the flag {@link #ENABLE_INSERTION_HANDLE_GESTURES}.
     */
    public static final String KEY_ENABLE_INSERTION_HANDLE_GESTURES =
            "widget__enable_insertion_handle_gestures";

    /**
     * The flag of delta height applies to the insertion handle when cursor control flag is enabled.
+0 −9
Original line number Diff line number Diff line
@@ -44,7 +44,6 @@ import com.android.frameworks.coretests.R;

import com.google.common.base.Strings;

import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -57,7 +56,6 @@ public class EditorCursorDragTest {
    public ActivityTestRule<TextViewActivity> mActivityRule = new ActivityTestRule<>(
            TextViewActivity.class);

    private boolean mOriginalFlagValue;
    private Instrumentation mInstrumentation;
    private Activity mActivity;

@@ -65,13 +63,6 @@ public class EditorCursorDragTest {
    public void before() throws Throwable {
        mInstrumentation = InstrumentationRegistry.getInstrumentation();
        mActivity = mActivityRule.getActivity();
        mOriginalFlagValue = Editor.FLAG_ENABLE_CURSOR_DRAG;
        Editor.FLAG_ENABLE_CURSOR_DRAG = true;
    }

    @After
    public void after() throws Throwable {
        Editor.FLAG_ENABLE_CURSOR_DRAG = mOriginalFlagValue;
    }

    @Test
+15 −43
Original line number Diff line number Diff line
@@ -31,8 +31,8 @@ import static android.widget.espresso.TextViewActions.doubleTapAndDragHandle;
import static android.widget.espresso.TextViewActions.doubleTapAndDragOnText;
import static android.widget.espresso.TextViewActions.doubleTapHandle;
import static android.widget.espresso.TextViewActions.dragHandle;
import static android.widget.espresso.TextViewActions.longPressAndDragOnText;
import static android.widget.espresso.TextViewActions.longPressAndDragHandle;
import static android.widget.espresso.TextViewActions.longPressAndDragOnText;
import static android.widget.espresso.TextViewActions.longPressHandle;
import static android.widget.espresso.TextViewActions.longPressOnTextAtIndex;
import static android.widget.espresso.TextViewAssertions.doesNotHaveStyledText;
@@ -514,29 +514,26 @@ public class TextViewActivityTest {
        onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.indexOf("f")));
    }

    @Test
    public void testInsertionHandle_touchThrough() {
    private void enableFlagsForInsertionHandleGestures() {
        final TextView textView = mActivity.findViewById(R.id.textview);
        boolean cursorControlEnabled = textView.getEditorForTesting().getCursorControlEnabled();
        boolean cursorDragEnabled = Editor.FLAG_ENABLE_CURSOR_DRAG;
        textView.getEditorForTesting().setCursorControlEnabled(true);
        Editor.FLAG_ENABLE_CURSOR_DRAG = true;
        final Editor editor = textView.getEditorForTesting();
        editor.setFlagCursorDragFromAnywhereEnabled(true);
        editor.setFlagInsertionHandleGesturesEnabled(true);
        // Note: We don't need to reset these flags explicitly at the end of each test, because a
        // fresh TextView and Editor will be created for each test.
    }

    @Test
    public void testInsertionHandle_touchThrough() {
        enableFlagsForInsertionHandleGestures();
        testInsertionHandle();
        testInsertionHandle_multiLine();

        textView.getEditorForTesting().setCursorControlEnabled(cursorControlEnabled);
        Editor.FLAG_ENABLE_CURSOR_DRAG = cursorDragEnabled;
    }

    @Test
    public void testInsertionHandle_longPressToSelect() {
        // This test only makes sense when Cursor Control flag is enabled.
        enableFlagsForInsertionHandleGestures();
        final TextView textView = mActivity.findViewById(R.id.textview);
        boolean cursorControlEnabled = textView.getEditorForTesting().getCursorControlEnabled();
        boolean cursorDragEnabled = Editor.FLAG_ENABLE_CURSOR_DRAG;
        textView.getEditorForTesting().setCursorControlEnabled(true);
        Editor.FLAG_ENABLE_CURSOR_DRAG = true;

        final String text = "hello the world";
        onView(withId(R.id.textview)).perform(replaceText(text));
@@ -546,20 +543,12 @@ public class TextViewActivityTest {

        onHandleView(com.android.internal.R.id.insertion_handle).perform(longPressHandle(textView));
        onView(withId(R.id.textview)).check(hasSelection("world"));

        textView.getEditorForTesting().setCursorControlEnabled(cursorControlEnabled);
        Editor.FLAG_ENABLE_CURSOR_DRAG = cursorDragEnabled;
    }

    @Test
    public void testInsertionHandle_longPressAndDragToSelect() {
        // This test only makes sense when Cursor Control flag is enabled.
        enableFlagsForInsertionHandleGestures();
        final TextView textView = mActivity.findViewById(R.id.textview);
        boolean cursorControlEnabled = textView.getEditorForTesting().getCursorControlEnabled();
        boolean cursorDragEnabled = Editor.FLAG_ENABLE_CURSOR_DRAG;
        textView.getEditorForTesting().setCursorControlEnabled(true);
        Editor.FLAG_ENABLE_CURSOR_DRAG = true;

        final String text = "hello the world";
        onView(withId(R.id.textview)).perform(replaceText(text));

@@ -569,19 +558,12 @@ public class TextViewActivityTest {
        onHandleView(com.android.internal.R.id.insertion_handle)
                .perform(longPressAndDragHandle(textView, Handle.INSERTION, text.indexOf('t')));
        onView(withId(R.id.textview)).check(hasSelection("the world"));

        textView.getEditorForTesting().setCursorControlEnabled(cursorControlEnabled);
        Editor.FLAG_ENABLE_CURSOR_DRAG = cursorDragEnabled;
    }

    @Test
    public void testInsertionHandle_doubleTapToSelect() {
        // This test only makes sense when Cursor Control flag is enabled.
        enableFlagsForInsertionHandleGestures();
        final TextView textView = mActivity.findViewById(R.id.textview);
        boolean cursorControlEnabled = textView.getEditorForTesting().getCursorControlEnabled();
        boolean cursorDragEnabled = Editor.FLAG_ENABLE_CURSOR_DRAG;
        textView.getEditorForTesting().setCursorControlEnabled(true);
        Editor.FLAG_ENABLE_CURSOR_DRAG = true;

        final String text = "hello the world";
        onView(withId(R.id.textview)).perform(replaceText(text));
@@ -591,19 +573,12 @@ public class TextViewActivityTest {

        onHandleView(com.android.internal.R.id.insertion_handle).perform(doubleTapHandle(textView));
        onView(withId(R.id.textview)).check(hasSelection("world"));

        textView.getEditorForTesting().setCursorControlEnabled(cursorControlEnabled);
        Editor.FLAG_ENABLE_CURSOR_DRAG = cursorDragEnabled;
    }

    @Test
    public void testInsertionHandle_doubleTapAndDragToSelect() {
        // This test only makes sense when Cursor Control flag is enabled.
        enableFlagsForInsertionHandleGestures();
        final TextView textView = mActivity.findViewById(R.id.textview);
        boolean cursorControlEnabled = textView.getEditorForTesting().getCursorControlEnabled();
        boolean cursorDragEnabled = Editor.FLAG_ENABLE_CURSOR_DRAG;
        textView.getEditorForTesting().setCursorControlEnabled(true);
        Editor.FLAG_ENABLE_CURSOR_DRAG = true;

        final String text = "hello the world";
        onView(withId(R.id.textview)).perform(replaceText(text));
@@ -614,9 +589,6 @@ public class TextViewActivityTest {
        onHandleView(com.android.internal.R.id.insertion_handle)
                .perform(doubleTapAndDragHandle(textView, Handle.INSERTION, text.indexOf('t')));
        onView(withId(R.id.textview)).check(hasSelection("the world"));

        textView.getEditorForTesting().setCursorControlEnabled(cursorControlEnabled);
        Editor.FLAG_ENABLE_CURSOR_DRAG = cursorDragEnabled;
    }

    @Test
+5 −2
Original line number Diff line number Diff line
@@ -106,8 +106,11 @@ final class CoreSettingsObserver extends ContentObserver {
        // add other global settings here...

        sDeviceConfigEntries.add(new DeviceConfigEntry(
                DeviceConfig.NAMESPACE_WIDGET, WidgetFlags.ENABLE_CURSOR_CONTROL,
                WidgetFlags.KEY_ENABLE_CURSOR_CONTROL, boolean.class));
                DeviceConfig.NAMESPACE_WIDGET, WidgetFlags.ENABLE_CURSOR_DRAG_FROM_ANYWHERE,
                WidgetFlags.KEY_ENABLE_CURSOR_DRAG_FROM_ANYWHERE, boolean.class));
        sDeviceConfigEntries.add(new DeviceConfigEntry(
                DeviceConfig.NAMESPACE_WIDGET, WidgetFlags.ENABLE_INSERTION_HANDLE_GESTURES,
                WidgetFlags.KEY_ENABLE_INSERTION_HANDLE_GESTURES, boolean.class));
        sDeviceConfigEntries.add(new DeviceConfigEntry(
                DeviceConfig.NAMESPACE_WIDGET, WidgetFlags.INSERTION_HANDLE_DELTA_HEIGHT,
                WidgetFlags.KEY_INSERTION_HANDLE_DELTA_HEIGHT, int.class));