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

Commit c09a04da authored by Yohei Yukawa's avatar Yohei Yukawa Committed by Android (Google) Code Review
Browse files

Merge "Polish new IME API for L: CursorAnchorInfo"

parents 931a0e27 0b01e7fc
Loading
Loading
Loading
Loading
+10 −2
Original line number Diff line number Diff line
@@ -34837,6 +34837,7 @@ package android.view.inputmethod {
    ctor public CursorAnchorInfo(android.os.Parcel);
    method public int describeContents();
    method public android.graphics.RectF getCharacterRect(int);
    method public int getCharacterRectFlags(int);
    method public java.lang.CharSequence getComposingText();
    method public int getComposingTextStart();
    method public float getInsertionMarkerBaseline();
@@ -34846,17 +34847,24 @@ package android.view.inputmethod {
    method public android.graphics.Matrix getMatrix();
    method public int getSelectionEnd();
    method public int getSelectionStart();
    method public boolean isInsertionMarkerClipped();
    method public void writeToParcel(android.os.Parcel, int);
    field public static final int CHARACTER_RECT_TYPE_FULLY_VISIBLE = 1; // 0x1
    field public static final int CHARACTER_RECT_TYPE_INVISIBLE = 3; // 0x3
    field public static final int CHARACTER_RECT_TYPE_MASK = 15; // 0xf
    field public static final int CHARACTER_RECT_TYPE_NOT_FEASIBLE = 4; // 0x4
    field public static final int CHARACTER_RECT_TYPE_PARTIALLY_VISIBLE = 2; // 0x2
    field public static final int CHARACTER_RECT_TYPE_UNSPECIFIED = 0; // 0x0
    field public static final android.os.Parcelable.Creator CREATOR;
  }
  public static final class CursorAnchorInfo.Builder {
    ctor public CursorAnchorInfo.Builder();
    method public android.view.inputmethod.CursorAnchorInfo.Builder addCharacterRect(int, float, float, float, float);
    method public android.view.inputmethod.CursorAnchorInfo.Builder addCharacterRect(int, float, float, float, float, int);
    method public android.view.inputmethod.CursorAnchorInfo build();
    method public void reset();
    method public android.view.inputmethod.CursorAnchorInfo.Builder setComposingText(int, java.lang.CharSequence);
    method public android.view.inputmethod.CursorAnchorInfo.Builder setInsertionMarkerLocation(float, float, float, float);
    method public android.view.inputmethod.CursorAnchorInfo.Builder setInsertionMarkerLocation(float, float, float, float, boolean);
    method public android.view.inputmethod.CursorAnchorInfo.Builder setMatrix(android.graphics.Matrix);
    method public android.view.inputmethod.CursorAnchorInfo.Builder setSelectionRange(int, int);
  }
+78 −7
Original line number Diff line number Diff line
@@ -44,6 +44,10 @@ public final class CursorAnchorInfo implements Parcelable {
     */
    private final CharSequence mComposingText;

    /**
     * {@code True} if the insertion marker is partially or entirely clipped by other UI elements.
     */
    private final boolean mInsertionMarkerClipped;
    /**
     * Horizontal position of the insertion marker, in the local coordinates that will be
     * transformed with the transformation matrix when rendered on the screen. This should be
@@ -86,11 +90,36 @@ public final class CursorAnchorInfo implements Parcelable {
     */
    private final Matrix mMatrix;

    public static final int CHARACTER_RECT_TYPE_MASK = 0x0f;
    /**
     * Type for {@link #CHARACTER_RECT_TYPE_MASK}: the editor did not specify any type of this
     * character. Editor authors should not use this flag.
     */
    public static final int CHARACTER_RECT_TYPE_UNSPECIFIED = 0;
    /**
     * Type for {@link #CHARACTER_RECT_TYPE_MASK}: the character is entirely visible.
     */
    public static final int CHARACTER_RECT_TYPE_FULLY_VISIBLE = 1;
    /**
     * Type for {@link #CHARACTER_RECT_TYPE_MASK}: some area of the character is invisible.
     */
    public static final int CHARACTER_RECT_TYPE_PARTIALLY_VISIBLE = 2;
    /**
     * Type for {@link #CHARACTER_RECT_TYPE_MASK}: the character is entirely invisible.
     */
    public static final int CHARACTER_RECT_TYPE_INVISIBLE = 3;
    /**
     * Type for {@link #CHARACTER_RECT_TYPE_MASK}: the editor gave up to calculate the rectangle
     * for this character. Input method authors should ignore the returned rectangle.
     */
    public static final int CHARACTER_RECT_TYPE_NOT_FEASIBLE = 4;

    public CursorAnchorInfo(final Parcel source) {
        mSelectionStart = source.readInt();
        mSelectionEnd = source.readInt();
        mComposingTextStart = source.readInt();
        mComposingText = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source);
        mInsertionMarkerClipped = (source.readInt() != 0);
        mInsertionMarkerHorizontal = source.readFloat();
        mInsertionMarkerTop = source.readFloat();
        mInsertionMarkerBaseline = source.readFloat();
@@ -112,6 +141,7 @@ public final class CursorAnchorInfo implements Parcelable {
        dest.writeInt(mSelectionEnd);
        dest.writeInt(mComposingTextStart);
        TextUtils.writeToParcel(mComposingText, dest, flags);
        dest.writeInt(mInsertionMarkerClipped ? 1 : 0);
        dest.writeFloat(mInsertionMarkerHorizontal);
        dest.writeFloat(mInsertionMarkerTop);
        dest.writeFloat(mInsertionMarkerBaseline);
@@ -129,6 +159,8 @@ public final class CursorAnchorInfo implements Parcelable {
                + mInsertionMarkerBaseline + mInsertionMarkerBottom;
        int hash = floatHash > 0 ? (int) floatHash : (int)(-floatHash);
        hash *= 31;
        hash += (mInsertionMarkerClipped ? 2 : 1);
        hash *= 31;
        hash += mSelectionStart + mSelectionEnd + mComposingTextStart;
        hash *= 31;
        hash += Objects.hashCode(mComposingText);
@@ -172,7 +204,8 @@ public final class CursorAnchorInfo implements Parcelable {
                || !Objects.equals(mComposingText, that.mComposingText)) {
            return false;
        }
        if (!areSameFloatImpl(mInsertionMarkerHorizontal, that.mInsertionMarkerHorizontal)
        if (mInsertionMarkerClipped != that.mInsertionMarkerClipped
                || !areSameFloatImpl(mInsertionMarkerHorizontal, that.mInsertionMarkerHorizontal)
                || !areSameFloatImpl(mInsertionMarkerTop, that.mInsertionMarkerTop)
                || !areSameFloatImpl(mInsertionMarkerBaseline, that.mInsertionMarkerBaseline)
                || !areSameFloatImpl(mInsertionMarkerBottom, that.mInsertionMarkerBottom)) {
@@ -195,6 +228,7 @@ public final class CursorAnchorInfo implements Parcelable {
        return "SelectionInfo{mSelection=" + mSelectionStart + "," + mSelectionEnd
                + " mComposingTextStart=" + mComposingTextStart
                + " mComposingText=" + Objects.toString(mComposingText)
                + " mInsertionMarkerClipped=" + mInsertionMarkerClipped
                + " mInsertionMarkerHorizontal=" + mInsertionMarkerHorizontal
                + " mInsertionMarkerTop=" + mInsertionMarkerTop
                + " mInsertionMarkerBaseline=" + mInsertionMarkerBaseline
@@ -256,25 +290,27 @@ public final class CursorAnchorInfo implements Parcelable {
         * @param lineBottom vertical position of the insertion marker, in the local coordinates
         * that will be transformed with the transformation matrix when rendered on the screen. This
         * should be calculated or compatible with {@link Layout#getLineBottom(int)}.
         * @param clipped {@code true} is the insertion marker is partially or entierly clipped by
         * other UI elements.
         */
        public Builder setInsertionMarkerLocation(final float horizontalPosition,
                final float lineTop, final float lineBaseline, final float lineBottom){
                final float lineTop, final float lineBaseline, final float lineBottom,
                final boolean clipped){
            mInsertionMarkerHorizontal = horizontalPosition;
            mInsertionMarkerTop = lineTop;
            mInsertionMarkerBaseline = lineBaseline;
            mInsertionMarkerBottom = lineBottom;
            mInsertionMarkerClipped = clipped;
            return this;
        }
        private float mInsertionMarkerHorizontal = Float.NaN;
        private float mInsertionMarkerTop = Float.NaN;
        private float mInsertionMarkerBaseline = Float.NaN;
        private float mInsertionMarkerBottom = Float.NaN;
        private boolean mInsertionMarkerClipped = false;

        /**
         * Adds the bounding box of the character specified with the index.
         * <p>
         * Editor authors should not call this method for characters that are invisible.
         * </p>
         *
         * @param index index of the character in Java chars units. Must be specified in
         * ascending order across successive calls.
@@ -286,19 +322,27 @@ public final class CursorAnchorInfo implements Parcelable {
         * coordinates, that is, right edge for LTR text and left edge for RTL text.
         * @param trailingEdgeY y coordinate of the trailing edge of the character in local
         * coordinates.
         * @param flags type and flags for this character. See
         * {@link #CHARACTER_RECT_TYPE_FULLY_VISIBLE} for example.
         * @throws IllegalArgumentException If the index is a negative value, or not greater than
         * all of the previously called indices.
         */
        public Builder addCharacterRect(final int index, final float leadingEdgeX,
                final float leadingEdgeY, final float trailingEdgeX, final float trailingEdgeY) {
                final float leadingEdgeY, final float trailingEdgeX, final float trailingEdgeY,
                final int flags) {
            if (index < 0) {
                throw new IllegalArgumentException("index must not be a negative integer.");
            }
            final int type = flags & CHARACTER_RECT_TYPE_MASK;
            if (type == CHARACTER_RECT_TYPE_UNSPECIFIED) {
                throw new IllegalArgumentException("Type except for "
                        + "CHARACTER_RECT_TYPE_UNSPECIFIED must be specified.");
            }
            if (mCharacterRectBuilder == null) {
                mCharacterRectBuilder = new SparseRectFArrayBuilder();
            }
            mCharacterRectBuilder.append(index, leadingEdgeX, leadingEdgeY, trailingEdgeX,
                    trailingEdgeY);
                    trailingEdgeY, flags);
            return this;
        }
        private SparseRectFArrayBuilder mCharacterRectBuilder = null;
@@ -346,6 +390,7 @@ public final class CursorAnchorInfo implements Parcelable {
            mSelectionEnd = -1;
            mComposingTextStart = -1;
            mComposingText = null;
            mInsertionMarkerClipped = false;
            mInsertionMarkerHorizontal = Float.NaN;
            mInsertionMarkerTop = Float.NaN;
            mInsertionMarkerBaseline = Float.NaN;
@@ -363,6 +408,7 @@ public final class CursorAnchorInfo implements Parcelable {
        mSelectionEnd = builder.mSelectionEnd;
        mComposingTextStart = builder.mComposingTextStart;
        mComposingText = builder.mComposingText;
        mInsertionMarkerClipped = builder.mInsertionMarkerClipped;
        mInsertionMarkerHorizontal = builder.mInsertionMarkerHorizontal;
        mInsertionMarkerTop = builder.mInsertionMarkerTop;
        mInsertionMarkerBaseline = builder.mInsertionMarkerBaseline;
@@ -404,6 +450,14 @@ public final class CursorAnchorInfo implements Parcelable {
        return mComposingText;
    }

    /**
     * Returns the visibility of the insertion marker.
     * @return {@code true} if the insertion marker is partially or entirely clipped.
     */
    public boolean isInsertionMarkerClipped() {
        return mInsertionMarkerClipped;
    }

    /**
     * Returns the horizontal start of the insertion marker, in the local coordinates that will
     * be transformed with {@link #getMatrix()} when rendered on the screen.
@@ -415,6 +469,7 @@ public final class CursorAnchorInfo implements Parcelable {
    public float getInsertionMarkerHorizontal() {
        return mInsertionMarkerHorizontal;
    }

    /**
     * Returns the vertical top position of the insertion marker, in the local coordinates that
     * will be transformed with {@link #getMatrix()} when rendered on the screen.
@@ -424,6 +479,7 @@ public final class CursorAnchorInfo implements Parcelable {
    public float getInsertionMarkerTop() {
        return mInsertionMarkerTop;
    }

    /**
     * Returns the vertical baseline position of the insertion marker, in the local coordinates
     * that will be transformed with {@link #getMatrix()} when rendered on the screen.
@@ -433,6 +489,7 @@ public final class CursorAnchorInfo implements Parcelable {
    public float getInsertionMarkerBaseline() {
        return mInsertionMarkerBaseline;
    }

    /**
     * Returns the vertical bottom position of the insertion marker, in the local coordinates
     * that will be transformed with {@link #getMatrix()} when rendered on the screen.
@@ -466,6 +523,20 @@ public final class CursorAnchorInfo implements Parcelable {
        return mCharacterRects.get(index);
    }

    /**
     * Returns the flags associated with the character specified with the index.
     * @param index index of the character in a Java chars.
     * @return {@link #CHARACTER_RECT_TYPE_UNSPECIFIED} if no flag is specified.
     */
    // TODO: Prepare a document about the expected behavior for surrogate pairs, combining
    // characters, and non-graphical chars.
    public int getCharacterRectFlags(final int index) {
        if (mCharacterRects == null) {
            return CHARACTER_RECT_TYPE_UNSPECIFIED;
        }
        return mCharacterRects.getFlags(index, CHARACTER_RECT_TYPE_UNSPECIFIED);
    }

    /**
     * Returns a new instance of {@link android.graphics.Matrix} that indicates the transformation
     * matrix that is to be applied other positional data in this class.
+47 −4
Original line number Diff line number Diff line
@@ -50,9 +50,15 @@ public final class SparseRectFArray implements Parcelable {
     */
    private final float[] mCoordinates;

    /**
     * Stores visibility information.
     */
    private final int[] mFlagsArray;

    public SparseRectFArray(final Parcel source) {
        mKeys = source.createIntArray();
        mCoordinates = source.createFloatArray();
        mFlagsArray = source.createIntArray();
    }

    /**
@@ -65,6 +71,7 @@ public final class SparseRectFArray implements Parcelable {
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeIntArray(mKeys);
        dest.writeFloatArray(mCoordinates);
        dest.writeIntArray(mFlagsArray);
    }

    @Override
@@ -79,6 +86,8 @@ public final class SparseRectFArray implements Parcelable {
            hash *= 31;
            hash += mCoordinates[i];
        }
        hash *= 31;
        hash += mFlagsArray[0];
        return hash;
    }

@@ -95,12 +104,13 @@ public final class SparseRectFArray implements Parcelable {
        }
        final SparseRectFArray that = (SparseRectFArray) obj;

        return Arrays.equals(mKeys, that.mKeys) && Arrays.equals(mCoordinates, that.mCoordinates);
        return Arrays.equals(mKeys, that.mKeys) && Arrays.equals(mCoordinates, that.mCoordinates)
                && Arrays.equals(mFlagsArray, that.mFlagsArray);
    }

    @Override
    public String toString() {
        if (mKeys == null || mCoordinates == null) {
        if (mKeys == null || mCoordinates == null || mFlagsArray == null) {
            return "SparseRectFArray{}";
        }
        final StringBuilder sb = new StringBuilder();
@@ -119,7 +129,8 @@ public final class SparseRectFArray implements Parcelable {
            sb.append(mCoordinates[baseIndex + 2]);
            sb.append(",");
            sb.append(mCoordinates[baseIndex + 3]);
            sb.append("]");
            sb.append("]:flagsArray=");
            sb.append(mFlagsArray[i]);
        }
        sb.append("}");
        return sb.toString();
@@ -153,6 +164,9 @@ public final class SparseRectFArray implements Parcelable {
            if (mCoordinates == null) {
                mCoordinates = new float[INITIAL_SIZE * 4];
            }
            if (mFlagsArray == null) {
                mFlagsArray = new int[INITIAL_SIZE];
            }
            final int requiredIndexArraySize = mCount + 1;
            if (mKeys.length <= requiredIndexArraySize) {
                final int[] newArray = new int[requiredIndexArraySize * 2];
@@ -165,6 +179,12 @@ public final class SparseRectFArray implements Parcelable {
                System.arraycopy(mCoordinates, 0, newArray, 0, mCount * 4);
                mCoordinates = newArray;
            }
            final int requiredFlagsArraySize = requiredIndexArraySize;
            if (mFlagsArray.length <= requiredFlagsArraySize) {
                final int[] newArray = new int[requiredFlagsArraySize * 2];
                System.arraycopy(mFlagsArray, 0, newArray, 0, mCount);
                mFlagsArray = newArray;
            }
        }

        /**
@@ -175,11 +195,13 @@ public final class SparseRectFArray implements Parcelable {
         * @param top top of the rectangle.
         * @param right right of the rectangle.
         * @param bottom bottom of the rectangle.
         * @param flags an arbitrary integer value to be associated with this rectangle.
         * @return the receiver object itself for chaining method calls.
         * @throws IllegalArgumentException If the index is not greater than all of existing keys.
         */
        public SparseRectFArrayBuilder append(final int key,
                final float left, final float top, final float right, final float bottom) {
                final float left, final float top, final float right, final float bottom,
                final int flags) {
            checkIndex(key);
            ensureBufferSize();
            final int baseCoordinatesIndex = mCount * 4;
@@ -187,6 +209,8 @@ public final class SparseRectFArray implements Parcelable {
            mCoordinates[baseCoordinatesIndex + 1] = top;
            mCoordinates[baseCoordinatesIndex + 2] = right;
            mCoordinates[baseCoordinatesIndex + 3] = bottom;
            final int flagsIndex = mCount;
            mFlagsArray[flagsIndex] = flags;
            mKeys[mCount] = key;
            ++mCount;
            return this;
@@ -194,6 +218,7 @@ public final class SparseRectFArray implements Parcelable {
        private int mCount = 0;
        private int[] mKeys = null;
        private float[] mCoordinates = null;
        private int[] mFlagsArray = null;
        private static int INITIAL_SIZE = 16;

        public boolean isEmpty() {
@@ -211,6 +236,7 @@ public final class SparseRectFArray implements Parcelable {
            if (mCount == 0) {
                mKeys = null;
                mCoordinates = null;
                mFlagsArray = null;
            }
            mCount = 0;
        }
@@ -220,11 +246,14 @@ public final class SparseRectFArray implements Parcelable {
        if (builder.mCount == 0) {
            mKeys = null;
            mCoordinates = null;
            mFlagsArray = null;
        } else {
            mKeys = new int[builder.mCount];
            mCoordinates = new float[builder.mCount * 4];
            mFlagsArray = new int[builder.mCount];
            System.arraycopy(builder.mKeys, 0, mKeys, 0, builder.mCount);
            System.arraycopy(builder.mCoordinates, 0, mCoordinates, 0, builder.mCount * 4);
            System.arraycopy(builder.mFlagsArray, 0, mFlagsArray, 0, builder.mCount);
        }
    }

@@ -246,6 +275,20 @@ public final class SparseRectFArray implements Parcelable {
                mCoordinates[baseCoordIndex + 3]);
    }

    public int getFlags(final int index, final int valueIfKeyNotFound) {
        if (mKeys == null) {
            return valueIfKeyNotFound;
        }
        if (index < 0) {
            return valueIfKeyNotFound;
        }
        final int arrayIndex = Arrays.binarySearch(mKeys, index);
        if (arrayIndex < 0) {
            return valueIfKeyNotFound;
        }
        return mFlagsArray[arrayIndex];
    }

    /**
     * Used to make this class parcelable.
     */
+19 −11
Original line number Diff line number Diff line
@@ -3088,13 +3088,22 @@ public class Editor {
                    final float bottom = layout.getLineBottom(line)
                            + viewportToContentVerticalOffset;
                    // Take TextView's padding and scroll into account.
                    if (isPositionVisible(left, top) && isPositionVisible(right, bottom)) {
                    // TODO: Check right-top and left-bottom as well.
                    final boolean leftTopVisible = isPositionVisible(left, top);
                    final boolean rightBottomVisible = isPositionVisible(right, bottom);
                    final int characterRectFlags;
                    if (leftTopVisible && rightBottomVisible) {
                        characterRectFlags = CursorAnchorInfo.CHARACTER_RECT_TYPE_FULLY_VISIBLE;
                    } else if (leftTopVisible || rightBottomVisible) {
                        characterRectFlags = CursorAnchorInfo.CHARACTER_RECT_TYPE_PARTIALLY_VISIBLE;
                    } else {
                        characterRectFlags = CursorAnchorInfo.CHARACTER_RECT_TYPE_INVISIBLE;
                    }
                    // Here offset is the index in Java chars.
                    // TODO: We must have a well-defined specification. For example, how
                    // RTL, surrogate pairs, and composition letters are handled must be
                    // documented.
                        builder.addCharacterRect(offset, left, top, right, bottom);
                    }
                    builder.addCharacterRect(offset, left, top, right, bottom, characterRectFlags);
                }
            }

@@ -3111,11 +3120,10 @@ public class Editor {
                final float insertionMarkerBottom = layout.getLineBottom(line)
                        + viewportToContentVerticalOffset;
                // Take TextView's padding and scroll into account.
                if (isPositionVisible(insertionMarkerX, insertionMarkerTop) &&
                        isPositionVisible(insertionMarkerX, insertionMarkerBottom)) {
                final boolean isClipped = !isPositionVisible(insertionMarkerX, insertionMarkerTop)
                        || !isPositionVisible(insertionMarkerX, insertionMarkerBottom);
                builder.setInsertionMarkerLocation(insertionMarkerX, insertionMarkerTop,
                            insertionMarkerBaseline, insertionMarkerBottom);
                }
                        insertionMarkerBaseline, insertionMarkerBottom, isClipped);
            }

            imm.updateCursorAnchorInfo(mTextView, builder.build());
+123 −34

File changed.

Preview size limit exceeded, changes collapsed.

Loading