Scribe in IMF: CursorAnchorInfo#getEditorBoundsInfo 3/N

Add a new field EditorBoundsInfo in CursorAnchorInfo
and implement it.

Bug: 203086136
Test: atest CurosrAnchorInfoTest

Change-Id: I7f225fa1236534bbd18920f8ce8293df23ea2ce7
This commit is contained in:
Taran Singh
2022-01-14 21:52:01 +00:00
committed by Prabir Pradhan
parent 2888d6598f
commit 14d8e9450e
5 changed files with 259 additions and 3 deletions

View File

@@ -52972,6 +52972,7 @@ package android.view.inputmethod {
method public int getCharacterBoundsFlags(int);
method public CharSequence getComposingText();
method public int getComposingTextStart();
method @Nullable public android.view.inputmethod.EditorBoundsInfo getEditorBoundsInfo();
method public float getInsertionMarkerBaseline();
method public float getInsertionMarkerBottom();
method public int getInsertionMarkerFlags();
@@ -52993,11 +52994,27 @@ package android.view.inputmethod {
method public android.view.inputmethod.CursorAnchorInfo build();
method public void reset();
method public android.view.inputmethod.CursorAnchorInfo.Builder setComposingText(int, CharSequence);
method @NonNull public android.view.inputmethod.CursorAnchorInfo.Builder setEditorBoundsInfo(@Nullable android.view.inputmethod.EditorBoundsInfo);
method public android.view.inputmethod.CursorAnchorInfo.Builder setInsertionMarkerLocation(float, float, float, float, int);
method public android.view.inputmethod.CursorAnchorInfo.Builder setMatrix(android.graphics.Matrix);
method public android.view.inputmethod.CursorAnchorInfo.Builder setSelectionRange(int, int);
}
public final class EditorBoundsInfo implements android.os.Parcelable {
method public int describeContents();
method @Nullable public android.graphics.RectF getEditorBounds();
method @Nullable public android.graphics.RectF getHandwritingBounds();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.view.inputmethod.EditorBoundsInfo> CREATOR;
}
public static final class EditorBoundsInfo.Builder {
ctor public EditorBoundsInfo.Builder();
method @NonNull public android.view.inputmethod.EditorBoundsInfo build();
method @NonNull public android.view.inputmethod.EditorBoundsInfo.Builder setEditorBounds(@Nullable android.graphics.RectF);
method @NonNull public android.view.inputmethod.EditorBoundsInfo.Builder setHandwritingBounds(@Nullable android.graphics.RectF);
}
public class EditorInfo implements android.text.InputType android.os.Parcelable {
ctor public EditorInfo();
method public int describeContents();

View File

@@ -8663,14 +8663,33 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (mAttachInfo == null) {
return;
}
RectF position = mAttachInfo.mTmpTransformRect;
position.set(0, 0, mRight - mLeft, mBottom - mTop);
mapRectFromViewToScreenCoords(position, clipToParent);
getBoundsToScreenInternal(position, clipToParent);
outRect.set(Math.round(position.left), Math.round(position.top),
Math.round(position.right), Math.round(position.bottom));
}
/**
* Gets the location of this view in screen coordinates.
*
* @param outRect The output location
* @param clipToParent Whether to clip child bounds to the parent ones.
* @hide
*/
public void getBoundsOnScreen(RectF outRect, boolean clipToParent) {
if (mAttachInfo == null) {
return;
}
RectF position = mAttachInfo.mTmpTransformRect;
getBoundsToScreenInternal(position, clipToParent);
outRect.set(position.left, position.top, position.right, position.bottom);
}
private void getBoundsToScreenInternal(RectF position, boolean clipToParent) {
position.set(0, 0, mRight - mLeft, mBottom - mTop);
mapRectFromViewToScreenCoords(position, clipToParent);
}
/**
* Map a rectangle from view-relative coordinates to screen-relative coordinates
*

View File

@@ -104,6 +104,13 @@ public final class CursorAnchorInfo implements Parcelable {
*/
private final SparseRectFArray mCharacterBoundsArray;
/**
* Container of rectangular position of Editor in the local coordinates that will be transformed
* with the transformation matrix when rendered on the screen.
* @see {@link EditorBoundsInfo}.
*/
private final EditorBoundsInfo mEditorBoundsInfo;
/**
* Transformation matrix that is applied to any positional information of this class to
* transform local coordinates into screen coordinates.
@@ -141,6 +148,7 @@ public final class CursorAnchorInfo implements Parcelable {
mInsertionMarkerBaseline = source.readFloat();
mInsertionMarkerBottom = source.readFloat();
mCharacterBoundsArray = source.readParcelable(SparseRectFArray.class.getClassLoader());
mEditorBoundsInfo = source.readTypedObject(EditorBoundsInfo.CREATOR);
mMatrixValues = source.createFloatArray();
}
@@ -163,6 +171,7 @@ public final class CursorAnchorInfo implements Parcelable {
dest.writeFloat(mInsertionMarkerBaseline);
dest.writeFloat(mInsertionMarkerBottom);
dest.writeParcelable(mCharacterBoundsArray, flags);
dest.writeTypedObject(mEditorBoundsInfo, flags);
dest.writeFloatArray(mMatrixValues);
}
@@ -216,6 +225,10 @@ public final class CursorAnchorInfo implements Parcelable {
return false;
}
if (!Objects.equals(mEditorBoundsInfo, that.mEditorBoundsInfo)) {
return false;
}
// Following fields are (partially) covered by hashCode().
if (mComposingTextStart != that.mComposingTextStart
@@ -248,6 +261,7 @@ public final class CursorAnchorInfo implements Parcelable {
+ " mInsertionMarkerBaseline=" + mInsertionMarkerBaseline
+ " mInsertionMarkerBottom=" + mInsertionMarkerBottom
+ " mCharacterBoundsArray=" + Objects.toString(mCharacterBoundsArray)
+ " mEditorBoundsInfo=" + mEditorBoundsInfo
+ " mMatrix=" + Arrays.toString(mMatrixValues)
+ "}";
}
@@ -266,6 +280,7 @@ public final class CursorAnchorInfo implements Parcelable {
private float mInsertionMarkerBottom = Float.NaN;
private int mInsertionMarkerFlags = 0;
private SparseRectFArrayBuilder mCharacterBoundsArrayBuilder = null;
private EditorBoundsInfo mEditorBoundsInfo = null;
private float[] mMatrixValues = null;
private boolean mMatrixInitialized = false;
@@ -355,6 +370,17 @@ public final class CursorAnchorInfo implements Parcelable {
return this;
}
/**
* Sets the current editor related bounds.
*
* @param bounds {@link EditorBoundsInfo} in local coordinates.
*/
@NonNull
public Builder setEditorBoundsInfo(@Nullable EditorBoundsInfo bounds) {
mEditorBoundsInfo = bounds;
return this;
}
/**
* Sets the matrix that transforms local coordinates into screen coordinates.
* @param matrix transformation matrix from local coordinates into screen coordinates. null
@@ -410,6 +436,7 @@ public final class CursorAnchorInfo implements Parcelable {
if (mCharacterBoundsArrayBuilder != null) {
mCharacterBoundsArrayBuilder.reset();
}
mEditorBoundsInfo = null;
}
}
@@ -425,6 +452,7 @@ public final class CursorAnchorInfo implements Parcelable {
mInsertionMarkerBottom = builder.mInsertionMarkerBottom;
mCharacterBoundsArray = builder.mCharacterBoundsArrayBuilder != null
? builder.mCharacterBoundsArrayBuilder.build() : null;
mEditorBoundsInfo = builder.mEditorBoundsInfo;
mMatrixValues = new float[9];
if (builder.mMatrixInitialized) {
System.arraycopy(builder.mMatrixValues, 0, mMatrixValues, 0, 9);
@@ -546,6 +574,14 @@ public final class CursorAnchorInfo implements Parcelable {
return mCharacterBoundsArray.getFlags(index, 0);
}
/**
* Returns {@link EditorBoundsInfo} editor related bounds.
*/
@Nullable
public EditorBoundsInfo getEditorBoundsInfo() {
return mEditorBoundsInfo;
}
/**
* 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.

View File

@@ -0,0 +1,177 @@
/*
* 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.NonNull;
import android.annotation.Nullable;
import android.graphics.RectF;
import android.os.Parcel;
import android.os.Parcelable;
import java.util.Objects;
/**
* Container of rectangular position related info for the Editor.
*/
public final class EditorBoundsInfo implements Parcelable {
/**
* Container of rectangular position of Editor in the current window.
*/
private final RectF mEditorBounds;
/**
* Container of rectangular position of Editor with additional padding around for initiating
* Stylus Handwriting in the current window.
*/
private final RectF mHandwritingBounds;
private final int mHashCode;
private EditorBoundsInfo(@NonNull Parcel source) {
mHashCode = source.readInt();
mEditorBounds = source.readTypedObject(RectF.CREATOR);
mHandwritingBounds = source.readTypedObject(RectF.CREATOR);
}
/**
* Returns the bounds of the Editor in local coordinates.
*
* Screen coordinates can be obtained by transforming with the
* {@link CursorAnchorInfo#getMatrix} of the containing {@code CursorAnchorInfo}.
*/
@Nullable
public RectF getEditorBounds() {
return mEditorBounds;
}
/**
* Returns the bounds of the area that should be considered for initiating stylus handwriting
* in local coordinates.
*
* Screen coordinates can be obtained by transforming with the
* {@link CursorAnchorInfo#getMatrix} of the containing {@code CursorAnchorInfo}.
*/
@Nullable
public RectF getHandwritingBounds() {
return mHandwritingBounds;
}
@Override
public int hashCode() {
return mHashCode;
}
@Override
public String toString() {
return "EditorBoundsInfo{mEditorBounds=" + mEditorBounds
+ " mHandwritingBounds=" + mHandwritingBounds
+ "}";
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj == null) {
return false;
}
EditorBoundsInfo bounds;
if (obj instanceof EditorBoundsInfo) {
bounds = (EditorBoundsInfo) obj;
} else {
return false;
}
return Objects.equals(bounds.mEditorBounds, mEditorBounds)
&& Objects.equals(bounds.mHandwritingBounds, mHandwritingBounds);
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(mHashCode);
dest.writeTypedObject(mEditorBounds, flags);
dest.writeTypedObject(mHandwritingBounds, flags);
}
/**
* Used to make this class parcelable.
*/
public static final @android.annotation.NonNull Parcelable.Creator<EditorBoundsInfo> CREATOR
= new Parcelable.Creator<EditorBoundsInfo>() {
@Override
public EditorBoundsInfo createFromParcel(@NonNull Parcel source) {
return new EditorBoundsInfo(source);
}
@Override
public EditorBoundsInfo[] newArray(int size) {
return new EditorBoundsInfo[size];
}
};
/**
* Builder for {@link CursorAnchorInfo}.
*/
public static final class Builder {
private RectF mEditorBounds = null;
private RectF mHandwritingBounds = null;
/**
* Sets the bounding box of the current editor.
*
* @param bounds {@link RectF} in local coordinates.
*/
@NonNull
public EditorBoundsInfo.Builder setEditorBounds(@Nullable RectF bounds) {
mEditorBounds = bounds;
return this;
}
/**
* Sets the current editor's bounds with padding for handwriting.
*
* @param bounds {@link RectF} in local coordinates.
*/
@NonNull
public EditorBoundsInfo.Builder setHandwritingBounds(@Nullable RectF bounds) {
mHandwritingBounds = bounds;
return this;
}
/**
* Returns {@link EditorBoundsInfo} using parameters in this
* {@link EditorBoundsInfo.Builder}.
*/
@NonNull
public EditorBoundsInfo build() {
return new EditorBoundsInfo(this);
}
}
private EditorBoundsInfo(final EditorBoundsInfo.Builder builder) {
mEditorBounds = builder.mEditorBounds;
mHandwritingBounds = builder.mHandwritingBounds;
int hash = Objects.hashCode(mEditorBounds);
hash *= 31;
hash += Objects.hashCode(mHandwritingBounds);
mHashCode = hash;
}
}

View File

@@ -115,6 +115,7 @@ import android.view.accessibility.AccessibilityNodeInfo;
import android.view.animation.LinearInterpolator;
import android.view.inputmethod.CorrectionInfo;
import android.view.inputmethod.CursorAnchorInfo;
import android.view.inputmethod.EditorBoundsInfo;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.ExtractedText;
import android.view.inputmethod.ExtractedTextRequest;
@@ -4570,6 +4571,12 @@ public class Editor {
mTextView.getLocationOnScreen(mTmpIntOffset);
mViewToScreenMatrix.postTranslate(mTmpIntOffset[0], mTmpIntOffset[1]);
builder.setMatrix(mViewToScreenMatrix);
final RectF bounds = new RectF();
mTextView.getBoundsOnScreen(bounds, false /* clipToParent */);
EditorBoundsInfo.Builder boundsBuilder = new EditorBoundsInfo.Builder();
//TODO(b/210039666): add Handwriting bounds once they're available.
builder.setEditorBoundsInfo(
boundsBuilder.setEditorBounds(bounds).build());
final float viewportToContentHorizontalOffset =
mTextView.viewportToContentHorizontalOffset();