summaryrefslogtreecommitdiff
path: root/core/java/android/inputmethodservice/InputMethodService.java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android/inputmethodservice/InputMethodService.java')
-rw-r--r--core/java/android/inputmethodservice/InputMethodService.java133
1 files changed, 132 insertions, 1 deletions
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index afaa085c7cbd..588f7cdde555 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -94,6 +94,7 @@ import android.util.PrintWriterPrinter;
import android.util.Printer;
import android.util.proto.ProtoOutputStream;
import android.view.Gravity;
+import android.view.InputChannel;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.LayoutInflater;
@@ -119,6 +120,7 @@ import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputContentInfo;
import android.view.inputmethod.InputMethod;
import android.view.inputmethod.InputMethodEditorTraceProto.InputMethodServiceTraceProto;
+import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.InputMethodSubtype;
import android.widget.FrameLayout;
@@ -142,6 +144,7 @@ import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
+import java.util.List;
import java.util.Objects;
/**
@@ -520,10 +523,14 @@ public class InputMethodService extends AbstractInputMethodService {
private boolean mAutomotiveHideNavBarForKeyboard;
private boolean mIsAutomotive;
+ private boolean mHandwritingStarted;
private Handler mHandler;
private boolean mImeSurfaceScheduledForRemoval;
private ImsConfigurationTracker mConfigTracker = new ImsConfigurationTracker();
+ /** Stylus handwriting Ink window. */
+ private InkWindow mInkWindow;
+
/**
* An opaque {@link Binder} token of window requesting {@link InputMethodImpl#showSoftInput}
* The original app window token is passed from client app window.
@@ -598,11 +605,15 @@ public class InputMethodService extends AbstractInputMethodService {
@MainThread
@Override
public final void initializeInternal(@NonNull IBinder token,
- IInputMethodPrivilegedOperations privilegedOperations, int configChanges) {
+ IInputMethodPrivilegedOperations privilegedOperations, int configChanges,
+ boolean stylusHwSupported) {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMS.initializeInternal");
mConfigTracker.onInitialize(configChanges);
mPrivOps.set(privilegedOperations);
InputMethodPrivilegedOperationsRegistry.put(token, mPrivOps);
+ if (stylusHwSupported) {
+ mInkWindow = new InkWindow(mWindow.getContext());
+ }
attachToken(token);
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
@@ -635,6 +646,9 @@ public class InputMethodService extends AbstractInputMethodService {
attachToWindowToken(token);
mToken = token;
mWindow.setToken(token);
+ if (mInkWindow != null) {
+ mInkWindow.setToken(token);
+ }
}
/**
@@ -818,6 +832,49 @@ public class InputMethodService extends AbstractInputMethodService {
/**
* {@inheritDoc}
+ * @hide
+ */
+ @Override
+ public void canStartStylusHandwriting(int requestId) {
+ if (DEBUG) Log.v(TAG, "canStartStylusHandwriting()");
+ if (mHandwritingStarted) {
+ Log.d(TAG, "There is an ongoing Handwriting session. ignoring.");
+ return;
+ }
+ if (!mInputStarted) {
+ Log.d(TAG, "Input should have started before starting Stylus handwriting.");
+ return;
+ }
+ if (onStartStylusHandwriting()) {
+ mPrivOps.onStylusHandwritingReady(requestId);
+ } else {
+ Log.i(TAG, "IME is not ready. Can't start Stylus Handwriting");
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ * @hide
+ */
+ @MainThread
+ @Override
+ public void startStylusHandwriting(
+ @NonNull InputChannel channel, @Nullable List<MotionEvent> stylusEvents) {
+ if (DEBUG) Log.v(TAG, "startStylusHandwriting()");
+ if (mHandwritingStarted) {
+ return;
+ }
+
+ mHandwritingStarted = true;
+ mShowInputRequested = false;
+
+ mInkWindow.show();
+ // TODO: deliver previous @param stylusEvents
+ // TODO: create spy receiver for @param channel
+ }
+
+ /**
+ * {@inheritDoc}
*/
@MainThread
@Override
@@ -2182,6 +2239,77 @@ public class InputMethodService extends AbstractInputMethodService {
}
/**
+ * Called when an app requests stylus handwriting
+ * {@link InputMethodManager#startStylusHandwriting(View)}.
+ *
+ * This will always be preceded by {@link #onStartInput(EditorInfo, boolean)} for the
+ * {@link EditorInfo} and {@link InputConnection} for which stylus handwriting is being
+ * requested.
+ *
+ * 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()}.
+ * @return {@code true} if IME can honor the request, {@code false} if IME cannot at this time.
+ */
+ public boolean onStartStylusHandwriting() {
+ // Intentionally empty
+ return false;
+ }
+
+ /**
+ * Called when the current stylus handwriting session was finished (either by the system or
+ * via {@link #finishStylusHandwriting()}.
+ *
+ * When this is called, the ink window has been made invisible, and the IME no longer
+ * intercepts handwriting-related {@code MotionEvent}s.
+ */
+ public void onFinishStylusHandwriting() {
+ // Intentionally empty
+ }
+
+ /**
+ * Returns the stylus handwriting inking window.
+ * IMEs supporting stylus input are expected to attach their inking views to this
+ * window (e.g. with {@link Window#setContentView(View)} )). Handwriting-related
+ * {@link MotionEvent}s are dispatched to the attached view hierarchy.
+ *
+ * Note: This returns {@code null} if IME doesn't support stylus handwriting
+ * i.e. if {@link InputMethodInfo#supportsStylusHandwriting()} is false.
+ * This method should be called after {@link #onStartStylusHandwriting()}.
+ * @see #onStartStylusHandwriting()
+ */
+ @Nullable
+ public final Window getStylusHandwritingWindow() {
+ return mInkWindow;
+ }
+
+ /**
+ * Finish the current stylus handwriting session.
+ *
+ * This dismisses the {@link #getStylusHandwritingWindow ink window} and stops intercepting
+ * stylus {@code MotionEvent}s.
+ *
+ * Note for IME developers: Call this method at any time to finish current handwriting session.
+ * Generally, this should be invoked after a short timeout, giving the user enough time
+ * to start the next stylus stroke, if any.
+ *
+ * Handwriting session will be finished by framework on next {@link #onFinishInput()}.
+ */
+ public final void finishStylusHandwriting() {
+ if (DEBUG) Log.v(TAG, "finishStylusHandwriting()");
+ if (mInkWindow == null) {
+ return;
+ }
+ if (!mHandwritingStarted) {
+ return;
+ }
+
+ mHandwritingStarted = false;
+ mInkWindow.hide(false /* remove */);
+ onFinishStylusHandwriting();
+ }
+
+ /**
* The system has decided that it may be time to show your input method.
* This is called due to a corresponding call to your
* {@link InputMethod#showSoftInput InputMethod.showSoftInput()}
@@ -2450,6 +2578,9 @@ public class InputMethodService extends AbstractInputMethodService {
mInputStarted = false;
mStartedInputConnection = null;
mCurCompletions = null;
+ if (mInkWindow != null) {
+ finishStylusHandwriting();
+ }
}
void doStartInput(InputConnection ic, EditorInfo attribute, boolean restarting) {