Loading core/api/current.txt +2 −0 Original line number Diff line number Diff line Loading @@ -19291,6 +19291,7 @@ package android.hardware.input { method @Nullable public android.view.InputDevice getInputDevice(int); method public int[] getInputDeviceIds(); method @FloatRange(from=0, to=1) public float getMaximumObscuringOpacityForTouch(); method public boolean isStylusPointerIconEnabled(); method public void registerInputDeviceListener(android.hardware.input.InputManager.InputDeviceListener, android.os.Handler); method public void unregisterInputDeviceListener(android.hardware.input.InputManager.InputDeviceListener); method @Nullable public android.view.VerifiedInputEvent verifyInputEvent(@NonNull android.view.InputEvent); Loading Loading @@ -50812,6 +50813,7 @@ package android.view { field public static final int TYPE_GRAB = 1020; // 0x3fc field public static final int TYPE_GRABBING = 1021; // 0x3fd field public static final int TYPE_HAND = 1002; // 0x3ea field public static final int TYPE_HANDWRITING = 1022; // 0x3fe field public static final int TYPE_HELP = 1003; // 0x3eb field public static final int TYPE_HORIZONTAL_DOUBLE_ARROW = 1014; // 0x3f6 field public static final int TYPE_NO_DROP = 1012; // 0x3f4 core/java/android/hardware/input/InputManager.java +22 −1 Original line number Diff line number Diff line Loading @@ -102,6 +102,8 @@ public final class InputManager { @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) private final IInputManager mIm; private final boolean mIsStylusPointerIconEnabled; // Guarded by mInputDevicesLock private final Object mInputDevicesLock = new Object(); private SparseArray<InputDevice> mInputDevices; Loading Loading @@ -324,6 +326,15 @@ public final class InputManager { } catch (RemoteException ex) { Log.w(TAG, "Could not get VelocityTracker strategy: " + ex); } // TODO(b/266013036): Pass a Context into InputManager constructor. final Context context = ActivityThread.currentApplication(); if (context != null) { mIsStylusPointerIconEnabled = context.getResources() .getBoolean(com.android.internal.R.bool.config_enableStylusPointerIcon); } else { mIsStylusPointerIconEnabled = false; } } /** Loading Loading @@ -1382,7 +1393,7 @@ public final class InputManager { * Changes the mouse pointer's icon shape into the specified id. * * @param iconId The id of the pointer graphic, as a value between * {@link PointerIcon.TYPE_ARROW} and {@link PointerIcon.TYPE_GRABBING}. * {@link PointerIcon.TYPE_ARROW} and {@link PointerIcon.TYPE_HANDWRITING}. * * @hide */ Loading @@ -1404,6 +1415,16 @@ public final class InputManager { } } /** * Check if showing a {@link android.view.PointerIcon} for styluses is enabled. * * @return true if a pointer icon will be shown over the location of a * stylus pointer, false if there is no pointer icon shown for styluses. */ public boolean isStylusPointerIconEnabled() { return mIsStylusPointerIconEnabled; } /** * Request or release pointer capture. * <p> Loading core/java/android/view/HandwritingInitiator.java +53 −1 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package android.view; import android.annotation.IdRes; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.graphics.Rect; import android.view.inputmethod.InputMethodManager; Loading Loading @@ -77,6 +78,15 @@ public class HandwritingInitiator { private int mConnectionCount = 0; private final InputMethodManager mImm; /** * The handwrite-able View that is currently the target of a hovering stylus pointer. This is * used to help determine whether the handwriting PointerIcon should be shown in * {@link #onResolvePointerIcon(Context, MotionEvent)} so that we can reduce the number of calls * to {@link #findBestCandidateView(float, float)}. */ @Nullable private View mCachedHoverTarget = null; @VisibleForTesting public HandwritingInitiator(@NonNull ViewConfiguration viewConfiguration, @NonNull InputMethodManager inputMethodManager) { Loading Loading @@ -307,6 +317,48 @@ public class HandwritingInitiator { return view.isStylusHandwritingAvailable(); } /** * Returns the pointer icon for the motion event, or null if it doesn't specify the icon. * This gives HandwritingInitiator a chance to show the stylus handwriting icon over a * handwrite-able area. */ public PointerIcon onResolvePointerIcon(Context context, MotionEvent event) { if (shouldShowHandwritingPointerIcon(event)) { return PointerIcon.getSystemIcon(context, PointerIcon.TYPE_HANDWRITING); } return null; } private boolean shouldShowHandwritingPointerIcon(MotionEvent event) { if (!event.isStylusPointer() || !event.isHoverEvent()) { return false; } if (event.getActionMasked() == MotionEvent.ACTION_HOVER_ENTER || event.getActionMasked() == MotionEvent.ACTION_HOVER_MOVE) { final float hoverX = event.getX(event.getActionIndex()); final float hoverY = event.getY(event.getActionIndex()); if (mCachedHoverTarget != null) { final Rect handwritingArea = getViewHandwritingArea(mCachedHoverTarget); if (isInHandwritingArea(handwritingArea, hoverX, hoverY, mCachedHoverTarget) && shouldTriggerStylusHandwritingForView(mCachedHoverTarget)) { return true; } } final View candidateView = findBestCandidateView(hoverX, hoverY); if (candidateView != null) { mCachedHoverTarget = candidateView; return true; } } mCachedHoverTarget = null; return false; } /** * Given the location of the stylus event, return the best candidate view to initialize * handwriting mode. Loading Loading @@ -437,7 +489,7 @@ public class HandwritingInitiator { * Return true if the (x, y) is inside by the given {@link Rect} with the View's * handwriting bounds with offsets applied. */ private boolean isInHandwritingArea(@Nullable Rect handwritingArea, private static boolean isInHandwritingArea(@Nullable Rect handwritingArea, float x, float y, View view) { if (handwritingArea == null) return false; Loading core/java/android/view/MotionEvent.java +23 −0 Original line number Diff line number Diff line Loading @@ -2321,6 +2321,29 @@ public final class MotionEvent extends InputEvent implements Parcelable { return nativeIsTouchEvent(mNativePtr); } /** * Returns {@code true} if this motion event is from a stylus pointer. * @hide */ public boolean isStylusPointer() { final int actionIndex = getActionIndex(); return isFromSource(InputDevice.SOURCE_STYLUS) && (getToolType(actionIndex) == TOOL_TYPE_STYLUS || getToolType(actionIndex) == TOOL_TYPE_ERASER); } /** * Returns {@code true} if this motion event is a hover event, identified by it having an action * of either {@link #ACTION_HOVER_ENTER}, {@link #ACTION_HOVER_MOVE} or * {@link #ACTION_HOVER_EXIT}. * @hide */ public boolean isHoverEvent() { return getActionMasked() == ACTION_HOVER_ENTER || getActionMasked() == ACTION_HOVER_EXIT || getActionMasked() == ACTION_HOVER_MOVE; } /** * Gets the motion event flags. * Loading core/java/android/view/PointerIcon.java +5 −0 Original line number Diff line number Diff line Loading @@ -138,6 +138,9 @@ public final class PointerIcon implements Parcelable { /** Type constant: grabbing. */ public static final int TYPE_GRABBING = 1021; /** Type constant: handwriting. */ public static final int TYPE_HANDWRITING = 1022; // OEM private types should be defined starting at this range to avoid // conflicts with any system types that may be defined in the future. private static final int TYPE_OEM_FIRST = 10000; Loading Loading @@ -601,6 +604,8 @@ public final class PointerIcon implements Parcelable { return com.android.internal.R.styleable.Pointer_pointerIconGrab; case TYPE_GRABBING: return com.android.internal.R.styleable.Pointer_pointerIconGrabbing; case TYPE_HANDWRITING: return com.android.internal.R.styleable.Pointer_pointerIconHandwriting; default: return 0; } Loading Loading
core/api/current.txt +2 −0 Original line number Diff line number Diff line Loading @@ -19291,6 +19291,7 @@ package android.hardware.input { method @Nullable public android.view.InputDevice getInputDevice(int); method public int[] getInputDeviceIds(); method @FloatRange(from=0, to=1) public float getMaximumObscuringOpacityForTouch(); method public boolean isStylusPointerIconEnabled(); method public void registerInputDeviceListener(android.hardware.input.InputManager.InputDeviceListener, android.os.Handler); method public void unregisterInputDeviceListener(android.hardware.input.InputManager.InputDeviceListener); method @Nullable public android.view.VerifiedInputEvent verifyInputEvent(@NonNull android.view.InputEvent); Loading Loading @@ -50812,6 +50813,7 @@ package android.view { field public static final int TYPE_GRAB = 1020; // 0x3fc field public static final int TYPE_GRABBING = 1021; // 0x3fd field public static final int TYPE_HAND = 1002; // 0x3ea field public static final int TYPE_HANDWRITING = 1022; // 0x3fe field public static final int TYPE_HELP = 1003; // 0x3eb field public static final int TYPE_HORIZONTAL_DOUBLE_ARROW = 1014; // 0x3f6 field public static final int TYPE_NO_DROP = 1012; // 0x3f4
core/java/android/hardware/input/InputManager.java +22 −1 Original line number Diff line number Diff line Loading @@ -102,6 +102,8 @@ public final class InputManager { @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) private final IInputManager mIm; private final boolean mIsStylusPointerIconEnabled; // Guarded by mInputDevicesLock private final Object mInputDevicesLock = new Object(); private SparseArray<InputDevice> mInputDevices; Loading Loading @@ -324,6 +326,15 @@ public final class InputManager { } catch (RemoteException ex) { Log.w(TAG, "Could not get VelocityTracker strategy: " + ex); } // TODO(b/266013036): Pass a Context into InputManager constructor. final Context context = ActivityThread.currentApplication(); if (context != null) { mIsStylusPointerIconEnabled = context.getResources() .getBoolean(com.android.internal.R.bool.config_enableStylusPointerIcon); } else { mIsStylusPointerIconEnabled = false; } } /** Loading Loading @@ -1382,7 +1393,7 @@ public final class InputManager { * Changes the mouse pointer's icon shape into the specified id. * * @param iconId The id of the pointer graphic, as a value between * {@link PointerIcon.TYPE_ARROW} and {@link PointerIcon.TYPE_GRABBING}. * {@link PointerIcon.TYPE_ARROW} and {@link PointerIcon.TYPE_HANDWRITING}. * * @hide */ Loading @@ -1404,6 +1415,16 @@ public final class InputManager { } } /** * Check if showing a {@link android.view.PointerIcon} for styluses is enabled. * * @return true if a pointer icon will be shown over the location of a * stylus pointer, false if there is no pointer icon shown for styluses. */ public boolean isStylusPointerIconEnabled() { return mIsStylusPointerIconEnabled; } /** * Request or release pointer capture. * <p> Loading
core/java/android/view/HandwritingInitiator.java +53 −1 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package android.view; import android.annotation.IdRes; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.graphics.Rect; import android.view.inputmethod.InputMethodManager; Loading Loading @@ -77,6 +78,15 @@ public class HandwritingInitiator { private int mConnectionCount = 0; private final InputMethodManager mImm; /** * The handwrite-able View that is currently the target of a hovering stylus pointer. This is * used to help determine whether the handwriting PointerIcon should be shown in * {@link #onResolvePointerIcon(Context, MotionEvent)} so that we can reduce the number of calls * to {@link #findBestCandidateView(float, float)}. */ @Nullable private View mCachedHoverTarget = null; @VisibleForTesting public HandwritingInitiator(@NonNull ViewConfiguration viewConfiguration, @NonNull InputMethodManager inputMethodManager) { Loading Loading @@ -307,6 +317,48 @@ public class HandwritingInitiator { return view.isStylusHandwritingAvailable(); } /** * Returns the pointer icon for the motion event, or null if it doesn't specify the icon. * This gives HandwritingInitiator a chance to show the stylus handwriting icon over a * handwrite-able area. */ public PointerIcon onResolvePointerIcon(Context context, MotionEvent event) { if (shouldShowHandwritingPointerIcon(event)) { return PointerIcon.getSystemIcon(context, PointerIcon.TYPE_HANDWRITING); } return null; } private boolean shouldShowHandwritingPointerIcon(MotionEvent event) { if (!event.isStylusPointer() || !event.isHoverEvent()) { return false; } if (event.getActionMasked() == MotionEvent.ACTION_HOVER_ENTER || event.getActionMasked() == MotionEvent.ACTION_HOVER_MOVE) { final float hoverX = event.getX(event.getActionIndex()); final float hoverY = event.getY(event.getActionIndex()); if (mCachedHoverTarget != null) { final Rect handwritingArea = getViewHandwritingArea(mCachedHoverTarget); if (isInHandwritingArea(handwritingArea, hoverX, hoverY, mCachedHoverTarget) && shouldTriggerStylusHandwritingForView(mCachedHoverTarget)) { return true; } } final View candidateView = findBestCandidateView(hoverX, hoverY); if (candidateView != null) { mCachedHoverTarget = candidateView; return true; } } mCachedHoverTarget = null; return false; } /** * Given the location of the stylus event, return the best candidate view to initialize * handwriting mode. Loading Loading @@ -437,7 +489,7 @@ public class HandwritingInitiator { * Return true if the (x, y) is inside by the given {@link Rect} with the View's * handwriting bounds with offsets applied. */ private boolean isInHandwritingArea(@Nullable Rect handwritingArea, private static boolean isInHandwritingArea(@Nullable Rect handwritingArea, float x, float y, View view) { if (handwritingArea == null) return false; Loading
core/java/android/view/MotionEvent.java +23 −0 Original line number Diff line number Diff line Loading @@ -2321,6 +2321,29 @@ public final class MotionEvent extends InputEvent implements Parcelable { return nativeIsTouchEvent(mNativePtr); } /** * Returns {@code true} if this motion event is from a stylus pointer. * @hide */ public boolean isStylusPointer() { final int actionIndex = getActionIndex(); return isFromSource(InputDevice.SOURCE_STYLUS) && (getToolType(actionIndex) == TOOL_TYPE_STYLUS || getToolType(actionIndex) == TOOL_TYPE_ERASER); } /** * Returns {@code true} if this motion event is a hover event, identified by it having an action * of either {@link #ACTION_HOVER_ENTER}, {@link #ACTION_HOVER_MOVE} or * {@link #ACTION_HOVER_EXIT}. * @hide */ public boolean isHoverEvent() { return getActionMasked() == ACTION_HOVER_ENTER || getActionMasked() == ACTION_HOVER_EXIT || getActionMasked() == ACTION_HOVER_MOVE; } /** * Gets the motion event flags. * Loading
core/java/android/view/PointerIcon.java +5 −0 Original line number Diff line number Diff line Loading @@ -138,6 +138,9 @@ public final class PointerIcon implements Parcelable { /** Type constant: grabbing. */ public static final int TYPE_GRABBING = 1021; /** Type constant: handwriting. */ public static final int TYPE_HANDWRITING = 1022; // OEM private types should be defined starting at this range to avoid // conflicts with any system types that may be defined in the future. private static final int TYPE_OEM_FIRST = 10000; Loading Loading @@ -601,6 +604,8 @@ public final class PointerIcon implements Parcelable { return com.android.internal.R.styleable.Pointer_pointerIconGrab; case TYPE_GRABBING: return com.android.internal.R.styleable.Pointer_pointerIconGrabbing; case TYPE_HANDWRITING: return com.android.internal.R.styleable.Pointer_pointerIconHandwriting; default: return 0; } Loading