diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index 12f245e87da20..e1af3ec7e6589 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -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 boolean getCursorControlEnabled() { - return mCursorControlEnabled; + public void setFlagCursorDragFromAnywhereEnabled(boolean enabled) { + mFlagCursorDragFromAnywhereEnabled = enabled; + } + + @VisibleForTesting + public boolean getFlagInsertionHandleGesturesEnabled() { + return mFlagInsertionHandleGesturesEnabled; + } + + @VisibleForTesting + 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() diff --git a/core/java/android/widget/WidgetFlags.java b/core/java/android/widget/WidgetFlags.java index 1a8e7a713e7a9..4305ddf873b55 100644 --- a/core/java/android/widget/WidgetFlags.java +++ b/core/java/android/widget/WidgetFlags.java @@ -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. diff --git a/core/tests/coretests/src/android/widget/EditorCursorDragTest.java b/core/tests/coretests/src/android/widget/EditorCursorDragTest.java index a602fa31281f6..82f589c012892 100644 --- a/core/tests/coretests/src/android/widget/EditorCursorDragTest.java +++ b/core/tests/coretests/src/android/widget/EditorCursorDragTest.java @@ -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 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 diff --git a/core/tests/coretests/src/android/widget/TextViewActivityTest.java b/core/tests/coretests/src/android/widget/TextViewActivityTest.java index 0c38e7136655c..88a6f9e4af4b0 100644 --- a/core/tests/coretests/src/android/widget/TextViewActivityTest.java +++ b/core/tests/coretests/src/android/widget/TextViewActivityTest.java @@ -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"))); } + private void enableFlagsForInsertionHandleGestures() { + final TextView textView = mActivity.findViewById(R.id.textview); + 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() { - 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; - + 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 diff --git a/services/core/java/com/android/server/am/CoreSettingsObserver.java b/services/core/java/com/android/server/am/CoreSettingsObserver.java index a03f0bb4e3999..4a2353cd19135 100644 --- a/services/core/java/com/android/server/am/CoreSettingsObserver.java +++ b/services/core/java/com/android/server/am/CoreSettingsObserver.java @@ -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));