summaryrefslogtreecommitdiff
path: root/core/java/android/inputmethodservice/InputMethodService.java
diff options
context:
space:
mode:
authorTaran Singh <tarandeep@google.com>2022-03-02 10:43:55 +0000
committerTaran Singh <tarandeep@google.com>2022-03-09 18:35:21 +0000
commit467fd168d5480e8c93b4f947fc9ce3216f887b2e (patch)
tree4f97a6dabd1f044896d7ca2cb257e6cb16e27a55 /core/java/android/inputmethodservice/InputMethodService.java
parente2722fe948b428ccc4679ce9466618a773225ebb (diff)
Introduce new IMS method for Stylus events and dispatch
As of today we show the InkWindow and dispatch Stylus events without waiting. At the time of dispatch, InkWindow is not added and first stylus gesture is skipped. In order to deliver the first gesture to IME, we should wait until InkWindow is added and IME's Inking View is attached. However, waiting for it will introduce latency in the system. To counter that, we introduce a new API method to listen for Stylus MotionEvent. IME can override the API method to listen to MotionEvents sooner. By default, the stylus MotionEvents are buffered until Ink view is visible. Change-Id: I3a18067da45fd15bf0f6e377da0a82cdd6df1d41 Fix: 222081673 Test: atest StylusHandwriting
Diffstat (limited to 'core/java/android/inputmethodservice/InputMethodService.java')
-rw-r--r--core/java/android/inputmethodservice/InputMethodService.java49
1 files changed, 45 insertions, 4 deletions
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index fbc0732affe1..4970d445b34d 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -142,6 +142,7 @@ import com.android.internal.inputmethod.IInputMethodPrivilegedOperations;
import com.android.internal.inputmethod.ImeTracing;
import com.android.internal.inputmethod.InputMethodPrivilegedOperations;
import com.android.internal.inputmethod.InputMethodPrivilegedOperationsRegistry;
+import com.android.internal.util.RingBuffer;
import com.android.internal.view.IInlineSuggestionsRequestCallback;
import com.android.internal.view.IInputContext;
import com.android.internal.view.InlineSuggestionsRequestInfo;
@@ -333,6 +334,17 @@ public class InputMethodService extends AbstractInputMethodService {
"persist.sys.ime.can_render_gestural_nav_buttons";
/**
+ * Number of {@link MotionEvent} to buffer if IME is not ready with Ink view.
+ * This number may be configured eventually based on device's touch sampling frequency.
+ */
+ private static final int MAX_EVENTS_BUFFER = 500;
+
+ /**
+ * A circular buffer of size MAX_EVENTS_BUFFER in case IME is taking too long to add ink view.
+ **/
+ private RingBuffer<MotionEvent> mPendingEvents;
+
+ /**
* Returns whether {@link InputMethodService} is responsible for rendering the back button and
* the IME switcher button or not when the gestural navigation is enabled.
*
@@ -957,7 +969,8 @@ public class InputMethodService extends AbstractInputMethodService {
mInkWindow.show();
// deliver previous @param stylusEvents
- stylusEvents.forEach(mInkWindow.getDecorView()::dispatchTouchEvent);
+ stylusEvents.forEach(InputMethodService.this::onStylusHandwritingMotionEvent);
+
// create receiver for channel
mHandwritingEventReceiver = new SimpleBatchedInputEventReceiver(
channel,
@@ -966,11 +979,11 @@ public class InputMethodService extends AbstractInputMethodService {
if (!(event instanceof MotionEvent)) {
return false;
}
- return mInkWindow.getDecorView().dispatchTouchEvent((MotionEvent) event);
+ onStylusHandwritingMotionEvent((MotionEvent) event);
+ return true;
});
}
-
/**
* {@inheritDoc}
* @hide
@@ -2360,7 +2373,8 @@ public class InputMethodService extends AbstractInputMethodService {
*
* If the IME supports handwriting for the current input, it should return {@code true},
* ensure its inking views are attached to the {@link #getStylusHandwritingWindow()}, and handle
- * stylus input received on the ink window via {@link #getCurrentInputConnection()}.
+ * stylus input received from {@link #onStylusHandwritingMotionEvent(MotionEvent)} on the
+ * {@link #getStylusHandwritingWindow()} via {@link #getCurrentInputConnection()}.
* @return {@code true} if IME can honor the request, {@code false} if IME cannot at this time.
*/
public boolean onStartStylusHandwriting() {
@@ -2369,6 +2383,33 @@ public class InputMethodService extends AbstractInputMethodService {
}
/**
+ * Called after {@link #onStartStylusHandwriting()} returns {@code true} for every Stylus
+ * {@link MotionEvent}.
+ * By default, this method forwards all {@link MotionEvent}s to the
+ * {@link #getStylusHandwritingWindow()} once its visible, however IME can override it to
+ * receive them sooner.
+ * @param motionEvent {@link MotionEvent} from stylus.
+ */
+ public void onStylusHandwritingMotionEvent(@NonNull MotionEvent motionEvent) {
+ if (mInkWindow.isInkViewVisible()) {
+ mInkWindow.getDecorView().dispatchTouchEvent(motionEvent);
+ } else {
+ if (mPendingEvents == null) {
+ mPendingEvents = new RingBuffer(MotionEvent.class, MAX_EVENTS_BUFFER);
+ }
+ mPendingEvents.append(motionEvent);
+ mInkWindow.setInkViewVisibilityListener(() -> {
+ if (mPendingEvents != null && !mPendingEvents.isEmpty()) {
+ for (MotionEvent event : mPendingEvents.toArray()) {
+ mInkWindow.getDecorView().dispatchTouchEvent(event);
+ }
+ mPendingEvents.clear();
+ }
+ });
+ }
+ }
+
+ /**
* Called when the current stylus handwriting session was finished (either by the system or
* via {@link #finishStylusHandwriting()}.
*