API for realtime Scribe gesture preview
Introduce new API to support gesture preview as user is operating over text. Bug: 254726230 Bug: 254727073 Test: InputConnectionEndToEndTest Change-Id: I6c2ac5a5aaeaeab78411d24870f573670304e898
This commit is contained in:
@@ -53398,7 +53398,7 @@ package android.view.inputmethod {
|
||||
method @NonNull public android.view.inputmethod.CursorAnchorInfo.Builder setTextAppearanceInfo(@Nullable android.view.inputmethod.TextAppearanceInfo);
|
||||
}
|
||||
|
||||
public final class DeleteGesture extends android.view.inputmethod.HandwritingGesture implements android.os.Parcelable {
|
||||
public final class DeleteGesture extends android.view.inputmethod.PreviewableHandwritingGesture implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method @NonNull public android.graphics.RectF getDeletionArea();
|
||||
method public int getGranularity();
|
||||
@@ -53414,7 +53414,7 @@ package android.view.inputmethod {
|
||||
method @NonNull public android.view.inputmethod.DeleteGesture.Builder setGranularity(int);
|
||||
}
|
||||
|
||||
public final class DeleteRangeGesture extends android.view.inputmethod.HandwritingGesture implements android.os.Parcelable {
|
||||
public final class DeleteRangeGesture extends android.view.inputmethod.PreviewableHandwritingGesture implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method @NonNull public android.graphics.RectF getDeletionEndArea();
|
||||
method @NonNull public android.graphics.RectF getDeletionStartArea();
|
||||
@@ -53456,11 +53456,13 @@ package android.view.inputmethod {
|
||||
method @Nullable public CharSequence getInitialTextAfterCursor(@IntRange(from=0) int, int);
|
||||
method @Nullable public CharSequence getInitialTextBeforeCursor(@IntRange(from=0) int, int);
|
||||
method public int getInitialToolType();
|
||||
method @NonNull public java.util.Set<java.lang.Class<? extends android.view.inputmethod.PreviewableHandwritingGesture>> getSupportedHandwritingGesturePreviews();
|
||||
method @NonNull public java.util.List<java.lang.Class<? extends android.view.inputmethod.HandwritingGesture>> getSupportedHandwritingGestures();
|
||||
method public final void makeCompatible(int);
|
||||
method public void setInitialSurroundingSubText(@NonNull CharSequence, int);
|
||||
method public void setInitialSurroundingText(@NonNull CharSequence);
|
||||
method public void setInitialToolType(int);
|
||||
method public void setSupportedHandwritingGesturePreviews(@NonNull java.util.Set<java.lang.Class<? extends android.view.inputmethod.PreviewableHandwritingGesture>>);
|
||||
method public void setSupportedHandwritingGestures(@NonNull java.util.List<java.lang.Class<? extends android.view.inputmethod.HandwritingGesture>>);
|
||||
method public void writeToParcel(android.os.Parcel, int);
|
||||
field @NonNull public static final android.os.Parcelable.Creator<android.view.inputmethod.EditorInfo> CREATOR;
|
||||
@@ -53635,6 +53637,7 @@ package android.view.inputmethod {
|
||||
method public default void performHandwritingGesture(@NonNull android.view.inputmethod.HandwritingGesture, @Nullable java.util.concurrent.Executor, @Nullable java.util.function.IntConsumer);
|
||||
method public boolean performPrivateCommand(String, android.os.Bundle);
|
||||
method public default boolean performSpellCheck();
|
||||
method public default boolean previewHandwritingGesture(@NonNull android.view.inputmethod.PreviewableHandwritingGesture, @Nullable android.os.CancellationSignal);
|
||||
method public default boolean replaceText(@IntRange(from=0) int, @IntRange(from=0) int, @NonNull CharSequence, int, @Nullable android.view.inputmethod.TextAttribute);
|
||||
method public boolean reportFullscreenMode(boolean);
|
||||
method public boolean requestCursorUpdates(int);
|
||||
@@ -53895,6 +53898,9 @@ package android.view.inputmethod {
|
||||
method @NonNull public android.view.inputmethod.JoinOrSplitGesture.Builder setJoinOrSplitPoint(@NonNull android.graphics.PointF);
|
||||
}
|
||||
|
||||
public abstract class PreviewableHandwritingGesture extends android.view.inputmethod.HandwritingGesture {
|
||||
}
|
||||
|
||||
public final class RemoveSpaceGesture extends android.view.inputmethod.HandwritingGesture implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method @NonNull public android.graphics.PointF getEndPoint();
|
||||
@@ -53910,7 +53916,7 @@ package android.view.inputmethod {
|
||||
method @NonNull public android.view.inputmethod.RemoveSpaceGesture.Builder setPoints(@NonNull android.graphics.PointF, @NonNull android.graphics.PointF);
|
||||
}
|
||||
|
||||
public final class SelectGesture extends android.view.inputmethod.HandwritingGesture implements android.os.Parcelable {
|
||||
public final class SelectGesture extends android.view.inputmethod.PreviewableHandwritingGesture implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method public int getGranularity();
|
||||
method @NonNull public android.graphics.RectF getSelectionArea();
|
||||
@@ -53926,7 +53932,7 @@ package android.view.inputmethod {
|
||||
method @NonNull public android.view.inputmethod.SelectGesture.Builder setSelectionArea(@NonNull android.graphics.RectF);
|
||||
}
|
||||
|
||||
public final class SelectRangeGesture extends android.view.inputmethod.HandwritingGesture implements android.os.Parcelable {
|
||||
public final class SelectRangeGesture extends android.view.inputmethod.PreviewableHandwritingGesture implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method public int getGranularity();
|
||||
method @NonNull public android.graphics.RectF getSelectionEndArea();
|
||||
|
||||
@@ -24,6 +24,7 @@ import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.graphics.RectF;
|
||||
import android.os.Bundle;
|
||||
import android.os.CancellationSignal;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ResultReceiver;
|
||||
import android.view.KeyEvent;
|
||||
@@ -696,6 +697,27 @@ final class IRemoteInputConnectionInvoker {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes one of {@link IRemoteInputConnection#previewHandwritingGesture(
|
||||
* InputConnectionCommandHeader, ParcelableHandwritingGesture, CancellationSignal)}
|
||||
*/
|
||||
@AnyThread
|
||||
public boolean previewHandwritingGesture(
|
||||
@NonNull ParcelableHandwritingGesture gesture,
|
||||
@Nullable CancellationSignal cancellationSignal) {
|
||||
if (cancellationSignal != null && cancellationSignal.isCanceled()) {
|
||||
return false; // cancelled.
|
||||
}
|
||||
|
||||
// TODO(b/254727073): Implement CancellationSignal
|
||||
try {
|
||||
mConnection.previewHandwritingGesture(createHeader(), gesture, null);
|
||||
return true;
|
||||
} catch (RemoteException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes {@link IRemoteInputConnection#requestCursorUpdates(InputConnectionCommandHeader, int,
|
||||
* int, AndroidFuture)}.
|
||||
|
||||
@@ -23,6 +23,7 @@ import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.graphics.RectF;
|
||||
import android.os.Bundle;
|
||||
import android.os.CancellationSignal;
|
||||
import android.os.Handler;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
@@ -34,6 +35,7 @@ import android.view.inputmethod.HandwritingGesture;
|
||||
import android.view.inputmethod.InputConnection;
|
||||
import android.view.inputmethod.InputContentInfo;
|
||||
import android.view.inputmethod.ParcelableHandwritingGesture;
|
||||
import android.view.inputmethod.PreviewableHandwritingGesture;
|
||||
import android.view.inputmethod.SurroundingText;
|
||||
import android.view.inputmethod.TextAttribute;
|
||||
import android.view.inputmethod.TextBoundsInfoResult;
|
||||
@@ -426,6 +428,14 @@ final class RemoteInputConnection implements InputConnection {
|
||||
consumer);
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
public boolean previewHandwritingGesture(
|
||||
@NonNull PreviewableHandwritingGesture gesture,
|
||||
@Nullable CancellationSignal cancellationSignal) {
|
||||
return mInvoker.previewHandwritingGesture(ParcelableHandwritingGesture.of(gesture),
|
||||
cancellationSignal);
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
public boolean requestCursorUpdates(int cursorUpdateMode) {
|
||||
if (mCancellationGroup.isCanceled()) {
|
||||
|
||||
@@ -33,7 +33,7 @@ import java.util.Objects;
|
||||
* <p>Note: This deletes all text <em>within</em> the given area. To delete a range <em>between</em>
|
||||
* two areas, use {@link DeleteRangeGesture}.</p>
|
||||
*/
|
||||
public final class DeleteGesture extends HandwritingGesture implements Parcelable {
|
||||
public final class DeleteGesture extends PreviewableHandwritingGesture implements Parcelable {
|
||||
|
||||
private @Granularity int mGranularity;
|
||||
private RectF mArea;
|
||||
|
||||
@@ -34,7 +34,7 @@ import java.util.Objects;
|
||||
* <p>Note: this deletes text within a range <em>between</em> two given areas. To delete all text
|
||||
* <em>within</em> a single area, use {@link DeleteGesture}.</p>
|
||||
*/
|
||||
public final class DeleteRangeGesture extends HandwritingGesture implements Parcelable {
|
||||
public final class DeleteRangeGesture extends PreviewableHandwritingGesture implements Parcelable {
|
||||
|
||||
private @Granularity int mGranularity;
|
||||
private RectF mStartArea;
|
||||
|
||||
@@ -55,8 +55,10 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* An EditorInfo describes several attributes of a text editing object
|
||||
@@ -534,6 +536,8 @@ public class EditorInfo implements InputType, Parcelable {
|
||||
|
||||
private @HandwritingGesture.GestureTypeFlags int mSupportedHandwritingGestureTypes;
|
||||
|
||||
private @HandwritingGesture.GestureTypeFlags int mSupportedHandwritingGesturePreviewTypes;
|
||||
|
||||
/**
|
||||
* Set the Handwriting gestures supported by the current {@code Editor}.
|
||||
* For an editor that supports Stylus Handwriting
|
||||
@@ -541,8 +545,11 @@ public class EditorInfo implements InputType, Parcelable {
|
||||
* supported gestures.
|
||||
* <p> If editor doesn't support one of the declared types, IME will not send those Gestures
|
||||
* to the editor. Instead they will fallback to using normal text input. </p>
|
||||
* <p>Note: A supported gesture may not have preview supported
|
||||
* {@link #getSupportedHandwritingGesturePreviews()}.</p>
|
||||
* @param gestures List of supported gesture classes including any of {@link SelectGesture},
|
||||
* {@link InsertGesture}, {@link DeleteGesture}.
|
||||
* @see #setSupportedHandwritingGesturePreviews(Set)
|
||||
*/
|
||||
public void setSupportedHandwritingGestures(
|
||||
@NonNull List<Class<? extends HandwritingGesture>> gestures) {
|
||||
@@ -584,6 +591,7 @@ public class EditorInfo implements InputType, Parcelable {
|
||||
* {@link InputMethodManager#startStylusHandwriting}, it also declares supported gestures.
|
||||
* @return List of supported gesture classes including any of {@link SelectGesture},
|
||||
* {@link InsertGesture}, {@link DeleteGesture}.
|
||||
* @see #getSupportedHandwritingGesturePreviews()
|
||||
*/
|
||||
@NonNull
|
||||
public List<Class<? extends HandwritingGesture>> getSupportedHandwritingGestures() {
|
||||
@@ -622,6 +630,86 @@ public class EditorInfo implements InputType, Parcelable {
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Handwriting gesture previews supported by the current {@code Editor}.
|
||||
* For an editor that supports Stylus Handwriting
|
||||
* {@link InputMethodManager#startStylusHandwriting}, it is also recommended that it declares
|
||||
* supported gesture previews.
|
||||
* <p>Note: A supported gesture {@link EditorInfo#getSupportedHandwritingGestures()} may not
|
||||
* have preview supported {@link EditorInfo#getSupportedHandwritingGesturePreviews()}.</p>
|
||||
* <p> If editor doesn't support one of the declared types, gesture preview will be ignored.</p>
|
||||
* @param gestures Set of supported gesture classes. One of {@link SelectGesture},
|
||||
* {@link SelectRangeGesture}, {@link DeleteGesture}, {@link DeleteRangeGesture}.
|
||||
* @see #setSupportedHandwritingGestures(List)
|
||||
*/
|
||||
public void setSupportedHandwritingGesturePreviews(
|
||||
@NonNull Set<Class<? extends PreviewableHandwritingGesture>> gestures) {
|
||||
Objects.requireNonNull(gestures);
|
||||
if (gestures.isEmpty()) {
|
||||
mSupportedHandwritingGesturePreviewTypes = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
int supportedTypes = 0;
|
||||
for (Class<? extends PreviewableHandwritingGesture> gesture : gestures) {
|
||||
Objects.requireNonNull(gesture);
|
||||
if (gesture.equals(SelectGesture.class)) {
|
||||
supportedTypes |= HandwritingGesture.GESTURE_TYPE_SELECT;
|
||||
} else if (gesture.equals(SelectRangeGesture.class)) {
|
||||
supportedTypes |= HandwritingGesture.GESTURE_TYPE_SELECT_RANGE;
|
||||
} else if (gesture.equals(DeleteGesture.class)) {
|
||||
supportedTypes |= HandwritingGesture.GESTURE_TYPE_DELETE;
|
||||
} else if (gesture.equals(DeleteRangeGesture.class)) {
|
||||
supportedTypes |= HandwritingGesture.GESTURE_TYPE_DELETE_RANGE;
|
||||
} else {
|
||||
throw new IllegalArgumentException(
|
||||
"Unsupported gesture type for preview: " + gesture);
|
||||
}
|
||||
}
|
||||
|
||||
mSupportedHandwritingGesturePreviewTypes = supportedTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the combination of Stylus handwriting gesture preview types
|
||||
* supported by the current {@code Editor}.
|
||||
* For an editor that supports Stylus Handwriting.
|
||||
* {@link InputMethodManager#startStylusHandwriting}, it also declares supported gesture
|
||||
* previews.
|
||||
* <p>Note: A supported gesture {@link EditorInfo#getSupportedHandwritingGestures()} may not
|
||||
* have preview supported {@link EditorInfo#getSupportedHandwritingGesturePreviews()}.</p>
|
||||
* @return Set of supported gesture preview classes. One of {@link SelectGesture},
|
||||
* {@link SelectRangeGesture}, {@link DeleteGesture}, {@link DeleteRangeGesture}.
|
||||
* @see #getSupportedHandwritingGestures()
|
||||
*/
|
||||
@NonNull
|
||||
public Set<Class<? extends PreviewableHandwritingGesture>>
|
||||
getSupportedHandwritingGesturePreviews() {
|
||||
Set<Class<? extends PreviewableHandwritingGesture>> set = new HashSet<>();
|
||||
if (mSupportedHandwritingGesturePreviewTypes == 0) {
|
||||
return set;
|
||||
}
|
||||
if ((mSupportedHandwritingGesturePreviewTypes & HandwritingGesture.GESTURE_TYPE_SELECT)
|
||||
== HandwritingGesture.GESTURE_TYPE_SELECT) {
|
||||
set.add(SelectGesture.class);
|
||||
}
|
||||
if ((mSupportedHandwritingGesturePreviewTypes
|
||||
& HandwritingGesture.GESTURE_TYPE_SELECT_RANGE)
|
||||
== HandwritingGesture.GESTURE_TYPE_SELECT_RANGE) {
|
||||
set.add(SelectRangeGesture.class);
|
||||
}
|
||||
if ((mSupportedHandwritingGesturePreviewTypes & HandwritingGesture.GESTURE_TYPE_DELETE)
|
||||
== HandwritingGesture.GESTURE_TYPE_DELETE) {
|
||||
set.add(DeleteGesture.class);
|
||||
}
|
||||
if ((mSupportedHandwritingGesturePreviewTypes
|
||||
& HandwritingGesture.GESTURE_TYPE_DELETE_RANGE)
|
||||
== HandwritingGesture.GESTURE_TYPE_DELETE_RANGE) {
|
||||
set.add(DeleteRangeGesture.class);
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
/**
|
||||
* If not {@code null}, this editor needs to talk to IMEs that run for the specified user, no
|
||||
* matter what user ID the calling process has.
|
||||
@@ -1114,6 +1202,9 @@ public class EditorInfo implements InputType, Parcelable {
|
||||
pw.println(prefix + "supportedHandwritingGestureTypes="
|
||||
+ InputMethodDebug.handwritingGestureTypeFlagsToString(
|
||||
mSupportedHandwritingGestureTypes));
|
||||
pw.println(prefix + "supportedHandwritingGesturePreviewTypes="
|
||||
+ InputMethodDebug.handwritingGestureTypeFlagsToString(
|
||||
mSupportedHandwritingGesturePreviewTypes));
|
||||
pw.println(prefix + "contentMimeTypes=" + Arrays.toString(contentMimeTypes));
|
||||
if (targetInputMethodUser != null) {
|
||||
pw.println(prefix + "targetInputMethodUserId=" + targetInputMethodUser.getIdentifier());
|
||||
@@ -1149,6 +1240,8 @@ public class EditorInfo implements InputType, Parcelable {
|
||||
newEditorInfo.contentMimeTypes = ArrayUtils.cloneOrNull(contentMimeTypes);
|
||||
newEditorInfo.targetInputMethodUser = targetInputMethodUser;
|
||||
newEditorInfo.mSupportedHandwritingGestureTypes = mSupportedHandwritingGestureTypes;
|
||||
newEditorInfo.mSupportedHandwritingGesturePreviewTypes =
|
||||
mSupportedHandwritingGesturePreviewTypes;
|
||||
return newEditorInfo;
|
||||
}
|
||||
|
||||
@@ -1177,6 +1270,7 @@ public class EditorInfo implements InputType, Parcelable {
|
||||
dest.writeString(fieldName);
|
||||
dest.writeBundle(extras);
|
||||
dest.writeInt(mSupportedHandwritingGestureTypes);
|
||||
dest.writeInt(mSupportedHandwritingGesturePreviewTypes);
|
||||
dest.writeBoolean(mInitialSurroundingText != null);
|
||||
if (mInitialSurroundingText != null) {
|
||||
mInitialSurroundingText.writeToParcel(dest, flags);
|
||||
@@ -1215,6 +1309,7 @@ public class EditorInfo implements InputType, Parcelable {
|
||||
res.fieldName = source.readString();
|
||||
res.extras = source.readBundle();
|
||||
res.mSupportedHandwritingGestureTypes = source.readInt();
|
||||
res.mSupportedHandwritingGesturePreviewTypes = source.readInt();
|
||||
boolean hasInitialSurroundingText = source.readBoolean();
|
||||
if (hasInitialSurroundingText) {
|
||||
res.mInitialSurroundingText =
|
||||
@@ -1258,6 +1353,8 @@ public class EditorInfo implements InputType, Parcelable {
|
||||
&& initialCapsMode == that.initialCapsMode
|
||||
&& fieldId == that.fieldId
|
||||
&& mSupportedHandwritingGestureTypes == that.mSupportedHandwritingGestureTypes
|
||||
&& mSupportedHandwritingGesturePreviewTypes
|
||||
== that.mSupportedHandwritingGesturePreviewTypes
|
||||
&& Objects.equals(autofillId, that.autofillId)
|
||||
&& Objects.equals(privateImeOptions, that.privateImeOptions)
|
||||
&& Objects.equals(packageName, that.packageName)
|
||||
|
||||
@@ -26,6 +26,7 @@ import android.annotation.Nullable;
|
||||
import android.graphics.RectF;
|
||||
import android.inputmethodservice.InputMethodService;
|
||||
import android.os.Bundle;
|
||||
import android.os.CancellationSignal;
|
||||
import android.os.Handler;
|
||||
import android.text.TextUtils;
|
||||
import android.view.KeyCharacterMap;
|
||||
@@ -1031,6 +1032,8 @@ public interface InputConnection {
|
||||
/**
|
||||
* Perform a handwriting gesture on text.
|
||||
*
|
||||
* <p>Note: A supported gesture {@link EditorInfo#getSupportedHandwritingGestures()} may not
|
||||
* have preview supported {@link EditorInfo#getSupportedHandwritingGesturePreviews()}.</p>
|
||||
* @param gesture the gesture to perform
|
||||
* @param executor The executor to run the callback on.
|
||||
* @param consumer if the caller passes a non-null consumer, the editor must invoke this
|
||||
@@ -1041,6 +1044,7 @@ public interface InputConnection {
|
||||
* completed. Will be invoked on the given {@link Executor}.
|
||||
* Default implementation provides a callback to {@link IntConsumer} with
|
||||
* {@link #HANDWRITING_GESTURE_RESULT_UNSUPPORTED}.
|
||||
* @see #previewHandwritingGesture(PreviewableHandwritingGesture, CancellationSignal)
|
||||
*/
|
||||
default void performHandwritingGesture(
|
||||
@NonNull HandwritingGesture gesture, @Nullable @CallbackExecutor Executor executor,
|
||||
@@ -1050,6 +1054,31 @@ public interface InputConnection {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Preview a handwriting gesture on text.
|
||||
* Provides a real-time preview for a gesture to user for an ongoing gesture. e.g. as user
|
||||
* begins to draw a circle around text, resulting selection {@link SelectGesture} is previewed
|
||||
* while stylus is moving over applicable text.
|
||||
*
|
||||
* <p>Note: A supported gesture {@link EditorInfo#getSupportedHandwritingGestures()} might not
|
||||
* have preview supported {@link EditorInfo#getSupportedHandwritingGesturePreviews()}.</p>
|
||||
* @param gesture the gesture to preview. Preview support for a gesture (regardless of whether
|
||||
* implemented by editor) can be determined if gesture subclasses
|
||||
* {@link PreviewableHandwritingGesture}. Supported previewable gestures include
|
||||
* {@link SelectGesture}, {@link SelectRangeGesture}, {@link DeleteGesture} and
|
||||
* {@link DeleteRangeGesture}.
|
||||
* @param cancellationSignal signal to cancel an ongoing preview.
|
||||
* @return true on successfully sending command to Editor, false if not implemented by editor or
|
||||
* the input connection is no longer valid or preview was cancelled with
|
||||
* {@link CancellationSignal}.
|
||||
* @see #performHandwritingGesture(HandwritingGesture, Executor, IntConsumer)
|
||||
*/
|
||||
default boolean previewHandwritingGesture(
|
||||
@NonNull PreviewableHandwritingGesture gesture,
|
||||
@Nullable CancellationSignal cancellationSignal) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* The editor is requested to call
|
||||
* {@link InputMethodManager#updateCursorAnchorInfo(android.view.View, CursorAnchorInfo)} at
|
||||
|
||||
@@ -22,6 +22,7 @@ import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.graphics.RectF;
|
||||
import android.os.Bundle;
|
||||
import android.os.CancellationSignal;
|
||||
import android.os.Handler;
|
||||
import android.view.KeyEvent;
|
||||
|
||||
@@ -335,6 +336,17 @@ public class InputConnectionWrapper implements InputConnection {
|
||||
mTarget.performHandwritingGesture(gesture, executor, consumer);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @throws NullPointerException if the target is {@code null}.
|
||||
*/
|
||||
@Override
|
||||
public boolean previewHandwritingGesture(
|
||||
@NonNull PreviewableHandwritingGesture gesture,
|
||||
@Nullable CancellationSignal cancellationSignal) {
|
||||
return mTarget.previewHandwritingGesture(gesture, cancellationSignal);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @throws NullPointerException if the target is {@code null}.
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.os.CancellationSignal;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A {@link HandwritingGesture} that can be
|
||||
* {@link InputConnection#previewHandwritingGesture(
|
||||
* PreviewableHandwritingGesture, CancellationSignal) previewed}.
|
||||
*
|
||||
* Note: An editor might only implement a subset of gesture previews and declares the supported
|
||||
* ones via {@link EditorInfo#getSupportedHandwritingGesturePreviews}.
|
||||
*
|
||||
* @see EditorInfo#setSupportedHandwritingGesturePreviews(Set)
|
||||
* @see EditorInfo#getSupportedHandwritingGesturePreviews()
|
||||
*/
|
||||
public abstract class PreviewableHandwritingGesture extends HandwritingGesture {
|
||||
PreviewableHandwritingGesture() {
|
||||
// intentionally empty.
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,9 @@ import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.graphics.RectF;
|
||||
import android.os.Bundle;
|
||||
import android.os.CancellationSignal;
|
||||
import android.os.Handler;
|
||||
import android.os.ICancellationSignal;
|
||||
import android.os.Looper;
|
||||
import android.os.ResultReceiver;
|
||||
import android.os.Trace;
|
||||
@@ -1015,6 +1017,34 @@ final class RemoteInputConnectionImpl extends IRemoteInputConnection.Stub {
|
||||
});
|
||||
}
|
||||
|
||||
@Dispatching(cancellable = true)
|
||||
@Override
|
||||
public void previewHandwritingGesture(
|
||||
InputConnectionCommandHeader header, ParcelableHandwritingGesture gestureContainer,
|
||||
ICancellationSignal transport) {
|
||||
|
||||
// TODO(b/254727073): Implement CancellationSignal receiver
|
||||
final CancellationSignal cancellationSignal = CancellationSignal.fromTransport(transport);
|
||||
// Previews always use PreviewableHandwritingGesture but if incorrectly wrong class is
|
||||
// passed, ClassCastException will be sent back to caller.
|
||||
final PreviewableHandwritingGesture gesture =
|
||||
(PreviewableHandwritingGesture) gestureContainer.get();
|
||||
|
||||
dispatchWithTracing("previewHandwritingGesture", () -> {
|
||||
if (header.mSessionId != mCurrentSessionId.get()
|
||||
|| (cancellationSignal != null && cancellationSignal.isCanceled())) {
|
||||
return; // cancelled
|
||||
}
|
||||
InputConnection ic = getInputConnection();
|
||||
if (ic == null || !isActive()) {
|
||||
Log.w(TAG, "previewHandwritingGesture on inactive InputConnection");
|
||||
return; // cancelled
|
||||
}
|
||||
|
||||
ic.previewHandwritingGesture(gesture, cancellationSignal);
|
||||
});
|
||||
}
|
||||
|
||||
@Dispatching(cancellable = true)
|
||||
@Override
|
||||
public void requestCursorUpdates(InputConnectionCommandHeader header, int cursorUpdateMode,
|
||||
|
||||
@@ -33,7 +33,7 @@ import java.util.Objects;
|
||||
* <p>Note: This selects all text <em>within</em> the given area. To select a range <em>between</em>
|
||||
* two areas, use {@link SelectRangeGesture}.</p>
|
||||
*/
|
||||
public final class SelectGesture extends HandwritingGesture implements Parcelable {
|
||||
public final class SelectGesture extends PreviewableHandwritingGesture implements Parcelable {
|
||||
|
||||
private @Granularity int mGranularity;
|
||||
private RectF mArea;
|
||||
@@ -72,7 +72,6 @@ public final class SelectGesture extends HandwritingGesture implements Parcelabl
|
||||
return mArea;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Builder for {@link SelectGesture}. This class is not designed to be thread-safe.
|
||||
*/
|
||||
|
||||
@@ -34,7 +34,7 @@ import java.util.Objects;
|
||||
* <p>Note: this selects text within a range <em>between</em> two given areas. To select all text
|
||||
* <em>within</em> a single area, use {@link SelectGesture}</p>
|
||||
*/
|
||||
public final class SelectRangeGesture extends HandwritingGesture implements Parcelable {
|
||||
public final class SelectRangeGesture extends PreviewableHandwritingGesture implements Parcelable {
|
||||
|
||||
private @Granularity int mGranularity;
|
||||
private RectF mStartArea;
|
||||
@@ -87,7 +87,6 @@ public final class SelectRangeGesture extends HandwritingGesture implements Parc
|
||||
return mEndArea;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Builder for {@link SelectRangeGesture}. This class is not designed to be thread-safe.
|
||||
*/
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.android.internal.inputmethod;
|
||||
|
||||
import android.graphics.RectF;
|
||||
import android.os.Bundle;
|
||||
import android.os.ICancellationSignal;
|
||||
import android.os.ResultReceiver;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.inputmethod.CompletionInfo;
|
||||
@@ -92,6 +93,9 @@ import com.android.internal.inputmethod.InputConnectionCommandHeader;
|
||||
void performHandwritingGesture(in InputConnectionCommandHeader header,
|
||||
in ParcelableHandwritingGesture gesture, in ResultReceiver resultReceiver);
|
||||
|
||||
void previewHandwritingGesture(in InputConnectionCommandHeader header,
|
||||
in ParcelableHandwritingGesture gesture, in ICancellationSignal transport);
|
||||
|
||||
void setComposingRegion(in InputConnectionCommandHeader header, int start, int end);
|
||||
|
||||
void setComposingRegionWithTextAttribute(in InputConnectionCommandHeader header, int start,
|
||||
|
||||
@@ -52,6 +52,8 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Supplemental tests that cannot be covered by CTS (e.g. due to hidden API dependencies).
|
||||
@@ -500,6 +502,7 @@ public class EditorInfoTest {
|
||||
+ "prefix: extras=null\n"
|
||||
+ "prefix: hintLocales=null\n"
|
||||
+ "prefix: supportedHandwritingGestureTypes=(none)\n"
|
||||
+ "prefix: supportedHandwritingGesturePreviewTypes=(none)\n"
|
||||
+ "prefix: contentMimeTypes=null\n");
|
||||
}
|
||||
|
||||
@@ -516,6 +519,8 @@ public class EditorInfoTest {
|
||||
info.label = "testLabel";
|
||||
info.setInitialToolType(MotionEvent.TOOL_TYPE_STYLUS);
|
||||
info.setSupportedHandwritingGestures(Arrays.asList(SelectGesture.class));
|
||||
info.setSupportedHandwritingGesturePreviews(
|
||||
Stream.of(SelectGesture.class).collect(Collectors.toSet()));
|
||||
info.packageName = "android.view.inputmethod";
|
||||
info.autofillId = new AutofillId(123);
|
||||
info.fieldId = 456;
|
||||
@@ -538,6 +543,7 @@ public class EditorInfoTest {
|
||||
+ "prefix2: extras=Bundle[{testKey=testValue}]\n"
|
||||
+ "prefix2: hintLocales=[en,es,zh]\n"
|
||||
+ "prefix2: supportedHandwritingGestureTypes=SELECT\n"
|
||||
+ "prefix2: supportedHandwritingGesturePreviewTypes=SELECT\n"
|
||||
+ "prefix2: contentMimeTypes=[image/png]\n"
|
||||
+ "prefix2: targetInputMethodUserId=10\n");
|
||||
}
|
||||
@@ -558,6 +564,7 @@ public class EditorInfoTest {
|
||||
+ "prefix: packageName=null autofillId=null fieldId=0 fieldName=null\n"
|
||||
+ "prefix: hintLocales=null\n"
|
||||
+ "prefix: supportedHandwritingGestureTypes=(none)\n"
|
||||
+ "prefix: supportedHandwritingGesturePreviewTypes=(none)\n"
|
||||
+ "prefix: contentMimeTypes=null\n");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user