From 08a94de0dea5e7fb94042acad29f51ddd05bb9d3 Mon Sep 17 00:00:00 2001 From: Justin Ghan Date: Wed, 27 Apr 2022 16:24:10 -0700 Subject: [PATCH] Scribe: Find candidate view in stylus down event In the initial implementation, HandwritingInitiator looks for a handwriting candidate view when a stylus motion has exceeded the touch slop distance. This updates the implementation to look for the handwriting candidate view in the stylus down event. The overall resulting behaviour is unchanged. This is needed for an upcoming change to stop dispatching MotionEvents to the view tree if they are for a stylus movement on a handwriting candidate view, in order to prevent scrolling before handwriting is initiated. Bug: 228210945 Test: atest CtsInputMethodTestCases:android.view.inputmethod.cts.StylusHandwritingTest Change-Id: I395c2ec4b16a3fd3cb56308da872ec959e93943e --- .../android/view/HandwritingInitiator.java | 37 ++++++++++--------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/core/java/android/view/HandwritingInitiator.java b/core/java/android/view/HandwritingInitiator.java index 3247bb7c6d389..270b479a55ed7 100644 --- a/core/java/android/view/HandwritingInitiator.java +++ b/core/java/android/view/HandwritingInitiator.java @@ -68,19 +68,9 @@ public class HandwritingInitiator { */ private final long mHandwritingTimeoutInMillis; - private State mState = new State(); + private final State mState = new State(); private final HandwritingAreaTracker mHandwritingAreasTracker = new HandwritingAreaTracker(); - /** - * Helper method to reset the internal state of this class. - * Calling this method will also prevent the following MotionEvents - * triggers handwriting until the next stylus ACTION_DOWN/ACTION_POINTER_DOWN - * arrives. - */ - private void reset() { - mState = new State(); - } - /** The reference to the View that currently has the input connection. */ @Nullable @VisibleForTesting @@ -132,6 +122,8 @@ public class HandwritingInitiator { mState.mStylusDownTimeInMillis = motionEvent.getEventTime(); mState.mStylusDownX = motionEvent.getX(actionIndex); mState.mStylusDownY = motionEvent.getY(actionIndex); + mState.mStylusDownCandidateView = new WeakReference<>( + findBestCandidateView(mState.mStylusDownX, mState.mStylusDownY)); mState.mShouldInitHandwriting = true; mState.mExceedTouchSlop = false; break; @@ -146,7 +138,7 @@ public class HandwritingInitiator { case MotionEvent.ACTION_UP: // If it's ACTION_CANCEL or ACTION_UP, all the pointers go up. There is no need to // check whether the stylus we are tracking goes up. - reset(); + mState.mShouldInitHandwriting = false; break; case MotionEvent.ACTION_MOVE: // Either we've already tried to initiate handwriting, or the ongoing MotionEvent @@ -158,7 +150,7 @@ public class HandwritingInitiator { final long timeElapsed = motionEvent.getEventTime() - mState.mStylusDownTimeInMillis; if (timeElapsed > mHandwritingTimeoutInMillis) { - reset(); + mState.mShouldInitHandwriting = false; return; } @@ -167,8 +159,13 @@ public class HandwritingInitiator { final float y = motionEvent.getY(pointerIndex); if (largerThanTouchSlop(x, y, mState.mStylusDownX, mState.mStylusDownY)) { mState.mExceedTouchSlop = true; - View candidateView = - findBestCandidateView(mState.mStylusDownX, mState.mStylusDownY); + View candidateView = mState.mStylusDownCandidateView.get(); + if (candidateView == null || !candidateView.isAttachedToWindow()) { + // If there was no candidate view found in the stylus down event, or if that + // candidate view is no longer attached, search again for a candidate view. + candidateView = findBestCandidateView(mState.mStylusDownX, + mState.mStylusDownY); + } if (candidateView != null) { if (candidateView == getConnectedView()) { startHandwriting(candidateView); @@ -266,7 +263,7 @@ public class HandwritingInitiator { mState.mStylusDownX, mState.mStylusDownY)) { startHandwriting(connectedView); } else { - reset(); + mState.mShouldInitHandwriting = false; } } @@ -274,7 +271,7 @@ public class HandwritingInitiator { @VisibleForTesting public void startHandwriting(@NonNull View view) { mImm.startStylusHandwriting(view); - reset(); + mState.mShouldInitHandwriting = false; } /** @@ -464,6 +461,12 @@ public class HandwritingInitiator { /** The initial location where the stylus pointer goes down. */ private float mStylusDownX = Float.NaN; private float mStylusDownY = Float.NaN; + /** + * The best candidate view to initialize handwriting mode based on the initial location + * where the stylus pointer goes down, or null if the location was not within any candidate + * view's handwriting area. + */ + private WeakReference mStylusDownCandidateView = new WeakReference<>(null); } /** The helper method to check if the given view is still active for handwriting. */