summaryrefslogtreecommitdiffstats
path: root/core/java/android
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/inputmethodservice/InputMethodService.java25
-rw-r--r--core/java/android/view/inputmethod/BaseInputConnection.java15
-rw-r--r--core/java/android/view/inputmethod/CursorAnchorInfoRequest.aidl19
-rw-r--r--core/java/android/view/inputmethod/CursorAnchorInfoRequest.java203
-rw-r--r--core/java/android/view/inputmethod/InputConnection.java11
-rw-r--r--core/java/android/view/inputmethod/InputConnectionWrapper.java6
-rw-r--r--core/java/android/view/inputmethod/InputMethodManager.java140
-rw-r--r--core/java/android/widget/AbsListView.java6
-rw-r--r--core/java/android/widget/Editor.java5
9 files changed, 359 insertions, 71 deletions
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 3417de1..8423d09 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -53,6 +53,7 @@ import android.view.WindowManager.BadTokenException;
import android.view.animation.AnimationUtils;
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.CursorAnchorInfo;
+import android.view.inputmethod.CursorAnchorInfoRequest;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.ExtractedText;
import android.view.inputmethod.ExtractedTextRequest;
@@ -251,18 +252,6 @@ public class InputMethodService extends AbstractInputMethodService {
*/
public static final int IME_VISIBLE = 0x2;
- /**
- * The IME does not require cursor/anchor position.
- */
- public static final int CURSOR_ANCHOR_MONITOR_MODE_NONE = 0x0;
-
- /**
- * Passing this flag into a call to {@link #setCursorAnchorMonitorMode(int)} will result in
- * the cursor rectangle being provided in screen coordinates to subsequent
- * {@link #onUpdateCursor(Rect)} callbacks.
- */
- public static final int CURSOR_ANCHOR_MONITOR_MODE_CURSOR_RECT = 0x1;
-
InputMethodManager mImm;
int mTheme = 0;
@@ -1722,8 +1711,9 @@ public class InputMethodService extends AbstractInputMethodService {
* Called when the application has reported a new location of its text cursor. This is only
* called if explicitly requested by the input method. The default implementation does nothing.
* @param newCursor The new cursor position, in screen coordinates if the input method calls
- * {@link #setCursorAnchorMonitorMode} with {@link #CURSOR_ANCHOR_MONITOR_MODE_CURSOR_RECT}.
- * Otherwise, this is in local coordinates.
+ * {@link InputConnection#requestCursorAnchorInfo(CursorAnchorInfoRequest)} with
+ * {@link CursorAnchorInfoRequest#FLAG_CURSOR_RECT_IN_SCREEN_COORDINATES}. Otherwise,
+ * this is in local coordinates.
*/
public void onUpdateCursor(Rect newCursor) {
// Intentionally empty
@@ -1741,13 +1731,6 @@ public class InputMethodService extends AbstractInputMethodService {
}
/**
- * Update the cursor/anthor monitor mode.
- */
- public void setCursorAnchorMonitorMode(int monitorMode) {
- mImm.setCursorAnchorMonitorMode(mToken, monitorMode);
- }
-
- /**
* Close this input method's soft input area, removing it from the display.
* The input method will continue running, but the user can no longer use
* it to generate input by touching the screen.
diff --git a/core/java/android/view/inputmethod/BaseInputConnection.java b/core/java/android/view/inputmethod/BaseInputConnection.java
index e1f40b7..338f3d2 100644
--- a/core/java/android/view/inputmethod/BaseInputConnection.java
+++ b/core/java/android/view/inputmethod/BaseInputConnection.java
@@ -429,6 +429,21 @@ public class BaseInputConnection implements InputConnection {
}
/**
+ * The default implementation is responsible for handling
+ * {@link CursorAnchorInfoRequest#TYPE_CURSOR_RECT}. In fact, for derived classes, calling
+ * {@code super.requestCursorAnchorInfo(request)} is the only way to handle
+ * {@link CursorAnchorInfoRequest#TYPE_CURSOR_RECT}.
+ */
+ public int requestCursorAnchorInfo(CursorAnchorInfoRequest request) {
+ if (request != null && mIMM != null &&
+ request.getRequestType() == CursorAnchorInfoRequest.TYPE_CURSOR_RECT) {
+ mIMM.setCursorRectMonitorMode(request.getRequestFlags());
+ return CursorAnchorInfoRequest.RESULT_SCHEDULED;
+ }
+ return CursorAnchorInfoRequest.RESULT_NOT_HANDLED;
+ }
+
+ /**
* The default implementation places the given text into the editable,
* replacing any existing composing text. The new text is marked as
* in a composing state with the composing style.
diff --git a/core/java/android/view/inputmethod/CursorAnchorInfoRequest.aidl b/core/java/android/view/inputmethod/CursorAnchorInfoRequest.aidl
new file mode 100644
index 0000000..41ef7cc6
--- /dev/null
+++ b/core/java/android/view/inputmethod/CursorAnchorInfoRequest.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.inputmethod;
+
+parcelable CursorAnchorInfoRequest;
diff --git a/core/java/android/view/inputmethod/CursorAnchorInfoRequest.java b/core/java/android/view/inputmethod/CursorAnchorInfoRequest.java
new file mode 100644
index 0000000..e4c94f2
--- /dev/null
+++ b/core/java/android/view/inputmethod/CursorAnchorInfoRequest.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package android.view.inputmethod;
+
+import android.inputmethodservice.InputMethodService;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.view.View;
+
+/**
+ * Used to enable or disable event notification for
+ * {@link InputMethodService#onUpdateCursorAnchorInfo(CursorAnchorInfo)}. This class is also used to
+ * enable {@link InputMethodService#onUpdateCursor(android.graphics.Rect)} for existing editors
+ * that have not supported {@link InputMethodService#onUpdateCursorAnchorInfo(CursorAnchorInfo)}.
+ */
+public final class CursorAnchorInfoRequest implements Parcelable {
+ private final int mRequestType;
+ private final int mRequestFlags;
+
+ /**
+ * Not handled by the editor.
+ */
+ public static final int RESULT_NOT_HANDLED = 0x00;
+ /**
+ * Request is scheduled in the editor task queue.
+ */
+ public static final int RESULT_SCHEDULED = 0x01;
+
+ /**
+ * The request is for {@link InputMethodService#onUpdateCursorAnchorInfo(CursorAnchorInfo)}.
+ * This mechanism is powerful enough to retrieve fine-grained positional information of
+ * characters in the editor.
+ */
+ public static final int TYPE_CURSOR_ANCHOR_INFO = 0x01;
+ /**
+ * The editor is requested to call
+ * {@link InputMethodManager#updateCursorAnchorInfo(android.view.View, CursorAnchorInfo)}
+ * whenever cursor/anchor position is changed. To disable monitoring, call
+ * {@link InputConnection#requestCursorAnchorInfo(CursorAnchorInfoRequest)} again with
+ * {@link #TYPE_CURSOR_ANCHOR_INFO} and this flag off.
+ * <p>
+ * This flag can be used together with {@link #FLAG_CURSOR_ANCHOR_INFO_IMMEDIATE}.
+ * </p>
+ */
+ public static final int FLAG_CURSOR_ANCHOR_INFO_MONITOR = 0x01;
+ /**
+ * The editor is requested to call
+ * {@link InputMethodManager#updateCursorAnchorInfo(android.view.View, CursorAnchorInfo)} at
+ * once, as soon as possible, regardless of cursor/anchor position changes. This flag can be
+ * used together with {@link #FLAG_CURSOR_ANCHOR_INFO_MONITOR}.
+ */
+ public static final int FLAG_CURSOR_ANCHOR_INFO_IMMEDIATE = 0x02;
+
+ /**
+ * The request is for {@link InputMethodService#onUpdateCursor(android.graphics.Rect)}. This
+ * mechanism has been available since API Level 3 (CUPCAKE) but only the cursor rectangle can
+ * be retrieved with this mechanism.
+ */
+ public static final int TYPE_CURSOR_RECT = 0x02;
+ /**
+ * The editor is requested to call
+ * {@link InputMethodManager#updateCursor(android.view.View, int, int, int, int)}
+ * whenever the cursor position is changed. To disable monitoring, call
+ * {@link InputConnection#requestCursorAnchorInfo(CursorAnchorInfoRequest)} again with
+ * {@link #TYPE_CURSOR_RECT} and this flag off.
+ * <p>
+ * This flag can be used together with {@link #FLAG_CURSOR_RECT_IN_SCREEN_COORDINATES}.
+ * </p>
+ */
+ public static final int FLAG_CURSOR_RECT_MONITOR = 0x01;
+ /**
+ * {@link InputMethodManager#updateCursor(android.view.View, int, int, int, int)} should be
+ * called back in screen coordinates. To receive cursor position in local coordinates, call
+ * {@link InputConnection#requestCursorAnchorInfo(CursorAnchorInfoRequest)} again with
+ * {@link #TYPE_CURSOR_RECT} and this flag off.
+ */
+ public static final int FLAG_CURSOR_RECT_IN_SCREEN_COORDINATES = 0x02;
+ /**
+ * {@link InputMethodManager#updateCursor(android.view.View, int, int, int, int)} should be
+ * called back in screen coordinates after coordinate conversion with {@link View#getMatrix()}.
+ * To disable coordinate conversion with {@link View#getMatrix()} again, call
+ * {@link InputConnection#requestCursorAnchorInfo(CursorAnchorInfoRequest)} with
+ * {@link #TYPE_CURSOR_RECT} and this flag off.
+ *
+ * <p>
+ * The flag is ignored if {@link #FLAG_CURSOR_RECT_IN_SCREEN_COORDINATES} is off.
+ * </p>
+ */
+ public static final int FLAG_CURSOR_RECT_WITH_VIEW_MATRIX = 0x04;
+
+ /**
+ * Constructs the object with request type and type-specific flags.
+ *
+ * @param requestType the type of this request. Currently {@link #TYPE_CURSOR_ANCHOR_INFO} or
+ * {@link #TYPE_CURSOR_RECT} is supported.
+ * @param requestFlags the flags for the given request type.
+ */
+ public CursorAnchorInfoRequest(int requestType, int requestFlags) {
+ mRequestType = requestType;
+ mRequestFlags = requestFlags;
+ }
+
+ /**
+ * Used to make this class parcelable.
+ *
+ * @param source the parcel from which the object is unmarshalled.
+ */
+ public CursorAnchorInfoRequest(Parcel source) {
+ mRequestType = source.readInt();
+ mRequestFlags = source.readInt();
+ }
+
+ /**
+ * @return the type of this request.
+ */
+ public int getRequestType() {
+ return mRequestType;
+ }
+
+ /**
+ * @return the flags that are specific to the type of this request.
+ */
+ public int getRequestFlags() {
+ return mRequestFlags;
+ }
+
+ /**
+ * Used to package this object into a {@link Parcel}.
+ *
+ * @param dest The {@link Parcel} to be written.
+ * @param flags The flags used for parceling.
+ */
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mRequestType);
+ dest.writeInt(mRequestFlags);
+ }
+
+ @Override
+ public int hashCode(){
+ return mRequestType * 31 + mRequestFlags;
+ }
+
+ @Override
+ public boolean equals(Object obj){
+ if (obj == null) {
+ return false;
+ }
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof CursorAnchorInfoRequest)) {
+ return false;
+ }
+ final CursorAnchorInfoRequest that = (CursorAnchorInfoRequest) obj;
+ if (hashCode() != that.hashCode()) {
+ return false;
+ }
+ return mRequestType != that.mRequestType && mRequestFlags == that.mRequestFlags;
+ }
+
+ @Override
+ public String toString() {
+ return "CursorAnchorInfoRequest{mRequestType=" + mRequestType
+ + " mRequestFlags=" + mRequestFlags
+ + "}";
+ }
+
+ /**
+ * Used to make this class parcelable.
+ */
+ public static final Parcelable.Creator<CursorAnchorInfoRequest> CREATOR =
+ new Parcelable.Creator<CursorAnchorInfoRequest>() {
+ @Override
+ public CursorAnchorInfoRequest createFromParcel(Parcel source) {
+ return new CursorAnchorInfoRequest(source);
+ }
+
+ @Override
+ public CursorAnchorInfoRequest[] newArray(int size) {
+ return new CursorAnchorInfoRequest[size];
+ }
+ };
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+}
diff --git a/core/java/android/view/inputmethod/InputConnection.java b/core/java/android/view/inputmethod/InputConnection.java
index 3537aec..dff91dc 100644
--- a/core/java/android/view/inputmethod/InputConnection.java
+++ b/core/java/android/view/inputmethod/InputConnection.java
@@ -723,4 +723,15 @@ public interface InputConnection {
* valid.
*/
public boolean performPrivateCommand(String action, Bundle data);
+
+ /**
+ * Called by the IME to ask the editor for calling back
+ * {@link InputMethodManager#updateCursorAnchorInfo(android.view.View, CursorAnchorInfo)} to
+ * notify cursor/anchor locations.
+ *
+ * @param request the details of the request.
+ * @return a result code that depends on {@link CursorAnchorInfoRequest#getRequestType()}. See
+ * {@link CursorAnchorInfoRequest} for details.
+ */
+ public int requestCursorAnchorInfo(CursorAnchorInfoRequest request);
}
diff --git a/core/java/android/view/inputmethod/InputConnectionWrapper.java b/core/java/android/view/inputmethod/InputConnectionWrapper.java
index a48473e..c831d7c 100644
--- a/core/java/android/view/inputmethod/InputConnectionWrapper.java
+++ b/core/java/android/view/inputmethod/InputConnectionWrapper.java
@@ -125,4 +125,8 @@ public class InputConnectionWrapper implements InputConnection {
public boolean performPrivateCommand(String action, Bundle data) {
return mTarget.performPrivateCommand(action, data);
}
-}
+
+ public int requestCursorAnchorInfo(CursorAnchorInfoRequest request) {
+ return mTarget.requestCursorAnchorInfo(request);
+ }
+ }
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index ace8808..623b5f9 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -25,8 +25,9 @@ import com.android.internal.view.IInputMethodSession;
import com.android.internal.view.InputBindResult;
import android.content.Context;
+import android.graphics.Matrix;
import android.graphics.Rect;
-import android.inputmethodservice.InputMethodService;
+import android.graphics.RectF;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
@@ -312,8 +313,9 @@ public final class InputMethodManager {
CompletionInfo[] mCompletions;
// Cursor position on the screen.
- Rect mTmpCursorRect = new Rect();
+ Rect mNextCursorRect = new Rect();
Rect mCursorRect = new Rect();
+ RectF mTempRectF = new RectF();
int mCursorSelStart;
int mCursorSelEnd;
int mCursorCandStart;
@@ -348,8 +350,13 @@ public final class InputMethodManager {
*/
private final int[] mViewTopLeft = new int[2];
+ /**
+ * The matrix to convert the view location into screen coordinates in {@link #updateCursor}.
+ */
+ private final Matrix mViewToScreenMatrix = new Matrix();
+
// -----------------------------------------------------------
-
+
/**
* Sequence number of this binding, as returned by the server.
*/
@@ -365,10 +372,28 @@ public final class InputMethodManager {
InputChannel mCurChannel;
ImeInputEventSender mCurSender;
+ private static final int CURSOR_RECT_MONITOR_MODE_NONE = 0x0;
+
+ private static final int CURSOR_RECT_MONITOR_FLAG_MASK =
+ CursorAnchorInfoRequest.FLAG_CURSOR_RECT_MONITOR |
+ CursorAnchorInfoRequest.FLAG_CURSOR_RECT_IN_SCREEN_COORDINATES |
+ CursorAnchorInfoRequest.FLAG_CURSOR_RECT_WITH_VIEW_MATRIX;
+
+ private static final int CURSOR_ANCHOR_INFO_MONITOR_MODE_NONE = 0x0;
+
+ private static final int CURSOR_ANCHOR_INFO_MONITOR_FLAG_MASK =
+ CursorAnchorInfoRequest.FLAG_CURSOR_ANCHOR_INFO_MONITOR |
+ CursorAnchorInfoRequest.FLAG_CURSOR_ANCHOR_INFO_IMMEDIATE;
+
+ /**
+ * The monitor mode for {@link #updateCursor(View, int, int, int, int)}.
+ */
+ private int mCursorRectMonitorMode = CURSOR_RECT_MONITOR_MODE_NONE;
+
/**
- * The current cursor/anchor monitor mode.
+ * The monitor mode for {@link #updateCursorAnchorInfo(View, CursorAnchorInfo)}.
*/
- int mCursorAnchorMonitorMode = InputMethodService.CURSOR_ANCHOR_MONITOR_MODE_NONE;
+ private int mCursorAnchorInfoMonitorMode = CURSOR_ANCHOR_INFO_MONITOR_MODE_NONE;
final Pool<PendingEvent> mPendingEventPool = new SimplePool<PendingEvent>(20);
final SparseArray<PendingEvent> mPendingEvents = new SparseArray<PendingEvent>(20);
@@ -382,7 +407,6 @@ public final class InputMethodManager {
static final int MSG_SEND_INPUT_EVENT = 5;
static final int MSG_TIMEOUT_INPUT_EVENT = 6;
static final int MSG_FLUSH_INPUT_EVENT = 7;
- static final int MSG_SET_CURSOR_ANCHOR_MONITOR_MODE = 8;
static final int MSG_SET_USER_ACTION_NOTIFICATION_SEQUENCE_NUMBER = 9;
class H extends Handler {
@@ -422,6 +446,9 @@ public final class InputMethodManager {
return;
}
+ mCursorAnchorInfoMonitorMode = CURSOR_ANCHOR_INFO_MONITOR_MODE_NONE;
+ mCursorRectMonitorMode = CURSOR_RECT_MONITOR_MODE_NONE;
+
setInputChannelLocked(res.channel);
mCurMethod = res.method;
mCurId = res.id;
@@ -514,15 +541,6 @@ public final class InputMethodManager {
finishedInputEvent(msg.arg1, false, false);
return;
}
- case MSG_SET_CURSOR_ANCHOR_MONITOR_MODE: {
- synchronized (mH) {
- mCursorAnchorMonitorMode = msg.arg1;
- // Clear the cache.
- mCursorRect.setEmpty();
- mCursorAnchorInfo = null;
- }
- return;
- }
case MSG_SET_USER_ACTION_NOTIFICATION_SEQUENCE_NUMBER: {
synchronized (mH) {
mNextUserActionNotificationSequenceNumber = msg.arg1;
@@ -594,11 +612,6 @@ public final class InputMethodManager {
}
@Override
- public void setCursorAnchorMonitorMode(int monitorMode) {
- mH.sendMessage(mH.obtainMessage(MSG_SET_CURSOR_ANCHOR_MONITOR_MODE, monitorMode, 0));
- }
-
- @Override
public void setUserActionNotificationSequenceNumber(int sequenceNumber) {
mH.sendMessage(mH.obtainMessage(MSG_SET_USER_ACTION_NOTIFICATION_SEQUENCE_NUMBER,
sequenceNumber, 0));
@@ -1535,37 +1548,45 @@ public final class InputMethodManager {
return false;
}
synchronized (mH) {
- return (mCursorAnchorMonitorMode &
- InputMethodService.CURSOR_ANCHOR_MONITOR_MODE_CURSOR_RECT) != 0;
+ return (mCursorRectMonitorMode & CursorAnchorInfoRequest.FLAG_CURSOR_RECT_MONITOR) != 0;
}
}
/**
- * Returns true if the current input method wants to receive the cursor rectangle in
- * screen coordinates rather than local coordinates in the attached view.
+ * Updates the result of {@link #isWatchingCursor(View)}.
*
* @hide
*/
- public boolean usesScreenCoordinatesForCursorLocked() {
- // {@link InputMethodService#CURSOR_ANCHOR_MONITOR_MODE_CURSOR_RECT} also means
- // that {@link InputMethodService#onUpdateCursor} should provide the cursor rectangle
- // in screen coordinates rather than local coordinates.
- return (mCursorAnchorMonitorMode &
- InputMethodService.CURSOR_ANCHOR_MONITOR_MODE_CURSOR_RECT) != 0;
+ public void setCursorRectMonitorMode(int flags) {
+ synchronized (mH) {
+ mCursorRectMonitorMode = (CURSOR_RECT_MONITOR_FLAG_MASK & flags);
+ }
}
/**
- * Set cursor/anchor monitor mode via {@link com.android.server.InputMethodManagerService}.
- * This is an internal method for {@link android.inputmethodservice.InputMethodService} and
- * should never be used from IMEs and applications.
+ * Returns true if the current input method wants to be notified when cursor/anchor location
+ * is changed.
*
* @hide
*/
- public void setCursorAnchorMonitorMode(IBinder imeToken, int monitorMode) {
- try {
- mService.setCursorAnchorMonitorMode(imeToken, monitorMode);
- } catch (RemoteException e) {
- throw new RuntimeException(e);
+ public boolean isCursorAnchorInfoEnabled() {
+ synchronized (mH) {
+ final boolean isImmediate = (mCursorAnchorInfoMonitorMode &
+ CursorAnchorInfoRequest.FLAG_CURSOR_ANCHOR_INFO_IMMEDIATE) != 0;
+ final boolean isMonitoring = (mCursorAnchorInfoMonitorMode &
+ CursorAnchorInfoRequest.FLAG_CURSOR_ANCHOR_INFO_MONITOR) != 0;
+ return isImmediate || isMonitoring;
+ }
+ }
+
+ /**
+ * Updates the result of {@link #isWatchingCursor(View)}.
+ *
+ * @hide
+ */
+ public void setCursorAnchorInfoMonitorMode(int flags) {
+ synchronized (mH) {
+ mCursorAnchorInfoMonitorMode = (CURSOR_ANCHOR_INFO_MONITOR_FLAG_MASK & flags);
}
}
@@ -1581,16 +1602,32 @@ public final class InputMethodManager {
return;
}
if (DEBUG) Log.d(TAG, "updateCursor");
- mTmpCursorRect.set(left, top, right, bottom);
- if (!Objects.equals(mCursorRect, mTmpCursorRect)) {
+ final boolean usesScreenCoordinates = (mCursorRectMonitorMode &
+ CursorAnchorInfoRequest.FLAG_CURSOR_RECT_IN_SCREEN_COORDINATES) != 0;
+ if (usesScreenCoordinates) {
+ view.getLocationOnScreen(mViewTopLeft);
+ final Matrix viewMatrix = view.getMatrix();
+ final boolean usesViewMatrix = (viewMatrix != null) && ((mCursorRectMonitorMode &
+ CursorAnchorInfoRequest.FLAG_CURSOR_RECT_WITH_VIEW_MATRIX) != 0);
+ if (usesViewMatrix) {
+ mTempRectF.set(left, top, right, bottom);
+ mViewToScreenMatrix.set(viewMatrix);
+ mViewToScreenMatrix.postTranslate(mViewTopLeft[0], mViewTopLeft[1]);
+ mViewToScreenMatrix.mapRect(mTempRectF);
+ mNextCursorRect.set((int)mTempRectF.left, (int)mTempRectF.top,
+ (int)mTempRectF.right, (int)mTempRectF.bottom);
+ } else {
+ mNextCursorRect.set(left + mViewTopLeft[0], top + mViewTopLeft[1],
+ right + mViewTopLeft[0], bottom + mViewTopLeft[1]);
+ }
+ } else {
+ mNextCursorRect.set(left, top, right, bottom);
+ }
+ if (!Objects.equals(mCursorRect, mNextCursorRect)) {
+ if (DEBUG) Log.v(TAG, "CURSOR CHANGE: " + mNextCursorRect);
try {
- if (DEBUG) Log.v(TAG, "CURSOR CHANGE: " + mCurMethod);
- mCursorRect.set(mTmpCursorRect);
- if (usesScreenCoordinatesForCursorLocked()) {
- view.getLocationOnScreen(mViewTopLeft);
- mTmpCursorRect.offset(mViewTopLeft[0], mViewTopLeft[1]);
- }
- mCurMethod.updateCursor(mTmpCursorRect);
+ mCurMethod.updateCursor(mNextCursorRect);
+ mCursorRect.set(mNextCursorRect);
} catch (RemoteException e) {
Log.w(TAG, "IME died: " + mCurId, e);
}
@@ -1613,7 +1650,11 @@ public final class InputMethodManager {
|| mCurrentTextBoxAttribute == null || mCurMethod == null) {
return;
}
- if (Objects.equals(mCursorAnchorInfo, cursorAnchorInfo)) {
+ // If immediate bit is set, we will call updateCursorAnchorInfo() even when the data has
+ // not been changed from the previous call.
+ final boolean isImmediate = (mCursorAnchorInfoMonitorMode &
+ CursorAnchorInfoRequest.FLAG_CURSOR_ANCHOR_INFO_IMMEDIATE) != 0;
+ if (!isImmediate && Objects.equals(mCursorAnchorInfo, cursorAnchorInfo)) {
Log.w(TAG, "Ignoring redundant updateCursorAnchorInfo: info=" + cursorAnchorInfo);
return;
}
@@ -1621,6 +1662,9 @@ public final class InputMethodManager {
try {
mCurMethod.updateCursorAnchorInfo(cursorAnchorInfo);
mCursorAnchorInfo = cursorAnchorInfo;
+ // Clear immediate bit (if any).
+ mCursorAnchorInfoMonitorMode &=
+ ~CursorAnchorInfoRequest.FLAG_CURSOR_ANCHOR_INFO_IMMEDIATE;
} catch (RemoteException e) {
Log.w(TAG, "IME died: " + mCurId, e);
}
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 3a1f6ed..9701c6f 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -68,6 +68,7 @@ import android.view.animation.LinearInterpolator;
import android.view.inputmethod.BaseInputConnection;
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.CorrectionInfo;
+import android.view.inputmethod.CursorAnchorInfoRequest;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.ExtractedText;
import android.view.inputmethod.ExtractedTextRequest;
@@ -5696,6 +5697,11 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
public boolean performPrivateCommand(String action, Bundle data) {
return getTarget().performPrivateCommand(action, data);
}
+
+ @Override
+ public int requestCursorAnchorInfo(CursorAnchorInfoRequest request) {
+ return getTarget().requestCursorAnchorInfo(request);
+ }
}
/**
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 170a316..66c4b81 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -3027,8 +3027,11 @@ public class Editor {
if (null == imm) {
return;
}
+ if (!imm.isActive(mTextView)) {
+ return;
+ }
// Skip if the IME has not requested the cursor/anchor position.
- if (!imm.isWatchingCursor(mTextView)) {
+ if (!imm.isCursorAnchorInfoEnabled()) {
return;
}
Layout layout = mTextView.getLayout();