From b2707856aba4fc9b063f26305f1fb603b19c1701 Mon Sep 17 00:00:00 2001 From: satok Date: Wed, 23 Mar 2011 23:18:49 -0700 Subject: [PATCH] Added InputConnectionCompatUtils and EditorInfoCompatUtils Change-Id: Ie69d5e90c4ee978d3ecb40b68e6466082569ca7a --- .../inputmethod/compat/CompatUtils.java | 14 +++++ .../compat/EditorInfoCompatUtils.java | 59 +++++++++++++++++++ .../compat/InputConnectionCompatUtils.java | 58 ++++++++++++++++++ .../android/inputmethod/latin/LatinIME.java | 22 ++++--- 4 files changed, 141 insertions(+), 12 deletions(-) create mode 100644 java/src/com/android/inputmethod/compat/EditorInfoCompatUtils.java create mode 100644 java/src/com/android/inputmethod/compat/InputConnectionCompatUtils.java diff --git a/java/src/com/android/inputmethod/compat/CompatUtils.java b/java/src/com/android/inputmethod/compat/CompatUtils.java index 07db4a1bb..a8086919c 100644 --- a/java/src/com/android/inputmethod/compat/CompatUtils.java +++ b/java/src/com/android/inputmethod/compat/CompatUtils.java @@ -20,6 +20,7 @@ import android.content.Intent; import android.text.TextUtils; import android.util.Log; +import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -90,6 +91,19 @@ public class CompatUtils { } } + public static Constructor getConstructor(Class targetClass, Class[] types) { + if (targetClass == null || types == null) return null; + try { + return targetClass.getConstructor(types); + } catch (SecurityException e) { + // ignore + return null; + } catch (NoSuchMethodException e) { + // ignore + return null; + } + } + public static Object invoke( Object receiver, Object defaultValue, Method method, Object... args) { if (receiver == null || method == null) return defaultValue; diff --git a/java/src/com/android/inputmethod/compat/EditorInfoCompatUtils.java b/java/src/com/android/inputmethod/compat/EditorInfoCompatUtils.java new file mode 100644 index 000000000..9d83b5463 --- /dev/null +++ b/java/src/com/android/inputmethod/compat/EditorInfoCompatUtils.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2011 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 com.android.inputmethod.compat; + +import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputConnection; + +import java.lang.reflect.Field; + +public class EditorInfoCompatUtils { + private static final Field FIELD_IME_FLAG_NAVIGATE_NEXT = CompatUtils.getField( + EditorInfo.class, "IME_FLAG_NAVIGATE_NEXT"); + private static final Field FIELD_IME_FLAG_NAVIGATE_PREVIOUS = CompatUtils.getField( + EditorInfo.class, "IME_FLAG_NAVIGATE_PREVIOUS"); + private static final Field FIELD_IME_ACTION_PREVIOUS = CompatUtils.getField( + EditorInfo.class, "IME_FLAG_ACTION_PREVIOUS"); + private static final Integer OBJ_IME_FLAG_NAVIGATE_NEXT = (Integer) CompatUtils + .getFieldValue(null, null, FIELD_IME_FLAG_NAVIGATE_NEXT); + private static final Integer OBJ_IME_FLAG_NAVIGATE_PREVIOUS = (Integer) CompatUtils + .getFieldValue(null, null, FIELD_IME_FLAG_NAVIGATE_PREVIOUS); + private static final Integer OBJ_IME_ACTION_PREVIOUS = (Integer) CompatUtils + .getFieldValue(null, null, FIELD_IME_ACTION_PREVIOUS); + + public static boolean hasFlagNavigateNext(int imeOptions) { + if (OBJ_IME_FLAG_NAVIGATE_NEXT == null) + return false; + return (imeOptions & OBJ_IME_FLAG_NAVIGATE_NEXT) != 0; + } + + public static boolean hasFlagNavigatePrevious(int imeOptions) { + if (OBJ_IME_FLAG_NAVIGATE_PREVIOUS == null) + return false; + return (imeOptions & OBJ_IME_FLAG_NAVIGATE_PREVIOUS) != 0; + } + + public static void performEditorActionNext(InputConnection ic) { + ic.performEditorAction(EditorInfo.IME_ACTION_NEXT); + } + + public static void performEditorActionPrevious(InputConnection ic) { + if (OBJ_IME_ACTION_PREVIOUS == null) + return; + ic.performEditorAction(OBJ_IME_ACTION_PREVIOUS); + } +} diff --git a/java/src/com/android/inputmethod/compat/InputConnectionCompatUtils.java b/java/src/com/android/inputmethod/compat/InputConnectionCompatUtils.java new file mode 100644 index 000000000..b4fe32765 --- /dev/null +++ b/java/src/com/android/inputmethod/compat/InputConnectionCompatUtils.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2011 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 com.android.inputmethod.compat; + +import android.util.Log; +import android.view.inputmethod.InputConnection; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +public class InputConnectionCompatUtils { + private static final String TAG = InputConnectionCompatUtils.class.getSimpleName(); + private static final Class CLASS_CorrectionInfo = CompatUtils + .getClass("android.view.inputmethod.CorrectionInfo"); + private static final Class[] INPUT_TYPE_CorrectionInfo = new Class[] { int.class, + CharSequence.class, CharSequence.class }; + private static final Constructor CONSTRUCTOR_CorrectionInfo = CompatUtils + .getConstructor(CLASS_CorrectionInfo, INPUT_TYPE_CorrectionInfo); + private static final Method METHOD_InputConnection_commitCorrection = CompatUtils + .getMethod(InputConnection.class, "commitCorrection", CLASS_CorrectionInfo); + + public static void commitCorrection(InputConnection ic, int offset, CharSequence oldText, + CharSequence newText) { + if (ic == null || CONSTRUCTOR_CorrectionInfo == null + || METHOD_InputConnection_commitCorrection == null) { + return; + } + Object[] args = { offset, oldText, newText }; + try { + Object correctionInfo = CONSTRUCTOR_CorrectionInfo.newInstance(args); + CompatUtils.invoke(ic, null, METHOD_InputConnection_commitCorrection, + correctionInfo); + } catch (IllegalArgumentException e) { + Log.e(TAG, "Error in commitCorrection: IllegalArgumentException"); + } catch (InstantiationException e) { + Log.e(TAG, "Error in commitCorrection: InstantiationException"); + } catch (IllegalAccessException e) { + Log.e(TAG, "Error in commitCorrection: IllegalAccessException"); + } catch (InvocationTargetException e) { + Log.e(TAG, "Error in commitCorrection: InvocationTargetException"); + } + } +} diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 05169dd9b..c050c834e 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -17,6 +17,8 @@ package com.android.inputmethod.latin; import com.android.inputmethod.compat.CompatUtils; +import com.android.inputmethod.compat.EditorInfoCompatUtils; +import com.android.inputmethod.compat.InputConnectionCompatUtils; import com.android.inputmethod.compat.InputMethodManagerCompatWrapper; import com.android.inputmethod.compat.InputMethodServiceCompatWrapper; import com.android.inputmethod.deprecated.VoiceProxy; @@ -64,7 +66,6 @@ import android.view.ViewParent; import android.view.Window; import android.view.WindowManager; import android.view.inputmethod.CompletionInfo; -import android.view.inputmethod.CorrectionInfo; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.ExtractedText; import android.view.inputmethod.ExtractedTextRequest; @@ -1267,9 +1268,8 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar private void handleTab() { final int imeOptions = getCurrentInputEditorInfo().imeOptions; - final int navigationFlags = - EditorInfo.IME_FLAG_NAVIGATE_NEXT | EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS; - if ((imeOptions & navigationFlags) == 0) { + if (!EditorInfoCompatUtils.hasFlagNavigateNext(imeOptions) + && !EditorInfoCompatUtils.hasFlagNavigatePrevious(imeOptions)) { sendDownUpKeyEvents(KeyEvent.KEYCODE_TAB); return; } @@ -1280,12 +1280,13 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar // True if keyboard is in either chording shift or manual temporary upper case mode. final boolean isManualTemporaryUpperCase = mKeyboardSwitcher.isManualTemporaryUpperCase(); - if ((imeOptions & EditorInfo.IME_FLAG_NAVIGATE_NEXT) != 0 + if (EditorInfoCompatUtils.hasFlagNavigateNext(imeOptions) && !isManualTemporaryUpperCase) { + EditorInfoCompatUtils.performEditorActionNext(ic); ic.performEditorAction(EditorInfo.IME_ACTION_NEXT); - } else if ((imeOptions & EditorInfo.IME_FLAG_NAVIGATE_PREVIOUS) != 0 + } else if (EditorInfoCompatUtils.hasFlagNavigatePrevious(imeOptions) && isManualTemporaryUpperCase) { - ic.performEditorAction(EditorInfo.IME_ACTION_PREVIOUS); + EditorInfoCompatUtils.performEditorActionPrevious(ic); } } @@ -1411,11 +1412,8 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar CharSequence typedWord = mWord.getTypedWord(); TextEntryState.backToAcceptedDefault(typedWord); if (!TextUtils.isEmpty(typedWord) && !typedWord.equals(mBestWord)) { - if (ic != null) { - CorrectionInfo correctionInfo = new CorrectionInfo( - mLastSelectionEnd - typedWord.length(), typedWord, mBestWord); - ic.commitCorrection(correctionInfo); - } + InputConnectionCompatUtils.commitCorrection( + ic, mLastSelectionEnd - typedWord.length(), typedWord, mBestWord); if (mCandidateView != null) mCandidateView.onAutoCorrectionInverted(mBestWord); }