Loading core/api/current.txt +11 −0 Original line number Diff line number Diff line Loading @@ -52201,6 +52201,7 @@ package android.view.inputmethod { method public boolean setComposingText(CharSequence, int); method public default boolean setImeConsumesInput(boolean); method public boolean setSelection(int, int); method @Nullable public default android.view.inputmethod.TextSnapshot takeSnapshot(); field public static final int CURSOR_UPDATE_IMMEDIATE = 1; // 0x1 field public static final int CURSOR_UPDATE_MONITOR = 2; // 0x2 field public static final int GET_EXTRACTED_TEXT_MONITOR = 1; // 0x1 Loading Loading @@ -52413,6 +52414,16 @@ package android.view.inputmethod { field @NonNull public static final android.os.Parcelable.Creator<android.view.inputmethod.SurroundingText> CREATOR; } public final class TextSnapshot { ctor public TextSnapshot(@NonNull android.view.inputmethod.SurroundingText, @IntRange(from=0xffffffff) int, @IntRange(from=0xffffffff) int, int); method @IntRange(from=0xffffffff) public int getCompositionEnd(); method @IntRange(from=0xffffffff) public int getCompositionStart(); method public int getCursorCapsMode(); method @IntRange(from=0xffffffff) public int getSelectionEnd(); method @IntRange(from=0xffffffff) public int getSelectionStart(); method @NonNull public android.view.inputmethod.SurroundingText getSurroundingText(); } } package android.view.inspector { core/java/android/view/inputmethod/BaseInputConnection.java +34 −0 Original line number Diff line number Diff line Loading @@ -979,4 +979,38 @@ public class BaseInputConnection implements InputConnection { .build(); return mTargetView.performReceiveContent(payload) == null; } /** * Default implementation that constructs {@link TextSnapshot} with information extracted from * {@link BaseInputConnection}. * * @return {@code null} when {@link TextSnapshot} cannot be fully taken. */ @Nullable @Override public TextSnapshot takeSnapshot() { final Editable content = getEditable(); if (content == null) { return null; } int composingStart = getComposingSpanStart(content); int composingEnd = getComposingSpanEnd(content); if (composingEnd < composingStart) { final int tmp = composingStart; composingStart = composingEnd; composingEnd = tmp; } final SurroundingText surroundingText = getSurroundingText( EditorInfo.MEMORY_EFFICIENT_TEXT_LENGTH / 2, EditorInfo.MEMORY_EFFICIENT_TEXT_LENGTH / 2, GET_TEXT_WITH_STYLES); if (surroundingText == null) { return null; } final int cursorCapsMode = getCursorCapsMode(TextUtils.CAP_MODE_CHARACTERS | TextUtils.CAP_MODE_WORDS | TextUtils.CAP_MODE_SENTENCES); return new TextSnapshot(surroundingText, composingStart, composingEnd, cursorCapsMode); } } core/java/android/view/inputmethod/InputConnection.java +23 −0 Original line number Diff line number Diff line Loading @@ -1034,4 +1034,27 @@ public interface InputConnection { default boolean setImeConsumesInput(boolean imeConsumesInput) { return false; } /** * Called by the system when it needs to take a snapshot of multiple text-related data in an * atomic manner. * * <p><strong>Editor authors</strong>: Supporting this method is strongly encouraged. Atomically * taken {@link TextSnapshot} is going to be really helpful for the system when optimizing IPCs * in a safe and deterministic manner. Return {@code null} if an atomically taken * {@link TextSnapshot} is unavailable. The system continues supporting such a scenario * gracefully.</p> * * <p><strong>IME authors</strong>: Currently IMEs cannot call this method directly and always * receive {@code null} as the result.</p> * * @return {@code null} if {@link TextSnapshot} is unavailable and/or this API is called from * IMEs. */ @Nullable default TextSnapshot takeSnapshot() { // Returning null by default because the composing text range cannot be retrieved from // existing APIs. return null; } } core/java/android/view/inputmethod/TextSnapshot.java 0 → 100644 +144 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.view.inputmethod; import android.annotation.IntRange; import android.annotation.NonNull; import java.util.Objects; /** * An immutable data snapshot of text editing state. */ public final class TextSnapshot { @NonNull private final SurroundingText mSurroundingText; @IntRange(from = -1) private final int mCompositionStart; @IntRange(from = -1) private final int mCompositionEnd; private final int mCursorCapsMode; /** * Creates a new instance of {@link TextSnapshot} * * @param surroundingText {@link SurroundingText} of the current edit field. * @param compositionStart The start index of the composing text. * {@code -1} if there is no composing text. * @param compositionEnd The end index of the composing text. * {@code -1} if there is no composing text. * @param cursorCapsMode The capitalization mode of the first character being edited in the * text. See {@link EditorInfo#initialCapsMode}. * @throws NullPointerException if {@code surroundingText} is {@code null}. * @throws IllegalArgumentException if {@code compositionStart} and/or {@code compositionEnd} * is less than {@code -1}. */ public TextSnapshot(@NonNull SurroundingText surroundingText, @IntRange(from = -1) int compositionStart, @IntRange(from = -1) int compositionEnd, int cursorCapsMode) { Objects.requireNonNull(surroundingText); mSurroundingText = surroundingText; if (compositionStart < -1) { throw new IllegalArgumentException("compositionStart must be -1 or higher but was " + compositionStart); } if (compositionEnd < -1) { throw new IllegalArgumentException("compositionEnd must be -1 or higher but was " + compositionEnd); } if (compositionStart == -1 && compositionEnd != -1) { throw new IllegalArgumentException("compositionEnd must be -1 if compositionStart is " + "-1 but was " + compositionEnd); } if (compositionStart != -1 && compositionEnd == -1) { throw new IllegalArgumentException("compositionStart must be -1 if compositionEnd is " + "-1 but was " + compositionStart); } if (compositionStart > compositionEnd) { throw new IllegalArgumentException("compositionStart=" + compositionStart + " must be" + " equal to or greater than compositionEnd=" + compositionEnd); } mCompositionStart = compositionStart; mCompositionEnd = compositionEnd; mCursorCapsMode = cursorCapsMode; } /** * @return {@link SurroundingText} of the current edit field. */ @NonNull public SurroundingText getSurroundingText() { return mSurroundingText; } /** * @return The start index of the selection range. {@code -1} if it is not available. */ @IntRange(from = -1) public int getSelectionStart() { if (mSurroundingText.getOffset() < 0) { return -1; } return mSurroundingText.getSelectionStart() + mSurroundingText.getOffset(); } /** * @return The end index of the selection range. {@code -1} if it is not available. */ @IntRange(from = -1) public int getSelectionEnd() { if (mSurroundingText.getOffset() < 0) { return -1; } return mSurroundingText.getSelectionEnd() + mSurroundingText.getOffset(); } /** * @return The end index of the composing text. {@code -1} if there is no composing text. */ @IntRange(from = -1) public int getCompositionStart() { return mCompositionStart; } /** * @return The end index of the composing text. {@code -1} if there is no composing text. */ @IntRange(from = -1) public int getCompositionEnd() { return mCompositionEnd; } /** * The capitalization mode of the first character being edited in the text. * * <p>Values may be any combination of the following values:</p> * <ul> * <li>{@link android.text.TextUtils#CAP_MODE_CHARACTERS TextUtils.CAP_MODE_CHARACTERS}</li> * <li>{@link android.text.TextUtils#CAP_MODE_CHARACTERS TextUtils.CAP_MODE_WORDS}</li> * <li>{@link android.text.TextUtils#CAP_MODE_CHARACTERS TextUtils.CAP_MODE_SENTENCES}</li> * </ul> * * <p>You should generally just take a non-zero value to mean "start out in caps mode" though. * </p> * @see EditorInfo#initialCapsMode */ public int getCursorCapsMode() { return mCursorCapsMode; } } Loading
core/api/current.txt +11 −0 Original line number Diff line number Diff line Loading @@ -52201,6 +52201,7 @@ package android.view.inputmethod { method public boolean setComposingText(CharSequence, int); method public default boolean setImeConsumesInput(boolean); method public boolean setSelection(int, int); method @Nullable public default android.view.inputmethod.TextSnapshot takeSnapshot(); field public static final int CURSOR_UPDATE_IMMEDIATE = 1; // 0x1 field public static final int CURSOR_UPDATE_MONITOR = 2; // 0x2 field public static final int GET_EXTRACTED_TEXT_MONITOR = 1; // 0x1 Loading Loading @@ -52413,6 +52414,16 @@ package android.view.inputmethod { field @NonNull public static final android.os.Parcelable.Creator<android.view.inputmethod.SurroundingText> CREATOR; } public final class TextSnapshot { ctor public TextSnapshot(@NonNull android.view.inputmethod.SurroundingText, @IntRange(from=0xffffffff) int, @IntRange(from=0xffffffff) int, int); method @IntRange(from=0xffffffff) public int getCompositionEnd(); method @IntRange(from=0xffffffff) public int getCompositionStart(); method public int getCursorCapsMode(); method @IntRange(from=0xffffffff) public int getSelectionEnd(); method @IntRange(from=0xffffffff) public int getSelectionStart(); method @NonNull public android.view.inputmethod.SurroundingText getSurroundingText(); } } package android.view.inspector {
core/java/android/view/inputmethod/BaseInputConnection.java +34 −0 Original line number Diff line number Diff line Loading @@ -979,4 +979,38 @@ public class BaseInputConnection implements InputConnection { .build(); return mTargetView.performReceiveContent(payload) == null; } /** * Default implementation that constructs {@link TextSnapshot} with information extracted from * {@link BaseInputConnection}. * * @return {@code null} when {@link TextSnapshot} cannot be fully taken. */ @Nullable @Override public TextSnapshot takeSnapshot() { final Editable content = getEditable(); if (content == null) { return null; } int composingStart = getComposingSpanStart(content); int composingEnd = getComposingSpanEnd(content); if (composingEnd < composingStart) { final int tmp = composingStart; composingStart = composingEnd; composingEnd = tmp; } final SurroundingText surroundingText = getSurroundingText( EditorInfo.MEMORY_EFFICIENT_TEXT_LENGTH / 2, EditorInfo.MEMORY_EFFICIENT_TEXT_LENGTH / 2, GET_TEXT_WITH_STYLES); if (surroundingText == null) { return null; } final int cursorCapsMode = getCursorCapsMode(TextUtils.CAP_MODE_CHARACTERS | TextUtils.CAP_MODE_WORDS | TextUtils.CAP_MODE_SENTENCES); return new TextSnapshot(surroundingText, composingStart, composingEnd, cursorCapsMode); } }
core/java/android/view/inputmethod/InputConnection.java +23 −0 Original line number Diff line number Diff line Loading @@ -1034,4 +1034,27 @@ public interface InputConnection { default boolean setImeConsumesInput(boolean imeConsumesInput) { return false; } /** * Called by the system when it needs to take a snapshot of multiple text-related data in an * atomic manner. * * <p><strong>Editor authors</strong>: Supporting this method is strongly encouraged. Atomically * taken {@link TextSnapshot} is going to be really helpful for the system when optimizing IPCs * in a safe and deterministic manner. Return {@code null} if an atomically taken * {@link TextSnapshot} is unavailable. The system continues supporting such a scenario * gracefully.</p> * * <p><strong>IME authors</strong>: Currently IMEs cannot call this method directly and always * receive {@code null} as the result.</p> * * @return {@code null} if {@link TextSnapshot} is unavailable and/or this API is called from * IMEs. */ @Nullable default TextSnapshot takeSnapshot() { // Returning null by default because the composing text range cannot be retrieved from // existing APIs. return null; } }
core/java/android/view/inputmethod/TextSnapshot.java 0 → 100644 +144 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.view.inputmethod; import android.annotation.IntRange; import android.annotation.NonNull; import java.util.Objects; /** * An immutable data snapshot of text editing state. */ public final class TextSnapshot { @NonNull private final SurroundingText mSurroundingText; @IntRange(from = -1) private final int mCompositionStart; @IntRange(from = -1) private final int mCompositionEnd; private final int mCursorCapsMode; /** * Creates a new instance of {@link TextSnapshot} * * @param surroundingText {@link SurroundingText} of the current edit field. * @param compositionStart The start index of the composing text. * {@code -1} if there is no composing text. * @param compositionEnd The end index of the composing text. * {@code -1} if there is no composing text. * @param cursorCapsMode The capitalization mode of the first character being edited in the * text. See {@link EditorInfo#initialCapsMode}. * @throws NullPointerException if {@code surroundingText} is {@code null}. * @throws IllegalArgumentException if {@code compositionStart} and/or {@code compositionEnd} * is less than {@code -1}. */ public TextSnapshot(@NonNull SurroundingText surroundingText, @IntRange(from = -1) int compositionStart, @IntRange(from = -1) int compositionEnd, int cursorCapsMode) { Objects.requireNonNull(surroundingText); mSurroundingText = surroundingText; if (compositionStart < -1) { throw new IllegalArgumentException("compositionStart must be -1 or higher but was " + compositionStart); } if (compositionEnd < -1) { throw new IllegalArgumentException("compositionEnd must be -1 or higher but was " + compositionEnd); } if (compositionStart == -1 && compositionEnd != -1) { throw new IllegalArgumentException("compositionEnd must be -1 if compositionStart is " + "-1 but was " + compositionEnd); } if (compositionStart != -1 && compositionEnd == -1) { throw new IllegalArgumentException("compositionStart must be -1 if compositionEnd is " + "-1 but was " + compositionStart); } if (compositionStart > compositionEnd) { throw new IllegalArgumentException("compositionStart=" + compositionStart + " must be" + " equal to or greater than compositionEnd=" + compositionEnd); } mCompositionStart = compositionStart; mCompositionEnd = compositionEnd; mCursorCapsMode = cursorCapsMode; } /** * @return {@link SurroundingText} of the current edit field. */ @NonNull public SurroundingText getSurroundingText() { return mSurroundingText; } /** * @return The start index of the selection range. {@code -1} if it is not available. */ @IntRange(from = -1) public int getSelectionStart() { if (mSurroundingText.getOffset() < 0) { return -1; } return mSurroundingText.getSelectionStart() + mSurroundingText.getOffset(); } /** * @return The end index of the selection range. {@code -1} if it is not available. */ @IntRange(from = -1) public int getSelectionEnd() { if (mSurroundingText.getOffset() < 0) { return -1; } return mSurroundingText.getSelectionEnd() + mSurroundingText.getOffset(); } /** * @return The end index of the composing text. {@code -1} if there is no composing text. */ @IntRange(from = -1) public int getCompositionStart() { return mCompositionStart; } /** * @return The end index of the composing text. {@code -1} if there is no composing text. */ @IntRange(from = -1) public int getCompositionEnd() { return mCompositionEnd; } /** * The capitalization mode of the first character being edited in the text. * * <p>Values may be any combination of the following values:</p> * <ul> * <li>{@link android.text.TextUtils#CAP_MODE_CHARACTERS TextUtils.CAP_MODE_CHARACTERS}</li> * <li>{@link android.text.TextUtils#CAP_MODE_CHARACTERS TextUtils.CAP_MODE_WORDS}</li> * <li>{@link android.text.TextUtils#CAP_MODE_CHARACTERS TextUtils.CAP_MODE_SENTENCES}</li> * </ul> * * <p>You should generally just take a non-zero value to mean "start out in caps mode" though. * </p> * @see EditorInfo#initialCapsMode */ public int getCursorCapsMode() { return mCursorCapsMode; } }