diff options
Diffstat (limited to 'core/java/android')
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(); |