Polish new IME API for L part 2: CursorAnchorInfo
This CL addresses feedbacks from internal customers for new
input method APIs that are mainly used for physical keyboard
support in L.
For performance reasons, #onUpdateCursorAnchorInfo is not called
back by default and each input method has to enable this
event notification explicitly whenever fine-grained character
locations are needed.
In L-preview, InputMethodSession#setCursorAnchorMonitorMode was
introduced for this purpose. However, we got several feedbacks
to be addressed.
- The effect of #setCursorAnchorMonitorMode is not preserved
during focus change. IMEs need to call
#setCursorAnchorMonitorMode every time when #onStartInput is
called. This is tricky and hard to understand.
- As #onUpdateCursorAnchorInfo is a new API, not all
applications/text editors have supported it. Therefore IMEs
can't always rely on it. However, there is no way to query
if the attached target is supporting this new API or not.
It would helpful for IME authors if we can provide a
reliable way to query if the attached input target is
supporting the new API or not.
In order to address these issues, the triggering method has
moved from InputMethodSession to InputConnection in this CL,
as an analogy of existing InputConnection#getExtractedText API,
which has provided similar functionality including optional
reactive event callbacks from the application to the IME.
BUG: 15812658
BUG: 16118603
Change-Id: I3c6b69bd9d79b199afe68d838f25effa6048e5cc
diff --git a/core/java/com/android/internal/view/IInputConnectionWrapper.java b/core/java/com/android/internal/view/IInputConnectionWrapper.java
index c792d78..897381d 100644
--- a/core/java/com/android/internal/view/IInputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/IInputConnectionWrapper.java
@@ -25,6 +25,7 @@
import android.view.KeyEvent;
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.CorrectionInfo;
+import android.view.inputmethod.CursorAnchorInfoRequest;
import android.view.inputmethod.ExtractedTextRequest;
import android.view.inputmethod.InputConnection;
@@ -54,6 +55,7 @@
private static final int DO_REPORT_FULLSCREEN_MODE = 100;
private static final int DO_PERFORM_PRIVATE_COMMAND = 120;
private static final int DO_CLEAR_META_KEY_STATES = 130;
+ private static final int DO_REQUEST_CURSOR_ANCHOR_INFO = 140;
private WeakReference<InputConnection> mInputConnection;
@@ -175,6 +177,11 @@
dispatchMessage(obtainMessageOO(DO_PERFORM_PRIVATE_COMMAND, action, data));
}
+ public void requestCursorAnchorInfo(CursorAnchorInfoRequest request, int seq,
+ IInputContextCallback callback) {
+ dispatchMessage(obtainMessageOSC(DO_REQUEST_CURSOR_ANCHOR_INFO, request, seq, callback));
+ }
+
void dispatchMessage(Message msg) {
// If we are calling this from the main thread, then we can call
// right through. Otherwise, we need to send the message to the
@@ -420,6 +427,23 @@
(Bundle)args.arg2);
return;
}
+ case DO_REQUEST_CURSOR_ANCHOR_INFO: {
+ SomeArgs args = (SomeArgs)msg.obj;
+ try {
+ InputConnection ic = mInputConnection.get();
+ if (ic == null || !isActive()) {
+ Log.w(TAG, "requestCursorAnchorInfo on inactive InputConnection");
+ args.callback.setRequestCursorAnchorInfoResult(0, args.seq);
+ return;
+ }
+ args.callback.setRequestCursorAnchorInfoResult(
+ ic.requestCursorAnchorInfo((CursorAnchorInfoRequest)args.arg1),
+ args.seq);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Got RemoteException calling requestCursorAnchorInfo", e);
+ }
+ return;
+ }
}
Log.w(TAG, "Unhandled message code: " + msg.what);
}
@@ -449,7 +473,15 @@
args.seq = seq;
return mH.obtainMessage(what, arg1, arg2, args);
}
-
+
+ Message obtainMessageOSC(int what, Object arg1, int seq, IInputContextCallback callback) {
+ SomeArgs args = new SomeArgs();
+ args.arg1 = arg1;
+ args.callback = callback;
+ args.seq = seq;
+ return mH.obtainMessage(what, 0, 0, args);
+ }
+
Message obtainMessageIOSC(int what, int arg1, Object arg2, int seq,
IInputContextCallback callback) {
SomeArgs args = new SomeArgs();