diff options
author | Yohei Yukawa <yukawa@google.com> | 2014-08-21 18:38:44 -0700 |
---|---|---|
committer | Yohei Yukawa <yukawa@google.com> | 2014-08-22 00:55:06 -0700 |
commit | a277db28e990d1f6f74ace0c32fe92401660a840 (patch) | |
tree | 88525827dbf2aff28871579a98e73a058a41a545 /core/java/android/view/inputmethod | |
parent | 97a50adde5eaee4216d537b2a90a9f33533d2926 (diff) | |
download | frameworks_base-a277db28e990d1f6f74ace0c32fe92401660a840.zip frameworks_base-a277db28e990d1f6f74ace0c32fe92401660a840.tar.gz frameworks_base-a277db28e990d1f6f74ace0c32fe92401660a840.tar.bz2 |
Remove CursorAnchorInfoRequest and related stuff
This CL removes CursorAnchorInfoRequest and related stuff
in favor of InputConnection.requestUpdateCursorAnchorInfo,
which is more easy to understand. This CL also deprecates
InputMethodManager#updateCursor and related stuff.
Rationale:
1. The spec of #updateCursor says that it provides the cursor
position in local coordinates, while the input method
requires it in the screen coordinates.
2. #updateCursor has never been enabled in AOSP, because
InputMethodManager#isWatchingCursor always returned false.
3. There has been no way to let
InputMethodManager#isWatchingCursor return true.
4. In L, InputMethodManager#updateCursorAnchorInfo is
introduced to address all the issues above.
Given that we no longer need to support #updateCursor,
CursorAnchorInfoRequest is overkill when we need to convey
just a couple of parameters.
BUG: 17185263
BUG: 17182367
Change-Id: I4a577bfd02b37b9e56c80b8b41bb25afa95dd8ef
Diffstat (limited to 'core/java/android/view/inputmethod')
6 files changed, 64 insertions, 325 deletions
diff --git a/core/java/android/view/inputmethod/BaseInputConnection.java b/core/java/android/view/inputmethod/BaseInputConnection.java index 8cae27b..4d2f57a 100644 --- a/core/java/android/view/inputmethod/BaseInputConnection.java +++ b/core/java/android/view/inputmethod/BaseInputConnection.java @@ -429,25 +429,10 @@ 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}. + * The default implementation does nothing. */ - public int requestCursorAnchorInfo(CursorAnchorInfoRequest request) { - // This implementation supports TYPE_CURSOR_RECT only. - if (request == null || - request.getRequestType() != CursorAnchorInfoRequest.TYPE_CURSOR_RECT) { - return CursorAnchorInfoRequest.RESULT_NOT_HANDLED; - } - if (mIMM == null) { - // In this case, TYPE_CURSOR_RECT is not handled. - // TODO: Return some notification code for the input method that indicates - // Cursor rect information is temporarily unavailable. - return CursorAnchorInfoRequest.RESULT_NOT_HANDLED; - } - mIMM.setCursorRectMonitorMode(request.getRequestFlags()); - return CursorAnchorInfoRequest.RESULT_SCHEDULED; + public boolean requestUpdateCursorAnchorInfo(int cursorUpdateMode) { + return false; } /** diff --git a/core/java/android/view/inputmethod/CursorAnchorInfoRequest.aidl b/core/java/android/view/inputmethod/CursorAnchorInfoRequest.aidl deleted file mode 100644 index 41ef7cc6..0000000 --- a/core/java/android/view/inputmethod/CursorAnchorInfoRequest.aidl +++ /dev/null @@ -1,19 +0,0 @@ -/* - * 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 deleted file mode 100644 index e4c94f2..0000000 --- a/core/java/android/view/inputmethod/CursorAnchorInfoRequest.java +++ /dev/null @@ -1,203 +0,0 @@ -/* - * 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 dff91dc..ca094c1 100644 --- a/core/java/android/view/inputmethod/InputConnection.java +++ b/core/java/android/view/inputmethod/InputConnection.java @@ -725,13 +725,34 @@ public interface InputConnection { public boolean performPrivateCommand(String action, Bundle data); /** - * Called by the IME to ask the editor for calling back + * 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 #REQUEST_UPDATE_CURSOR_ANCHOR_INFO_MONITOR}. + */ + public static final int REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE = 1 << 0; + + /** + * 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#requestUpdateCursorAnchorInfo(int)} again with this flag off. + * <p> + * This flag can be used together with {@link #REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE}. + * </p> + */ + public static final int REQUEST_UPDATE_CURSOR_ANCHOR_INFO_MONITOR = 1 << 1; + + /** + * Called by the input method 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. + * @param cursorUpdateMode {@link #REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE} and/or + * {@link #REQUEST_UPDATE_CURSOR_ANCHOR_INFO_MONITOR} + * @return {@code true} if the request is scheduled. {@code false} to indicate that when the + * application will not call + * {@link InputMethodManager#updateCursorAnchorInfo(android.view.View, CursorAnchorInfo)}. */ - public int requestCursorAnchorInfo(CursorAnchorInfoRequest request); + public boolean requestUpdateCursorAnchorInfo(int cursorUpdateMode); } diff --git a/core/java/android/view/inputmethod/InputConnectionWrapper.java b/core/java/android/view/inputmethod/InputConnectionWrapper.java index c831d7c..d95df25 100644 --- a/core/java/android/view/inputmethod/InputConnectionWrapper.java +++ b/core/java/android/view/inputmethod/InputConnectionWrapper.java @@ -126,7 +126,7 @@ public class InputConnectionWrapper implements InputConnection { return mTarget.performPrivateCommand(action, data); } - public int requestCursorAnchorInfo(CursorAnchorInfoRequest request) { - return mTarget.requestCursorAnchorInfo(request); + public boolean requestUpdateCursorAnchorInfo(int cursorUpdateMode) { + return mTarget.requestUpdateCursorAnchorInfo(cursorUpdateMode); } } diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java index eec3570..0a472c7 100644 --- a/core/java/android/view/inputmethod/InputMethodManager.java +++ b/core/java/android/view/inputmethod/InputMethodManager.java @@ -313,9 +313,8 @@ public final class InputMethodManager { CompletionInfo[] mCompletions; // Cursor position on the screen. - Rect mNextCursorRect = new Rect(); + Rect mTmpCursorRect = new Rect(); Rect mCursorRect = new Rect(); - RectF mTempRectF = new RectF(); int mCursorSelStart; int mCursorSelEnd; int mCursorCandStart; @@ -372,28 +371,12 @@ 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; + private static final int REQUEST_UPDATE_CURSOR_ANCHOR_INFO_NONE = 0x0; /** * The monitor mode for {@link #updateCursorAnchorInfo(View, CursorAnchorInfo)}. */ - private int mCursorAnchorInfoMonitorMode = CURSOR_ANCHOR_INFO_MONITOR_MODE_NONE; + private int mRequestUpdateCursorAnchorInfoMonitorMode = REQUEST_UPDATE_CURSOR_ANCHOR_INFO_NONE; final Pool<PendingEvent> mPendingEventPool = new SimplePool<PendingEvent>(20); final SparseArray<PendingEvent> mPendingEvents = new SparseArray<PendingEvent>(20); @@ -446,8 +429,8 @@ public final class InputMethodManager { return; } - mCursorAnchorInfoMonitorMode = CURSOR_ANCHOR_INFO_MONITOR_MODE_NONE; - mCursorRectMonitorMode = CURSOR_RECT_MONITOR_MODE_NONE; + mRequestUpdateCursorAnchorInfoMonitorMode = + REQUEST_UPDATE_CURSOR_ANCHOR_INFO_NONE; setInputChannelLocked(res.channel); mCurMethod = res.method; @@ -1540,59 +1523,49 @@ public final class InputMethodManager { } /** - * Returns true if the current input method wants to watch the location + * Return true if the current input method wants to watch the location * of the input editor's cursor in its window. - */ - public boolean isWatchingCursor(View view) { - if (!isActive(view)) { - return false; - } - synchronized (mH) { - return (mCursorRectMonitorMode & CursorAnchorInfoRequest.FLAG_CURSOR_RECT_MONITOR) != 0; - } - } - - /** - * Updates the result of {@link #isWatchingCursor(View)}. * - * @hide + * @deprecated Use {@link InputConnection#requestUpdateCursorAnchorInfo(int)} instead. */ - public void setCursorRectMonitorMode(int flags) { - synchronized (mH) { - mCursorRectMonitorMode = (CURSOR_RECT_MONITOR_FLAG_MASK & flags); - } + @Deprecated + public boolean isWatchingCursor(View view) { + return false; } /** - * Returns true if the current input method wants to be notified when cursor/anchor location + * Return true if the current input method wants to be notified when cursor/anchor location * is changed. * * @hide */ 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; + final boolean isImmediate = (mRequestUpdateCursorAnchorInfoMonitorMode & + InputConnection.REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE) != 0; + final boolean isMonitoring = (mRequestUpdateCursorAnchorInfoMonitorMode & + InputConnection.REQUEST_UPDATE_CURSOR_ANCHOR_INFO_MONITOR) != 0; return isImmediate || isMonitoring; } } /** - * Updates the result of {@link #isWatchingCursor(View)}. + * Set the requested mode for {@link #updateCursorAnchorInfo(View, CursorAnchorInfo)}. * * @hide */ - public void setCursorAnchorInfoMonitorMode(int flags) { + public void setUpdateCursorAnchorInfoMode(int flags) { synchronized (mH) { - mCursorAnchorInfoMonitorMode = (CURSOR_ANCHOR_INFO_MONITOR_FLAG_MASK & flags); + mRequestUpdateCursorAnchorInfoMonitorMode = flags; } } /** * Report the current cursor location in its window. + * + * @deprecated Use {@link #updateCursorAnchorInfo(View, CursorAnchorInfo)} instead. */ + @Deprecated public void updateCursor(View view, int left, int top, int right, int bottom) { checkFocus(); synchronized (mH) { @@ -1601,33 +1574,15 @@ public final class InputMethodManager { || mCurrentTextBoxAttribute == null || mCurMethod == null) { return; } - if (DEBUG) Log.d(TAG, "updateCursor"); - 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); + + mTmpCursorRect.set(left, top, right, bottom); + if (!mCursorRect.equals(mTmpCursorRect)) { + if (DEBUG) Log.d(TAG, "updateCursor"); + try { - mCurMethod.updateCursor(mNextCursorRect); - mCursorRect.set(mNextCursorRect); + if (DEBUG) Log.v(TAG, "CURSOR CHANGE: " + mCurMethod); + mCurMethod.updateCursor(mTmpCursorRect); + mCursorRect.set(mTmpCursorRect); } catch (RemoteException e) { Log.w(TAG, "IME died: " + mCurId, e); } @@ -1652,8 +1607,8 @@ public final class InputMethodManager { } // 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; + final boolean isImmediate = (mRequestUpdateCursorAnchorInfoMonitorMode & + InputConnection.REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE) != 0; if (!isImmediate && Objects.equals(mCursorAnchorInfo, cursorAnchorInfo)) { // TODO: Consider always emitting this message once we have addressed redundant // calls of this method from android.widget.Editor. @@ -1668,8 +1623,8 @@ public final class InputMethodManager { mCurMethod.updateCursorAnchorInfo(cursorAnchorInfo); mCursorAnchorInfo = cursorAnchorInfo; // Clear immediate bit (if any). - mCursorAnchorInfoMonitorMode &= - ~CursorAnchorInfoRequest.FLAG_CURSOR_ANCHOR_INFO_IMMEDIATE; + mRequestUpdateCursorAnchorInfoMonitorMode &= + ~InputConnection.REQUEST_UPDATE_CURSOR_ANCHOR_INFO_IMMEDIATE; } catch (RemoteException e) { Log.w(TAG, "IME died: " + mCurId, e); } |