Loading java/src/com/android/inputmethod/compat/InputConnectionCompatUtils.java +70 −6 Original line number Original line Diff line number Diff line Loading @@ -16,12 +16,15 @@ package com.android.inputmethod.compat; package com.android.inputmethod.compat; import android.util.Log; import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputConnection; import java.lang.reflect.Constructor; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.Method; public final class InputConnectionCompatUtils { public final class InputConnectionCompatUtils { private static final String TAG = InputConnectionCompatUtils.class.getSimpleName(); // Note that CursorAnchorInfoRequest is supposed to be available in API level 21 and later. // Note that CursorAnchorInfoRequest is supposed to be available in API level 21 and later. private static Class<?> getCursorAnchorInfoRequestClass() { private static Class<?> getCursorAnchorInfoRequestClass() { try { try { Loading @@ -48,23 +51,84 @@ public final class InputConnectionCompatUtils { } } /** /** * A local copy of CursorAnchorInfoRequest.RESULT_NOT_HANDLED until the SDK becomes publicly * Local copies of some constants in CursorAnchorInfoRequest until the SDK becomes publicly * available. * available. */ */ private final static int CURSOR_ANCHOR_INFO_REQUEST_RESULT_NOT_HANDLED = 0; private final static int RESULT_NOT_HANDLED = 0; private final static int RESULT_SCHEDULED = 1; private final static int TYPE_CURSOR_ANCHOR_INFO = 1; private final static int FLAG_CURSOR_ANCHOR_INFO_MONITOR = 1; private final static int FLAG_CURSOR_ANCHOR_INFO_IMMEDIATE = 2; private final static int TYPE_CURSOR_RECT = 2; private final static int FLAG_CURSOR_RECT_MONITOR = 1; private final static int FLAG_CURSOR_RECT_IN_SCREEN_COORDINATES = 2; private final static int FLAG_CURSOR_RECT_WITH_VIEW_MATRIX = 4; public static int requestCursorAnchorInfo(final InputConnection inputConnection, private static int requestCursorAnchorInfoImpl(final InputConnection inputConnection, final int type, final int flags) { final int type, final int flags) { if (!isRequestCursorAnchorInfoAvailable()) { if (!isRequestCursorAnchorInfoAvailable()) { return CURSOR_ANCHOR_INFO_REQUEST_RESULT_NOT_HANDLED; return RESULT_NOT_HANDLED; } } final Object requestObject = CompatUtils.newInstance( final Object requestObject = CompatUtils.newInstance( CONSTRUCTOR_CursorAnchorInfoRequest, type, flags); CONSTRUCTOR_CursorAnchorInfoRequest, type, flags); if (requestObject == null) { if (requestObject == null) { return CURSOR_ANCHOR_INFO_REQUEST_RESULT_NOT_HANDLED; return RESULT_NOT_HANDLED; } } return (Integer) CompatUtils.invoke(inputConnection, return (Integer) CompatUtils.invoke(inputConnection, CURSOR_ANCHOR_INFO_REQUEST_RESULT_NOT_HANDLED /* defaultValue */, RESULT_NOT_HANDLED /* defaultValue */, METHOD_requestCursorAnchorInfo, requestObject); METHOD_requestCursorAnchorInfo, requestObject); } } /** * Requests the editor to call back {@link InputMethodManager#updateCursorAnchorInfo}. * @param inputConnection the input connection to which the request is to be sent. * @param enableMonitor {@code true} to request the editor to call back the method whenever the * cursor/anchor position is changed. * @param requestImmediateCallback {@code true} to request the editor to call back the method * as soon as possible to notify the current cursor/anchor position to the input method. * @return {@code false} if the request is not handled. Otherwise returns {@code true}. */ public static boolean requestCursorAnchorInfo(final InputConnection inputConnection, final boolean enableMonitor, final boolean requestImmediateCallback) { final int requestFlags = (enableMonitor ? FLAG_CURSOR_ANCHOR_INFO_MONITOR : 0) | (requestImmediateCallback ? FLAG_CURSOR_ANCHOR_INFO_IMMEDIATE : 0); final int requestResult = requestCursorAnchorInfoImpl(inputConnection, TYPE_CURSOR_ANCHOR_INFO, requestFlags); switch (requestResult) { case RESULT_NOT_HANDLED: return false; case RESULT_SCHEDULED: return true; default: Log.w(TAG, "requestCursorAnchorInfo returned unknown result=" + requestResult + " for type=TYPE_CURSOR_ANCHOR_INFO flags=" + requestFlags); return true; } } /** * Requests the editor to call back {@link InputMethodManager#updateCursor}. * @param inputConnection the input connection to which the request is to be sent. * @param enableMonitor {@code true} to request the editor to call back the method whenever the * cursor position is changed. * @return {@code false} if the request is not handled. Otherwise returns {@code true}. */ public static boolean requestCursorRect(final InputConnection inputConnection, final boolean enableMonitor) { final int requestFlags = enableMonitor ? FLAG_CURSOR_RECT_MONITOR | FLAG_CURSOR_RECT_IN_SCREEN_COORDINATES | FLAG_CURSOR_RECT_WITH_VIEW_MATRIX : 0; final int requestResult = requestCursorAnchorInfoImpl(inputConnection, TYPE_CURSOR_RECT, requestFlags); switch (requestResult) { case RESULT_NOT_HANDLED: return false; case RESULT_SCHEDULED: return true; default: Log.w(TAG, "requestCursorAnchorInfo returned unknown result=" + requestResult + " for type=TYPE_CURSOR_RECT flags=" + requestFlags); return true; } } } } Loading
java/src/com/android/inputmethod/compat/InputConnectionCompatUtils.java +70 −6 Original line number Original line Diff line number Diff line Loading @@ -16,12 +16,15 @@ package com.android.inputmethod.compat; package com.android.inputmethod.compat; import android.util.Log; import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputConnection; import java.lang.reflect.Constructor; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.lang.reflect.Method; public final class InputConnectionCompatUtils { public final class InputConnectionCompatUtils { private static final String TAG = InputConnectionCompatUtils.class.getSimpleName(); // Note that CursorAnchorInfoRequest is supposed to be available in API level 21 and later. // Note that CursorAnchorInfoRequest is supposed to be available in API level 21 and later. private static Class<?> getCursorAnchorInfoRequestClass() { private static Class<?> getCursorAnchorInfoRequestClass() { try { try { Loading @@ -48,23 +51,84 @@ public final class InputConnectionCompatUtils { } } /** /** * A local copy of CursorAnchorInfoRequest.RESULT_NOT_HANDLED until the SDK becomes publicly * Local copies of some constants in CursorAnchorInfoRequest until the SDK becomes publicly * available. * available. */ */ private final static int CURSOR_ANCHOR_INFO_REQUEST_RESULT_NOT_HANDLED = 0; private final static int RESULT_NOT_HANDLED = 0; private final static int RESULT_SCHEDULED = 1; private final static int TYPE_CURSOR_ANCHOR_INFO = 1; private final static int FLAG_CURSOR_ANCHOR_INFO_MONITOR = 1; private final static int FLAG_CURSOR_ANCHOR_INFO_IMMEDIATE = 2; private final static int TYPE_CURSOR_RECT = 2; private final static int FLAG_CURSOR_RECT_MONITOR = 1; private final static int FLAG_CURSOR_RECT_IN_SCREEN_COORDINATES = 2; private final static int FLAG_CURSOR_RECT_WITH_VIEW_MATRIX = 4; public static int requestCursorAnchorInfo(final InputConnection inputConnection, private static int requestCursorAnchorInfoImpl(final InputConnection inputConnection, final int type, final int flags) { final int type, final int flags) { if (!isRequestCursorAnchorInfoAvailable()) { if (!isRequestCursorAnchorInfoAvailable()) { return CURSOR_ANCHOR_INFO_REQUEST_RESULT_NOT_HANDLED; return RESULT_NOT_HANDLED; } } final Object requestObject = CompatUtils.newInstance( final Object requestObject = CompatUtils.newInstance( CONSTRUCTOR_CursorAnchorInfoRequest, type, flags); CONSTRUCTOR_CursorAnchorInfoRequest, type, flags); if (requestObject == null) { if (requestObject == null) { return CURSOR_ANCHOR_INFO_REQUEST_RESULT_NOT_HANDLED; return RESULT_NOT_HANDLED; } } return (Integer) CompatUtils.invoke(inputConnection, return (Integer) CompatUtils.invoke(inputConnection, CURSOR_ANCHOR_INFO_REQUEST_RESULT_NOT_HANDLED /* defaultValue */, RESULT_NOT_HANDLED /* defaultValue */, METHOD_requestCursorAnchorInfo, requestObject); METHOD_requestCursorAnchorInfo, requestObject); } } /** * Requests the editor to call back {@link InputMethodManager#updateCursorAnchorInfo}. * @param inputConnection the input connection to which the request is to be sent. * @param enableMonitor {@code true} to request the editor to call back the method whenever the * cursor/anchor position is changed. * @param requestImmediateCallback {@code true} to request the editor to call back the method * as soon as possible to notify the current cursor/anchor position to the input method. * @return {@code false} if the request is not handled. Otherwise returns {@code true}. */ public static boolean requestCursorAnchorInfo(final InputConnection inputConnection, final boolean enableMonitor, final boolean requestImmediateCallback) { final int requestFlags = (enableMonitor ? FLAG_CURSOR_ANCHOR_INFO_MONITOR : 0) | (requestImmediateCallback ? FLAG_CURSOR_ANCHOR_INFO_IMMEDIATE : 0); final int requestResult = requestCursorAnchorInfoImpl(inputConnection, TYPE_CURSOR_ANCHOR_INFO, requestFlags); switch (requestResult) { case RESULT_NOT_HANDLED: return false; case RESULT_SCHEDULED: return true; default: Log.w(TAG, "requestCursorAnchorInfo returned unknown result=" + requestResult + " for type=TYPE_CURSOR_ANCHOR_INFO flags=" + requestFlags); return true; } } /** * Requests the editor to call back {@link InputMethodManager#updateCursor}. * @param inputConnection the input connection to which the request is to be sent. * @param enableMonitor {@code true} to request the editor to call back the method whenever the * cursor position is changed. * @return {@code false} if the request is not handled. Otherwise returns {@code true}. */ public static boolean requestCursorRect(final InputConnection inputConnection, final boolean enableMonitor) { final int requestFlags = enableMonitor ? FLAG_CURSOR_RECT_MONITOR | FLAG_CURSOR_RECT_IN_SCREEN_COORDINATES | FLAG_CURSOR_RECT_WITH_VIEW_MATRIX : 0; final int requestResult = requestCursorAnchorInfoImpl(inputConnection, TYPE_CURSOR_RECT, requestFlags); switch (requestResult) { case RESULT_NOT_HANDLED: return false; case RESULT_SCHEDULED: return true; default: Log.w(TAG, "requestCursorAnchorInfo returned unknown result=" + requestResult + " for type=TYPE_CURSOR_RECT flags=" + requestFlags); return true; } } } }