Loading core/java/android/widget/Editor.java +52 −24 Original line number Diff line number Diff line Loading @@ -83,6 +83,7 @@ import android.view.DisplayListCanvas; import android.view.DragAndDropPermissions; import android.view.DragEvent; import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.InputDevice; import android.view.LayoutInflater; import android.view.Menu; Loading Loading @@ -176,6 +177,8 @@ public class Editor { private boolean mInsertionControllerEnabled; private boolean mSelectionControllerEnabled; private final boolean mHapticTextHandleEnabled; // Used to highlight a word when it is corrected by the IME private CorrectionHighlighter mCorrectionHighlighter; Loading Loading @@ -320,6 +323,8 @@ public class Editor { // Synchronize the filter list, which places the undo input filter at the end. mTextView.setFilters(mTextView.getFilters()); mProcessTextIntentActionsHandler = new ProcessTextIntentActionsHandler(this); mHapticTextHandleEnabled = mTextView.getContext().getResources().getBoolean( com.android.internal.R.bool.config_enableHapticTextHandle); } ParcelableParcel saveInstanceState() { Loading Loading @@ -4253,7 +4258,7 @@ public class Editor { mNumberPreviousOffsets++; } private void filterOnTouchUp() { private void filterOnTouchUp(boolean fromTouchScreen) { final long now = SystemClock.uptimeMillis(); int i = 0; int index = mPreviousOffsetIndex; Loading @@ -4265,7 +4270,7 @@ public class Editor { if (i > 0 && i < iMax && (now - mPreviousOffsetsTimes[index]) > TOUCH_UP_FILTER_DELAY_BEFORE) { positionAtCursorOffset(mPreviousOffsets[index], false); positionAtCursorOffset(mPreviousOffsets[index], false, fromTouchScreen); } } Loading @@ -4282,7 +4287,7 @@ public class Editor { public void invalidate() { super.invalidate(); if (isShowing()) { positionAtCursorOffset(getCurrentCursorOffset(), true); positionAtCursorOffset(getCurrentCursorOffset(), true, false); } }; Loading @@ -4301,7 +4306,7 @@ public class Editor { // Make sure the offset is always considered new, even when focusing at same position mPreviousOffset = -1; positionAtCursorOffset(getCurrentCursorOffset(), false); positionAtCursorOffset(getCurrentCursorOffset(), false, false); } protected void dismiss() { Loading Loading @@ -4338,7 +4343,7 @@ public class Editor { protected abstract void updateSelection(int offset); public abstract void updatePosition(float x, float y); protected abstract void updatePosition(float x, float y, boolean fromTouchScreen); protected boolean isAtRtlRun(@NonNull Layout layout, int offset) { return layout.isRtlCharAt(offset); Loading @@ -4357,8 +4362,11 @@ public class Editor { * @param offset Cursor offset. Must be in [-1, length]. * @param forceUpdatePosition whether to force update the position. This should be true * when If the parent has been scrolled, for example. * @param fromTouchScreen {@code true} if the cursor is moved with motion events from the * touch screen. */ protected void positionAtCursorOffset(int offset, boolean forceUpdatePosition) { protected void positionAtCursorOffset(int offset, boolean forceUpdatePosition, boolean fromTouchScreen) { // A HandleView relies on the layout, which may be nulled by external methods Layout layout = mTextView.getLayout(); if (layout == null) { Loading @@ -4372,6 +4380,9 @@ public class Editor { if (offsetChanged || forceUpdatePosition) { if (offsetChanged) { updateSelection(offset); if (fromTouchScreen && mHapticTextHandleEnabled) { mTextView.performHapticFeedback(HapticFeedbackConstants.TEXT_HANDLE_MOVE); } addPositionToTouchUpFilter(offset); } final int line = layout.getLineForOffset(offset); Loading Loading @@ -4404,7 +4415,7 @@ public class Editor { @Override public void updatePosition(int parentPositionX, int parentPositionY, boolean parentPositionChanged, boolean parentScrolled) { positionAtCursorOffset(getCurrentCursorOffset(), parentScrolled); positionAtCursorOffset(getCurrentCursorOffset(), parentScrolled, false); if (parentPositionChanged || mPositionHasChanged) { if (mIsDragging) { // Update touchToWindow offset in case of parent scrolling while dragging Loading Loading @@ -4516,12 +4527,13 @@ public class Editor { xInWindow - mTouchToWindowOffsetX + mHotspotX + getHorizontalOffset(); final float newPosY = yInWindow - mTouchToWindowOffsetY + mTouchOffsetY; updatePosition(newPosX, newPosY); updatePosition(newPosX, newPosY, ev.isFromSource(InputDevice.SOURCE_TOUCHSCREEN)); break; } case MotionEvent.ACTION_UP: filterOnTouchUp(); filterOnTouchUp(ev.isFromSource(InputDevice.SOURCE_TOUCHSCREEN)); mIsDragging = false; updateDrawable(); break; Loading Loading @@ -4702,7 +4714,7 @@ public class Editor { } @Override public void updatePosition(float x, float y) { protected void updatePosition(float x, float y, boolean fromTouchScreen) { Layout layout = mTextView.getLayout(); int offset; if (layout != null) { Loading @@ -4715,7 +4727,7 @@ public class Editor { } else { offset = -1; } positionAtCursorOffset(offset, false); positionAtCursorOffset(offset, false, fromTouchScreen); if (mTextActionMode != null) { invalidateActionMode(); } Loading Loading @@ -4806,12 +4818,13 @@ public class Editor { } @Override public void updatePosition(float x, float y) { protected void updatePosition(float x, float y, boolean fromTouchScreen) { final Layout layout = mTextView.getLayout(); if (layout == null) { // HandleView will deal appropriately in positionAtCursorOffset when // layout is null. positionAndAdjustForCrossingHandles(mTextView.getOffsetForPosition(x, y)); positionAndAdjustForCrossingHandles(mTextView.getOffsetForPosition(x, y), fromTouchScreen); return; } Loading Loading @@ -4854,12 +4867,12 @@ public class Editor { // to the current position. mLanguageDirectionChanged = true; mTouchWordDelta = 0.0f; positionAndAdjustForCrossingHandles(offset); positionAndAdjustForCrossingHandles(offset, fromTouchScreen); return; } else if (mLanguageDirectionChanged && !isLvlBoundary) { // We've just moved past the boundary so update the position. After this we can // figure out if the user is expanding or shrinking to go by word or character. positionAndAdjustForCrossingHandles(offset); positionAndAdjustForCrossingHandles(offset, fromTouchScreen); mTouchWordDelta = 0.0f; mLanguageDirectionChanged = false; return; Loading Loading @@ -4893,7 +4906,7 @@ public class Editor { final int nextOffset = (atRtl == isStartHandle()) ? layout.getOffsetToRightOf(mPreviousOffset) : layout.getOffsetToLeftOf(mPreviousOffset); positionAndAdjustForCrossingHandles(nextOffset); positionAndAdjustForCrossingHandles(nextOffset, fromTouchScreen); return; } } Loading Loading @@ -4972,14 +4985,15 @@ public class Editor { if (positionCursor) { mPreviousLineTouched = currLine; positionAndAdjustForCrossingHandles(offset); positionAndAdjustForCrossingHandles(offset, fromTouchScreen); } mPrevX = x; } @Override protected void positionAtCursorOffset(int offset, boolean forceUpdatePosition) { super.positionAtCursorOffset(offset, forceUpdatePosition); protected void positionAtCursorOffset(int offset, boolean forceUpdatePosition, boolean fromTouchScreen) { super.positionAtCursorOffset(offset, forceUpdatePosition, fromTouchScreen); mInWord = (offset != -1) && !getWordIteratorWithText().isBoundary(offset); } Loading @@ -4995,7 +5009,7 @@ public class Editor { return superResult; } private void positionAndAdjustForCrossingHandles(int offset) { private void positionAndAdjustForCrossingHandles(int offset, boolean fromTouchScreen) { final int anotherHandleOffset = isStartHandle() ? mTextView.getSelectionEnd() : mTextView.getSelectionStart(); if ((isStartHandle() && offset >= anotherHandleOffset) Loading @@ -5020,14 +5034,14 @@ public class Editor { } else { offset = TextUtils.unpackRangeEndFromLong(range); } positionAtCursorOffset(offset, false); positionAtCursorOffset(offset, false, fromTouchScreen); return; } } // Handles can not cross and selection is at least one character. offset = getNextCursorOffset(anotherHandleOffset, !isStartHandle()); } positionAtCursorOffset(offset, false); positionAtCursorOffset(offset, false, fromTouchScreen); } private boolean positionNearEdgeOfScrollingView(float x, boolean atRtl) { Loading Loading @@ -5470,7 +5484,8 @@ public class Editor { private void updateCharacterBasedSelection(MotionEvent event) { final int offset = mTextView.getOffsetForPosition(event.getX(), event.getY()); Selection.setSelection((Spannable) mTextView.getText(), mStartOffset, offset); updateSelectionInternal(mStartOffset, offset, event.isFromSource(InputDevice.SOURCE_TOUCHSCREEN)); } private void updateWordBasedSelection(MotionEvent event) { Loading Loading @@ -5528,7 +5543,8 @@ public class Editor { } } mLineSelectionIsOn = currLine; Selection.setSelection((Spannable) mTextView.getText(), startOffset, offset); updateSelectionInternal(startOffset, offset, event.isFromSource(InputDevice.SOURCE_TOUCHSCREEN)); } private void updateParagraphBasedSelection(MotionEvent event) { Loading @@ -5539,7 +5555,19 @@ public class Editor { final long paragraphsRange = getParagraphsRange(start, end); final int selectionStart = TextUtils.unpackRangeStartFromLong(paragraphsRange); final int selectionEnd = TextUtils.unpackRangeEndFromLong(paragraphsRange); updateSelectionInternal(selectionStart, selectionEnd, event.isFromSource(InputDevice.SOURCE_TOUCHSCREEN)); } private void updateSelectionInternal(int selectionStart, int selectionEnd, boolean fromTouchScreen) { final boolean performHapticFeedback = fromTouchScreen && mHapticTextHandleEnabled && ((mTextView.getSelectionStart() != selectionStart) || (mTextView.getSelectionEnd() != selectionEnd)); Selection.setSelection((Spannable) mTextView.getText(), selectionStart, selectionEnd); if (performHapticFeedback) { mTextView.performHapticFeedback(HapticFeedbackConstants.TEXT_HANDLE_MOVE); } } /** Loading core/res/res/values/config.xml +5 −0 Original line number Diff line number Diff line Loading @@ -147,6 +147,11 @@ fading edges is prohibitively expensive on most GPUs. --> <bool name="config_ui_enableFadingMarquee">false</bool> <!-- Enables or disables haptic effect when the text insertion/selection handle is moved manually by the user. Off by default, since the expected haptic feedback may not be available on some devices. --> <bool name="config_enableHapticTextHandle">false</bool> <!-- Whether dialogs should close automatically when the user touches outside of them. This should not normally be modified. --> <bool name="config_closeDialogWhenTouchOutside">true</bool> Loading core/res/res/values/symbols.xml +1 −0 Original line number Diff line number Diff line Loading @@ -273,6 +273,7 @@ <java-symbol type="bool" name="config_syncstorageengine_masterSyncAutomatically" /> <java-symbol type="bool" name="config_telephony_use_own_number_for_voicemail" /> <java-symbol type="bool" name="config_ui_enableFadingMarquee" /> <java-symbol type="bool" name="config_enableHapticTextHandle" /> <java-symbol type="bool" name="config_use_strict_phone_number_comparation" /> <java-symbol type="bool" name="config_single_volume" /> <java-symbol type="bool" name="config_voice_capable" /> Loading Loading
core/java/android/widget/Editor.java +52 −24 Original line number Diff line number Diff line Loading @@ -83,6 +83,7 @@ import android.view.DisplayListCanvas; import android.view.DragAndDropPermissions; import android.view.DragEvent; import android.view.Gravity; import android.view.HapticFeedbackConstants; import android.view.InputDevice; import android.view.LayoutInflater; import android.view.Menu; Loading Loading @@ -176,6 +177,8 @@ public class Editor { private boolean mInsertionControllerEnabled; private boolean mSelectionControllerEnabled; private final boolean mHapticTextHandleEnabled; // Used to highlight a word when it is corrected by the IME private CorrectionHighlighter mCorrectionHighlighter; Loading Loading @@ -320,6 +323,8 @@ public class Editor { // Synchronize the filter list, which places the undo input filter at the end. mTextView.setFilters(mTextView.getFilters()); mProcessTextIntentActionsHandler = new ProcessTextIntentActionsHandler(this); mHapticTextHandleEnabled = mTextView.getContext().getResources().getBoolean( com.android.internal.R.bool.config_enableHapticTextHandle); } ParcelableParcel saveInstanceState() { Loading Loading @@ -4253,7 +4258,7 @@ public class Editor { mNumberPreviousOffsets++; } private void filterOnTouchUp() { private void filterOnTouchUp(boolean fromTouchScreen) { final long now = SystemClock.uptimeMillis(); int i = 0; int index = mPreviousOffsetIndex; Loading @@ -4265,7 +4270,7 @@ public class Editor { if (i > 0 && i < iMax && (now - mPreviousOffsetsTimes[index]) > TOUCH_UP_FILTER_DELAY_BEFORE) { positionAtCursorOffset(mPreviousOffsets[index], false); positionAtCursorOffset(mPreviousOffsets[index], false, fromTouchScreen); } } Loading @@ -4282,7 +4287,7 @@ public class Editor { public void invalidate() { super.invalidate(); if (isShowing()) { positionAtCursorOffset(getCurrentCursorOffset(), true); positionAtCursorOffset(getCurrentCursorOffset(), true, false); } }; Loading @@ -4301,7 +4306,7 @@ public class Editor { // Make sure the offset is always considered new, even when focusing at same position mPreviousOffset = -1; positionAtCursorOffset(getCurrentCursorOffset(), false); positionAtCursorOffset(getCurrentCursorOffset(), false, false); } protected void dismiss() { Loading Loading @@ -4338,7 +4343,7 @@ public class Editor { protected abstract void updateSelection(int offset); public abstract void updatePosition(float x, float y); protected abstract void updatePosition(float x, float y, boolean fromTouchScreen); protected boolean isAtRtlRun(@NonNull Layout layout, int offset) { return layout.isRtlCharAt(offset); Loading @@ -4357,8 +4362,11 @@ public class Editor { * @param offset Cursor offset. Must be in [-1, length]. * @param forceUpdatePosition whether to force update the position. This should be true * when If the parent has been scrolled, for example. * @param fromTouchScreen {@code true} if the cursor is moved with motion events from the * touch screen. */ protected void positionAtCursorOffset(int offset, boolean forceUpdatePosition) { protected void positionAtCursorOffset(int offset, boolean forceUpdatePosition, boolean fromTouchScreen) { // A HandleView relies on the layout, which may be nulled by external methods Layout layout = mTextView.getLayout(); if (layout == null) { Loading @@ -4372,6 +4380,9 @@ public class Editor { if (offsetChanged || forceUpdatePosition) { if (offsetChanged) { updateSelection(offset); if (fromTouchScreen && mHapticTextHandleEnabled) { mTextView.performHapticFeedback(HapticFeedbackConstants.TEXT_HANDLE_MOVE); } addPositionToTouchUpFilter(offset); } final int line = layout.getLineForOffset(offset); Loading Loading @@ -4404,7 +4415,7 @@ public class Editor { @Override public void updatePosition(int parentPositionX, int parentPositionY, boolean parentPositionChanged, boolean parentScrolled) { positionAtCursorOffset(getCurrentCursorOffset(), parentScrolled); positionAtCursorOffset(getCurrentCursorOffset(), parentScrolled, false); if (parentPositionChanged || mPositionHasChanged) { if (mIsDragging) { // Update touchToWindow offset in case of parent scrolling while dragging Loading Loading @@ -4516,12 +4527,13 @@ public class Editor { xInWindow - mTouchToWindowOffsetX + mHotspotX + getHorizontalOffset(); final float newPosY = yInWindow - mTouchToWindowOffsetY + mTouchOffsetY; updatePosition(newPosX, newPosY); updatePosition(newPosX, newPosY, ev.isFromSource(InputDevice.SOURCE_TOUCHSCREEN)); break; } case MotionEvent.ACTION_UP: filterOnTouchUp(); filterOnTouchUp(ev.isFromSource(InputDevice.SOURCE_TOUCHSCREEN)); mIsDragging = false; updateDrawable(); break; Loading Loading @@ -4702,7 +4714,7 @@ public class Editor { } @Override public void updatePosition(float x, float y) { protected void updatePosition(float x, float y, boolean fromTouchScreen) { Layout layout = mTextView.getLayout(); int offset; if (layout != null) { Loading @@ -4715,7 +4727,7 @@ public class Editor { } else { offset = -1; } positionAtCursorOffset(offset, false); positionAtCursorOffset(offset, false, fromTouchScreen); if (mTextActionMode != null) { invalidateActionMode(); } Loading Loading @@ -4806,12 +4818,13 @@ public class Editor { } @Override public void updatePosition(float x, float y) { protected void updatePosition(float x, float y, boolean fromTouchScreen) { final Layout layout = mTextView.getLayout(); if (layout == null) { // HandleView will deal appropriately in positionAtCursorOffset when // layout is null. positionAndAdjustForCrossingHandles(mTextView.getOffsetForPosition(x, y)); positionAndAdjustForCrossingHandles(mTextView.getOffsetForPosition(x, y), fromTouchScreen); return; } Loading Loading @@ -4854,12 +4867,12 @@ public class Editor { // to the current position. mLanguageDirectionChanged = true; mTouchWordDelta = 0.0f; positionAndAdjustForCrossingHandles(offset); positionAndAdjustForCrossingHandles(offset, fromTouchScreen); return; } else if (mLanguageDirectionChanged && !isLvlBoundary) { // We've just moved past the boundary so update the position. After this we can // figure out if the user is expanding or shrinking to go by word or character. positionAndAdjustForCrossingHandles(offset); positionAndAdjustForCrossingHandles(offset, fromTouchScreen); mTouchWordDelta = 0.0f; mLanguageDirectionChanged = false; return; Loading Loading @@ -4893,7 +4906,7 @@ public class Editor { final int nextOffset = (atRtl == isStartHandle()) ? layout.getOffsetToRightOf(mPreviousOffset) : layout.getOffsetToLeftOf(mPreviousOffset); positionAndAdjustForCrossingHandles(nextOffset); positionAndAdjustForCrossingHandles(nextOffset, fromTouchScreen); return; } } Loading Loading @@ -4972,14 +4985,15 @@ public class Editor { if (positionCursor) { mPreviousLineTouched = currLine; positionAndAdjustForCrossingHandles(offset); positionAndAdjustForCrossingHandles(offset, fromTouchScreen); } mPrevX = x; } @Override protected void positionAtCursorOffset(int offset, boolean forceUpdatePosition) { super.positionAtCursorOffset(offset, forceUpdatePosition); protected void positionAtCursorOffset(int offset, boolean forceUpdatePosition, boolean fromTouchScreen) { super.positionAtCursorOffset(offset, forceUpdatePosition, fromTouchScreen); mInWord = (offset != -1) && !getWordIteratorWithText().isBoundary(offset); } Loading @@ -4995,7 +5009,7 @@ public class Editor { return superResult; } private void positionAndAdjustForCrossingHandles(int offset) { private void positionAndAdjustForCrossingHandles(int offset, boolean fromTouchScreen) { final int anotherHandleOffset = isStartHandle() ? mTextView.getSelectionEnd() : mTextView.getSelectionStart(); if ((isStartHandle() && offset >= anotherHandleOffset) Loading @@ -5020,14 +5034,14 @@ public class Editor { } else { offset = TextUtils.unpackRangeEndFromLong(range); } positionAtCursorOffset(offset, false); positionAtCursorOffset(offset, false, fromTouchScreen); return; } } // Handles can not cross and selection is at least one character. offset = getNextCursorOffset(anotherHandleOffset, !isStartHandle()); } positionAtCursorOffset(offset, false); positionAtCursorOffset(offset, false, fromTouchScreen); } private boolean positionNearEdgeOfScrollingView(float x, boolean atRtl) { Loading Loading @@ -5470,7 +5484,8 @@ public class Editor { private void updateCharacterBasedSelection(MotionEvent event) { final int offset = mTextView.getOffsetForPosition(event.getX(), event.getY()); Selection.setSelection((Spannable) mTextView.getText(), mStartOffset, offset); updateSelectionInternal(mStartOffset, offset, event.isFromSource(InputDevice.SOURCE_TOUCHSCREEN)); } private void updateWordBasedSelection(MotionEvent event) { Loading Loading @@ -5528,7 +5543,8 @@ public class Editor { } } mLineSelectionIsOn = currLine; Selection.setSelection((Spannable) mTextView.getText(), startOffset, offset); updateSelectionInternal(startOffset, offset, event.isFromSource(InputDevice.SOURCE_TOUCHSCREEN)); } private void updateParagraphBasedSelection(MotionEvent event) { Loading @@ -5539,7 +5555,19 @@ public class Editor { final long paragraphsRange = getParagraphsRange(start, end); final int selectionStart = TextUtils.unpackRangeStartFromLong(paragraphsRange); final int selectionEnd = TextUtils.unpackRangeEndFromLong(paragraphsRange); updateSelectionInternal(selectionStart, selectionEnd, event.isFromSource(InputDevice.SOURCE_TOUCHSCREEN)); } private void updateSelectionInternal(int selectionStart, int selectionEnd, boolean fromTouchScreen) { final boolean performHapticFeedback = fromTouchScreen && mHapticTextHandleEnabled && ((mTextView.getSelectionStart() != selectionStart) || (mTextView.getSelectionEnd() != selectionEnd)); Selection.setSelection((Spannable) mTextView.getText(), selectionStart, selectionEnd); if (performHapticFeedback) { mTextView.performHapticFeedback(HapticFeedbackConstants.TEXT_HANDLE_MOVE); } } /** Loading
core/res/res/values/config.xml +5 −0 Original line number Diff line number Diff line Loading @@ -147,6 +147,11 @@ fading edges is prohibitively expensive on most GPUs. --> <bool name="config_ui_enableFadingMarquee">false</bool> <!-- Enables or disables haptic effect when the text insertion/selection handle is moved manually by the user. Off by default, since the expected haptic feedback may not be available on some devices. --> <bool name="config_enableHapticTextHandle">false</bool> <!-- Whether dialogs should close automatically when the user touches outside of them. This should not normally be modified. --> <bool name="config_closeDialogWhenTouchOutside">true</bool> Loading
core/res/res/values/symbols.xml +1 −0 Original line number Diff line number Diff line Loading @@ -273,6 +273,7 @@ <java-symbol type="bool" name="config_syncstorageengine_masterSyncAutomatically" /> <java-symbol type="bool" name="config_telephony_use_own_number_for_voicemail" /> <java-symbol type="bool" name="config_ui_enableFadingMarquee" /> <java-symbol type="bool" name="config_enableHapticTextHandle" /> <java-symbol type="bool" name="config_use_strict_phone_number_comparation" /> <java-symbol type="bool" name="config_single_volume" /> <java-symbol type="bool" name="config_voice_capable" /> Loading